def rotating1(bits): rotatingbin = [] #Add a single bit offset so bits array index # matches documentation for readbility bits = '0' + bits ##BIT 5-21 (159-175) Time of last encoded location ## update Ver 2.0 if bits[5:22] == '1' * 17: time = 'UTC time is not available or the time is more than 24 hours old' else: time = Func.sec2utc(bits[5:22]) ## endupdate rotatingbin.append([ '159-175 (Rotating field 5-21)', bits[5:22], 'Time of last encoded location', time ]) ##BIT 22-31 (176-185) Altitude of encoded location altitude = Func.getaltitude(bits[22:32]) rotatingbin.append([ '176-185 (Rotating field 22-31)', bits[22:32], 'Altitude of encoded location:', altitude ]) ##BIT 32-35 (186-189) Triggering event try: trigger = definitions.triggering_event[bits[32:36]] except KeyError: trigger = 'ERROR: Unknown trigger' rotatingbin.append([ '186-189 (Rotating field 32-35)', bits[32:36], 'Triggering event', trigger ]) ##BIT 36-37 (190-191) GNSS Status gnss = definitions.gnss_status[bits[36:38]] rotatingbin.append( ['190-191 (Rotating field 36-37)', bits[36:38], 'GNSS status', gnss]) ##BIT 38-39 (192-193) Remaining battery capacity battery = definitions.inflight_battery[bits[38:40]] rotatingbin.append([ '192-193 (Rotating field 38-39)', bits[38:40], 'Remaining battery capacity', battery ]) ##BIT 40-48 (194-202) Spare if Func.checkzeros(bits[40:]): rotatingbin.append( ['194-202 (Rotating field 40-48)', bits[40:], 'Spare', 'OK']) else: rotatingbin.append([ '194-202 (Rotating field 40-48)', bits[40:], 'Spare', 'ERROR: Should be 0s' ]) return rotatingbin
def rotating3(bits): rotatingbin = [] #Add a single bit offset so bits array index # matches documentation for readbility bits = '0' + bits ##BIT 5-48 (159-202) As defined by national administrations if Func.checkzeros(bits[5:]): rotatingbin.append([ '159-202 (Rotating field 5-48)', bits[5:], 'As defined by national administrations', 'default' ]) else: rotatingbin.append([ '159-202 (Rotating field 5-48)', bits[5:], 'As defined by national administrations', '' ]) return rotatingbin
def vesselIDfill(self, deduct_offset, bits): self.vesselID = bits[0:3] self.tablebin.append([ self.bitlabel(91, 93, deduct_offset), self.vesselID, 'Vessel ID Type', Func.getVesselid(self.vesselID) ]) ############################################## # Vessel 0: No aircraft or maritime identity # ############################################## if self.vesselID == '000': if Func.checkzeros(bits[3:47]): self.tablebin.append([ self.bitlabel(94, 137, deduct_offset), bits[3:47], 'Vessel ID type is none', 'All 0 - OK' ]) else: self.tablebin.append([ self.bitlabel(94, 137, deduct_offset), bits[3:47], 'Vessel ID type is none', 'Error! Should be all 0' ]) ########################### # Vessel 1: Maritime MMSI # ########################### elif self.vesselID == '001': self.mmsi = Func.bin2dec(bits[3:33]) if self.mmsi == 111111: self.tablebin.append([ self.bitlabel(94, 123, deduct_offset), bits[3:33], 'MMSI:', 'No MMSI available' ]) else: self.mmsi_string = str(self.mmsi).zfill(9) self.tablebin.append([ self.bitlabel(94, 123, deduct_offset), bits[3:33], 'Unique ship station identity MIDxxYYYY:', self.mmsi_string ]) self.mmsi_country = Func.countryname(int( self.mmsi_string[0:3])) self.tablebin.append([ '', '', 'Flag state of vessel:', self.mmsi_string[0:3] + ' ' + self.mmsi_country ]) self.tablebin.append( ['', '', 'Unique vessel number', self.mmsi_string[3:]]) self.epirb_ais = Func.bin2dec(bits[33:47]) if self.epirb_ais == 10922: self.tablebin.append([ self.bitlabel(124, 137, deduct_offset), bits[33:47], 'EPIRB-AIS System Identity:', 'No EPIRB-AIS System' ]) else: self.epirb_ais_str = str(self.epirb_ais).zfill(4) self.epirb_ais_str = '974xx' + self.epirb_ais_str self.tablebin.append([ self.bitlabel(124, 137, deduct_offset), bits[33:47], 'EPIRB-AIS System Identity', self.epirb_ais_str ]) ############################# # Vessel 2: Radio Call Sign # ############################# elif self.vesselID == '010': self.callsign = Func.getCallsign(bits[3:45]) self.tablebin.append([ self.bitlabel(94, 135, deduct_offset), bits[3:45], 'Radio Callsign', self.callsign ]) if Func.checkzeros(bits[45:47]): status_check = 'OK' else: status_check = 'ERROR' self.tablebin.append([ self.bitlabel(136, 137, deduct_offset), bits[45:47], 'Spare should be 0', status_check ]) ######################################################### # Vessel 3: Aricraft Registration Marking (Tail Number) # ######################################################### elif self.vesselID == '011': self.tailnum = Func.getTailNum(bits[3:45]) self.tablebin.append([ self.bitlabel(94, 135, deduct_offset), bits[3:45], 'Aircraft Registration Marking:', self.tailnum ]) if bits[45:47] == '00': status_check = 'OK' else: status_check = 'ERROR' self.tablebin.append([ self.bitlabel(136, 137, deduct_offset), bits[45:47], 'Spare should be 0', status_check ]) ############################################## # Vessel 4: Aircraft Aviation 24 Bit Address # ############################################## elif self.vesselID == '100': self.aviationBitAddress = Func.bin2dec(bits[3:27]) self.tablebin.append([ self.bitlabel(94, 117, deduct_offset), bits[3:27], 'Aviation 24 bit address', str(self.aviationBitAddress) ]) if Func.checkzeros(bits[27:47]): status_check = 'OK' else: status_check = 'ERROR' self.tablebin.append([ self.bitlabel(118, 137, deduct_offset), bits[27:47], 'Spare should be 0', status_check ]) ################################################# # Vessel 5: Aircraft Operator and Serial Number # ################################################# elif self.vesselID == '101': self.operator = Func.baudot2str(bits[3:21], 3) self.serialnum = Func.bin2dec(bits[21:33]) self.tablebin.append([ self.bitlabel(94, 111, deduct_offset), bits[3:21], 'Aircraft operator:', self.operator ]) self.tablebin.append([ self.bitlabel(112, 123, deduct_offset), bits[21:33], 'Serial number:', str(self.serialnum) ]) if Func.checkones(bits[33:47]): status_check = 'OK' else: status_check = 'ERROR' self.tablebin.append([ self.bitlabel(124, 137, deduct_offset), bits[33:47], 'Spare all should be 1', status_check ])
def processHex(self, strhex): ##All second generation beacon messages must be EXACTLY 250 bits ##in length for the program to function properly. self.bits = Func.hex2bin(strhex) self.bchstring = '' self.tablebin = [] self.rotatingbin = [] self.longitude = self.latitude = 'na' self.location = (0, 0) self.courseloc = ('na', 'na') self.errors = [] self.fixedbits = '' self.testprotocol = '' if len(self.bits) == 252 or len(self.bits) == 204: self.type = "Complete message" pbit = self.bits[0:2] if pbit == '00': padding = 'OK' else: padding = 'ERROR! left padding should be 00' self.errors.append(padding) ##Add an additional bit to ensure that bits in array line up with bits in documentation and only include important bits 1-202 self.bits = "0" + self.bits[2:] ##Add the 23 Hex ID to our table self.beaconHexID = self.uinSgb() self.tablebin.append( ['', '', 'Beacon 23 Hex ID:', self.beaconHexID]) self.tablebin.append(['left padding', pbit, '', padding]) ##BIT 1-20 Type Approval Certificate # self.tac = Func.bin2dec(self.bits[1:21]) if self.tac < 10000: warn = 'WARNING!: SGB requires TAC No >=10,000' else: warn = '' self.tablebin.append([ '1-20', self.bits[1:21], 'Type Approval Cert No: ' + str(self.tac), warn ]) ##BIT 21-30 Serial Number self.serialNum = Func.bin2dec(self.bits[21:31]) self.tablebin.append([ '21-30', self.bits[21:31], 'Serial Number:', str(self.serialNum) ]) ##BIT 31-40 Country code self.countryCode = Func.bin2dec(self.bits[31:41]) self.countryName = Func.countryname(self.countryCode) self.tablebin.append([ '31-40', self.bits[31:41], 'Country code:', str(self.countryCode) + ' ' + str(self.countryName) ]) ##BIT 41 Status of homing device self.status = Func.homing(self.bits[41]) self.tablebin.append( ['41', self.bits[41], 'Status of homing device:', self.status]) ##BIT 42 Self-test function self.selfTestStatus = Func.selfTest(self.bits[42]) self.tablebin.append( ['42', self.bits[42], 'Self-test flag:', self.selfTestStatus]) ##BIT 43 Test protocol self.testprotocol = Func.testProtocol(self.bits[43]) self.tablebin.append([ '43', self.bits[43], 'Test protocol flag:', self.testprotocol ]) ##BIT 44-90 Encoded GNSS location self.latitude = Func.getlatitude(self.bits[44:67]) self.tablebin.append( ['44-66', self.bits[44:67], 'Latitude:', self.latitude[0]]) self.longitude = Func.getlongitude(self.bits[67:91]) self.tablebin.append( ['67-90', self.bits[67:91], 'Longitude:', self.longitude[0]]) self.location = (self.latitude[1], self.longitude[1]) ################################ # # # BIT 91-137 VESSEL ID FIELD # # # ################################ self.vesselIDfill(0, self.bits[91:138]) ## BIT 138-139 Beacon Type self.tablebin.append([ '138-139', self.bits[138:140], 'Beacon Type:', Func.getBeaconType(self.bits[138:140]) ]) ## BIT 140 RLS capability self.tablebin.append([ '140', self.bits[140], 'RLS capability:', Func.rls(self.bits[140]) ]) ##BIT 140-154 Spare bits if Func.checkones(self.bits[141:155]) and not Func.checkones( self.bits[155:159]): self.tablebin.append([ '141-154', self.bits[141:155], 'Spare bits', 'OK - all bits 1 and rotating field not a cancellation message' ]) elif Func.checkones(self.bits[141:155]) and Func.checkones( self.bits[155:159]): e = 'ERROR! - all bits 1 and rotatating field is a cancellation message (for a cancellation message these bits should be set to 0)' self.errors.append(e) self.tablebin.append( ['141-154', self.bits[141:155], 'Spare bits', e]) elif Func.checkzeros(self.bits[141:155]) and Func.checkones( self.bits[155:159]): self.tablebin.append([ '141-154', self.bits[141:155], 'Spare bits', 'OK - all bits 0 and rotating field is cancellation message (unless this is a cancellation message, these bits should be set to 1' ]) elif Func.checkzeros(self.bits[141:155]) and not Func.checkones( self.bits[155:159]): e = 'ERROR!- all bits 0 and rotating field is not cancellation message' self.errors.append(e) self.tablebin.append( ['141-154', self.bits[141:155], 'Spare bits', e]) else: e = 'ERROR: Bits 141-154 should be set to all 1 or all 0 in the case that the rotating field is a cancellation message' self.errors.append(e) self.tablebin.append([ '141-154', self.bits[141:155], 'Cancellation message status:', e ]) ####################################### # # # BIT 155-202 48 BIT ROTATING FIELD # # # ####################################### self.rotatingID = Func.bin2dec(self.bits[155:159]) ###################################################### # Rotating Field 0: C/S G.008 Objective Requirements # ###################################################### if self.rotatingID == 0: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#0) C/S G.008 Objective Requirements' ]) self.rotatingbin = rotating.rotating0(self.bits[155:203]) ######################################## # Rotating Field 1: Inflight Emergency # ######################################## elif self.rotatingID == 1: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#1) Inflight Emergency' ]) self.rotatingbin = rotating.rotating1(self.bits[155:203]) ######################### # Rotating Field 2: RLS # ######################### elif self.rotatingID == 2: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#2) RLS' ]) self.rotatingbin = rotating.rotating2(self.bits[155:203]) ################################## # Rotating Field 3: National Use # ################################## elif self.rotatingID == 3: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#3) National Use' ]) self.rotatingbin = rotating.rotating3(self.bits[155:203]) ########################################### # Rotating Field 15: Cancellation Message # ########################################### elif self.rotatingID == 15: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#15) Cancellation Message' ]) self.rotatingbin = rotating.rotating15(self.bits[155:203]) ################################## # All other rotating fields spare # ################################## else: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', 'Spare' ]) ##Add rotating field data to our list self.tablebin.extend(self.rotatingbin) #################################### # 48-BIT BCH ERROR CORRECTING CODE # #################################### if len(self.bits) == 251: self.tablebin.append( ['203-250', self.bits[203:], 'Encoded BCH', 'Encoded BCH']) ##Calculate the BCH self.calculatedBCH = Func.calcBCH(self.bits[1:], 0, 202, 250) self.bchstring = writebch.calcBCH(self.bits[1:], 0, 202, 250)[1] self.tablebin.append( ['Calculated', self.calculatedBCH, 'Computed', '']) ##Compare to the BCH in the beacon message bcherr = self.BCHerrors = Func.errors(self.calculatedBCH, self.bits[203:]) if bcherr > 0: bcherror = 'COMPUTED BCH DOES NOT MATCH ENCODED BCH!!' self.errors.append(bcherror) self.tablebin.append(['', '', '', bcherror]) elif len(self.bits) == 92: self.type = 'uin' ##Add an additional bit to ensure that bits in array line up with bits in documentation self.bits = "0" + self.bits self.latitude = self.longitude = 'No data available' self.tablebin.append(['Unique ID', 'Second Generation', '', '']) self.tablebin.append([ '1', self.bits[1], 'should be 1', ['ERROR', 'OK'][int(self.bits[1])] ]) ##BIT 2-11 Country code self.countryCode = Func.bin2dec(self.bits[2:12]) self.countryName = Func.countryname(self.countryCode) self.tablebin.append([ '2-11', self.bits[2:12], 'Country code:', str(self.countryCode) + ' ' + str(self.countryName) ]) ##BIT 12-14 Should be 101 if self.bits[12:15] == '101': status_check = 'OK' else: status_check = 'ERROR' self.tablebin.append( ['12-14', self.bits[12:15], 'Should be 101', status_check]) ##BIT 15-34 Type Approval Certificate # self.tac = Func.bin2dec(self.bits[15:35]) if self.tac < 10000: warn = 'WARNING! SGB specifications requires TAC No >=10,000' else: warn = '' self.tablebin.append([ '15-34', self.bits[15:35], 'Type Approval Cert No: ' + str(self.tac), warn ]) ##BIT 35-44 Beacon Serial Number self.serialNum = Func.bin2dec(self.bits[35:45]) self.tablebin.append([ '35-44', self.bits[35:45], 'Serial Number', str(self.serialNum) ]) if self.bits[61:] == '0' * 32: print('truncated sgb 15 hex id') self.tablebin.append([ '45-47', self.bits[45:48], 'Vessel ID Type', Func.getVesselid(self.bits[45:48]) ]) self.tablebin.append([ '48-60', self.bits[48:], 'Remaining bits', 'Truncated SGB Hex ID does not allow vessel ID information to be decoded' ]) else: ##BIT 45-91 Aircraft / Vessel ID self.vesselIDfill(46, self.bits[45:92]) ##BIT 92 Fixed value 1 if self.bits[92] == '1': status_check = 'OK' else: status_check = 'ERROR' self.tablebin.append( ['92', self.bits[92], 'Fixed 1', status_check]) else: self.type = ( 'Hex string length of ' + str(len(strhex)) + '.' + '\nBit string length of ' + str(len(self.bits)) + '.' + '\nLength of First Gen Beacon Hex String must be 15, 22 or 30' + '\nLength of Second Gen Beacon Bit String must be 204 or 252 bits' ) raise Gen2Error('LengthError', self.type)
def vesselIDfill(self, deduct_offset, bits): self.vesselID = bits[0:3] self.tablebin.append([ self.bitlabel(91, 93, deduct_offset), self.vesselID, 'Vessel ID Type', Func.getVesselid(self.vesselID) ]) if self.vesselID == '111' and self.bits[ 43] == '0' and deduct_offset != 45: e = 'ERROR! Bit 43 is 0 for system testing message. When vessel ID bits are set to 111, vessel id field is reserved for system testing and the test bit 43 must be 1 for non-operational use.' self.tablebin.append( ['', 'Vessel ID', 'Reserved for system testing', e]) self.errors.append(e) self.validhex = False elif self.vesselID == '111' and self.bits[ 45] == '0' and deduct_offset == 45: e = 'ERROR! Test flag bit 45 in SGB 23 Hex ID (bit 43 in full message) set to 0 for system testing message. When vessel ID bits are set to 111, vessel id field is reserved for system testing and the test bit 45 must be 1 for non-operational use.' self.tablebin.append( ['', 'Vessel ID', 'Reserved for system testing', e]) self.errors.append(e) self.validhex = False ############################################## # Vessel 0: No aircraft or maritime identity # ############################################## if self.vesselID == '000': if Func.checkzeros(bits[3:47]): self.tablebin.append([ self.bitlabel(94, 137, deduct_offset), bits[3:47], 'Vessel ID', 'With vessel id type set to none (000), bits 94-137 all 0. Valid' ]) else: e = 'Warning: With Vessel ID type set to none (000), bits 94-137 should be all 0 (unless national assigned)' self.tablebin.append([ self.bitlabel(94, 137, deduct_offset), bits[3:47], 'Vessel ID', e ]) self.errors.append(e) self.validhex = False ########################### # Vessel 1: Maritime MMSI # ########################### elif self.vesselID == '001': self.mmsi = Func.bin2dec(bits[3:33]) if self.mmsi == 111111: self.mmsi_string = 'No MMSI available' self.tablebin.append([ self.bitlabel(94, 123, deduct_offset), bits[3:33], 'MMSI:', self.mmsi_string ]) else: self.mmsi_string = str(self.mmsi).zfill(9) self.tablebin.append([ self.bitlabel(94, 123, deduct_offset), bits[3:33], 'Unique ship station identity where the first 3 digits are MID (MIDxxxxxx):', self.mmsi_string ]) self.mmsi_country = Func.countryname(int( self.mmsi_string[0:3])) self.tablebin.append([ '', '', 'Flag state of vessel:', self.mmsi_string[0:3] + ' ' + self.mmsi_country ]) self.tablebin.append( ['', '', 'Unique vessel number', self.mmsi_string[3:]]) self.epirb_ais = Func.bin2dec(bits[33:47]) if self.epirb_ais == 10922: self.epirb_ais_str = 'No EPIRB-AIS System' self.tablebin.append([ self.bitlabel(124, 137, deduct_offset), bits[33:47], 'EPIRB-AIS System Identity:', self.epirb_ais_str ]) else: self.epirb_ais_str = str(self.epirb_ais).zfill(4) self.epirb_ais_str = '974xx' + self.epirb_ais_str self.tablebin.append([ self.bitlabel(124, 137, deduct_offset), bits[33:47], 'EPIRB-AIS System Identity', self.epirb_ais_str ]) self._id = '{}-{}'.format(self.mmsi_string, self.epirb_ais_str) ############################# # Vessel 2: Radio Call Sign # ############################# elif self.vesselID == '010': self.callsign = Func.getCallsign(bits[3:45]) self._id = self.callsign self.tablebin.append([ self.bitlabel(94, 135, deduct_offset), bits[3:45], 'Radio Callsign', self.callsign, definitions.moreinfo['sgb_radio_callsign'] ]) if Func.checkzeros(bits[45:47]): status_check = 'OK' else: status_check = 'ERROR' self.validhex = False self.tablebin.append([ self.bitlabel(136, 137, deduct_offset), bits[45:47], 'Spare should be 0', status_check ]) ######################################################### # Vessel 3: Aricraft Registration Marking (Tail Number) # ######################################################### elif self.vesselID == '011': self.tailnum = Func.getTailNum(bits[3:45]) self._id = self.tailnum self.tablebin.append([ self.bitlabel(94, 135, deduct_offset), bits[3:45], 'Aircraft Registration Marking:', self.tailnum ]) if bits[45:47] == '00': status_check = 'OK' else: status_check = 'ERROR' self.validhex = False self.tablebin.append([ self.bitlabel(136, 137, deduct_offset), bits[45:47], 'Spare should be 00', status_check ]) ############################################################ # Vessel 4: Aircraft Aviation 24 Bit Address (and ICAO 3LD)# ############################################################ elif self.vesselID == '100': self.aviationBitAddress = Func.bin2dec(bits[3:27]) h = Func.bin2hex(bits[3:27]) self._id = ' Decimal: {} Hex: {}'.format(self.aviationBitAddress, h) self.tablebin.append([ self.bitlabel(94, 117, deduct_offset), bits[3:27], 'Aviation 24 bit address', self._id ]) if Func.checkzeros(bits[27:47]): status_check = 'OK' self.tablebin.append([ self.bitlabel(118, 137, deduct_offset), bits[27:47], 'Spare should be 0 ', status_check ]) elif not Func.checkzeros(bits[27:47]): self.operator = Func.baudotshort2str(bits[27:42], 3) self.tablebin.append([ self.bitlabel(138, 152, deduct_offset + 20), bits[27:42], 'Aircraft operator designator:', self.operator ]) if not Func.checkzeros(bits[42:47]): status_check = 'ERROR' self.validhex = False else: status_check = 'OK' self.tablebin.append([ self.bitlabel(153, 157, deduct_offset + 20), bits[42:47], 'Spare should be 0 ', status_check ]) ################################################# # Vessel 5: Aircraft Operator and Serial Number # ################################################# elif self.vesselID == '101': self.operator = Func.baudotshort2str(bits[3:18], 3) self._id = 'Aircraft Operator: {} Aircraft Serial No. #{}'.format( self.operator, Func.bin2dec(bits[21:33])) # self.SerialNum = Func.bin2dec(bits[21:33]) self.tablebin.append([ self.bitlabel(94, 108, deduct_offset), bits[3:18], 'Aircraft operator designator:', self.operator ]) self.tablebin.append([ self.bitlabel(109, 120, deduct_offset), bits[21:33], 'Aircraft serial number:', str(Func.bin2dec(bits[21:33])) ]) if Func.checkones(bits[33:50]): status_check = 'OK' else: status_check = 'ERROR' self.validhex = False self.tablebin.append([ self.bitlabel(124, 137, deduct_offset), bits[33:47], 'Spare 17 bits all should be 1', status_check ]) elif self.vesselID == '111' and self.bits[43] == '1': self.tablebin.append([ self.bitlabel(94, 137, deduct_offset), bits[3:47], 'Vessel ID', 'Reserved for system testing and test protocol bit 43 set to 1. Bits may contain information whereas default bits 94-137 normally 0s' ]) elif self.vesselID == '111' and self.bits[43] == '0': self.tablebin.append([ self.bitlabel(94, 137, deduct_offset), bits[3:47], 'Vessel ID', 'Reserved for system testing' ]) elif self.vesselID == '110': e = 'ERROR! Vessel ID type 110 not defined by T.018. Should not be used' self.tablebin.append([ self.bitlabel(94, 137, deduct_offset), bits[3:47], 'Spare', e ]) self.errors.append(e) self.validhex = False
def processHex(self, strhex): ##All second generation beacon messages must be EXACTLY 250 bits ##in length for the program to function properly. self.bits = Func.hex2bin(strhex) self.inputhex = strhex self.bchstring = '' self.tablebin = [] self.rotatingbin = [] self.longitude = self.latitude = 'na' self.location = (0, 0) self.courseloc = ('na', 'na') self.errors = [] self.warnings = [] self.fixedbits = '' self.testprotocol = '' self._id = 'na' self.SerialNum = 0 self.tac = 0 if len(self.bits) == 252 or len(self.bits) == 204: self.type = "Complete SGB message" pbit = self.bits[0:2] if pbit == '00': padding = 'Normal mode transmission (i.e., operational mode)' elif pbit == '10': padding = 'Self-test mode transmission' else: padding = 'ERROR! first two bits not 00 nor 10' self.errors.append(padding) self.tablebin.append(['Left pad', pbit, '', padding]) ##Add an additional bit to ensure that bits in array line up with bits in documentation and only include important bits 1-202 self.bits = "0" + self.bits[2:] ##Add the 23 Hex ID to our table self.beaconHexID = self.uinSgb() #self.tablebin.append(['','','Beacon 23 Hex ID:',self.beaconHexID]) #self.tablebin.append(['left padding',pbit,'',padding]) ##T018 Issue 1 - Rev 4: Bit 1-16 Type Approval Certificate # (previously BIT 1-20 Type Approval Certificate #) self.tac = Func.bin2dec(self.bits[1:17]) if self.tac < 10000: warn = '# {} Warning: SGB specifications stipulate TAC No should be greater than 10,000'.format( self.tac) self.warnings.append('TAC ' + warn) elif self.tac > 65520: warn = '# {} - System beacon'.format(self.tac) else: warn = '# {}'.format(self.tac) self.tablebin.append( ['1-16', self.bits[1:17], 'Type Approval Cert No: ', warn]) ##T018 Issue 1 - Rev 4: Bit 17-30 Serial Number (previously bit 21-30 Serial Number) self.SerialNum = Func.bin2dec(self.bits[17:31]) self.tablebin.append([ '17-30', self.bits[17:31], 'Beacon serial number:', str(self.SerialNum) ]) ##BIT 31-40 Country code self.countryCode = Func.bin2dec(self.bits[31:41]) self.countryName = Func.countryname(self.countryCode) self.tablebin.append([ '31-40', self.bits[31:41], 'Country code:', str(self.countryCode) + ' ' + str(self.countryName), definitions.moreinfo['country_code'] ]) ##BIT 41 Status of homing device self.status = Func.homing(self.bits[41]) self.tablebin.append( ['41', self.bits[41], 'Status of homing device:', self.status]) ####T018 Issue 1 - Rev 4: Bit 42: RLS Function ( previously Bit 42 Self-test function ) self.tablebin.append([ '42', self.bits[42], 'RLS function capability:', Func.rls(self.bits[42]) ]) ##BIT 43 Test protocol self.testprotocol = Func.testProtocol(self.bits[43]) self.tablebin.append([ '43', self.bits[43], 'Test protocol flag:', self.testprotocol ]) ##BIT 44-90 Encoded GNSS location self.latitude = Func.getlatitude(self.bits[44:67]) if 'Invalid' in self.latitude[0]: self.errors.append(self.latitude[0]) self.tablebin.append( ['44-66', self.bits[44:67], 'Latitude:', self.latitude[0]]) self.longitude = Func.getlongitude(self.bits[67:91]) if 'Invalid' in self.longitude[0]: self.errors.append(self.longitude[0]) self.tablebin.append( ['67-90', self.bits[67:91], 'Longitude:', self.longitude[0]]) self.location = (self.latitude[1], self.longitude[1]) ################################ # # # BIT 91-137 VESSEL ID FIELD # # # ################################ self.vesselIDfill(0, self.bits[91:138]) ## T018 Iss.1 Rev.4 Bit 138-140 Beacon Type (previous (Bit 138-139 Beacon Type) self.tablebin.append([ '138-140', self.bits[138:141], 'Beacon Type:', Func.getBeaconType(self.bits[138:141]) ]) ## T018 Iss.1 Rev.4 removed ''' self.tablebin.append(['140', self.bits[140], 'RLS capability:', Func.rls(self.bits[140])]) ''' ##BIT 141-154 Spare bits if Func.checkones(self.bits[141:155]) and not Func.checkones( self.bits[155:159]): self.tablebin.append([ '141-154', self.bits[141:155], 'Spare bits', 'OK - all bits 1 and rotating field not a cancellation message' ]) elif Func.checkones(self.bits[141:155]) and Func.checkones( self.bits[155:159]): e = 'ERROR! - all bits 1 and rotatating field is a cancellation message (for a cancellation message these bits should be set to 0)' self.errors.append(e) self.tablebin.append( ['141-154', self.bits[141:155], 'Spare bits', e]) elif Func.checkzeros(self.bits[141:155]) and Func.checkones( self.bits[155:159]): self.tablebin.append([ '141-154', self.bits[141:155], 'Spare bits', 'OK - all bits 0 and rotating field is cancellation message (unless this is a cancellation message, these bits should be set to 1' ]) elif Func.checkzeros(self.bits[141:155]) and not Func.checkones( self.bits[155:159]): e = 'ERROR!- all bits 0 and rotating field is not cancellation message' self.errors.append(e) self.tablebin.append( ['141-154', self.bits[141:155], 'Spare bits', e]) else: e = 'ERROR: Bits 141-154 should be set to all 1 or all 0 in the case that the rotating field is a cancellation message' self.errors.append(e) self.tablebin.append([ '141-154', self.bits[141:155], 'Cancellation message status:', e ]) ####################################### # # # BIT 155-202 48 BIT ROTATING FIELD # # # ####################################### self.rotatingID = Func.bin2dec(self.bits[155:159]) ###################################################### # Rotating Field 0: C/S G.008 Objective Requirements # ###################################################### if self.rotatingID == 0: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#0) C/S G.008 Objective Requirements' ]) self.rotatingbin = rotating.rotating0(self.bits[155:203]) ######################################## # Rotating Field 1: Inflight Emergency # ######################################## elif self.rotatingID == 1: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#1) ELT(DT) In-flight Emergency' ]) self.rotatingbin = rotating.rotating1(self.bits[155:203]) ######################### # Rotating Field 2: RLS # ######################### elif self.rotatingID == 2: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#2) RLS' ]) self.rotatingbin = rotating.rotating2(self.bits[155:203]) ################################## # Rotating Field 3: National Use # ################################## elif self.rotatingID == 3: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#3) National Use' ]) self.rotatingbin = rotating.rotating3(self.bits[155:203]) ########################################### # Rotating Field 15: Cancellation Message # ########################################### elif self.rotatingID == 15: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#15) Cancellation Message' ]) self.rotatingbin = rotating.rotating15(self.bits[155:203]) ################################## # All other rotating fields spare # ################################## else: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', 'Spare' ]) ##Add rotating field data to our list self.tablebin.extend(self.rotatingbin) #################################### # 48-BIT BCH ERROR CORRECTING CODE # #################################### if len(self.bits) == 251: # 251 length means 250 plus the stub 0, minus the extra 2 digits of front padding in self.bits self.tablebin.append( ['203-250', self.bits[203:], 'Encoded BCH', 'Encoded BCH']) ##Calculate the BCH self.calculatedBCH = Func.calcBCH(self.bits[1:], 0, 202, 250) self.bchstring = writebch.calcBCH(self.bits[1:], 0, 202, 250)[1] self.tablebin.append( ['Calculated', self.calculatedBCH, 'Computed', '']) #self.tablebin.append(['','','','self.calculatedBCH {} : self.bchstring {} {}'.format(self.calculatedBCH,self.bchstring,self.calculatedBCH==self.bchstring)]) ##Compare to the BCH in the beacon message bcherr = self.BCHerrors = Func.errors(self.calculatedBCH, self.bits[203:]) if bcherr > 0: bcherror = 'ERROR! COMPUTED BCH DOES NOT MATCH ENCODED BCH!!' self.errors.append(bcherror) else: bcherror = 'VALID BCH: COMPUTED BCH MATCHES' self.tablebin.append(['', '', '', bcherror]) elif len(self.bits) == 203: # if user enters a hex 51 excluding bch, then this ,means 202 information bits plus stub 0 minues the 2 digits of front padding self.tablebin.append([ '203-250', 'NA', 'Encoded BCH', 'Not provided in a 51 Hex. Computed below' ]) self.calculatedBCH = Func.calcBCH(self.bits[1:], 0, 202, 250) hexBCH = Func.bin2hex(self.calculatedBCH) self.tablebin.append([ '203-250', self.calculatedBCH, 'Calculated BCH', 'Hex Value: {}'.format(hexBCH) ]) self.tablebin.append([ 'Complete Message', '', 'Hex Value: {}{}'.format(self.inputhex, hexBCH), '' ]) elif len(self.bits) == 92: self.type = 'uin' ##Add an additional bit to ensure that bits in array line up with bits in documentation self.bits = "0" + self.bits self.latitude = self.longitude = 'No data available' self.tablebin.append(['Unique ID', 'Second Generation', '', '']) self.tablebin.append([ '1', self.bits[1], 'SGB requires this bit value be 1', ['ERROR', 'OK'][int(self.bits[1])] ]) if self.bits[1] == '0': self.validhex = False self.errors.append( 'Error: SGB beacon UIN fixed first bit not set to 1') ##BIT 2-11 Country code self.countryCode = Func.bin2dec(self.bits[2:12]) self.countryName = Func.countryname(self.countryCode) if self.countryName == 'Unknown MID': self.validhex = False self.errors.append('Error: Bad country code: ' + self.countryName) self.tablebin.append([ '2-11', self.bits[2:12], 'Country code:', str(self.countryCode) + ' ' + str(self.countryName), definitions.moreinfo['country_code'] ]) ##BIT 12-14 Should be 101 status check for SGB if self.bits[12:15] == '101': status_check = 'OK' else: status_check = 'ERROR' self.validhex = False self.errors.append('Error: Bits 12-14 should be 101') self.tablebin.append( ['12-14', self.bits[12:15], 'Should be 101', status_check]) ##BIT 15-30 Type Approval Certificate # self.tac = Func.bin2dec(self.bits[15:31]) if self.tac < 10000: warn = 'Type Approval # {} :: WARNING! SGB specifications requires TAC No >=10,000'.format( self.tac) self.validhex = False self.errors.append(warn) else: warn = str(self.tac) self.tablebin.append( ['15-30', self.bits[15:31], 'Type Approval Cert No: ', warn]) ##BIT 31-44 Beacon Serial Number self.SerialNum = Func.bin2dec(self.bits[31:45]) self.tablebin.append([ '31-44', self.bits[35:45], 'Beacon serial number', str(self.SerialNum) ]) self.testprotocol = Func.testProtocol(self.bits[45]) self.tablebin.append([ '45', self.bits[45], 'Test protocol flag:', str(self.testprotocol) ]) if self.bits[45] == '1': self.validhex = False if self.bits[61:] == '0' * 32 and self.bits[46:49] != '111': self.tablebin.append([ '46-48', self.bits[46:49], 'Vessel ID Type', Func.getVesselid(self.bits[46:49]) ]) self.tablebin.append([ '49-60', self.bits[49:61], 'Partial vessel ID', 'WARNING!! = No Identification information or truncated SGB 15 Hex (incomplete partial vessel ID. ' ]) self.tablebin.append( ['61-92', self.bits[61:], 'Remaining bits', '']) #self.vesselIDfill(46, self.bits[46:93]) else: ##BIT 45-91 Aircraft / Vessel ID self.vesselIDfill(45, self.bits[46:93]) ##T018 Iss.1 Rev 4 removed : (was BIT 92 Fixed value 1) ''' if self.bits[92]=='1': status_check = 'OK' else: status_check = 'ERROR' self.tablebin.append(['92', self.bits[92], 'Fixed 1', status_check]) ''' else: self.type = ( 'Hex string length of ' + str(len(strhex)) + '.' + '\nBit string length of ' + str(len(self.bits)) + '.' + '\nLength of First Gen Beacon Hex String must be 15, 22 or 30' + '\nLength of Second Gen Beacon Bit String must be 204 or 252 bits' ) raise Gen2Error('LengthError', self.type)
def rotating2(bits): rotatingbin = [] #Add a single bit offset so bits array index # matches documentation for readbility bits = '0' + bits ##BIT 5-6 (159-160) Beacon Type beacon = definitions.beacon_type[bits[5:7]] rotatingbin.append( ['159-160 (Rotating field 5-6)', bits[5:7], 'Beacon type', beacon]) ##BIT 7-12 (161-166) Beacon RLS Capability if bits[7] == '1': rotatingbin.append([ '161 (Rotating field 7)', bits[7], 'Capability to process automatically generated (Acknowledgement RLM Type-1)', 'Acknowledgement Type-1 accepted by this beacon' ]) else: rotatingbin.append([ '161 (Rotating field 7)', bits[7], 'Capability to process automatically generated (Acknowledgement RLM Type-1)', 'Acknowledgement Type-1 not requested and not accepted by this beacon' ]) if bits[8] == '1': rotatingbin.append([ '162 (Rotating field 8)', bits[8], 'Capability to process manually generated RLM (e.g. Acknowledgement Type-2)', 'Manually generated RLM accepted by this beacon' ]) else: rotatingbin.append([ '162 (Rotating field 8)', bits[8], 'Capability to process manually generated RLM (e.g. Acknowledgement Type-2)', 'Manually generated RLM not requested and not accepted by this beacon' ]) rotatingbin.append([ '163-166 (Rotating field 9-12)', bits[9:13], 'Reserved for future use', 'Reserved' ]) ##BIT 13-15 (167-169) RLS Provider Identification try: rlsp = definitions.rls_provider[bits[13:16]] except KeyError: rlsp = 'Unknown RLS provider' rotatingbin.append([ '167-169 (Rotating field 13-15)', bits[13:16], 'RLS Provider Identification', rlsp ]) ##BIT 16-37 (170-190) Beacon Feedback (acknowledgement of RLM reception) if bits[13:16] == '001': if bits[16] == '0': rotatingbin.append([ '170 (Rotating field 16)', bits[16], 'RLM Short/Long message identifier', 'Short RLM' ]) else: rotatingbin.append([ '170 (Rotating field 16)', bits[16], 'RLM Short/Long message identifier', 'Long RLM' ]) rotatingbin.append( ['171 (Rotating field 17)', bits[17], 'Reserved', 'Reserved']) if (bits[16] == '0') & (bits[17] == '0'): rotatingbin.append([ '172-190 (Rotating field 18-37)', bits[18:38], 'RLM', 'Copy of bits 61-80 of the short RLM in the Open Service Signal in Space (section 5.2 of OS SIS ICD)' ]) else: rotatingbin.append([ '172-190 (Rotating field 18-37)', bits[18:38], 'To be defined', 'To be defined' ]) else: rotatingbin.append([ '170-190 (Rotating field 16-37)', bits[16:38], 'Reserved', 'Reserved' ]) ##BIT 38-48 (191-202) Unassigned if Func.checkzeros(bits[38:]): rotatingbin.append( ['191-202 (Rotating field 38-48)', bits[38:], 'Unassigned', 'OK']) else: rotatingbin.append([ '191-202 (Rotating field 38-48)', bits[38:], 'Unassigned', 'ERROR: Should be all 0s' ]) return rotatingbin
def rotating0(bits): rotatingbin = [] #Add a single bit offset so bits array index # matches documentation for readbility bits = '0' + bits ##BIT 5-10 (159-164) Elapsed time since activation (0 to 63 hours in 1 hour steps) t_act = Func.bin2dec(bits[5:11]) rotatingbin.append([ '159-164 (Rotating field 5-10)', bits[5:11], 'Elapsed time since activation:', str(t_act) + ' hours' ]) ##BIT 11-21 (165-175) Time from last encoded location (0 to 2047 minutes in 1 minute steps) t_encoded = Func.bin2dec(bits[11:22]) rotatingbin.append([ '165-175 (Rotating field 11-21)', bits[11:22], 'Time from last encoded location:', str(t_encoded) + ' minutes' ]) ##BIT 22-31 (176-185) Altitude of encoded location altitude = Func.getaltitude(bits[22:32]) rotatingbin.append([ '176-185 (Rotating field 22-31)', bits[22:32], 'Altitude of encoded location: ', altitude ]) ##BIT 32-39 (186-193) Dilution of precision hdop = Func.getDOP(bits[32:36]) rotatingbin.append( ['186-189 (Rotating field 32-34)', bits[32:36], 'HDOP:', hdop]) vdop = Func.getDOP(bits[36:40]) rotatingbin.append( ['190-193 (Rotating field 35-39)', bits[36:40], 'VDOP:', vdop]) ##BIT 40-41 (194-195) Automated/manual activation notification activation = definitions.activation_note[bits[40:42]] rotatingbin.append([ '194-194 (Rotating field 40-41)', bits[40:42], 'Automated/manual activation notification', activation ]) ##BIT 42-44 (196-198) Remaining battery capacity battery = definitions.battery[bits[42:45]] rotatingbin.append([ '196-198 (Rotating field 42-44)', bits[42:45], 'Remaining battery capacity', battery ]) ##BIT 45-46 (199-200) GNSS status gnss = definitions.gnss_status[bits[45:47]] rotatingbin.append( ['199-200 (Rotating field 45-46)', bits[45:47], 'GNSS status', gnss]) ##BIT 47-48 (201-202) Spare if Func.checkzeros(bits[47:]): rotatingbin.append( ['201-202 (Rotating field 47-48)', bits[47:], 'Spare', 'OK']) else: rotatingbin.append([ '201-202 (Rotating field 47-48)', bits[47:], 'Spare', 'ERROR: Should be 00' ]) return rotatingbin
def processHex(self, strhex): ##All second generation beacon messages must be EXACTLY 250 bits ##in length for the program to function properly. self.bits = Func.hex2bin(strhex) if len(self.bits) == 250 or len(self.bits) == 202: self.tablebin = [] self.rotatingbin = [] ##Add an additional bit to ensure that bits in array line up with bits in documentation self.bits = "0" + self.bits ##BIT 1-20 Type Approval Certificate # self.tac = Func.bin2dec(self.bits[1:21]) self.tablebin.append([ '1-20', self.bits[1:21], 'Type Approval Certificate #:', str(self.tac) ]) ##BIT 21-30 Serial Number self.serialNum = Func.bin2dec(self.bits[21:31]) self.tablebin.append([ '21-30', self.bits[21:31], 'Serial Number:', str(self.serialNum) ]) ##BIT 31-40 Country code self.countryCode = Func.bin2dec(self.bits[31:41]) self.countryName = Func.countryname(self.countryCode) self.tablebin.append([ '31-40', self.bits[31:41], 'Country code:', str(self.countryCode) + ' ' + str(self.countryName) ]) ##BIT 41 Status of homing device self.status = Func.homing(self.bits[41]) self.tablebin.append( ['41', self.bits[41], 'Status of homing device:', self.status]) ##BIT 42 Self-test function self.selfTestStatus = Func.selfTest(self.bits[42]) self.tablebin.append([ '42', self.bits[42], 'Self-test function:', self.selfTestStatus ]) ##BIT 43 User cancellation self.cancel = Func.cancellation(self.bits[43]) self.tablebin.append( ['43', self.bits[43], 'User cancellation:', self.cancel]) ##BIT 44-90 Encoded GNSS location self.latitude = Func.getlatitude(self.bits[44:67]) self.tablebin.append( ['44-66', self.bits[44:67], 'Latitude:', self.latitude[0]]) self.longitude = Func.getlongitude(self.bits[67:91]) self.tablebin.append( ['67-90', self.bits[67:91], 'Longitude:', self.longitude[0]]) self.location = (self.latitude[1], self.longitude[1]) ################################ # # # BIT 91-137 VESSEL ID FIELD # # # ################################ self.vesselID = self.bits[91:94] ############################################## # Vessel 0: No aircraft or maritime identity # ############################################## if self.vesselID == '000': self.tablebin.append([ '91-93', self.bits[91:94], 'Vessel ID:', 'No aircraft or maritime identity' ]) if Func.checkzeros(self.bits[94:138]): self.tablebin.append( ['94-137', self.bits[94:138], 'Spare:', 'All 0 - OK']) else: self.tablebin.append([ '94-137', self.bits[94:138], 'Spare:', 'ERROR: Bits 94-137 should be 0' ]) ########################### # Vessel 1: Maritime MMSI # ########################### elif self.vesselID == '001': self.tablebin.append( ['91-93', self.bits[91:94], 'Vessel ID:', 'MMSI']) self.mmsi = Func.bin2dec(self.bits[94:124]) if self.mmsi == 111111: self.tablebin.append([ '94-123', self.bits[94:124], 'MMSI:', 'No MMSI available' ]) else: self.mmsi_string = str(self.mmsi).zfill(9) self.tablebin.append([ '94-123', self.bits[94:124], 'Unique ship station identity M1I2D3X4X5X6X7X8X9:', self.mmsi_string ]) self.mmsi_country = Func.countryname( int(self.mmsi_string[0:3])) self.tablebin.append([ '', '', 'Flag state of vessel:', self.mmsi_string[0:3] + ' ' + self.mmsi_country ]) self.tablebin.append([ '', '', 'Unique vessel number:', self.mmsi_string[3:] ]) self.epirb_ais = Func.bin2dec(self.bits[124:138]) if self.epirb_ais == 10922: self.tablebin.append([ '124-137', self.bits[124:138], 'EPIRB-AIS System Identity:', 'No EPIRB-AIS System' ]) else: self.epirb_ais_str = str(self.epirb_ais).zfill(4) self.epirb_ais_str = '974' + self.mmsi_string[ 3:5] + self.epirb_ais_str self.tablebin.append([ '124-137', self.bits[123:137], 'EPIRB-AIS System Identity:', self.epirb_ais_str ]) ############################# # Vessel 2: Radio Call Sign # ############################# elif self.vesselID == '010': self.tablebin.append([ '91-93', self.bits[91:94], 'Vessel ID:', 'Radio Call Sign' ]) self.callsign = Func.getCallsign(self.bits[94:136]) self.tablebin.append([ '94-135', self.bits[94:136], 'Radio Callsign:', self.callsign ]) if Func.checkzeros(self.bits[136:138]): self.tablebin.append([ '136-137', self.bits[136:138], 'Spare:', 'All 0 - OK' ]) else: self.tablebin.append([ '136-137', self.bits[136:138], 'Spare:', 'ERROR: Bits 136-137 should be all 0s' ]) ######################################################### # Vessel 3: Aricraft Registration Marking (Tail Number) # ######################################################### elif self.vesselID == '011': self.tablebin.append([ '91-93', self.bits[91:94], 'Vessel ID:', 'Aircraft Registration Marking (Tail Number)' ]) self.tailnum = Func.getTailNum(self.bits[94:136]) self.tablebin.append([ '94-135', self.bits[94:136], 'Aircraft Registration Marking:', self.tailnum ]) if Func.checkzeros(self.bits[135:137]): self.tablebin.append( ['136-137', self.bits[136:138], 'Spare:', 'OK']) else: self.tablebin.append([ '136-137', self.bits[136:138], 'Spare:', 'ERROR: Bits 136-137 should be all 0s' ]) ############################################## # Vessel 4: Aircraft Aviation 24 Bit Address # ############################################## elif self.vesselID == '100': self.tablebin.append([ '91-93', self.bits[91:94], 'Vessel ID:', 'Aircraft Aviation 24 Bit Address' ]) self.aviationBitAddress = Func.bin2dec(self.bits[93:117]) self.tablebin.append([ '94-117', self.bits[94:118], 'Aviation 24 bit address:', str(self.aviationBitAddress) ]) if Func.checkzeros(self.bits[117:137]): self.tablebin.append( ['118-137', self.bits[118:138], 'Spare:', 'OK']) else: self.tablebin.append([ '118-137', self.bits[118:138], 'Spare:', 'ERROR: Bits 118-137 following aviation 24 bit address should be 0' ]) ################################################# # Vessel 5: Aircraft Operator and Serial Number # ################################################# elif self.vesselID == '101': self.tablebin.append([ '91-93', self.bits[91:94], 'Vessel ID:', 'Aircraft Operator and Serial Number' ]) self.operator = Func.baudot2str(self.bits[94:112], 3) self.serialnum = Func.bin2dec(self.bits[112:124]) self.tablebin.append([ '94-111', self.bits[94:112], 'Aircraft operator:', self.operator ]) self.tablebin.append([ '112-123', self.bits[112:124], 'Serial number:', str(self.serialnum) ]) if Func.checkones(self.bits[124:138]): self.tablebin.append( ['124-137', self.bits[124:138], 'Spare:', 'OK']) else: self.tablebin.append([ '124-137', self.bits[124:138], 'Spare:', 'ERROR: Bits 124-137 following aircraft operator and serial numbers should be 1' ]) ########################## # Other Vessel IDs Spare # ########################## else: self.tablebin.append( ['91-93', self.bits[91:94], 'Vessel ID:', 'Spare']) ##BIT 138-154 Spare bits [137-153] if Func.checkones(self.bits[138:155]): self.tablebin.append( ['138-154', self.bits[138:155], 'Spare:', 'OK']) else: self.tablebin.append([ '138-154', self.bits[138:155], 'Spare:', 'ERROR: Bits 138-154 should be 1s' ]) ####################################### # # # BIT 155-202 48 BIT ROTATING FIELD # # # ####################################### self.rotatingID = Func.bin2dec(self.bits[155:159]) ###################################################### # Rotating Field 0: C/S G.008 Objective Requirements # ###################################################### if self.rotatingID == 0: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#0) C/S G.008 Objective Requirements' ]) self.rotatingbin = rotating.rotating0(self.bits[155:203]) ######################################## # Rotating Field 1: Inflight Emergency # ######################################## elif self.rotatingID == 1: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#1) Inflight Emergency' ]) self.rotatingbin = rotating.rotating1(self.bits[155:203]) ######################### # Rotating Field 2: RLS # ######################### elif self.rotatingID == 2: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#2) RLS' ]) self.rotatingbin = rotating.rotating2(self.bits[155:203]) ################################## # Rotating Field 3: National Use # ################################## elif self.rotatingID == 3: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#3) National Use' ]) self.rotatingbin = rotating.rotating3(self.bits[155:203]) ########################################### # Rotating Field 15: Cancellation Message # ########################################### elif self.rotatingID == 15: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', '(#15) Cancellation Message' ]) self.rotatingbin = rotating.rotating15(self.bits[155:203]) ################################## # All other roating fields spare # ################################## else: self.tablebin.append([ '155-158 (Rotating field 1-4)', self.bits[155:159], 'Rotating Field Type:', 'Spare' ]) ##Add rotating field data to our list self.tablebin.extend(self.rotatingbin) #################### # BEACON 23 HEX ID # #################### self.hexID = [] ##Hex ID BIT 1 = fixed binary 1 self.hexID.append('1') ##Hex ID BIT 2-11 = BITS 31-40 (C/S Country Code) self.hexID.append(self.bits[31:41]) ##Hex ID BIT 12 = fixed binary 1 self.hexID.append('1') ##Hex ID BIT 13 = fixed binary 0 self.hexID.append('0') ##Hex ID BIT 14 = fixed binary 1 self.hexID.append('1') ##Hex ID BIT 15-34 = BITS 1-20 (C/S TAC No) self.hexID.append(self.bits[1:21]) ##Hex ID BIT 35-44 = BITS 21-30 (Beacon Serial Number) self.hexID.append(self.bits[21:31]) ##Hex ID BIT 45-47 = BITS 91-93 (Aircraft/Vessel ID Type) self.hexID.append(self.bits[91:94]) ##Hex ID BIT 48-91 = BITS 94-137 (Aircraft/Vessel ID) self.hexID.append(self.bits[94:138]) ##Hex ID BIT 92 = fixed binary 1 self.hexID.append('1') ##Join list together and convert to Hexadecimal self.beaconHexID = Func.bin2hex(''.join(self.hexID)) ##Add the 23 Hex ID to our table self.tablebin.append( ['', '', 'Beacon 23 Hex ID:', self.beaconHexID]) #################################### # 48-BIT BCH ERROR CORRECTING CODE # #################################### if len(self.bits) == 251: ##Calculate the BCH self.calculatedBCH = Func.calcBCH(self.bits[1:], 0, 202, 250) ##Compare to the BCH in the beacon message self.BCHerrors = Func.errors(self.calculatedBCH, self.bits[203:]) ##Write the number of errors to our table self.tablebin.append( ['', '', 'Number of BCH errors:', str(self.BCHerrors)]) else: self.type = ( 'Hex string length of ' + str(len(strhex)) + '.' + '\nBit string length of ' + str(len(self.bits)) + '.' + '\nLength of First Gen Beacon Hex String must be 15, 22 or 30' + '\nLength of Second Gen Beacon Bit String must be 250 bits') raise Gen2Error('LengthError', self.type)
def vesselIDfill(self,deduct_offset,bits): self.vesselID = bits[0:3] self.tablebin.append([self.bitlabel(91,93,deduct_offset), self.vesselID , 'Vessel ID Type', Func.getVesselid(self.vesselID)]) if self.vesselID == '111' and self.bits[43]=='0': self.tablebin.append(['','','Reserved for system testing','ERROR! Test protocol bit 43 is zero']) self.validhex=False ############################################## # Vessel 0: No aircraft or maritime identity # ############################################## if self.vesselID == '000': if Func.checkzeros(bits[3:47]): self.tablebin.append([self.bitlabel(94,137,deduct_offset), bits[3:47], 'Vessel ID type is none', 'All 0 - OK']) else: self.tablebin.append([self.bitlabel(94, 137,deduct_offset), bits[3:47], 'Vessel ID type is none', 'Unless national assigned, should be all 0']) self.validhex = False ########################### # Vessel 1: Maritime MMSI # ########################### elif self.vesselID == '001': self.mmsi = Func.bin2dec(bits[3:33]) if self.mmsi == 111111: self.tablebin.append([self.bitlabel(94,123,deduct_offset), bits[3:33], 'MMSI:', 'No MMSI available']) else: self.mmsi_string = str(self.mmsi).zfill(9) self.tablebin.append([self.bitlabel(94,123,deduct_offset), bits[3:33], 'Unique ship station identity where the first 3 digits are MID (MIDxxxxxx):', self.mmsi_string]) self.mmsi_country = Func.countryname(int(self.mmsi_string[0:3])) self.tablebin.append(['', '', 'Flag state of vessel:', self.mmsi_string[0:3] + ' ' + self.mmsi_country]) self.tablebin.append(['', '', 'Unique vessel number', self.mmsi_string[3:]]) self.epirb_ais = Func.bin2dec(bits[33:47]) if self.epirb_ais == 10922: self.tablebin.append([self.bitlabel(124,137,deduct_offset), bits[33:47], 'EPIRB-AIS System Identity:', 'No EPIRB-AIS System']) else: self.epirb_ais_str = str(self.epirb_ais).zfill(4) self.epirb_ais_str = '974xx' + self.epirb_ais_str self.tablebin.append([self.bitlabel(124,137,deduct_offset), bits[33:47], 'EPIRB-AIS System Identity', self.epirb_ais_str]) ############################# # Vessel 2: Radio Call Sign # ############################# elif self.vesselID == '010': self.callsign = Func.getCallsign(bits[3:45]) self.tablebin.append([self.bitlabel(94,135,deduct_offset), bits[3:45], 'Radio Callsign', self.callsign, definitions.moreinfo['sgb_radio_callsign']]) if Func.checkzeros(bits[45:47]): status_check='OK' else: status_check = 'ERROR' self.validhex = False self.tablebin.append([self.bitlabel(136,137,deduct_offset), bits[45:47], 'Spare should be 0', status_check]) ######################################################### # Vessel 3: Aricraft Registration Marking (Tail Number) # ######################################################### elif self.vesselID == '011': self.tailnum = Func.getTailNum(bits[3:45]) self.tablebin.append([self.bitlabel(94,135,deduct_offset), bits[3:45], 'Aircraft Registration Marking:', self.tailnum]) if bits[45:47]=='00': status_check = 'OK' else: status_check = 'ERROR' self.validhex = False self.tablebin.append([self.bitlabel(136,137,deduct_offset), bits[45:47], 'Spare should be 00', status_check]) ############################################## # Vessel 4: Aircraft Aviation 24 Bit Address # ############################################## elif self.vesselID == '100': self.aviationBitAddress = Func.bin2dec(bits[3:27]) self.tablebin.append([self.bitlabel(94,117,deduct_offset), bits[3:27], 'Aviation 24 bit address', str(self.aviationBitAddress)]) if Func.checkzeros(bits[27:47]): status_check = 'OK' else: status_check = 'ERROR' self.validhex = False self.tablebin.append([self.bitlabel(118,137,deduct_offset), bits[27:47], 'Spare should be 0', status_check]) ################################################# # Vessel 5: Aircraft Operator and Serial Number # ################################################# elif self.vesselID == '101': self.operator = Func.baudot2str(bits[3:21], 3) self.serialnum = Func.bin2dec(bits[21:33]) self.tablebin.append([self.bitlabel(94,111,deduct_offset), bits[3:21], 'Aircraft operator designator:', self.operator]) self.tablebin.append([self.bitlabel(112,123,deduct_offset), bits[21:33], 'Aircraft Serial number:', str(self.serialnum)]) if Func.checkones(bits[33:47]): status_check = 'OK' else: status_check = 'ERROR' self.validhex = False self.tablebin.append([self.bitlabel(124,137,deduct_offset), bits[33:47], 'Spare all should be 1', status_check]) elif self.vesselID == '111' and self.bits[43]=='1': self.tablebin.append([self.bitlabel(94, 137, deduct_offset), bits[3:47], 'Reserved for system testing','OK. Test protocol bit 43 set to 1. May contain information; default bits 94-137 - 0s']) elif self.vesselID == '111' and self.bits[43]=='0': self.tablebin.append([self.bitlabel(94, 137, deduct_offset), bits[3:47], 'Reserved for system testing', '']) elif self.vesselID == '110': self.tablebin.append([self.bitlabel(94, 137, deduct_offset), bits[3:47], 'Spare', 'ERROR! Not defined by T.018. Should not be used']) self.validhex = False