Skip to content

Commit

Permalink
tidy up
Browse files Browse the repository at this point in the history
  • Loading branch information
pwoods25443 committed Sep 10, 2020
1 parent c8b6af8 commit 6a9eb43
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 87 deletions.
25 changes: 9 additions & 16 deletions ais_tools/ais.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,24 @@


message_types = {
18: [ais18.AIS18Transcoder()],
18: ais18.ais18_fields,
24: [ais24.AIS24Transcoder()],
25: [ais25.AIS25Transcoder()],
25: ais25.ais25_fields,
}


class AISMessageTypeTranscoder(MessageTranscoder):
class AISMessageTranscoder(MessageTranscoder):

def get_fields(self, message=None):
msg_type = message.get('id')
def message_type_fields(self, msg_type):
if msg_type not in message_types:
raise DecodeError('AIS: Unknown message type {}'.format(msg_type))
fields = message_types.get(msg_type, [])
return fields

return message_types.get(msg_type, [])

ais_fields = [
Uint(name='id', nbits=6, default=0),
AISMessageTypeTranscoder(),
]
def encode_fields(self, message):
return self.message_type_fields(message.get('id'))


class AISMessageTranscoder(MessageTranscoder):
def __init__(self):
super().__init__(ais_fields)
def decode_fields(self, bits, message):
return self.message_type_fields(message.get('id', bits[0:6].uint))

def encode_nmea(self, message):
return bits_to_nmea(byte_align(self.encode(message)))
Expand Down
6 changes: 1 addition & 5 deletions ais_tools/ais18.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@
from ais_tools.transcode import LatLonTranscoder as LatLon


class AIS18Transcoder(transcode.MessageTranscoder):
def __init__(self):
super().__init__(ais18_fields)


class AIS18CommState(transcode.MessageTranscoder):
def get_fields(self, message=None):
unit_flag = message.get('unit_flag', 0)
Expand Down Expand Up @@ -41,6 +36,7 @@ def get_fields(self, message=None):


