-
Notifications
You must be signed in to change notification settings - Fork 105
Open
Description
I have this old python 2 scratch code. It might be good to clean this up and add it as a contrib binary.
#!/usr/bin/env python
"""Find good test messages in AIS hub data.
Going to create some classes that tracking finding instances of each type of message that we would
like to have a test message for.
See also:
http://git.savannah.gnu.org/cgit/gpsd.git/tree/test/sample.aivdm
"""
import ais
import datetime
from pprint import pprint
import re
import sys
import Queue
# how do I define what a good set it?
# Want over range in all fields if possible
MMSI_LIST = (0, 1, 10, 99, 111, 1111, 10101, 111111, 123456, 1193046, 10101010,
10000000, 100000000, 111111111, 123456789, 999999999)
def AlmostEqual(a, b, percent = 0.1):
if abs(a) > abs(b):
delta = abs(a) * (percent * 1e-2)
if b > a + delta or b < a - delta:
return False
else:
delta = abs(b) * (percent * 1e-2)
if a > b + delta or a < b - delta:
return False
return True
def AisSplit(line):
fields = line.split(',')
if len(fields) == 9:
hdr, total, line_num, seq, chan, body, checksum, station, timestamp = fields
elif len(fields) > 9:
hdr, total, line_num, seq, chan, body, checksum = fields[:7]
timestamp = fields[-1]
station = 'runknown'
else:
print 'Wrong number of fields', len(fields)
print ' line str:', line
return None
if seq: seq = int(seq)
return {
'hdr': hdr,
'total': int(total),
'line_num': int(line_num),
'seq': int(seq) if seq else seq,
'chan': chan,
'body': body,
'checksum': checksum.split('*')[1],
'pad': int(checksum.split('*')[0]),
'station': station,
'timestamp': int(timestamp),
'raw': line.strip(),
}
class Normalize(Queue.Queue):
"""Single station AIS normalize"""
def __init__(self):
self.channels = {}
for chan in range(10):
self.channels[chan] = []
Queue.Queue.__init__(self)
def put(self, line_str, line_num=None):
if not isinstance(line_str, str): raise TypeError('Expect single lines')
line = AisSplit(line_str)
seq = line['seq']
if seq == '':
line['raw'] = [line['raw']] # always a list
Queue.Queue.put(self, line)
return
if line['line_num'] == 1:
self.channels[seq] = [line]
return
if line['line_num'] != line['total']:
self.channels[seq].append(line)
return
# Complete multi line
line['raw'] = [l['raw'] for l in self.channels[seq]] + [line['raw']]
if len(line['raw']) != line['total']:
self.channels[seq] = []
return
line['body'] = ''.join([l['body'] for l in self.channels[seq]]) + line['body']
line['total'] = 1
line['line_num'] = 1
self.channels[seq] = []
Queue.Queue.put(self, line)
def Sog(msg, s):
sog = msg['sog']
if sog == 0: s.add('sog_0')
elif sog > 5 and sog < 10: s.add('sog_low')
elif sog > 30 and sog < 50: s.add('sog_high')
elif sog > 50 and sog < 100: s.add('sog_crazy')
elif sog > 102.19 and sog < 102.21: s.add('sog_or_higher')
elif sog > 102.29 and sog < 102.31: s.add('sog_or_unknown')
def LonLat(msg, s, prefix=''):
x = msg['x']; y = msg['y']
# These are bad
if x > 180 and y < 90: s.add(prefix + 'x_undef')
if x < 180 and y > 90: s.add(prefix + 'y_undef')
# This is okay
if x > 180 and y > 90: s.add(prefix + 'xy_undef')
# All bad
if x < -180 and y > -90: s.add(prefix + 'x_neg_undef')
if x > -180 and y < -90: s.add(prefix + 'y_neg_undef')
if x < -180 and y < -90: s.add(prefix + 'xy_neg_undef')
if x == 0 and y == 0: s.add(prefix + 'x0_y0')
if x > 2 and x < 15:
if y > 2 and y < 15: s.add(prefix + 'x_low_y_low')
if y > 60 and y < 90: s.add(prefix + 'x_low_y_high')
if y < -2 and y > -15: s.add(prefix + 'x_low_y_neglow')
if y < -50 and y > -90: s.add(prefix + 'x_low_y_neghigh')
if x < -2 and x > -15:
if y > 2 and y < 15: s.add(prefix + 'x_neglow_y_low')
if y > 60 and y < 90: s.add(prefix + 'x_neglow_y_high')
if y < -2 and y > -15: s.add(prefix + 'x_neglow_y_neglow')
if y < -50 and y > -90: s.add(prefix + 'x_neglow_y_neghigh')
if x == -180: s.add(prefix + 'x_neg180') # Unlikely
if x == 180: s.add(prefix + 'x180') # Unlikely
if x <= -179 and x > -180:
if y > 2 and y < 15: s.add(prefix + 'x_neg179_y_low')
if y > 60 and y < 90: s.add(prefix + 'x_neg179_y_high')
if y < -2 and y > -15: s.add(prefix + 'x_neg179_y_neglow')
if y < -50 and y > -90: s.add(prefix + 'x_neg179_y_neghigh')
if x >= 179 and x < 180:
if y > 2 and y < 15: s.add(prefix + 'x_179_y_low')
if y > 60 and y < 90: s.add(prefix + 'x_179_y_high')
if y < -2 and y > -15: s.add(prefix + 'x_179_y_neglow')
if y < -50 and y > -90: s.add(prefix + 'x_179_y_neghigh')
if y == -90: s.add(prefix + 'y_neg90') # Unlikely
if y == 90: s.add(prefix + 'y90') # Unlikely
def Cog(msg, s):
cog = msg['cog'] # steps of 0.1
if cog == 0: s.add('cog0')
if cog > 9 and cog < 10: s.add('cog9_9') # has a decimal
if cog > 89.9 and cog <= 90: s.add('cog90')
if cog > 179.8 and cog <= 180: s.add('cog180')
if cog > 269.8 and cog <= 270: s.add('cog270')
if cog == 360: s.add('cog360')
if cog > 365: s.add('cogTooHigh')
def TrueHeading(msg, s):
th = msg['true_heading']
if th in (0, 90, 180, 270, 359): s.add('th%d' % th)
if th == 360: s.add('th_bad_360') # NOT valid
if th > 400 and th < 500: s.add('th_wonky')
if th == 511: s.add('th_na')
class Msg1(object):
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('ns_%d' % msg['nav_status'])
# +/- 708
rot = msg['rot']
if rot > 709: s.add('rot_over')
elif rot < -709: s.add('rot_under')
elif rot > 20 and rot < 100: s.add('rot_pos')
elif rot < -20 and rot > -100: s.add('rot_neg')
elif rot == 0: s.add('rot_0')
Sog(msg, s)
s.add('pa_%d' % msg['position_accuracy'])
LonLat(msg, s)
Cog(msg, s)
TrueHeading(msg,s)
# 61 is hard to find
ts = msg['timestamp']
if ts in (0,30,59,60,61,62,63): s.add('ts%d' % ts)
# 0,1,2. 3 is not valid
s.add('sm%d' % msg['special_manoeuvre'])
s.add('spare%d' % msg['spare'])
s.add('raim%d' % msg['raim'])
# SOTDMA
if msg['id'] in (1,2):
# 2 is hard to find
s.add('ss%d' % msg['sync_state'] )
s.add('sm%d' % msg['slot_timeout'])
if 'received_stations' in msg:
rs = msg['received_stations']
if rs in (0,1,5): s.add('rs%d' % rs)
if rs > 50 and rs < 100: s.add('rs_med')
if rs > 100 and rs < 500: s.add('rs_high')
if rs > 500 and rs < 1000: s.add('rs_very_high')
if rs > 1000 and rs < 15000: s.add('rs_insane')
if rs > 16000: s.add('rs_top')
if rs == 2**14-1: s.add('rs_max')
if 'slot_number' in msg:
sn = msg['slot_number']
if sn in (0,1,10,2248, 2249):
s.add('sn%d' % sn)
if sn > 2250: s.add('sn_too_high')
if 'utc_hour' in msg:
hr = msg['utc_hour']; mn = msg['utc_min']; u_spare = msg['utc_spare']
if hr in (0, 12, 23, 24, 31):
s.add('hr%d' % hr)
if hr > 24 and hr < 31: s.add('hr_over')
if mn in (0, 11, 59, 60, 127): s.add('mn%d' % mn)
if mn > 60 and mn < 127: s.add('mn_over')
s.add('utc_spare%d' % u_spare)
if 'slot_offset' in msg:
so = msg['slot_offset']
if so in (0,1, 2248, 2249, 2250, 2**14-2, 2**14-1):
s.add('so%d' % so)
if so > 2260 and so < 15000: s.add('so_too_high')
# ITDMA
if msg['id'] == 3:
# 2 is hard to find
s.add('itdma_ss%d' % msg['sync_state'])
slot_inc = msg['slot_increment']
if slot_inc in (0, 1, 2248, 2249, 2250, 8191): # last 2 not valid
s.add('slot_inc%d' % slot_inc)
s.add('nslots%d' % msg['slots_to_allocate'])
s.add('keep%d' % msg['keep_flag'])
return len(s) - s_len_begin > 0
class Msg4(object):
def __init__(self):
self.states = set()
self.key_set = set()
self.now = datetime.datetime.utcnow()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
s.add('repeat%d' % msg['repeat_indicator'])
s.add('year%d' % msg['year'])
if msg['month'] in (0,1,12,13,15): s.add('mon%d' % msg['month'])
if msg['day'] in (0,1,15,31): s.add('day%d' % msg['day'])
if msg['hour'] in (0,12,23,24,25,31): s.add('hr%d' % msg['hour'])
if msg['minute'] in (0,1,59,60,61,63): s.add('mn%d' % msg['minute'])
if msg['second'] in (0,1,59,60,61,63): s.add('sec%d' % msg['second'])
s.add('pa_%d' % msg['position_accuracy'])
LonLat(msg, s)
s.add('ft%d' % msg['fix_type'])
# TODO: Transmission control for long-range broadcast message
s.add('transmission_ctl_%d' % msg['transmission_ctl'])
spare = msg['spare']
if not spare: s.add('spare0')
if spare > 0 and spare < 2**9-1: s.add('spare_invalid')
if spare == 2**9-1: s.add('spare_max')
s.add('raim_%d' % msg['raim'])
Sotdma(msg, s)
return len(s) - s_len_begin > 0
def TrimAisStr(a_str):
at_pos = a_str.find('@')
if -1 == at_pos: return a_str
return a_str[:at_pos]
def Name(msg, s, length = 20):
name_raw = msg['name']
name = TrimAisStr(name_raw)
if len(name) == length / 2:
s.add('namelen%d'%len(name))
if len(name) < 4 or len(name) > length - 4:
s.add('namelen%d'%len(name))
if name_raw.count('@') < 4 or name_raw.count('@') > length - 4:
s.add('name@cnt%d' % name_raw.count('@'))
if re.search(r'[^ @]+@+\W+', name_raw): s.add('name_space_after@')
# #$&(+,-.0123456789:;<=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\ Careful with the last slash
for c in r'#$&(+,-.0189:;<=?@AB YZ\\':
if c in name: s.add('name_%s' % c)
def Dim(msg, s):
for c in 'abcd':
dim = msg['dim_%s' % c]
sizes = [0,1,30,63]
if c in 'ab': sizes.append(511)
if dim in sizes: s.add('dim_%s_%d' % (c, dim))
class Msg5(object):
def __init__(self):
self.states = set()
self.key_set = set()
self.now = datetime.datetime.utcnow()
self.junk = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
mmsi = msg['mmsi']
if mmsi in MMSI_LIST: s.add('mmsi%d' % mmsi)
s.add('repeat%d' % msg['repeat_indicator'])
s.add('ver%d' % msg['ais_version'])
if 1:
imo = msg['imo_num']
if imo in (0,1,int(1e9), 123456789, 999999998,999999999):
s.add('imo%d' % imo)
if imo > 200000000 and imo < 800000000: s.add('imo_9dig')
if imo > 20000000 and imo < 80000000: s.add('imo_8dig')
if imo > 2000000 and imo < 8000000: s.add('imo_7dig')
if imo > 200000 and imo < 800000: s.add('imo_6dig')
if imo > 20000 and imo < 80000: s.add('imo_5dig')
if imo > 2000 and imo < 8000: s.add('imo_4dig')
if imo > 200 and imo < 800: s.add('imo_3dig')
if imo > 20 and imo < 80: s.add('imo_2dig')
if imo > 2 and imo < 8: s.add('imo_1dig')
if 1:
call_raw = msg['callsign']
call = TrimAisStr(call_raw)
s.add('calllen%d'%len(call))
s.add('call@cnt%d' % call_raw.count('@'))
if re.search(r'[^ @]+@+\W+', call_raw): s.add('call_space_after@')
# #$&(+,-.0123456789:;<=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\ Careful with the last slash
for c in r'#$&(+,-.0189:;<=?@AB YZ\\':
if c in call: s.add('imo_%s' % c)
Name(msg, s)
s.add('tc%d' % msg['type_and_cargo'])
Dim(msg, s)
s.add('ft%d' % msg['fix_type'])
mon = msg['eta_month']; day = msg['eta_day']
hr = msg['eta_hour']; mn = msg['eta_minute']
if mon in (0,1,12,13,15): s.add('mon%d' % mon)
if day in (0,1,15,31): s.add('day%d' % day)
if hr in (0, 12, 23, 24, 31): s.add('hr%d' % hr)
if hr > 24 and hr < 31: s.add('hr_over')
if mn in (0, 11, 59, 60, 127): s.add('mn%d' % mn)
if mn > 60 and mn < 127: s.add('mn_over')
dr = msg['draught']
for val in (0.0, 0.1, 12.4, 25.5):
if AlmostEqual(dr, val): s.add('dr%.1f' % val)
dest_raw = msg['destination']
dest = TrimAisStr(dest_raw)
if len(dest) < 4 or len(dest) > 16:
s.add('destlen%d'%len(dest))
if dest_raw.count('@') < 4 or dest_raw.count('@') > 16:
s.add('dest@cnt%d' % dest_raw.count('@'))
if re.search(r'[^ @]+@+\W+', dest_raw): s.add('dest_space_after@')
for c in r'#$&(+,-.0189:;<=?@AB YZ\\':
if c in dest: s.add('dest_%s' % c)
s.add('dte%d' % msg['dte'])
s.add('spare%d' % msg['spare'])
return len(s) - s_len_begin > 0
def AisString(msg, s, str_name, length = 20, prefix=''):
if prefix: prefix = prefix + '_'
name_raw = msg[str_name]
name = TrimAisStr(name_raw)
if len(name) == length / 2:
s.add(prefix+'namelen%d'%len(name))
if len(name) < 4 or len(name) > length - 4:
s.add(prefix+'namelen%d'%len(name))
if name_raw.count('@') < 4 or name_raw.count('@') > length - 4:
s.add(prefix+'name@cnt%d' % name_raw.count('@'))
if re.search(r'[^ @]+@+\W+', name_raw): s.add(prefix+'name_space_after@')
# #$&(+,-.0123456789:;<=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\ Careful with the last slash
for c in r'#$&(+,-.0189:;<=?@AB YZ\\':
if c in name: s.add(prefix+'name_%s' % c)
class Msg6(object):
def __init__(self):
self.states = set()
self.key_set = set()
#self.now = datetime.datetime.utcnow()
#self.junk = set()
#self.dacs = {1: Msg6Dac1()}
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
#if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
#s.add('repeat%d' % msg['repeat_indicator'])
#s.add('dac%d_fi%d' % (msg['dac'], msg['fi']))
#s.add('seq%d' % msg['seq'])
#s.add('spare%d' % msg['spare'])
#dac = msg['dac']
#if dac not in self.dacs: return len(s) - s_len_begin > 0
# retransmit
dac = msg['dac']
fi = msg['fi']
if 1 == dac:
if 0 == fi:
s.add('m6_%d_%d_ack_required_%s' % (dac, fi, msg['ack_required']))
if msg['msg_seq'] < 10 or msg['msg_seq'] > (2**11-10):
s.add('m6_%d_%d_msg_seq_%s' % (dac, fi, msg['msg_seq']))
AisString(msg, s, 'text', length=154, prefix='m6_%d_%d_text' % (dac, fi))
s.add('m6_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
if 1 == fi:
s.add('m6_%d_%d_ack_dac_%s' % (dac, fi, msg['ack_dac']))
if msg['msg_seq'] < 10 or msg['msg_seq'] > (2**11-10):
s.add('m6_%d_%d_msg_seq_%s' % (dac, fi, msg['msg_seq']))
s.add('m6_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
if 2 == fi:
s.add('m6_%d_%d_req_dac_%s' % (dac, fi, msg['req_dac']))
s.add('m6_%d_%d_req_fi_%s' % (dac, fi, msg['req_fi']))
if 3 == fi:
s.add('m6_%d_%d_req_dac_%s' % (dac, fi, msg['req_dac']))
s.add('m6_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
if 4 == fi and 'ack_dac' in msg:
s.add('m6_%d_%d_ack_dac_%s' % (dac, fi, msg['ack_dac']))
# TODO: check all the bits of the bloody array
s.add('m6_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
if 12 == fi and 'imo_cat' in msg:
# TODO: no messages yet found that work
AisString(msg, s, 'last_port', length=154, prefix='m6_%d_%d_last_port' % (dac, fi))
s.add('m6_%d_%d_utc_month_dep_%s' % (dac, fi, msg['utc_month_dep']))
s.add('m6_%d_%d_utc_day_dep_%s' % (dac, fi, msg['utc_day_dep']))
s.add('m6_%d_%d_utc_hour_dep_%s' % (dac, fi, msg['utc_hour_dep']))
s.add('m6_%d_%d_utc_min_dep_%s' % (dac, fi, msg['utc_min_dep']))
AisString(msg, s, 'next_port', length=154, prefix='m6_%d_%d_next_port' % (dac, fi))
s.add('m6_%d_%d_utc_month_next_%s' % (dac, fi, msg['utc_month_next']))
s.add('m6_%d_%d_utc_day_next_%s' % (dac, fi, msg['utc_day_next']))
s.add('m6_%d_%d_utc_hour_next_%s' % (dac, fi, msg['utc_hour_next']))
s.add('m6_%d_%d_utc_min_next_%s' % (dac, fi, msg['utc_min_next']))
s.add('m6_%d_%d_main_danger_%s' % (dac, fi, msg['main_danger']))
s.add('m6_%d_%d_imo_cat_%s' % (dac, fi, msg['imo_cat']))
s.add('m6_%d_%d_un_%s' % (dac, fi, msg['un']))
s.add('m6_%d_%d_value_%s' % (dac, fi, msg['value']))
s.add('m6_%d_%d_value_unit_%s' % (dac, fi, msg['value_unit']))
s.add('m6_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
if 14 == fi and 'x' in msg:
LonLat(msg, s, prefix='m6_%d_%d_' % (dac, fi))
s.add('m6_%d_%d_utc_hour_from_%s' % (dac, fi, msg['utc_hour_from']))
s.add('m6_%d_%d_utc_min_from_%s' % (dac, fi, msg['utc_min_from']))
s.add('m6_%d_%d_utc_hour_to_%s' % (dac, fi, msg['utc_hour_to']))
s.add('m6_%d_%d_utc_min_to_%s' % (dac, fi, msg['utc_min_to']))
s.add('m6_%d_%d_cur_dir_%s' % (dac, fi, msg['cur_dir']))
s.add('m6_%d_%d_cur_speed_%s' % (dac, fi, msg['cur_speed']))
if 18 == fi:
# IMO Circ 289
LonLat(msg, s, prefix='m6_%d_%d_' % (dac, fi))
s.add('m6_%d_%d_link_id_%s' % (dac, fi, msg['link_id']))
s.add('m6_%d_%d_utc_month_%s' % (dac, fi, msg['utc_month']))
s.add('m6_%d_%d_utc_day_%s' % (dac, fi, msg['utc_day']))
s.add('m6_%d_%d_utc_hour_%s' % (dac, fi, msg['utc_hour']))
s.add('m6_%d_%d_utc_min_%s' % (dac, fi, msg['utc_min']))
AisString(msg, s, 'port_berth', length=20, prefix='m6_%d_%d_port' % (dac, fi))
AisString(msg, s, 'dest', length=5, prefix='m6_%d_%d_dest' % (dac, fi))
# TODO focus spare2
s.add('m6_%d_%d_spare2_0_%s' % (dac, fi, msg['spare2_0']))
s.add('m6_%d_%d_spare2_1_%s' % (dac, fi, msg['spare2_1']))
if 20 == fi and 'link_id' in msg:
s.add('m6_%d_%d_link_id_%s' % (dac, fi, msg['link_id']))
s.add('m6_%d_%d_length_%s' % (dac, fi, msg['length']))
s.add('m6_%d_%d_depth_%s' % (dac, fi, msg['depth']))
s.add('m6_%d_%d_position_%s' % (dac, fi, msg['position']))
s.add('m6_%d_%d_utc_month_%s' % (dac, fi, msg['utc_month']))
s.add('m6_%d_%d_utc_day_%s' % (dac, fi, msg['utc_day']))
s.add('m6_%d_%d_utc_hour_%s' % (dac, fi, msg['utc_hour']))
s.add('m6_%d_%d_utc_min_%s' % (dac, fi, msg['utc_min']))
for i in range(26):
s.add('m6_%d_%d_services%d_%s' % (dac, fi, i, msg['services'][i]))
AisString(msg, s, 'name', length=20, prefix='m6_%d_%d_name' % (dac, fi))
if 20 == fi and 'amount' in msg:
s.add('m6_%d_%d_amount_unit_%s' % (dac, fi, msg['amount_unit']))
s.add('m6_%d_%d_amount_%s' % (dac, fi, msg['amount']))
for cargo in msg['cargos']:
if 'imdg' in cargo: s.add('m6_%d_%d_imdg_%s' % (dac, fi, msg['imdg']))
if 'spare' in cargo: s.add('m6_%d_%d_spare_%s' % (dac, fi, msg['spare']))
if 'un' in cargo: s.add('m6_%d_%d_un_%s' % (dac, fi, msg['un']))
if 'bc' in cargo: s.add('m6_%d_%d_bc_%s' % (dac, fi, msg['bc']))
if 'marpol_oil' in cargo: s.add('m6_%d_%d_marpol_oil_%s' % (dac, fi, msg['marpol_oil']))
if 'marpol_cat' in cargo: s.add('m6_%d_%d_marpol_cat_%s' % (dac, fi, msg['marpol_cat']))
# TODO: 28 Route
# TODO: 30 Addressed Text
if 32 == fi and 'utc_month' in msg:
s.add('m6_%d_%d_utc_month_%s' % (dac, fi, msg['utc_month']))
s.add('m6_%d_%d_utc_day_%s' % (dac, fi, msg['utc_day']))
for win_num, window in enumerate(msg['windows']):
LonLat(msg, s, prefix='m6_%d_%d_window%d' % (dac, fi, win_num))
s.add('m6_%d_%d_from_utc_hour_%s' % (dac, fi, msg['from_utc_hour']))
s.add('m6_%d_%d_from_utc_min_%s' % (dac, fi, msg['from_utc_min']))
s.add('m6_%d_%d_to_utc_hour_%s' % (dac, fi, msg['to_utc_hour']))
s.add('m6_%d_%d_to_utc_min_%s' % (dac, fi, msg['to_utc_min']))
s.add('m6_%d_%d_cur_dir_%s' % (dac, fi, msg['cur_dir']))
s.add('m6_%d_%d_cur_speed_%s' % (dac, fi, msg['cur_speed']))
if 40 == fi:
s.add('m6_%d_%d_persons_%s' % (dac, fi, msg['persons']))
# TODO: check all the bits of the bloody array
s.add('m6_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
# s.add('m6_%d_%d__%s' % (dac, fi, msg['']))
return len(s) - s_len_begin > 0
class Msg7_13(object):
def __init__(self):
self.states = set()
self.key_set = set()
self.now = datetime.datetime.utcnow()
self.junk = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('ack_len%d' % len(msg['acks']))
for i in range(len(msg['acks'])):
s.add('ack_seq_%d_%d' % (i, msg['acks'][i][1]))
return len(s) - s_len_begin > 0
######################################################################
# 8... this is complicated
class Msg8(object):
def __init__(self):
self.states = set()
self.key_set = set()
self.now = datetime.datetime.utcnow()
self.junk = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('dac%d_fi%d' % (msg['dac'], msg['fi']))
dac = msg['dac']
fi = msg['fi']
if 1 == dac:
if 0 == fi and 'text' in msg:
s.add('m8_%d_%d_ack_required_%s' % (dac, fi, msg['ack_required']))
if msg['msg_seq'] < 10 or msg['msg_seq'] > (2**11-10):
s.add('m8_%d_%d_msg_seq_%s' % (dac, fi, msg['msg_seq']))
AisString(msg, s, 'text', length=154, prefix='m8_%d_%d_text' % (dac, fi)) # TODO: length bits or characters?
s.add('m8_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
if 11 == fi and 'x' in msg:
LonLat(msg, s, prefix='m8_%d_%d_' % (dac, fi))
# TODO: limit most of these
s.add('m8_%d_%d_wind_ave_%s' % (dac, fi, msg['wind_ave']))
s.add('m8_%d_%d_wind_gust_%s' % (dac, fi, msg['wind_gust']))
s.add('m8_%d_%d_wind_dir_%s' % (dac, fi, msg['wind_dir']))
s.add('m8_%d_%d_wind_gust_dir_%s' % (dac, fi, msg['wind_gust_dir']))
s.add('m8_%d_%d_air_temp_%s' % (dac, fi, msg['air_temp']))
s.add('m8_%d_%d_rel_humid_%s' % (dac, fi, msg['rel_humid']))
s.add('m8_%d_%d_dew_point_%s' % (dac, fi, msg['dew_point']))
s.add('m8_%d_%d_air_pres_%s' % (dac, fi, msg['air_pres']))
s.add('m8_%d_%d_air_pres_trend_%s' % (dac, fi, msg['air_pres_trend']))
s.add('m8_%d_%d_horz_vis_%s' % (dac, fi, msg['horz_vis']))
s.add('m8_%d_%d_water_level_%s' % (dac, fi, msg['water_level']))
s.add('m8_%d_%d_water_level_trend_%s' % (dac, fi, msg['water_level_trend']))
s.add('m8_%d_%d_surf_cur_speed_%s' % (dac, fi, msg['surf_cur_speed']))
s.add('m8_%d_%d_surf_cur_dir_%s' % (dac, fi, msg['surf_cur_dir']))
s.add('m8_%d_%d_cur_speed_2_%s' % (dac, fi, msg['cur_speed_2']))
s.add('m8_%d_%d_cur_dir_2_%s' % (dac, fi, msg['cur_dir_2']))
s.add('m8_%d_%d_cur_depth_2_%s' % (dac, fi, msg['cur_depth_2']))
s.add('m8_%d_%d_cur_speed_3_%s' % (dac, fi, msg['cur_speed_3']))
s.add('m8_%d_%d_cur_dir_3_%s' % (dac, fi, msg['cur_dir_3']))
s.add('m8_%d_%d_cur_depth_3_%s' % (dac, fi, msg['cur_depth_3']))
s.add('m8_%d_%d_wave_height_%s' % (dac, fi, msg['wave_height']))
s.add('m8_%d_%d_wave_period_%s' % (dac, fi, msg['wave_period']))
s.add('m8_%d_%d_wave_dir_%s' % (dac, fi, msg['wave_dir']))
s.add('m8_%d_%d_swell_height_%s' % (dac, fi, msg['swell_height']))
s.add('m8_%d_%d_swell_period_%s' % (dac, fi, msg['swell_period']))
s.add('m8_%d_%d_swell_dir_%s' % (dac, fi, msg['swell_dir']))
s.add('m8_%d_%d_sea_state_%s' % (dac, fi, msg['sea_state']))
s.add('m8_%d_%d_water_temp_%s' % (dac, fi, msg['water_temp']))
s.add('m8_%d_%d_precip_type_%s' % (dac, fi, msg['precip_type']))
s.add('m8_%d_%d_ice_%s' % (dac, fi, msg['ice']))
s.add('m8_%d_%d_ext_water_level_%s' % (dac, fi, msg['ext_water_level']))
s.add('m8_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
if 13 == fi and 'spare2' in msg:
# TODO: cleanup many of these have wide ranges
s.add('m8_%d_%d_reason_%s' % (dac, fi, msg['reason']))
s.add('m8_%d_%d_location_from_%s' % (dac, fi, msg['location_from']))
s.add('m8_%d_%d_location_to_%s' % (dac, fi, msg['location_to']))
s.add('m8_%d_%d_radius_%s' % (dac, fi, msg['radius']))
s.add('m8_%d_%d_units_%s' % (dac, fi, msg['units']))
s.add('m8_%d_%d_day_from_%s' % (dac, fi, msg['day_from']))
s.add('m8_%d_%d_month_from_%s' % (dac, fi, msg['month_from']))
s.add('m8_%d_%d_hour_from_%s' % (dac, fi, msg['hour_from']))
s.add('m8_%d_%d_minute_from_%s' % (dac, fi, msg['minute_from']))
s.add('m8_%d_%d_day_to_%s' % (dac, fi, msg['day_to']))
s.add('m8_%d_%d_month_to_%s' % (dac, fi, msg['month_to']))
s.add('m8_%d_%d_hour_to_%s' % (dac, fi, msg['hour_to']))
s.add('m8_%d_%d_minute_to_%s' % (dac, fi, msg['minute_to']))
s.add('m8_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
if 15 == fi and 'spare2' in msg:
# TODO: untested
s.add('m8_%d_%d_air_draught_%s' % (dac, fi, msg['air_draught']))
s.add('m8_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
if 16 == fi and 'spare2' in msg:
s.add('m8_%d_%d_persons_%s' % (dac, fi, msg['persons']))
s.add('m8_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
if 17 == fi and 'targets' in msg:
# TODO: untested
for target_num, target in enumerate(msg['targets']):
LonLat(msg, s, prefix='m8_%d_%d_%d' % (dac, fi, target_num))
s.add('m8_%d_%d_type_%s' % (dac, fi, msg['type']))
s.add('m8_%d_%d_id_%s' % (dac, fi, msg['id']))
s.add('m8_%d_%d_spare_%s' % (dac, fi, msg['spare']))
s.add('m8_%d_%d_cog_%s' % (dac, fi, msg['cog']))
s.add('m8_%d_%d_timestamp_%s' % (dac, fi, msg['timestamp']))
s.add('m8_%d_%d_sog_%s' % (dac, fi, msg['sog']))
if 19 == fi and 'link_id' in msg:
LonLat(msg, s, prefix='m8_%d_%d' % (dac, fi))
s.add('m8_%d_%d_link_id_%s' % (dac, fi, msg['link_id']))
s.add('m8_%d_%d_name_%s' % (dac, fi, msg['name']))
s.add('m8_%d_%d_status_%s' % (dac, fi, msg['status']))
s.add('m8_%d_%d_signal_%s' % (dac, fi, msg['signal']))
s.add('m8_%d_%d_utc_hour_next_%s' % (dac, fi, msg['utc_hour_next']))
s.add('m8_%d_%d_utc_min_next_%s' % (dac, fi, msg['utc_min_next']))
s.add('m8_%d_%d_next_signal_%s' % (dac, fi, msg['next_signal']))
s.add('m8_%d_%d_spare2_0_%s' % (dac, fi, msg['spare2_0']))
s.add('m8_%d_%d_spare2_1_%s' % (dac, fi, msg['spare2_1']))
s.add('m8_%d_%d_spare2_2_%s' % (dac, fi, msg['spare2_2']))
s.add('m8_%d_%d_spare2_3_%s' % (dac, fi, msg['spare2_3']))
if 21 == fi and 'x' in msg:
LonLat(msg, s, prefix='m8_%d_%d' % (dac, fi))
# TODO: remove duplicates and limit what we are saving for each.
if 'utc_month' in msg: s.add('m8_%d_%d_utc_month_%s' % (dac, fi, msg['utc_month']))
if 'utc_day' in msg: s.add('m8_%d_%d_utc_day_%s' % (dac, fi, msg['utc_day']))
if 'utc_hour' in msg: s.add('m8_%d_%d_utc_hour_%s' % (dac, fi, msg['utc_hour']))
if 'utc_min' in msg: s.add('m8_%d_%d_utc_min_%s' % (dac, fi, msg['utc_min']))
if 'location' in msg: s.add('m8_%d_%d_location_%s' % (dac, fi, msg['location']))
if 'wx' in msg: s.add('m8_%d_%d_wx_%s' % (dac, fi, msg['wx']))
if 'horz_viz' in msg: s.add('m8_%d_%d_horz_viz_%s' % (dac, fi, msg['horz_viz']))
if 'humidity' in msg: s.add('m8_%d_%d_humidity_%s' % (dac, fi, msg['humidity']))
if 'wind_speed' in msg: s.add('m8_%d_%d_wind_speed_%s' % (dac, fi, msg['wind_speed']))
if 'wind_dir' in msg: s.add('m8_%d_%d_wind_dir_%s' % (dac, fi, msg['wind_dir']))
if 'pressure' in msg: s.add('m8_%d_%d_pressure_%s' % (dac, fi, msg['pressure']))
if 'pressure_tendency' in msg: s.add('m8_%d_%d_pressure_tendency_%s' % (dac, fi, msg['pressure_tendency']))
if 'air_temp' in msg: s.add('m8_%d_%d_air_temp_%s' % (dac, fi, msg['air_temp']))
if 'water_temp' in msg: s.add('m8_%d_%d_water_temp_%s' % (dac, fi, msg['water_temp']))
if 'wave_period' in msg: s.add('m8_%d_%d_wave_period_%s' % (dac, fi, msg['wave_period']))
if 'wave_height' in msg: s.add('m8_%d_%d_wave_height_%s' % (dac, fi, msg['wave_height']))
if 'wave_dir' in msg: s.add('m8_%d_%d_wave_dir_%s' % (dac, fi, msg['wave_dir']))
if 'swell_height' in msg: s.add('m8_%d_%d_swell_height_%s' % (dac, fi, msg['swell_height']))
if 'swell_dir' in msg: s.add('m8_%d_%d_swell_dir_%s' % (dac, fi, msg['swell_dir']))
if 'swell_period' in msg: s.add('m8_%d_%d_swell_period_%s' % (dac, fi, msg['swell_period']))
if 'spare2' in msg: s.add('m8_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
if 'cog' in msg: s.add('m8_%d_%d_cog_%s' % (dac, fi, msg['cog']))
if 'sog' in msg: s.add('m8_%d_%d_sog_%s' % (dac, fi, msg['sog']))
if 'heading' in msg: s.add('m8_%d_%d_heading_%s' % (dac, fi, msg['heading']))
if 'pressure", msg.pressure);' in msg: s.add('m8_%d_%d_pressure", msg.pressure);_%s' % (dac, fi, msg['pressure", msg.pressure);']))
if 'rel_pressure' in msg: s.add('m8_%d_%d_rel_pressure_%s' % (dac, fi, msg['rel_pressure']))
if 'pressure_tendency' in msg: s.add('m8_%d_%d_pressure_tendency_%s' % (dac, fi, msg['pressure_tendency']))
if 'wind_dir' in msg: s.add('m8_%d_%d_wind_dir_%s' % (dac, fi, msg['wind_dir']))
if 'wind_speed_ms' in msg: s.add('m8_%d_%d_wind_speed_ms_%s' % (dac, fi, msg['wind_speed_ms']))
if 'wind_dir_rel' in msg: s.add('m8_%d_%d_wind_dir_rel_%s' % (dac, fi, msg['wind_dir_rel']))
if 'wind_speed_rel' in msg: s.add('m8_%d_%d_wind_speed_rel_%s' % (dac, fi, msg['wind_speed_rel']))
if 'wind_gust_speed' in msg: s.add('m8_%d_%d_wind_gust_speed_%s' % (dac, fi, msg['wind_gust_speed']))
if 'wind_gust_dir' in msg: s.add('m8_%d_%d_wind_gust_dir_%s' % (dac, fi, msg['wind_gust_dir']))
if 'air_temp_raw' in msg: s.add('m8_%d_%d_air_temp_raw_%s' % (dac, fi, msg['air_temp_raw']))
if 'humidity' in msg: s.add('m8_%d_%d_humidity_%s' % (dac, fi, msg['humidity']))
if 'water_temp_raw' in msg: s.add('m8_%d_%d_water_temp_raw_%s' % (dac, fi, msg['water_temp_raw']))
if 'horz_viz' in msg: s.add('m8_%d_%d_horz_viz_%s' % (dac, fi, msg['horz_viz']))
if 'wx' in msg: s.add('m8_%d_%d_wx_%s' % (dac, fi, msg['wx']))
if 'wx_next1' in msg: s.add('m8_%d_%d_wx_next1_%s' % (dac, fi, msg['wx_next1']))
if 'wx_next2' in msg: s.add('m8_%d_%d_wx_next2_%s' % (dac, fi, msg['wx_next2']))
if 'cloud_total' in msg: s.add('m8_%d_%d_cloud_total_%s' % (dac, fi, msg['cloud_total']))
if 'cloud_low' in msg: s.add('m8_%d_%d_cloud_low_%s' % (dac, fi, msg['cloud_low']))
if 'cloud_low_type' in msg: s.add('m8_%d_%d_cloud_low_type_%s' % (dac, fi, msg['cloud_low_type']))
if 'cloud_middle_type' in msg: s.add('m8_%d_%d_cloud_middle_type_%s' % (dac, fi, msg['cloud_middle_type']))
if 'cloud_high_type' in msg: s.add('m8_%d_%d_cloud_high_type_%s' % (dac, fi, msg['cloud_high_type']))
if 'alt_lowest_cloud_base' in msg: s.add('m8_%d_%d_alt_lowest_cloud_base_%s' % (dac, fi, msg['alt_lowest_cloud_base']))
if 'wave_period' in msg: s.add('m8_%d_%d_wave_period_%s' % (dac, fi, msg['wave_period']))
if 'wave_height' in msg: s.add('m8_%d_%d_wave_height_%s' % (dac, fi, msg['wave_height']))
if 'swell_dir' in msg: s.add('m8_%d_%d_swell_dir_%s' % (dac, fi, msg['swell_dir']))
if 'swell_period' in msg: s.add('m8_%d_%d_swell_period_%s' % (dac, fi, msg['swell_period']))
if 'swell_height' in msg: s.add('m8_%d_%d_swell_height_%s' % (dac, fi, msg['swell_height']))
if 'swell_dir_2' in msg: s.add('m8_%d_%d_swell_dir_2_%s' % (dac, fi, msg['swell_dir_2']))
if 'swell_period_2' in msg: s.add('m8_%d_%d_swell_period_2_%s' % (dac, fi, msg['swell_period_2']))
if 'swell_height_2' in msg: s.add('m8_%d_%d_swell_height_2_%s' % (dac, fi, msg['swell_height_2']))
if 'ice_thickness' in msg: s.add('m8_%d_%d_ice_thickness_%s' % (dac, fi, msg['ice_thickness']))
if 'ice_accretion' in msg: s.add('m8_%d_%d_ice_accretion_%s' % (dac, fi, msg['ice_accretion']))
if 'ice_accretion_cause' in msg: s.add('m8_%d_%d_ice_accretion_cause_%s' % (dac, fi, msg['ice_accretion_cause']))
if 'sea_ice_concentration' in msg: s.add('m8_%d_%d_sea_ice_concentration_%s' % (dac, fi, msg['sea_ice_concentration']))
if 'amt_type_ice' in msg: s.add('m8_%d_%d_amt_type_ice_%s' % (dac, fi, msg['amt_type_ice']))
if 'ice_situation' in msg: s.add('m8_%d_%d_ice_situation_%s' % (dac, fi, msg['ice_situation']))
if 'ice_devel' in msg: s.add('m8_%d_%d_ice_devel_%s' % (dac, fi, msg['ice_devel']))
if 'bearing_ice_edge' in msg: s.add('m8_%d_%d_bearing_ice_edge_%s' % (dac, fi, msg['bearing_ice_edge']))
if 22 == fi and 'link_id' in msg:
# TODO: not yet tested
s.add('m8_%d_%d_link_id_%s' % (dac, fi, msg['link_id']))
s.add('m8_%d_%d_notice_type_%s' % (dac, fi, msg['notice_type']))
s.add('m8_%d_%d_month_%s' % (dac, fi, msg['month']))
s.add('m8_%d_%d_day_%s' % (dac, fi, msg['day']))
s.add('m8_%d_%d_hour_%s' % (dac, fi, msg['hour']))
s.add('m8_%d_%d_minute_%s' % (dac, fi, msg['minute']))
if 24 == fi and 'link_id' in msg:
# TODO not yet tested - no messages found
for item_num, item in msg['solas']:
s.add('m8_%d_%d_link_id_%s' % (dac, fi, msg['link_id']))
s.add('m8_%d_%d_air_draught_%s' % (dac, fi, msg['air_draught']))
s.add('m8_%d_%d_last_port_%s' % (dac, fi, msg['last_port'])) # TODO: string
s.add('m8_%d_%d_next_port_0_%s' % (dac, fi, msg['next_port'][0])) # TODO: string
s.add('m8_%d_%d_next_port_1_%s' % (dac, fi, msg['next_port'][1])) # TODO: string
for solas_num in range(26):
s.add('m8_%d_%d_solas_%d_%d' % (dac, fi, item_num, msg['solas'][item_num]))
s.add('m8_%d_%d_ice_class_%s' % (dac, fi, msg['ice_class']))
s.add('m8_%d_%d_shaft_power_%s' % (dac, fi, msg['shaft_power']))
s.add('m8_%d_%d_vhf_%s' % (dac, fi, msg['vhf']))
s.add('m8_%d_%d_lloyds_ship_type_%s' % (dac, fi, msg['lloyds_ship_type']))
s.add('m8_%d_%d_gross_tonnage_%s' % (dac, fi, msg['gross_tonnage']))
s.add('m8_%d_%d_laden_ballast_%s' % (dac, fi, msg['laden_ballast']))
s.add('m8_%d_%d_heavy_oil_%s' % (dac, fi, msg['heavy_oil']))
s.add('m8_%d_%d_light_oil_%s' % (dac, fi, msg['light_oil']))
s.add('m8_%d_%d_diesel_%s' % (dac, fi, msg['diesel']))
s.add('m8_%d_%d_bunker_oil_%s' % (dac, fi, msg['bunker_oil']))
s.add('m8_%d_%d_persons_%s' % (dac, fi, msg['persons']))
s.add('m8_%d_%d_spare2_%s' % (dac, fi, msg['spare2']))
if 26 == fi: # and 'link_id' in msg:
# TODO not yet tested
if 27 == fi and 'link_id' in msg:
# TODO not yet tested - no messages found
s.add('m8_%d_%d_link_id_%s' % (dac, fi, msg['link_id']))
s.add('m8_%d_%d_sender_type_%s' % (dac, fi, msg['sender_type']))
s.add('m8_%d_%d_route_type_%s' % (dac, fi, msg['route_type']))
s.add('m8_%d_%d_utc_month_%s' % (dac, fi, msg['utc_month']))
s.add('m8_%d_%d_utc_day_%s' % (dac, fi, msg['utc_day']))
s.add('m8_%d_%d_utc_hour_%s' % (dac, fi, msg['utc_hour']))
s.add('m8_%d_%d_utc_min_%s' % (dac, fi, msg['utc_min']))
s.add('m8_%d_%d_duration_%s' % (dac, fi, msg['duration']))
for waypt_num, waypt in msg['waypoints']:
waypt_msg = {'x': waypt[0], 'y': waypt[1]}
LonLat(waypt_msg, s, prefix='m8_%d_%d_%d' % (dac, fi, waypt_num))
if 29 == fi and 'link_id' in msg:
s.add('m8_%d_%d_link_id_%s' % (dac, fi, msg['link_id']))
AisString(msg, s, 'text', length=161, prefix='m8_%d_%d_text' % (dac, fi))
if 31 == fi and 'x' in msg:
LonLat(msg, s, prefix='m8_%d_%d_' % (dac, fi))
# TODO: limit a lot of these...
s.add('m8_%d_%d_position_accuracy_%s' % (dac, fi, msg['position_accuracy']))
s.add('m8_%d_%d_utc_day_%s' % (dac, fi, msg['utc_day']))
s.add('m8_%d_%d_utc_hour_%s' % (dac, fi, msg['utc_hour']))
s.add('m8_%d_%d_utc_min_%s' % (dac, fi, msg['utc_min']))
s.add('m8_%d_%d_wind_ave_%s' % (dac, fi, msg['wind_ave']))
s.add('m8_%d_%d_wind_gust_%s' % (dac, fi, msg['wind_gust']))
s.add('m8_%d_%d_wind_dir_%s' % (dac, fi, msg['wind_dir']))
s.add('m8_%d_%d_wind_gust_dir_%s' % (dac, fi, msg['wind_gust_dir']))
s.add('m8_%d_%d_air_temp_%s' % (dac, fi, msg['air_temp']))
s.add('m8_%d_%d_rel_humid_%s' % (dac, fi, msg['rel_humid']))
s.add('m8_%d_%d_dew_point_%s' % (dac, fi, msg['dew_point']))
s.add('m8_%d_%d_air_pres_%s' % (dac, fi, msg['air_pres']))
s.add('m8_%d_%d_air_pres_trend_%s' % (dac, fi, msg['air_pres_trend']))
s.add('m8_%d_%d_horz_vis_%s' % (dac, fi, msg['horz_vis']))
s.add('m8_%d_%d_water_level_%s' % (dac, fi, msg['water_level']))
s.add('m8_%d_%d_water_level_trend_%s' % (dac, fi, msg['water_level_trend']))
s.add('m8_%d_%d_surf_cur_speed_%s' % (dac, fi, msg['surf_cur_speed']))
s.add('m8_%d_%d_surf_cur_dir_%s' % (dac, fi, msg['surf_cur_dir']))
s.add('m8_%d_%d_cur_speed_2_%s' % (dac, fi, msg['cur_speed_2']))
s.add('m8_%d_%d_cur_dir_2_%s' % (dac, fi, msg['cur_dir_2']))
s.add('m8_%d_%d_cur_depth_2_%s' % (dac, fi, msg['cur_depth_2']))
s.add('m8_%d_%d_cur_speed_3_%s' % (dac, fi, msg['cur_speed_3']))
s.add('m8_%d_%d_cur_dir_3_%s' % (dac, fi, msg['cur_dir_3']))
s.add('m8_%d_%d_cur_depth_3_%s' % (dac, fi, msg['cur_depth_3']))
s.add('m8_%d_%d_wave_height_%s' % (dac, fi, msg['wave_height']))
s.add('m8_%d_%d_wave_period_%s' % (dac, fi, msg['wave_period']))
s.add('m8_%d_%d_wave_dir_%s' % (dac, fi, msg['wave_dir']))
s.add('m8_%d_%d_swell_height_%s' % (dac, fi, msg['swell_height']))
s.add('m8_%d_%d_swell_period_%s' % (dac, fi, msg['swell_period']))
s.add('m8_%d_%d_swell_dir_%s' % (dac, fi, msg['swell_dir']))
s.add('m8_%d_%d_sea_state_%s' % (dac, fi, msg['sea_state']))
s.add('m8_%d_%d_water_temp_%s' % (dac, fi, msg['water_temp']))
s.add('m8_%d_%d_precip_type_%s' % (dac, fi, msg['precip_type']))
s.add('m8_%d_%d_salinity_%s' % (dac, fi, msg['salinity']))
s.add('m8_%d_%d_ice_%s' % (dac, fi, msg['ice']))
return len(s) - s_len_begin > 0
######################################################################
# 9 - Standard SAR aircraft position report
class Msg9(object):
def __init__(self):
self.states = set()
self.key_set = set()
self.now = datetime.datetime.utcnow()
self.junk = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
sog = msg['sog']
if sog == 0: s.add('sog_0')
elif sog > 5 and sog < 10: s.add('sog_low')
elif sog > 30 and sog < 50: s.add('sog_high')
elif sog > 50 and sog < 100: s.add('sog_crazy')
elif sog > 102.19 and sog < 102.21: s.add('sog_or_higher')
elif sog > 102.29 and sog < 102.31: s.add('sog_or_unknown')
s.add('pa_%d' % msg['position_accuracy'])
x = msg['x']; y = msg['y']
# These are bad
if x > 180 and y < 90: s.add('x_undef')
if x < 180 and y > 90: s.add('y_undef')
# This is okay
if x > 180 and y > 90: s.add('xy_undef')
# All bad
if x < -180 and y > -90: s.add('x_neg_undef')
if x > -180 and y < -90: s.add('y_neg_undef')
if x < -180 and y < -90: s.add('xy_neg_undef')
if x == 0 and y == 0: s.add('x0_y0')
if x > 2 and x < 15:
if y > 2 and y < 15: s.add('x_low_y_low')
if y > 60 and y < 90: s.add('x_low_y_high')
if y < -2 and y > -15: s.add('x_low_y_neglow')
if y < -50 and y > -90: s.add('x_low_y_neghigh')
cog = msg['cog'] # steps of 0.1
if cog == 0: s.add('cog0')
if cog > 9 and cog < 10: s.add('cog9_9') # has a decimal
if cog > 89.9 and cog <= 90: s.add('cog90')
if cog > 179.8 and cog <= 180: s.add('cog180')
if cog > 269.8 and cog <= 270: s.add('cog270')
if cog == 360: s.add('cog360')
if cog > 365: s.add('cogTooHigh')
ts = msg['timestamp']
if ts in (0,30,59,60,61,62,63): # 61 is hard to find
s.add('ts%d' % ts)
s.add('alt_sensor%d' % msg['alt_sensor'])
if msg['spare'] in (0, 1, 126, 127): s.add('spare%d' % msg['spare'])
s.add('dte%d' % msg['dte'])
s.add('spare2_%d' % msg['spare2'])
return len(s) - s_len_begin > 0
class Msg10(object): # ':'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('spare_%d' %msg['spare'])
if msg['dest_mmsi'] in MMSI_LIST: s.add('dest_mmsi%d' % msg['dest_mmsi'])
s.add('spare2_%d' %msg['spare2'])
return len(s) - s_len_begin > 0
Msg11 = Msg4
class Msg12(object): # '<'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('seq_%d' %msg['seq_num'])
if msg['dest_mmsi'] in MMSI_LIST: s.add('dest_mmsi%d' % msg['dest_mmsi'])
s.add('retransmitted_%s' %msg['retransmitted'])
s.add('spare_%d' %msg['spare'])
lengths = range(12) + [48, 49, 85, 86, 122, 123, 156]
if len(msg['text']) in lengths:
s.add('text_%d' % len(msg['text']))
return len(s) - s_len_begin > 0
#Msg13 = Msg7
class Msg14(object): # '<'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('spare_%d' %msg['spare'])
lengths = [0, 1, 2, 15, 16, 17, 53, 54, 90, 91, 128, 129, 161]
if len(msg['text']) in lengths:
s.add('text_%d' % len(msg['text']))
return len(s) - s_len_begin > 0
class Msg15(object): # '?'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('spare_%d' %msg['spare'])
if msg['mmsi_1'] in MMSI_LIST: s.add('mmsi_1_%d' % msg['mmsi_1'])
mmsi1 = msg['mmsi_1']
s.add('msg_1_1_%d' % msg['msg_1_1'])
if msg['slot_offset_1_1'] in (0,1,100, 4094, 4095):
s.add('slot_offset_1_1_%d' % msg['slot_offset_1_1'])
s.add('spare2_%d' %msg['spare2'])
s.add('msg_1_1_%d' % msg['msg_1_1'])
if msg['slot_offset_1_1'] in (0,1,100, 4094, 4095):
s.add('slot_offset_1_1_%d' % msg['slot_offset_1_1'])
s.add('spare3_%d' %msg['spare3'])
if msg['mmsi_2'] in MMSI_LIST: s.add('mmsi_2_%d' % msg['mmsi_2'])
s.add('msg_2_%d' % msg['msg_2'])
if msg['slot_offset_2'] in (0,1,100, 4094, 4095):
s.add('slot_offset_2_%d' % msg['slot_offset_2'])
return len(s) - s_len_begin > 0
class Msg16(object): # '?'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('spare_%d' % msg['spare'])
if msg['dest_mmsi_a'] in MMSI_LIST: s.add('dest_mmsi_a_%d' % msg['mmsi'])
if msg['offset_a'] in (0,1,10,4094,4095): s.add('offset_a_%d' % msg['offset_a'])
if msg['inc_a'] in (0,1,8,1022, 1023): s.add('inc_a_%d' % msg['inc_a'])
if 'dest_mmsi_b' in msg:
if msg['dest_mmsi_b'] in MMSI_LIST: s.add('dest_mmsi_b_%d' % msg['mmsi'])
if msg['offset_b'] in (0,1,10,4094,4095): s.add('offset_b_%d' % msg['offset_b'])
if msg['inc_b'] in (0,1,8,1022, 1023): s.add('inc_b_%d' % msg['inc_b'])
if 'spare2' in msg: s.add('spare2_%d' % msg['spare2'])
return len(s) - s_len_begin > 0
class Msg17(object): # 'A'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('spare_%d' % msg['spare'])
# TODO: fix this
if 'spare2' in msg: s.add('spare2_%d' % msg['spare2'])
return len(s) - s_len_begin > 0
def Sotdma(msg, s):
if 'sync_state' in msg: s.add('ss%d' % msg['sync_state'] )
if 'slot_timeout' in msg: s.add('sm%d' % msg['slot_timeout'])
if 'received_stations' in msg:
rs = msg['received_stations']
if rs in (0,1,5): s.add('rs%d' % rs)
if rs > 50 and rs < 100: s.add('rs_med')
if rs > 100 and rs < 500: s.add('rs_high')
if rs > 500 and rs < 1000: s.add('rs_very_high')
if rs > 1000 and rs < 15000: s.add('rs_insane')
if rs > 16000: s.add('rs_top')
if rs == 2**14-1: s.add('rs_max')
if 'slot_number' in msg:
sn = msg['slot_number']
if sn in (0,1,10,2248, 2249):
s.add('sn%d' % sn)
if sn > 2250: s.add('sn_too_high')
if 'utc_hour' in msg:
hr = msg['utc_hour']; mn = msg['utc_min']; u_spare = msg['utc_spare']
if hr in (0, 12, 23, 24, 31):
s.add('hr%d' % hr)
if hr > 24 and hr < 31: s.add('hr_over')
if mn in (0, 11, 59, 60, 127): s.add('mn%d' % mn)
if mn > 60 and mn < 127: s.add('mn_over')
s.add('utc_spare%d' % u_spare)
if 'slot_offset' in msg:
so = msg['slot_offset']
if so in (0,1, 2248, 2249, 2250, 2**14-2, 2**14-1):
s.add('so%d' % so)
if so > 2260 and so < 15000: s.add('so_too_high')
def Itdma(msg, s):
if 'sync_state' in msg: s.add('itdma_ss%d' % msg['sync_state'])
slot_inc = msg['slot_increment']
# last 2 not valid
if slot_inc in (0, 1, 2248, 2249, 2250, 8191): s.add('slot_inc%d' % slot_inc)
s.add('nslots%d' % msg['slots_to_allocate'])
s.add('keep%d' % msg['keep_flag'])
class Msg18(object): # 'B'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('spare_%d' % msg['spare'])
Sog(msg, s)
# sog = msg['sog']
# if sog == 0: s.add('sog_0')
# elif sog > 5 and sog < 10: s.add('sog_low')
# elif sog > 30 and sog < 50: s.add('sog_high')
# elif sog > 50 and sog < 100: s.add('sog_crazy')
# elif sog > 102.19 and sog < 102.21: s.add('sog_or_higher')
# elif sog > 102.29 and sog < 102.31: s.add('sog_or_unknown')
s.add('pa_%d' % msg['position_accuracy'])
x = msg['x']; y = msg['y']
# These are bad
if x > 180 and y < 90: s.add('x_undef')
if x < 180 and y > 90: s.add('y_undef')
# This is okay
if x > 180 and y > 90: s.add('xy_undef')
if x == 0 and y == 0: s.add('x0_y0')
if x > 2 and x < 15:
if y > 2 and y < 15: s.add('x_low_y_low')
if y > 60 and y < 90: s.add('x_low_y_high')
if y < -2 and y > -15: s.add('x_low_y_neglow')
if y < -50 and y > -90: s.add('x_low_y_neghigh')
cog = msg['cog'] # steps of 0.1
if cog == 0: s.add('cog0')
if cog > 9 and cog < 10: s.add('cog9_9') # has a decimal
if cog > 89.9 and cog <= 90: s.add('cog90')
if cog > 179.8 and cog <= 180: s.add('cog180')
if cog > 269.8 and cog <= 270: s.add('cog270')
if cog == 360: s.add('cog360')
if cog > 365: s.add('cogTooHigh')
th = msg['true_heading']
if th in (0, 90, 180, 270, 359):
s.add('th%d' % th)
if th == 360: s.add('th_bad_360') # NOT valid
if th > 400 and th < 500: s.add('th_wonky')
if th == 511: s.add('th_na')
ts = msg['timestamp']
if ts in (0,30,59,60,61,62,63): s.add('ts%d' % ts)
if 'spare2' in msg: s.add('spare2_%d' % msg['spare2'])
s.add('unit_flag_%d' % msg['unit_flag'])
s.add('display_flag_%d' % msg['display_flag'])
s.add('dsc_flag_%d' % msg['dsc_flag'])
s.add('band_flag_%d' % msg['band_flag'])
s.add('m22_flag_%d' % msg['m22_flag'])
s.add('mode_flag_%d' % msg['mode_flag'])
s.add('raim_%d' % msg['raim'])
if not msg['commstate_flag']:
Sotdma(msg, s)
elif not msg['unit_flag']:
Itdma(msg, s)
return len(s) - s_len_begin > 0
class Msg19(object): # 'C'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
if 1:
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('spare_%d' % msg['spare'])
s.add('spare_%d' % msg['spare'])
Sog(msg, s)
s.add('pa_%d' % msg['position_accuracy'])
LonLat(msg, s)
Cog(msg, s)
TrueHeading(msg, s)
# 61 is hard to find
ts = msg['timestamp']
if ts in (0,30,59,60,61,62,63): s.add('ts%d' % ts)
s.add('spare2_%d' % msg['spare2'])
Name(msg, s)
s.add('tc%d' % msg['type_and_cargo'])
Dim(msg, s)
s.add('ft%d' % msg['fix_type'])
s.add('raim_%d' % msg['raim'])
s.add('dte%d' % msg['dte'])
s.add('assigned_mode_%d' % msg['assigned_mode'])
s.add('spare_3%d' % msg['spare3'])
return len(s) - s_len_begin > 0
class Msg20(object): # 'D'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('spare_%d' % msg['spare'])
for res_num, res in enumerate(msg['reservations']):
if res['offset'] in (0,1, 10, 4094, 4095):
s.add('offset_%d_%d' % (res_num, res['offset']))
s.add('num_slots_%d_%d' % (res_num, res['num_slots']))
s.add('timeout_%d_%d' % (res_num, res['timeout']))
if res['incr'] in (0,1, 10, 2046, 2047):
s.add('incr_%d_%d' % (res_num, res['incr']))
return len(s) - s_len_begin > 0
class Msg21(object): # 'E'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('aton_type_%d' % msg['aton_type'])
# TODO: Name length issue
Name(msg, s, length=20+14)
s.add('pa_%d' % msg['position_accuracy'])
LonLat(msg, s)
Dim(msg, s)
s.add('ft%d' % msg['fix_type'])
ts = msg['timestamp']
if ts in (0,30,59,60,61,62,63): s.add('ts%d' % ts)
for field in ('off_pos', 'aton_status', 'raim', 'virtual_aton', 'assigned_mode'):
s.add('%s_%d' % (field, msg[field]))
return len(s) - s_len_begin > 0
class Msg22(object): # 'F'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
for field in ('spare', 'chan_a', 'chan_b', 'txrx_mode', 'power_low',
'chan_a_bandwidth', 'chan_b_bandwidth', 'zone_size'):
s.add('%s_%d' % (field, msg[field]))
if 'x1' in msg:
for which in (1,2):
x = msg['x%d' % which]; y = msg['y%d' % which]
if x > 180 and y < 90: s.add('x_undef%d' % which)
if x < 180 and y > 90: s.add('y_undef%d' % which)
if x > 180 and y > 90: s.add('xy_undef%d' % which)
if x < -180 and y > -90: s.add('x_neg_undef%d' % which)
if x > -180 and y < -90: s.add('y_neg_undef%d' % which)
if x < -180 and y < -90: s.add('xy_neg_undef%d' % which)
if x == 0 and y == 0: s.add('x0_y0%d' % which)
else:
if msg['dest_mmsi_1'] in MMSI_LIST: s.add('dest_mmsi_1_%d' % msg['dest_mmsi_1'])
if msg['dest_mmsi_2'] in MMSI_LIST: s.add('dest_mmsi_2_%d' % msg['dest_mmsi_2'])
if msg['spare2'] in (0, 1, 49407, 547448, 549235, 558017, 8388606, 8388607):
s.add('spare2_%d' % msg['spare2'])
return len(s) - s_len_begin > 0
class Msg23(object): # 'G'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
for which in (1,2):
x = msg['x%d' % which]; y = msg['y%d' % which]
if x > 180 and y < 90: s.add('x_undef%d' % which)
if x < 180 and y > 90: s.add('y_undef%d' % which)
if x > 180 and y > 90: s.add('xy_undef%d' % which)
if x < -180 and y > -90: s.add('x_neg_undef%d' % which)
if x > -180 and y < -90: s.add('y_neg_undef%d' % which)
if x < -180 and y < -90: s.add('xy_neg_undef%d' % which)
if x == 0 and y == 0: s.add('x0_y0%d' % which)
for field in ('station_type', 'type_and_cargo', 'txrx_mode', 'interval_raw',
'quiet'):
s.add('%s_%d' % (field, msg[field]))
if msg['spare2'] in (0, 1, 2, 4, 4194302, 4194303):
s.add('spare2_%d' % msg['spare2'])
if msg['spare3'] in (0, 1, 2, 4, 60, 61, 62, 63):
s.add('spare3_%d' % msg['spare3'])
return len(s) - s_len_begin > 0
class Msg24(object): # 'H'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
if msg['part_num'] == 0:
AisString(msg, s, 'name', length = 20)
elif msg['part_num'] == 1:
s.add('type_and_cargo_%s' % msg['type_and_cargo'])
AisString(msg, s, 'vendor_id', length=7)
AisString(msg, s, 'callsign', length=7)
Dim(msg, s)
s.add('spare_%s' % msg['spare'])
elif msg['part_num'] == 2:
if 'part_2' not in s: print 'Ais24 part 2 not yet defined'
s.add('part_2')
elif msg['part_num'] == 3:
if 'part_3' not in s: print 'Ais24 part 3 not yet defined'
s.add('part_3')
return len(s) - s_len_begin > 0
class Msg25(object): # 'I'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
if 'dest_mmsi' in msg and msg['dest_mmsi'] in MMSI_LIST:
s.add('dest_mmsi_%d' % msg['dest_mmsi'])
if 'dac' in msg: s.add('dac_fi_%d_%d' % (msg['dac'], msg['fi']))
else: s.add('no_dac_fi')
# TODO: handle payloads
return len(s) - s_len_begin > 0
class Msg26(object): # 'K'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
if 'dest_mmsi' in msg and msg['dest_mmsi'] in MMSI_LIST:
s.add('dest_mmsi_%d' % msg['dest_mmsi'])
if 'dac' in msg: s.add('dac_fi_%d_%d' % (msg['dac'], msg['fi']))
else: s.add('no_dac_fi')
# TODO: handle payloads
# TODO: commstate
return len(s) - s_len_begin > 0
class Msg27(object): # 'L'
def __init__(self):
self.states = set()
self.key_set = set()
def CheckKeep(self, msg):
for key in msg:
self.key_set.add(key)
s = self.states
s_len_begin = len(s)
if msg['mmsi'] in MMSI_LIST: s.add('mmsi%d' % msg['mmsi'])
s.add('repeat%d' % msg['repeat_indicator'])
s.add('pa_%d' % msg['position_accuracy'])
s.add('raim%d' % msg['raim'])
s.add('ns_%d' % msg['nav_status'])
LonLat(msg, s)
if msg['sog'] in (0, 1, 8, 16, 61, 62, 63): s.add('sog_%d' % msg['sog'])
if msg['cog'] in (0, 1, 8, 16, 90, 180, 270, 359, 360, 361, 510, 511): s.add('cog_%d' % msg['cog'])
s.add('gnss_%d' % msg['gnss'])
s.add('spare_%d' % msg['spare'])
return len(s) - s_len_begin > 0
def main():
norm = Normalize()
handlers = {
'1': Msg1(),
'2': Msg1(),
'3': Msg1(),
'4': Msg4(),
'5': Msg5(),
'6': Msg6(),
'7': Msg7_13(),
'8': Msg8(),
'9': Msg9(),
':': Msg10(),
';': Msg11(), # 11 and 4 are the same
'<': Msg12(),
'=': Msg7_13(), # No message 13's found
'>': Msg14(),
'?': Msg15(),
'@': Msg16(),
'A': Msg17(),
'B': Msg18(),
'C': Msg19(),
'D': Msg20(),
'E': Msg21(),
'F': Msg22(),
'G': Msg23(),
'H': Msg24(),
'I': Msg25(),
'J': Msg26(),
'K': Msg27(),
# 'L': Msg28(), # Not yet defined
}
lengths = {}
decoded_counts = {}
unhandled_msg_types = set()
o = open('keep.ais', 'w')
for filename in sys.argv[1:]:
print '# file:', filename
for line_num, line in enumerate(open(filename)):
if line_num % 100000 == 0:
print 'line:', line_num
if not line.startswith('!AIVD'):
continue
#if line_num >= 1000: break
norm.put(line.strip(), line_num)
del line # Do not use this any more!
try:
result = norm.get(False)
except Queue.Empty:
continue
body = result['body']
if not body:
continue
msg_type = body[0]
pad = result['pad']
key = '%s_%d' % (msg_type, 6*len(body)-pad)
if key not in lengths:
lengths[key] = 0
else:
lengths[key] += 1
if msg_type not in handlers:
if msg_type not in unhandled_msg_types:
unhandled_msg_types.add(msg_type)
print 'not handled: msg="%s"' % msg_type
continue
try:
msg = ais.decode(body, pad)
except Exception as e:
if 'AIS_ERR_BAD_BIT_COUNT' not in str(e) and 'AIS_ERR_MSG_TOO_LONG' not in str(e):
sys.stderr.write('Error: %s: %s' % (e, result) )
continue
if msg_type not in decoded_counts:
decoded_counts[msg_type] = 1
else:
decoded_counts[msg_type] += 1
msg_handler = handlers[msg_type]
if msg_handler.CheckKeep(msg):
if 1:
for raw in result['raw']:
o.write(raw)
o.write('\n')
pass
if 0:
for h in handlers:
if handlers[h].states:
m = handlers[h]
print 'states:', h, len(m.states), sorted(m.states)
print 'keys:', h, sorted([str(key) for key in m.key_set])
print 'lengths:', lengths
print 'decoded_counts:', decoded_counts
if __name__ == '__main__':
main()Metadata
Metadata
Assignees
Labels
No labels