def parse_ais_messages(self, raw, bits, source='internal'): "Generator code - read forever from source stream, parsing AIS messages." values = {} values['length'] = bits.bitlen # Without the following magic, we'd have a subtle problem near # certain variable-length messages: DSV reports would # sometimes have fewer fields than expected, because the # unpacker would never generate cooked tuples for the omitted # part of the message. Presently a known issue for types 15 # and 16 only. (Would never affect variable-length messages in # which the last field type is 'string' or 'raw'). bits.extend_to(168) # Magic recursive unpacking operation try: cooked = ais.aivdm_unpack(0, bits, 0, values, ais.aivdm_decode) # We now have a list of tuples containing unpacked fields # Collect some field groups into ISO8601 format for (offset, template, label, legend, formatter) in ais.field_groups: segment = cooked[offset:offset + len(template)] if map(lambda x: x[0], segment) == template: group = ais.formatter(*map(lambda x: x[1], segment)) group = (label, group, 'string', legend, None) cooked = cooked[:offset] + [group] + cooked[offset + len(template):] # Apply the postprocessor stage cooked = ais.postprocess(cooked) expected = ais.lengths.get(values['msgtype'], None) # Check length; has to be done after so we have the type field bogon = False if expected is not None: if type(expected) == type(0): expected_range = (expected, expected) else: expected_range = expected actual = values['length'] if not (actual >= expected_range[0] and actual <= expected_range[1]): raise Exception( "invalid length %d(%d..%d)" % (actual, expected_range[0], expected_range[1])) # We're done, hand back a decoding #AVNLog.ld('decoded AIS data',cooked) self.storeAISdata(cooked, source=source) return True except: (exc_type, exc_value, exc_traceback) = sys.exc_info() AVNLog.debug("exception %s while decoding AIS data %s", exc_value, raw.strip()) return False
def parse_ais_messages(self,raw,bits): "Generator code - read forever from source stream, parsing AIS messages." values = {} values['length'] = bits.bitlen # Without the following magic, we'd have a subtle problem near # certain variable-length messages: DSV reports would # sometimes have fewer fields than expected, because the # unpacker would never generate cooked tuples for the omitted # part of the message. Presently a known issue for types 15 # and 16 only. (Would never affect variable-length messages in # which the last field type is 'string' or 'raw'). bits.extend_to(168) # Magic recursive unpacking operation try: cooked = ais.aivdm_unpack(0, bits, 0, values, ais.aivdm_decode) # We now have a list of tuples containing unpacked fields # Collect some field groups into ISO8601 format for (offset, template, label, legend, formatter) in ais.field_groups: segment = cooked[offset:offset+len(template)] if map(lambda x: x[0], segment) == template: group = ais.formatter(*map(lambda x: x[1], segment)) group = (label, group, 'string', legend, None) cooked = cooked[:offset]+[group]+cooked[offset+len(template):] # Apply the postprocessor stage cooked = ais.postprocess(cooked) expected = ais.lengths.get(values['msgtype'], None) # Check length; has to be done after so we have the type field bogon = False if expected is not None: if type(expected) == type(0): expected_range = (expected, expected) else: expected_range = expected actual = values['length'] if not (actual >= expected_range[0] and actual <= expected_range[1]): raise AISUnpackingException(0, "length", actual) # We're done, hand back a decoding #AVNLog.ld('decoded AIS data',cooked) self.storeAISdata(cooked) return True except: (exc_type, exc_value, exc_traceback) = sys.exc_info() AVNLog.debug("exception %s while decoding AIS data %s",exc_value,raw.strip()) return False