ais18_fields = [
Uint(name='id', nbits=6, default=0),
Uint(name='repeat_indicator', nbits=2),
Uint(name='mmsi', nbits=30),
Uint(name='spare', nbits=8),
Expand Down
104 changes: 54 additions & 50 deletions ais_tools/ais24.py
Original file line number Diff line number Diff line change
@@ -1,96 +1,100 @@
from ais_tools import transcode
from ais_tools.transcode import MessageTranscoder as Message
from ais_tools.transcode import DynamicTranscoder
from ais_tools.transcode import DecodeError
from ais_tools.transcode import UintTranscoder as Uint
from ais_tools.transcode import ASCII6Transcoder as ASCII6


class AIS24Transcoder(Message):
def __init__(self):
super().__init__(ais24_fields)


class AIS24PartAB(Message):
def get_fields(self, message=None):
part_num = message.get('part_num', 0)
def part_AB_fields(self, part_num):
if part_num == 0:
return ais24_part_A_fields
elif part_num == 1:
return ais24_part_B_fields
else:
raise DecodeError('AIS24: unknown part number {}'.format(part_num))

def encode_fields(self, message):
return self.part_AB_fields(message.get('part_num'))

def decode_fields(self, bits, message):
return self.part_AB_fields(message.get('id', bits[38:40].uint))

class VendorID(DynamicTranscoder):
def __init__(self):
self.vendorid_1371_2 = Message(ais24_vendorid_ITU_R_1371_2)
self.vendorid_1371_4 = Message(ais24_vendorid_ITU_R_1371_4)

def encoder(self, message):
class VendorID(Message):
def __init__(self, vendorid_1371_2, vendorid_1371_4):
self.vendorid_1371_2 = vendorid_1371_2
self.vendorid_1371_4 = vendorid_1371_4

def encode_fields(self, message):
if 'vendor_id' in message:
return self.vendorid_1371_2
else:
return self.vendorid_1371_4

def decoders(self, message):
return [self.vendorid_1371_2, self.vendorid_1371_4]
def decode(self, bits, message=None):
message = message or {}
pos = bits.pos
for d in self.vendorid_1371_2:
message.update(d.decode(bits, message))
bits.pos = pos # reset read position to read the same bits again for multiple decoders
for d in self.vendorid_1371_4:
message.update(d.decode(bits, message))
return message


class DimensionOrMothership(Message):
def __init__(self):
def __init__(self, dim_fields, mothership_fields):
super().__init__()
self.shipDimension = Message(ais24_part_B_dimension_fields)
self.mothershipMMSI = Message(ais24_part_B_mothership_fields)
self.dim_fields = dim_fields
self.mothership_fields = mothership_fields

def get_fields(self, message=None):
mmsi = message.get('id')
if mmsi // 10000000 == 98:
return [self.mothershipMMSI]
return self.mothership_fields
else:
return [self.shipDimension]
return self.dim_fields


# COMMON FIELDS
ais24_fields = [
# PART A
ais24_part_A_fields = [
Uint(name='id', nbits=6, default=0),
Uint(name='repeat_indicator', nbits=2),
Uint(name='mmsi', nbits=30),
Uint(name='part_num', nbits=2),
AIS24PartAB()
]

# PART A
ais24_part_A_fields = [
ASCII6(name='name', nbits=120),
]

# PART B
ais24_vendorid_ITU_R_1371_2 =[
ASCII6(name='vendor_id', nbits=42, default='@@@@@@@'),
]

ais24_vendorid_ITU_R_1371_4 =[
ASCII6(name='vendor_id_1371_4', nbits=18, default='@@@'),
Uint(name='vendor_model', nbits=4),
Uint(name='vendor_serial', nbits=20),
]

ais24_part_B_dimension_fields = [
Uint(name='dim_a', nbits=9),
Uint(name='dim_b', nbits=9),
Uint(name='dim_c', nbits=6),
Uint(name='dim_d', nbits=6),
]

ais24_part_B_mothership_fields = [
Uint(name='mothership_mmsi', nbits=30),
]

ais24_part_B_fields = [
Uint(name='id', nbits=6, default=0),
Uint(name='repeat_indicator', nbits=2),
Uint(name='mmsi', nbits=30),
Uint(name='part_num', nbits=2),
Uint(name='type_and_cargo', nbits=8),
VendorID(),
VendorID(
[
ASCII6(name='vendor_id', nbits=42, default='@@@@@@@'),
],
[
ASCII6(name='vendor_id_1371_4', nbits=18, default='@@@'),
Uint(name='vendor_model', nbits=4),
Uint(name='vendor_serial', nbits=20),
],
),
ASCII6(name='callsign', nbits=42, default='@@@@@@@'),
DimensionOrMothership(),
DimensionOrMothership(
[
Uint(name='dim_a', nbits=9),
Uint(name='dim_b', nbits=9),
Uint(name='dim_c', nbits=6),
Uint(name='dim_d', nbits=6),
],
[
Uint(name='mothership_mmsi', nbits=30),
]
),
Uint(name='gps_type', nbits=4),
Uint(name='spare', nbits=2),
]
Expand Down
21 changes: 7 additions & 14 deletions ais_tools/ais25.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,36 @@
from ais_tools import transcode
from ais_tools.transcode import DecodeError
from ais_tools.transcode import UintTranscoder as Uint
from ais_tools.transcode import ASCII6Transcoder as ASCII6
from ais_tools.transcode import VariableLengthASCII6Transcoder as VarASCII6

# Using this coding http://www.e-navigation.nl/content/text-using-6-bit-ascii-1


class AIS25Transcoder(transcode.MessageTranscoder):
def __init__(self):
super().__init__(ais25_fields)

# Using this coding http://www.e-navigation.nl/content/text-using-6-bit-ascii-1

class AIS25Destination(transcode.MessageTranscoder):
def get_fields(self, message=None):
addressed = message.get('addressed', 0)
if addressed:
return ais25_destination_fields
return self._fields
else:
return []


ais25_fields = [
Uint(name='id', nbits=6, default=0),
Uint(name='repeat_indicator', nbits=2),
Uint(name='mmsi', nbits=30),
Uint(name='part_num', nbits=2),
Uint(name='addressed', nbits=1),
Uint(name='use_app_id', nbits=1),
AIS25Destination(),
AIS25Destination([
Uint(name='dest_mmsi', nbits=30),
Uint(name='spare', nbits=2),
]),
Uint(name='dac', nbits=10, default=1),
Uint(name='fi', nbits=6),
Uint(name='text_seq', nbits=11),
VarASCII6(name='text', default='')
]

ais25_destination_fields = [
Uint(name='dest_mmsi', nbits=30),
Uint(name='spare', nbits=2),
]



Expand Down
10 changes: 8 additions & 2 deletions ais_tools/transcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,21 @@ def __init__(self, fields=None):
def get_fields(self, message=None):
return self._fields

def encode_fields(self, message):
return self.get_fields(message)

def decode_fields(self, bits, message):
return self.get_fields(message)

def encode(self, message):
bits = Bits()
for f in self.get_fields(message):
for f in self.encode_fields(message):
bits += f.encode(message)
return bits

def decode(self, bits, message=None):
message = message or {}
for f in self.get_fields(message):
for f in self.decode_fields(bits, message):
message.update(f.decode(bits, message))
return message

Expand Down

0 comments on commit 6a9eb43

Please sign in to comment.