A Windows DLL and sample C, VB and Java programs for IMDG Code Substances and Calculations (TUPS Libraries) Author: Exis Technologies Limited, October 2012 This is a toolkit for software developers wanting to integrate IMDG Code functionality into their own in-house cargo management systems. With these routines you can retrieve substance data from the Dangerous Goods List (chapter 3.2). Fields such as Name, Class, Marine Pollutant, Special provisions, Packing instruction number, Limited Quantity, Stowage and Segregation, Properties and Observations are available. These records are retrievable by UN number and variant. 'Next' and 'Previous' UN numbers are also locatable. You can also retrieve the general stowage requirements from chapter 7.1 for a substance, according to its class, subrisks, packing group, etc. You can also check the stowage and segregation requirements for several substances in a load; whether it is prohibited, allowed on deck only, or on or under deck, on a passenger or cargo sailing; and whether the mix of substances need to be segregated from one another. Segregation is according to the classes and subsidiary risks of section 7.2.1.16 and 7.2.7, the segregation groups of chapter 3.1, special requirements from the Dangerous Goods List such as 'segregation as for class 5.1 but away from...', and other paragraphs of chapter 7.2. The degree of segregation required between two loads can also be obtained. The text of the Special Provisions of chapter 3.3, and the Packing, IBC and Tank Instructions and Provisions of chapters 4.1 and 4.2 are retrievable by name. The 32-bit windows DLL is called ctups.dll. Following normal windows conventions, the routines use the WINAPI calling convention. There are sample programs with source code written in C and VB. These are intended to show very simply how the routines can be called rather than to be the basis of a complete end-user system. We also supply ctups.h (for C) and tupsdecl.bas (for VB) for you to include in your own programs to define all the routines and constants. For calling from other languages you can use these as a guide to write your own equivalent. C programs should be linked with the import library ctups.lib (unless you are doing LoadLibrary and GetProcAddress calls). VB programs need to find the dll, for instance by puttting it into the <system> directory or your program's working directory. A similar Java program (Subsdemo.java) is also provided. It uses the same data file and calls other .class files but does not use the DLL. The data file is around 2 Mb in size. It is binary and portable between Windows/DOS, VMS, AS/400 and RS/6000 systems ('big-endian' versions will flip 16-bit integers from low-high to highlow byte order as they read). Accessing a substance record requires just one disk 'seek'. Packaging Instructions and Consolidated Comments will take several. The current version corresponds to IMDG Amendment 35-10, published in November 2010. This was usable during the transition year of 2011 and became mandatory from 1 January 2012. IMDG Code errata and future amendments will require changes to the data file and possibly to the routines also. Amendment 36-12 is due to be published in late 2012, and the year 2013 will be the transition period during which either amendment 35 or 36 can be used. The download package In the zip file you have 20 files: readme.rtf ctups.dll ctups.h ctups.lib subs.ind these instructions the DLL the H file to include in your C program the import library to link with your program the data file (sample data only, only 20% of the substances) subsdemo.exe subsdemo.cpp subsdemo.rc makedemo.bat a simple demonstration program written in C the source for subsdemo.exe the resource script for subsdemo.exe the commands to compile and link subsdemo VBexample.exe frmTups.frm tupsdecl.bas prjTupsExample.vbp prjTupsExample.vbw a simple demonstration program written in VB the source for vbexample.exe declarations for VB visual basic project visual basic workspace Subsdemo.java Subsdemo.class Subsdemo$1.class DGLoad.class DGSubs.class Tups.class a simple demonstration program written in Java swing ) ) Java class files ) ) ) Getting started with subsdemo.exe or VBexample.exe The exe files, ctups.dll and subs.ind should be in the same directory. At first you can only look up UN numbers ending in 0 or 5. Run subsdemo.exe (for a C example) or vbexample.exe (for VB). To look up a substance, type 1230 in the UN number box, and press 'Substance'. You see the primary class, packing group, stowage category, limited quantity value, emergency schedule and packing instruction for Methanol, and the stowage and segregation comments. UN 1230 var 0 Class 3 PG II Cat B LQ= 1 L EmS= F-E,S-D PI= P001 METHANOL|| Clear of living quarters. Type 2430 and press 'Substance'. You see variant 1 of ALKYLPHENOLS, SOLID, N.O.S., with qualifying descriptive text and a variation description 'Packing group I.' after the name. Type 2 into the variant box, press 'Substance' again, and see the second variant. To look up a packing provision, type PP4 in the phrase name box and press 'Phrase'. PP4 For UN 1774, packagings shall meet the packing group II performance level. To see a special provision, type 191 into the box an press 'Phrase' again. Receptacles with a capacity not exceeding 50 ml containing only non-toxic constituents are not subject to the provisions of this Code. Examples of other phrases are: packing instruction (P302), IBC instruction (IBC02), tank instruction (T3), IBC provision (B6), tank provision (TP10). To check for segregation requirements within a load, start a load by clicking the radio button for 'Closed / Passenger'. Type 1790 in the UN number box, 2 in the variant box, and press 'Add to load'. You see return code 97 - this substance is not allowed on passenger sailings. Start another load by clicking the radio button for 'Closed / Cargo'. Press 'Add to Load', and this time it is allowed (return code 0). The label numbers (bitsfields 4000 and 800) are decoded as primary class 8, subrisk 6.1 (refer to the description of function TupsLabCom). Add another substance by putting 1230 and 0 in the UN and variant boxes, and press 'Add to Load'. There is no clash, and class 3 (bitfield 20) is added to the labels. Add a few more substances (e.g. substances 1400, 1515, 3250), and you will start to see clashes - a set of 3 numbers means substance sequence number 'i' clashes with number 'j', and the degree of segregation required is 'k'. You may also see return code 98 - this substance is only allowed in tanks (e.g. substance 3250). Having built one load you can check how it should be segregated against another one. Start the second load by clicking the radio button for 'Closed / Second', and add a few substances to that. In this case the set of 3 numbers means that substance sequence number 'i' in load one clashes with number 'j' in load two and the degree of segregation required is 'k'. For a more complete explanation refer to the technical document section "Compatibility between loads". Recompiling the sample programs Subsdemo is a small, simple windows program. If you want to add more features, edit the .cpp or .rc file. makedemo.bat compiles and links the program. This works with Microsoft C++ versions 5 and 6. Slight changes may be needed for other compilers. It assumes that 'cl', 'rc' and 'link' are to be found in the path, an that environment variables INCLUDE and LIB point to the standard .h and .lib files. VBexample is an equivalent program in VB, which is most easily worked with inside Visual Studio. If you want to run the program from inside Visual Studio, it is easiest to uncomment the 'ChDrive' and 'ChDir' calls in 'Sub Form_Load', and set the values to your own working directory. Specification of the routines Initialization int TupsInit(char *name) Function TupsInit (ByVal fname As String) As Long This should be called first. It opens the substance file and performs various initializations. name the filename, "subs.ind", with any necessary directory specification. return value -1 = Can't open file -2 = Can't get enough memory (unlikely, except in 16-bit versions) -28 = Unactivated copy. Other negative values = various copy protection failures. +ve = OK (the file handle of subs.ind) With an unactivated copy and other protection failures, the system works in 'demo mode'. This only accepts UN numbers ending in 0 or 5, and some of the fields of the dangerous goods list are blank (struct tups, elements pp, ibci, ibcp, tankun, tankimo, tankp,flash and explim; specprov shows only the first provision) Substance Lookups int TupsSub(int un, int suffix) Function TupsSub (ByVal un As Long, ByVal suf As Long) As Long Finds a substance on file. UN number suffix un suffix Note: Where a UN number has no variants, it will be have suffix 0 (e.g. UN 2050, suffix 0). Those with variants are numbered 1 upwards (e.g. 2810 suffixes 1, 2 and 3 are for packing groups I, II and III). A search for suffix 0 or 1 will equally find either of 0 and 1. Alternatively, suffix may be -1 or -2, to find the respectively the next or previous UN number (and suffix 0 or 1) to the one specified. return value 99 if no such substance 0 = OK int TupsRead(int field, char *buf) Sub TupsInfo (ByVal field As Integer, buffer As Any) TUPS_STOW* Sub TupsRead (ByVal field As Integer, ByVal buffer As String) 'used for TUPS_INFO and 'used for other values Reads data for the substance last found with TupsSub. 'buf' can be variously a pointer to a char array, an array of shorts or a 'struct tups' into which the data will be copied. Note that the user must provide a buffer of sufficient size. field TUPS_NAME retrieves Proper Shipping Name, qualifying descriptive text and variation comments. A '|' character (ascii 124) separates the three items, and a NULL terminates it. The string may include embedded linefeed characters. TUPS_STOW retrieves (as an array of shorts, terminated by a zero) the stowage and segregation phrase codes from column 16 of the Dangerous Goods List. See TupsCom for converting the codes to printable phrases. TUPS_STOWC retrieves general stowage comment codes applicable to Cargo ships, for this class, subrisks, packing group, etc, from chapter 7.1 of the code. TUPS_STOWP ditto for passenger ships. TUPS_PROP retrieves as text the properties and observations from column 17 of the Dangerous Goods List. TUPS_INFO retrieves assorted data from the Dangerous Goods List:struct tups { short un; // UN number short suf; // suffix char prim[5]; // primary class char secn[6]; // secondary class (subrisk) char tert[4]; // tertiary class char mp; // Marine pollutant, null, Y, S (=severe, PP) or C (=conditional, bullet) char ulineems; // Underlined EmS. 1 = fire, 2 = spillage, 3 = both char ems [8]; // Emergency Schedule char classcode[5] // ADR classification code char flags; // additional user data required - see below char specprov[28]; // special provisions char lq[10]; // limited quantity char pi[16]; // packing instructions and provisions char pp[26]; char ibci[11]; // IBC instructions and provisions char ibcp[15]; char tankun[7]; // tank instructions, UN, IMO and provisions char tankimo[9]; char tankp[25]; char flash[26]; // flashpoint char explim[28]; // explosive limits char scat[3]; // stowage category, A to E or 01 to 15 char pg[4]; // packing group, null, I, II or III char state; // S,L,G,E,A for solid, liquid, gas, explosive substance or explosive article }; which is declared in an H file. or 'Type tups' which is declared in tupsdecl.bas Note that there are 2 versions of this routine for VB, 'TupsRead' to return a string, and 'TupsInfo' to return an array or a 'tups' structure. The value returned in 'flags' indicates whether any additional information is required from the user to print on a Dangerous Goods Note or manifest. It is the combination of:1 Technical name required (special provision 274 and others) 2 Possible marine pollutant 4 Flashpoint required (class 3 or subrisk 3) 8 Control and emergency temperatures (items under temperature control) 16 Radionuclide, category, activity and transport index required (class 7) 32 May be carried in limited quantity 64 Net explosive content required (class 1) 128 Warn user about special provisions 900 (certain formulations are prohibited) int TupsCom(short code, char *cbuf) Function TupsCom (ByVal code As Integer, ByVal buffer As String) As Long Obtains the comment text related to a numeric comment code. The text will be nullterminated and may include linefeed (ascii 10) characters. code code number (retrieved from TupsRead) to look up cbuf char array into which the phrase will be copied return value 0 = OK 1 = no such comment. int TupsPhrase(char *code, char *cbuf) Function TupsPhrase (ByVal name As String, ByVal buffer As String) As Long Obtains the text related to a text comment code. The text will be null-terminated and may include linefeed (ascii 10) characters. The codes may be packing instructions Pxxx, IBC instructions IBCxx, tank instructions Txx, packing provisions PPxx, Bx or TPxx, or special provisions, numeric. Provisions retrieved by TupsRead may include several codes (e.g. "PP25 PP26 PP31") separated by spaces. It is for the user to split these into separate null-terminated codes for this routine. code phrase name to look up cbuf char array into which the phrase will be copied return value 0 = OK 1 = no such comment. Hint: If the user enters a UN number, call TupsSub for that UN number and suffix zero. For an return code of 99 tell him 'invalid UN number'. Otherwise, if it retrieves suffix zero, there are no variants and you can show him the substance details. If it retrieves variant 1, call TupsRead(TUPS_NAME... to get the description of the first variant, then TupsSub and TupsRead for variants 2, 3, etc until a return of 99 indicates no more variations. Ask him to select one. Checking a Single Load void TupsNewLoad(int mode, int type, short *clashlist, int max_clash) Sub TupsNewLoad (ByVal mode As Long, ByVal utype As Long, clist, ByVal les As Long) For validation of a single load, this empties the load, and specifies whether it is to be checked for passenger or cargo sailings, and open or closed units, or a tank. mode TUPS_PSNGR for a passenger sailing TUPS_CARGO for a cargo sailing and may be or'ed with TUPS_NOCHECK to suppress validation as each substance is added. type TUPS_OPEN TUPS_CLOSED TUPS_TANK according to the unit type clashlist array of shorts which becomes filled with triplets describing each clash a) sequence number of first substance counting from 1 b) sequence number of second substance c) degree of clash - see values 1 to 10 for TupsAddSub The list is terminated by a zero value. With a single load (a) < (b). With VB, pass the first element of the array, clashlist(0) max_clash maximum number of clashes to report. Filling of clashlist stops when this is reached. Thus clashlist can be dimensioned to [3*max_clash +1]. int TupsAddSub(int un, int suffix) Function TupsAddSub(ByVal un As Long, ByVal suf As Long) As Long Adds a substance to the load, and (unless TUPS_NOCHECK applies) validates it against the load so far. Details of clashes with previous substances will appear in 'clashlist' un suffix UN number suffix return value 99 if no such substance 98 if not valid in a tank / must be in a tank, when this unit isn't / is a tank. 97 if substance prohibited (entirely, or on this passenger sailing). 96 if this explosive is not allowed in this open unit. 88 if failed to expand working space (16-bit versions are limited to about 440 substances in a single load). 1 to 10 highest clash value if this substance clashes with others already in the load. 0 if no clash or if TUPS_NOCHECK is set. With a return value of 88 upwards, the substance is not added to the load, and so is not checked against future substances which will be added. Return values 1 thru 4 are 'away from', etc, as in section 7.2 of the IMDG Code. 1 "Away from" 2 "Separated from" 3 "Separated by a complete compartment or hold from" 4 "Separated longitudinally by an intervening complete compartment or hold from" We also use numbers 5 to 10 in relation to explosives: 5 If UNDER DECK – "Separated from". If ON DECK - not less than 6 metres apart. 6 As 4, and also as remote as possible from each other. 7 As 4, and also as remote as possible from each other, and not more than 50 kg total net explosive mass per ship. 8 As 4, and also as remote as possible from each other, and not more than 10 kg total net explosive mass per ship. 9 Not on same ship 10 If UNDER DECK – As 4. If ON DECK - not less than 6 metres apart. Note: In setting the highest clash value, 5 is more severe than 2, but less than 3. Hint: Items carried in limited quantities (see IMDG chapter 3.4) are allowed on or under deck on both passenger and cargo sailings, need not bear hazard labels, and need not be segregated from other incompatible goods. Don't call TupsAddSub for limited quantity substances. int TupsEditLoad(int seq, int un, int suffix) Function TupsEditLoad (ByVal seq As Long, ByVal un As Long, ByVal suf As Long) As Long Changes a substance in a load, but does not recheck the validation. seq sequence number within the load, numbered from 1 upwards. un UN number (or zero to remove it from the load) suffix suffix return value 99 to 96 as with TupsAddSub 0 = OK int TupsReCalc() Function TupsReCalc () As Long Re-validates a load, if it was originally defined as TUPS_NOCHECK, or when one or several changes have been made with TupsEditLoad. return value 0 if no clash 1 to 10 highest clash value if a clash. void TupsLabCom(short *lab_com) Sub TupsLabCom (labcom As Integer) retrieves the aggregate list of labels and stowage comment codes for the items in the load. filled with a list of consolidated label and comment data for the current load. lab_com[0] bitfields for primary labels lab_com[1] bitfields for subrisk labels lab_com[2...] comment codes. Use TupsCom to convert to phrases. With VB, pass the first element of the array, lab_com(0) lab_com The bitsfields for labels represent (in hex): 0001 0002 0004 0008 0010 0020 0040 0080 0100 0200 0400 0800 1000 2000 4000 8000 marine pollutant explosive (1) flammable gas (2.1) non-flammable gas (2.2) toxic gas (2.3) flammable liquid (3) flammable solid (4.1) spontaneous combustible (4.2) dangerous when wet (4.3) oxidizing substance (5.1) organic peroxide (5.2) toxic (6.1) infectious (6.2) radioactive (7) corrosive (8) miscellaneous (9) Bit '1' for a primary label indicates a marine pollutant label is definitely required. '1' for a secondary label indicates one may be required, depending on concentration or composition (at least one item was 'marine pollutant bullet', but none were definite marine pollutants).. lab_com[2] will always be 1 (prohibited), 2 (as approved by competent authority), 3 (ondeck only) or 4 (on or under deck). Some other values later in the list will restrict the load to various parts of a ship, e.g. 32 (Clear of living quarters) or 60 (Stow in a well ventilated space). Compatibility between loads. Having built one load with TupsNewLoad and TupsAddSub, TupsNewLoad can be called again with a mode of TUPS_SECOND Tups_AddSub is then called for each substance in the second load. Note: a) b) c) d) e) if the first load was known to be valid, time is saved if it is built with a TUPS_NOCHECK flag. further loads can be checked against the first with more TupsNewLoad / TUPS_SECOND calls. TupsEditLoad, TupsReCalc and TupsLabCom are not appropriate with a TUPS_SECOND load. in 'clashlist', (a) is the sequence number of an item within the first load, (b) within the second. to check ten loads against each other build load one as a first load, then check it against loads two to ten in turn. Then build load two as a first load and check it against loads three to ten in turn, and so on, i.e. you need to use a nested loop. Notes for VB users In the above descriptions, 'short' means 'Integer', 'int' means 'Long', and 'char*' means String. The function declarations are thus:Function Sub Sub Function Function Function Sub Function Function Function Function Sub Function Function Sub TupsInit (ByVal fname As String) As Long TupsRead (ByVal field As Integer, ByVal buffer As String) TupsInfo (ByVal field As Integer, buffer As tups) TupsSub (ByVal un As Long, ByVal suf As Long) As Long TupsCom (ByVal code As Integer, ByVal buffer As String) As Long TupsPhrase (ByVal name As String, ByVal buffer As String) As Long TupsNewLoad (ByVal p1 As Long, ByVal p2 As Long, clist, ByVal les As Long) TupsAddSub(ByVal un As Long, ByVal suf As Long) As Long TupsEditLoad (ByVal seq As Long, ByVal un As Long, ByVal suf As Long) As Long TupsReCalc () As Long TupsEnd () As Long TupsLabCom (labcom As Integer) TupsClashes (clashes As Integer, ByVal maxnum As Long) As Long Tups_Start (ByVal code As Long) As Long TupsDistance (ByVal opclo As Integer, ByVal degree As Integer, ByVal shiptype As Integer, ByVal ondeck As Integer, foraft As Integer, athwart As Integer, notes As Integer) To pass an array to the DLL, pass the first element. So for example, the call to TupsLabCom is Dim labcom(40) as Integer call TupsLabCom(labcom(0)) There is an extra declaration 'TupsInfo', which is the same as TupsRead, but with the second argument of type 'tups' so you can call TupsInfo (TUPS_INFO, details) Null-terminated strings are not handled nicely in VB, so the sample program includes a Function sTrim(s As String) As String which converts a null-terminated string to a VB String The Java routines Subsdemo.java is a small demonstration program written in Java. The Java routines it calls are thread-safe, so they could be used by a multi-threaded server application. There is one static class 'Tups' which controls the data file and is used for phrase lookups. An instance of a class 'DGSubs' is used for substance lookups, and one of class 'DGLoad' is used for load validation. The routines can be operated with two data files open, for instance during an IMDG transition year, when the files may be for two different amendments. Substance lookups and load validation can be done against either of the files. class Tups public static int start(String filename, int ver) This should be the first routine called. On an initial call it opens the data file and does various initialisations. Subsequent calls to the routine for the same file number (e.g. by other threads in a multi-threaded server application) are harmless and have no effect. Any exception of 'file not found' or a disk read error is caught and returns a 1. filename ver the filename, "subs.ind", with any necessary directory specification. = 0 or 1, the data file number. return value 0 = OK 1 = error, probably unable to read the file public static synchronized void unload(int ver) This closes the data file, for instance if it needs to be replaced by a revised version without restarting the application or taking down a server. No other routines should be used until another call to 'start' has been made to open another file. If the data file is changed and a user has existing instances of class DGSubs, the next routine called should be TupsSub (to look up a new substance) rather than one which gets information about the 'current' substance. Similarly, if there are existing instances of DGLoad, the next routine should be TupsNewLoad to start a new load rather than continue working with the substances in an existing load. Calling unload is harmless if the file is not open, and catches any exceptions returned by the file close. ver = 0 or 1, the data file number. public static int TupsCom(short code, StringBuffer phrase, int ver) Obtains the comment text related to a numeric comment code. The text may include linefeed (ascii 10) characters. Calling this without the file being open returns 1, the same as 'code number not found'. code phrase ver the comment number the phrase = 0 or 1, the data file number when running with 2 amendments. return value 0 = OK 1 = no such comment number 2 = an exception such as a disk read error has been caught. public static int TupsPhrase(String phrasecode, StringBuffer phrase, int ver) Obtains the text related to a named comment code. The text may include linefeed (ascii 10) characters. The codes may be special provisions (2 or 3 digits, as in IMDG chapter 3.3), packing instructions (Pxxx or LPxx), IBC instructions (IBCxx), tank instructions (Txx), or packing provisions (PPxx, Bx or TPxx), as in IMDG chapters 4.1 and 4.2. Calling this without the file being open returns 1, the same as 'phrase name not found'. phrasecode phrase ver the phrase name the phrase = 0 or 1, the data file number when running with 2 amendments. return value 0 = OK 1 = no such phrase 2 = an exception such as a disk read error has been caught. public static int TupsFindIndex(String name, int language, int ver) Find the location in the index where a name starting with this string would be found. name language ver the name to be looked up = 0 for the english index, 1 for the german. = the file number, 0 or 1 return value the sequence in the index where such a name would be locate, from 0 at the beginning to a maximum value at the end public static int TupsIndex(int num, int language, int ver, StringBuffer name) Return the name at a particular location in the index. The string returned will be fixed format, as follows:UN number 4 digits, or all spaces Class 4 characters, e.g. '3', '6.1' or '1.3G' Marine pollutant 1 character N, Y S, or C for no, yes, severe or conditional Sort string 10 characters, capitals, ignoring spaces, digits, punctuation, and standard prefixes Name variable length, as printed in the book. For example, 29333 NMETHYLCHLOalpha-Methyl alpha-Chloropropionate, see num language ver name the position number to be looked up = 0 for the english index, 1 for the german. = the file number, 0 or 1 set to the name at that location return value 0 = success 1 = failure, num is negative or greater than the nunber of names in the index class DGSubs Public member variables short un; short suf; StringBuffer prim; StringBuffer secn; StringBuffer tert; // UN number // suffix // primary class // secondary class // tertiary class char mp; // null, Y, S or C for No, Yes (P), // Severe (PP) or possible (bullet) byte ulineems; // whether the EmS is underlined // 1=fire, 2=spillage, 3=both StringBuffer ems; // EmS StringBuffer specprov; // special provisions StringBuffer lq; // limited quantity StringBuffer pi; // packing instructions and provisions StringBuffer pp; StringBuffer ibci; // IBC instructions and provisions StringBuffer ibcp; StringBuffer tankun; // tank UN, IMO and provisions StringBuffer tankimo; StringBuffer tankp; StringBuffer flash // flashpoint StringBuffer explim; // explosive limits StringBuffer scat; // stowage category StringBuffer pg; // IMDG packing group StringBuffer classcode // ADR classification code StringBuffer ADRlq // ADR LQ code StringBuffer ADRlqin // ADR LQ inner package limit StringBuffer ADRlqout // ADR LQ outer package limit StringBuffer ADRlqin2 // ADR LQ inner, shrinkwrap package limit StringBuffer ADRlqout2 // ADR LQ outer shrinkwrap package limit char state; // S,L,G,E,A for solid, liquid, gas, // explosive substance or article int flags // flags indicating what additional data // is required from the user float fpmin // minimum value for flashpoint float fpmax // maximum value for flashpoint Description of Data Elements of class DGSubs short un UN number. Currently in the range 4 to 3473, with gaps, and the range will increase with time. Conventionally shown as 4 digits with leading zeros. short suf suffix, used where a UN number has more than 1 record. Where there is only one record, this is zero. Otherwise they are numbered consecutively from 1 up to a current maximum of 35 (for UN 0190) char state S,L,G,E,A for solid, liquid, gas, explosive substance or article int flags extra information required from user, or to alert him of. See below for the codes. char mp space,Y for yes (P), S for severe (PP), or C for conditional (bullet) byte ulineems underlined EmS blank = no, 1=fire, 2=spillage, 3=both underlined float fpmin minimum value for flashpoint. Set to 999 when a flashpoint is not required. float fpmax maximum value for flashpoint. StringBuffer variables Name prim secn tert ems Size 4 5 3 7 specprov 26 Description primary class, e.g '1.3G', '2.3', '8' secondary class, e.g. 4.1, 8, SP290 tertiary class, e.g '6.1', '3' Emergency Schedule, blank or e.g. 'F-A,S-U', 'F-B,S-G', indicating the fire and spillage schedules. The format is always F-x,S-y. For underlined EmS's, see the flag ulineems. special provisions, blank or e.g "138", "29 117". A group of 2- or 3-digit lq 9 pi 14 pp 24 ibci ibcp 9 9 tankun 9 tankimo 7 tankp 23 flash 25 explim 26 scat pg classcode ADRlq 2 3 4 8 ADRlqin ADRlqout ADRlqin2 ADRlqout2 6 6 6 14 numbers separated by a single space limited quantity value, blank, "None", "See SP301", "See SP251", or e.g. "5 kg", "120 ml", "5 L". The units is one of ml, L, g or kg, with a single space after the integer number. packing instruction, blank or e.g. 'P001', 'P520', 'P112(a)', 'P110(a) or (b)', 'P621 LP621', "See 4.1.9". Where the is a large packing instruction, this is always preceded by the ordinary packing instruction. The 'or' format appears only with P110. packing provision, blank or e.g. 'PP8', 'PP26 PP31', 'PP17 L2', "See 4.1.9". Where the are several, they are separated by a single space. IBC instruction, blank or e.g. 'IBC01', 'IBC520', "See 4.1.9". IBC provision, blank or e.g. 'B3', 'B4 B6', "See 4.1.9". Where the are several, they are separated by a single space. UN tank instruction, blank or e.g. 'T1', 'T50', 'T3 BK2'. Where there is both a tank and a BK2 instruction, these are separated by a single space IMO tank instruction, blank or e.g. 'T1', 'T13', 'T8 TP28', "TP91". Where there is both an instruction and a provision, these are separated by a single space. Note that the transitional provisions for IMO tanks are dure to expire on 1/1/2010, and this field is empty in the draft amendment 34. tank provisions, blank or e.g. 'TP1', 'TP1 TP28'. Where there are several, these are separated by a single space flashpoint, blank or e.g. '-2°C c.c.', '48°C o.c.', '-18°C to 23°C c.c.', 'below 5°C c.c.', '23°C c.c. or above', '-21°C c.c. (pure product)', 'above 60°C c.c.', 'approximately 32°C c.c.'. The presence of impurites may make an actual flashpoint differ either above or below the published value. explosive limits, blank or e.g. '0.8% to 6%', ' '4% to 75%', '1.3% to …' when the top limit is uncertain. stowage category. blank, 'A' to 'E', or '01' to '15' for explosives. packing group, blank, or 'I', 'II' or 'III. ADR classification code, blank or e.g. '1.3G', '5F', 'CW1' ADR LQ code, 'LQ0' to 'LQ28', or 'IMDG' for items not listed in ADR, 'N' for not restricted under ADR, 'X' for forbidden under ADR, or 'SPACE' for UN 3359 ADR LQ inner package limit, e.g. 'None', '120 mL', '5 L', '100 g', '1 kg' ADR LQ outer package limit, e.g. 'None', '400 mL', '2 L', '24 kg', '-' ADR LQ inner, shrinkwrap package limit, e.g. 'None', '120 mL', '3 L', '6 kg'. ADR LQ outer shrinkwrap package limit, e.g. 'None', '120 mL', '2 L', '20 L and 20 kg'. The value returned in 'flags' indicates whether any additional information is required from the user to print on a Dangerous Goods Note or manifest. It is the combination of:1 Technical name required (special provision 274 and others) 2 Possible marine pollutant (mp is 'C') 4 Flashpoint required (class 3 or subrisk 3) 8 Control and emergency temperatures (items under temperature control) 16 Radionuclide, category, activity and transport index required (class 7) 32 May be carried in limited quantity (LQ is not 'None') 64 Net explosive content required (class 1) 128 Warn user about special provisions 900 (certain formulations of this UN number are prohibited) 256 May be viscous, pg III with flashpoint below 23 if 2.3.2.2 applies 512 Extemely inflammable substance listed in 7.2.7.1.3.2 1024 An explosive (except 1.4S or one of the groups below) not permitted with any 'flags=512' substance 2048 An explosive for life-saving, max 50 kg with any 'flags=512' substance 4096 8192 A group C, D or E explosive max 10 kg with any 'flags=512' substance A group G explosive (with certain exceptions) max 10 kg with any 'flags=512' substance Note that the actual data sizes are subject to change at future IMDG amendments and errata updates. In particular, the following changes are in the draft version of amendment 34-08, still subject to change and due to be published in October 2008. 'mp' This will only contain values blank or 'Y'. Values 'C' and 'S' are no longer used. 'lq' Value 'None' will be replaced by '0'. ''tankimo' This field will be empty, as the transitional provisions for IMO tanks will have expired when 34-08 becomes mandatory. 'eq' Excepted quantity. A new field, which may be blank, or a value from 'E0' to 'E5'. public int SetVersion(int ver) Set subsequent operations to use the specified file number. File number zero will be used if this routine is not called. ver = 0 or 1, the data file number. return value 0 = Error, ver is out of range, or the data file is not open 1 = OK. public int TupsSub(int unno, int suffix) Finds a substance on file. unno suffix UN number suffix. Where a substance has no variants, it will be numbered 0. Those with variants are numbered 1 upwards. A search for suffix 0 or 1 will equally find either of 0 and 1. Alternatively, suffix may be -1 or -2, to find respectively the next or previous UN number (and suffix 0 or 1) to the one specified. return value 0 = OK. The member variables are now set up. 99 = no such substance. The UN number / suffix combination does not exist, or for next / previous UN number, the specified UN number was already at or beyond the end of the range. 100 = a disk exception has been trapped. public int TupsName(short wanted, StringBuffer name) Retrieves the Proper Shipping Name, qualifying descriptive text and variation description for the current substance, or the 'Properties and Observations' from the Dangerous Goods List. wanted name return value = Tups.NAME (3) for the Proper Shipping name (english). = Tups.GERMAN (5) for the Proper Shipping name (german). = Tups.PROPS (4) for Properties and Observations the name or properties are put into this variable 0 = OK. 99 = there is no current substance - TupsSub was not called or returned an error. 100 = a disk exception has been trapped. public int TupsRead(short wanted, short codes[]) Reads a set of stowage comment code numbers. These can be passed to Tups.TupsCom to be converted to phrases. wanted codes = Tups.STOW (2) for phrases shown on the 'Stowage and Segregation' in the Dangerous Goods List = Tups.STOWP (1) for general stowage phrases for this class, packing group, subsidiary risk, etc from IMDG chapter 7.1, for passenger sailings = Tups.STOWC (0) as above, but for cargo sailings. array of shorts to receive the code numbers. An array of 20 elements will be sufficient. The list is terminated by a zero value. For wanted values other than 2, the first number will always be one of the following (the text can be obtained from TupsCom). 1 Prohibited. 2 As approved by the competent authorities of the countries involved in the shipment. 3 On deck only. 4 On or under deck. 22 On or under deck in closed CTU. 23 On deck only in closed CTU. 24 On deck in closed CTU or under deck. 26 On deck in closed CTU or under deck Magazine stowage type 'C'. 27 On deck in closed CTU or under deck Magazine stowage type 'A'. return value 0 = OK. 99 = there is no current substance - TupsSub was not called or returned an error. 100 = a disk exception has been trapped. public int TupsPack(String outer, String inner, int numout, int numin, float net, float gross, float nec, float capacity, float limits[]) Checks the packaging entered for a substance against its packing, IBC or tank instructions and provisions. outer inner numout numin islq net gross nec capacity limits outer packing code inner packing code number of outer or single packages number of inner packages (zero if not combination packing) 1 if in limited quantities, 0 otherwise net weight (kg) gross weight (kg) net explosive content (kg) capacity (litres) set to the maximum permitted quantites per package:net weight per inner capacity per inner net weight per outer gross weight per outer capacity per outer NEC per outer return value 0 = OK -1 = no current substance -2 = not allowed in limited quantity -3 = limited quantity only allowed in inner and outer packaging -4 = not allowed in packages / IBCs / tanks -5 = outer or numouter not specified -6 = a free-text packing instruction - not checked 100 = a disk exception has been trapped. Otherwise it is a combination of these codes 1 = inner packaging type not allowed 2 = outer packaging type not allowed 4 = net weight per inner packaging exceeded 8 = capacity per inner packaging exceeded 16 = net weight per outer package exceeded 32 = gross weight per outer package exceeded 64 = capacity per outer package exceeded 128 = NEC per outer package exceeded 256 = outer packaging code unknown 512 = LQ quantity exceeded (set in combination with 'exceeded' codes) public int TupsOfferPack(String selected, int islq, StringBuffer choices) This produces a list of choices to guide a user through packing selection, for the current substance. 'choices' comes back as a set of options separated by '|' characters that could be offered in a menu. Starting with 'selected' as empty will give choices such as "Inner then outer packaging|Outer then inner packing|Single Packing|IBC|Tank Instruction T7" according to the packing instructions and provisions for this substance. Calling again with 'selected' equal to one of those strings such as "Single Packaging" will return a list of the valid single packaging types, such as "1A1 steel drums|1B1 aluminuim drums|1H1 plastics drums|3A1 steel jerricans|3B1 aluminuim jerricans|3H1 plastics jerricans". The return code indicate whether a futher selection is needed, e.g for inner packaging after the outer has been selected. selected islq choices return value Empty for an initial choice, the string selected from the one offered last time for a subsequent selection 1 if in limited quantities, 0 otherwise list of choices to offer the user 0 = OK, a list of choices has been built -1 = no current substance -2 = not allowed in limited quantity 1 = the selection process is complete 2 = a free-text packing instruction has been selected. No list of options has been provided 100 = a disk exception has been trapped. class DGLoad Constructor public DGLoad(int maxs) maxs An overestimate of the maximum number of substances in the load. For a value below 16, 16 is used. There is a memory overhead of 50 * maxs for each DGLoad object, so do not set it extravagantly large. For segregation between loads, maxs needs to be at least 1 greater than the number of items in the first load. public int SetLoadVer(int ver) Set subsequent operations to use the specified file number. File number zero will be used if this routine is not called. This should not be called after the first substance has been added to the load. ver = 0 or 1, the data file number. return value 0 = OK. -1 = Error, ver is out of range, or the data file is not open, or there are already substance in the load public void TupsNewLoad(short mode, short unittype) For validation of a single load:DGLoad.PSNGR (4) for a passenger sailing DGLoad.CARGO (0) for a cargo sailing type DGLoad.OPEN (1) or DGLoad.CLOSED (2) or DGLoad.TANK (3) according to the unit type For segregation checks between this load and others, see later. mode public int TupsAddSub(int un, int suffix) public int TupsAddSub(int un, int suffix, float nec, String groups, int stowseg[]) Adds a substance to the load, and validates it against the load so far. un suffix nec groups stowseg[] return value UN number Suffix net explosive content in kg (ignored except for explosives of compatibitly groups B, C, D, E, G and N) code letters for additional segregation group to which this substance belongs extra stowage and segregation code numbers to apply to this substance 99 if no such substance 98 if not valid in a tank / must be in a tank, when the unit type is / is not a tank 97 if the substance is prohibited (totally, or on this passenger sailing) 96 if the explosive is not allowed in this open unit. 95 if the total net explosive content exceeds that permitted on this passenger sailing 94 if a port, vessel or operator restriction prohibits this item 100 = a disk exception has been trapped. 88 if MAXSUB items are already in the load. 1 to 10 highest clash value if segregation is required from previous items. 0 if no segregation required With a return value of 88 upwards, the substance is not added to the load. Return values 1 thru 4 are 'away from', 'separated from', etc, as in section 7.2 of the IMDG Code. We also use numbers 5 to 10 in relation to explosives. 1 Away from 2 Separated from 3 Separated by a complete compartment or hold from 4 Separated longitudinally by an intervening complete compartment or hold from 5 If UNDER DECK - "Separated from". If ON DECK - not less than 6 metres apart. 6 As 4, and also as remote as possible from each other. 7 As 4, and also as remote as possible from each other, and not more than 50 kg total net explosive mass per ship. As 4, and also as remote as possible from each other, and not more than 10 kg total net explosive mass per ship. 9 Not on same ship 10 If UNDER DECK - As 4. If ON DECK - not less than 6 metres apart. In setting the highest clash value, 5 is more severe than 2, but less than 3. 8 public int TupsEditLoad(int seq, int un, int suffix) Changes a substance in a load, but does not recheck the validation. seq un suffix return value sequence number within the load, numbered from 1 upwards. UN number (or zero to remove an item from the load) Suffix 100 to 94 as with TupsAddSub 0 = OK public int TupsReCalc() re-validates a load, when one or several changes have been made with TupsEditLoad. return value 0 if no clash 1 to 10 highest clash value if a clash. public void TupsLabCom(short lab_com[]) lab_com becomes filled with a list of consolidated label and comment data for the current load. lab_com[0] - bitfields for primary labels lab_com[1] - bitfields for subrisk labels lab_com[2...] - comment codes, terminated by a zero value. Use TupsCom to convert to phrases. The bitsfields for labels represent (in hex) 1 marine pollutant 2 explosive (1) 4 flammable gas (2.1) 8 non-flammable gas (2.2) 10 toxic gas (2.3) 20 flammable liquid (3) 40 flammable solid (4.1) 80 spontaneous combustible (4.2) 100 dangerous when wet (4.3) 200 oxidizing substance (5.1) 400 organic peroxide (5.2) 800 toxic (6.1) 1000 infectious (6.2) 2000 radioactive (7) 4000 corrosive (8) 8000 miscellaneous (9) Bit '1' in prims indicates a marine pollutant label is definitely required. '1' is secs indicates one may be required, depending on concentration or composition. lab_com[2] will always be 1 (prohibited), 2 (as approved by competent authority), 3 (on-deck only) or 4 (on or under deck) - the stowage position according to IMDG. Some other values in later elements of lab_com will restrict the load to various parts of a ship, e.g. 32 (Clear of living quarters) or 60 (Stow in a well ventilated space). public int TupsClashes(short list[], int maxnum) This returns details of the individual clashes between items in the load. The list is filled with sets of three numbers being:the sequence number of one item in the load the sequence number of the item it clashes with the degree of clash (1 to 10) the number of clashes stored in 'list', so 'list' can be dimensioned to 3*maxnum+1. the number of clashes stored in 'list'. maxnum return value The list ends with a zero value for the first sequence number. For validation of a single load the first sequence number will always be smaller than the second. Compatibility between loads. Having built one load with TupsNewLoad and TupsAddSub, TupsNewLoad can be called again with a mode of DGLoad.SECOND (64). Tups_AddSub is then called for each substance in the second load, and will check them for segregation from all the items in the first load. Note:a) further loads can be checked against the first with more TupsNewLoad / TUPS_SECOND calls. b) TupsEditLoad, TupsReCalc and TupsLabCom are not appropriate with a TUPS_SECOND load. c) in TupsClashes, the first sequence number refers to an item within the first load, the second to an item within the second load. If one 'first load' is being checked against all the other loads on the ship as 'second loads', a return value of 95 from TupsAddSub will indicate that the total explosive content of a passenger ship (IMDG 7.1.7.5) has been exceeded. Contacting Exis Technologies Limited If you have any questions or comments please contact Exis Technologies Limited by, email: telephone: fax: support@existec.com +44 (0)1325 466672 +44 (0)1325 466643 Sample Source Code - C and VB This code shows data being retrieved and displayed using printf calls. A windows program would show the data in dialog boxes. a) Open the file if (TupsInit("subs.ind") == -1) {printf("subs.ind not found\n"); return 2; } ChDir ("\tupslib") ' find the DLL and data file in this directory ret = TupsInit("subs.ind") results.Text = "TupsInit returned " + CStr(ret) b) Show various details of UN 2050 short labc[20], clist[31]; int un, i; struct tups info; char buf[700]; ret = TupsSub(2050,0); if (ret ===0) { TupsRead(TUPS_INFO, (char *)&info); TupsRead(TUPS_NAME, buf); printf(" UN %04d %d EmS = %s PI = %s\n Name = %s\n\nStowage:- ", info.un, info.suf, info.ems, info.pi, buf); TupsRead(TUPS_STOW, (char *)labc); // stowage from DGL for (i=0; labc[i] > 0; i++) { TupsCom(labc[i],buf); printf(" %s\n", buf); } printf("\nCargo:- "); TupsRead(TUPS_STOWC,(char *)labc); // general stowage for for (i=0; labc[i] > 0; i++) // this class and packing group { TupsCom(labc[i],buf); printf(" %s\n", buf); } TupsRead(TUPS_PROP,buf); printf("\n Properties and Observations %s\n",buf); } Dim subsname As String, codes(20) As Integer, i As Integer Dim details As tups subsname = String$(5120, 0) unno = txUNno.Text suf = txSuf.Text ret = TupsSub(2050, 0) ' look up the substance If (ret <> 0) Then results.Text = "TupsSub returned " + CStr(ret) Else Call TupsInfo(TUPS_INFO, details) ' write various details Call TupsRead(TUPS_NAME, subsname) results.Text = "UN " + CStr(details.un) + " " + CStr(details.suf) + " EmS = " + sTrim(details.ems) + " PI= " + sTrim(details.pi) + Chr(13) + Chr(10) + "Name= " + sTrim(subsname) Call TupsInfo(TUPS_STOW, codes(0)) i = 0 While codes(i) > 0 ' stowage and segregation comments Call TupsCom(codes(i), subsname) results.Text = results.Text + Chr(13) + Chr(10) + sTrim(subsname) i = i + 1 Wend End If c) Special Provision 944 ret = TupsPhrase("941",buf); if (ret == 0) printf(" %s\n", buf); Dim Comment As String Comment = String$(5120, 0) ret = TupsPhrase("941", Comment) If (ret = 0) Then results.Text = "Phrase 941 is " + sTrim(Comment) End If d) Show variations of UN 2810 un = 2810; ret = TupsSub(un,0); if (ret ==0) { TupsRead(TUPS_INFO, &info); if (info.suf > 0) { printf("Variations exist\n"); i = info.suf; while(ret == 0) // have found variant 1 { TupsRead(TUPS_NAME,buf); p = strchr(buf, '|'); // start of descriptive text p = strchr(p+1, '|'); // start of variation description printf(" %d - %s\n",i,p+1); i++; ret = TupsSub(un,i); // look for next one } } } e) Check 3 items in a load TupsNewLoad(TUPS_CARGO, TUPS_CLOSED, clist,10); ret = TupsAddSub(1230,0); // methanol i = TupsAddSub(1790,1); // hydrofluoric acid, pg I if (i > ret) ret = i; i = TupsAddSub(1605,0); // ethylene dibromide if (i > ret) ret = i; if (ret == 0) { TupsLabCom(labc); printf("Load complies - labels %04x %04x\n", labc[0], labc[1]); for (i=2; labc[i] > 0; i++) { TupsCom(labc[i],buf); printf(" %s\n", buf); // stowage requirements } } if (ret > 0 && ret <= 10) printf("LOAD DOES NOT COMPLY Segregation of degree %d required\n", ret); // could use clist to say which ones give the problem if (ret > 10) printf("Load not valid"); f) Check a 2 item load against the previous one TupsNewLoad(TUPS_SECOND, TUPS_CLOSED, clist,10); ret = TupsAddSub(1065,0); // neon i = TupsAddSub(1500,0); // sodium nitrite if (i > ret) ret = i; if (ret == 0) printf("No segregation required\n"); if (ret > 0 && ret <= 10) printf("Segregation of degree %d required between these 2 loads\n", ret); // could use clist to say which ones give the problem if (ret > 10) printf("Load not valid"); (Note that 1065 needs to be 'away from' 1230. However, since both units are 'closed', this requirement is automatically satisfied, and no clash is reported. 1500 needs to be 'separated from' both 1230 and 1790.)
© Copyright 2024