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
            ])
Example #2
0
    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.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 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)
Example #5
0
    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)
    try:
        userInput = raw_input('\nPlease enter country code: ')
    except EOFError:
        userInput = 0
    try:
        countrycode = int(userInput)
    except ValueError:
        print 'Error: value must be an integer'
        countrycode = 0
    else:
        bits_countrycode = Func1.dec2bin(countrycode).zfill(10)
        if len(bits_countrycode) != 10:
            print 'Error: input too high.'
        else:
            break
printtxt('Country: {} {} - binary: {}\n'.format(str(countrycode),Func2.countryname(countrycode),bits_countrycode))




################################
#  BIT 91-137 VESSEL ID FIELD  #
################################
while next_step == False:
    vesselID_list=['0: No aircraft or maritime identity',
                   '1: Maritime MMSI',
                   '2: Radio Call Sign',
                   '3: Aircraft Registration Marking (Tail Number)',
                   '4: Aircraft Aviation 24 Bit Address',
                   '5: Aircraft Operator and Serial Number',
                   '6: Spare',
Example #7
0
##BIT 31-40 Country code
while next_step == False:
    userInput = raw_input('\nPlease enter country code: ')
    try:
        countrycode = int(userInput)
    except ValueError:
        print 'Error: value must be an integer'
        countrycode = 0
    else:
        bits_countrycode = Func1.dec2bin(countrycode).zfill(10)
        if len(bits_countrycode) != 10:
            print 'Error: input too high.'
        else:
            break
print 'You entered: ' + str(countrycode) + ' ' +Func2.countryname(countrycode)


##BIT 41 Status of homing device
while next_step == False:
    print '\nPlease enter homing status: '
    print '0: Beacon is not equipped with any homing signals or they have been deliberately disabled.  If beacon has been activated, no homing device is functional or it has been deliberately disabled'
    print '1: Beacon is equipped with at least one homing signal. If beacon has been activated, at least one homing device is functional and transmitting'
    userInput = raw_input()
    try:
        status = int(userInput)
    except ValueError:
        print 'Error: value must be an integer'
        status = 0
    else:
        bits_status = str(status)
Example #8
0
    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
        userInput = raw_input('\nPlease enter country code: ')
    except EOFError:
        userInput = 0
    try:
        countrycode = int(userInput)
    except ValueError:
        print 'Error: value must be an integer'
        countrycode = 0
    else:
        bits_countrycode = Func1.dec2bin(countrycode).zfill(10)
        if len(bits_countrycode) != 10:
            print 'Error: input too high.'
        else:
            break
printtxt('Country: {} {} - binary: {}\n'.format(str(countrycode),
                                                Func2.countryname(countrycode),
                                                bits_countrycode))

################################
#  BIT 91-137 VESSEL ID FIELD  #
################################
while next_step == False:
    vesselID_list = [
        '0: No aircraft or maritime identity', '1: Maritime MMSI',
        '2: Radio Call Sign', '3: Aircraft Registration Marking (Tail Number)',
        '4: Aircraft Aviation 24 Bit Address',
        '5: Aircraft Operator and Serial Number', '6: Spare', '7: Spare'
    ]
    #91-93
    for i in vesselID_list:
        print i
Example #10
0
    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.tablebin = []
        self.rotatingbin = []

        if len(self.bits) == 252 or len(self.bits) == 202 or len(
                self.bits) == 204 or len(self.bits) == 250:

            ##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.vesselIDfill(0, self.bits[91:138])

            ##BIT 138-154 Spare bits [137-154]
            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) == 253:
                self.tablebin.append(
                    ['203-204 (padding)', self.bits[203:205], '', ''])
                self.tablebin.append([
                    '205: (bch)', self.bits[205:], 'Encoded BCH', 'Encoded BCH'
                ])
                ##Calculate the BCH
                self.calculatedBCH = Func.calcBCH(self.bits[1:], 0, 202, 250)

                self.tablebin.append(
                    ['Calculated', self.calculatedBCH, 'Computed', ''])

                ##Compare to the BCH in the beacon message
                self.BCHerrors = Func.errors(self.calculatedBCH,
                                             self.bits[205:])

                ##Write the number of errors to our table
                self.tablebin.append(
                    ['', '', 'Number of BCH errors:',
                     str(self.BCHerrors)])
        elif len(self.bits) == 92:
            self.type = (
                'Hex string length of {}. \nBit length of {}. \nThis is a second generation beacon UIN'
                .format(str(len(strhex)), str(len(self.bits))))
            ##Add an additional bit to ensure that bits in array line up with bits in documentation
            self.bits = "0" + self.bits
            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])
            self.tablebin.append([
                '15-34', self.bits[15:35], 'Type Approval Certificate #',
                str(self.tac)
            ])
            ##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)
            ])

            ##BIT 45-91 Aircraft / Vessel ID
            self.vesselIDfill(46, self.bits[45:92])

            ##BIT 92 Fixed value 1
            self.tablebin.append(
                ['92', self.bits[92], 'Fixed 1', self.bits[92] == '1'])

        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)