Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F86484304
aisMsg.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Oct 6, 18:46
Size
13 KB
Mime Type
text/x-python
Expires
Tue, Oct 8, 18:46 (2 d)
Engine
blob
Format
Raw Data
Handle
21431512
Attached To
R890 mux0183
aisMsg.py
View Options
#!/usr/bin/python
import
math
from
bitBuf
import
bitBuf
from
nmea
import
NMEAaddChecksum
#----------------------------------
# AIS message
# ITU-R M.1371-4 Annex 8
#----------------------------------
encodingTable
=
"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW`abcdefghijklmnopqrstuvw"
class
AISmsg
:
def
__init__
(
self
)
:
self
.
type
=
0
self
.
repeat
=
0
self
.
mmsi
=
0
self
.
bb
=
bitBuf
()
self
.
aisframe
=
''
self
.
padding
=
0
self
.
sentence
=
''
def
_bin2asc
(
self
)
:
out
=
''
if
self
.
bb
.
bit
==
0
:
self
.
bb
.
buff
.
pop
()
# delete last element
for
c
in
self
.
bb
.
buff
:
if
c
<
64
:
out
+=
encodingTable
[
c
]
return
out
# Encapsulate AIS frame in multiple NMEA frames
def
EncapInAIVDM
(
self
)
:
multi
=
[]
count
=
(
len
(
self
.
aisframe
)
-
1
)
/
60
# MAX_AIS=60
count
+=
1
segment
=
0
for
i
in
range
(
0
,
count
)
:
subframe
=
self
.
aisframe
[
segment
:
segment
+
60
]
aivdm
=
"!AIVDM,"
+
str
(
count
)
+
","
+
str
(
i
+
1
)
+
",,A,"
+
subframe
segment
+=
60
if
i
!=
count
-
1
:
aivdm
+=
",0"
else
:
aivdm
+=
","
+
str
(
self
.
padding
)
aivdm
=
NMEAaddChecksum
(
aivdm
)
multi
.
append
(
aivdm
)
return
multi
def
Encode
(
self
)
:
self
.
_encode
()
return
self
.
EncapInAIVDM
()
def
_asc2bin
(
self
,
c
)
:
byte
=
ord
(
c
)
-
48
if
byte
>
40
:
byte
-=
8
return
byte
def
getBits
(
self
,
aChar
,
first
,
nb
)
:
return
(
aChar
>>
(
6
-
(
first
+
nb
)))
&
~
(
~
0
<<
nb
)
def
read_uint
(
self
,
buf
,
firstBit
,
nbBits
)
:
idx
=
firstBit
/
6
byte
=
self
.
_asc2bin
(
buf
[
idx
])
bit
=
firstBit
%
6
count
=
min
(
nbBits
,
6
-
bit
)
val
=
self
.
getBits
(
byte
,
bit
,
count
)
nbBits
-=
(
6
-
bit
)
while
nbBits
>
0
:
idx
+=
1
byte
=
self
.
_asc2bin
(
buf
[
idx
])
count
=
min
(
nbBits
,
6
)
val
=
val
<<
count
val
|=
self
.
getBits
(
byte
,
0
,
count
)
nbBits
-=
count
return
val
def
read_int
(
self
,
buf
,
firstBit
,
nbBits
)
:
val
=
self
.
read_uint
(
buf
,
firstBit
,
nbBits
)
if
((
val
>>
(
nbBits
-
1
)
&
1
)
==
1
)
:
val
|=
(
~
0
<<
nbBits
)
return
val
def
read_string
(
self
,
buf
,
firstBit
,
nbBits
)
:
str
=
''
for
i
in
range
(
0
,
nbBits
/
6
)
:
idx
=
self
.
read_uint
(
buf
,
firstBit
,
6
)
if
idx
<=
31
:
c
=
chr
(
idx
+
ord
(
'@'
))
elif
idx
<=
63
:
c
=
chr
(
idx
)
else
:
c
=
'@'
str
=
str
+
c
if
c
==
'@'
:
break
firstBit
+=
6
while
str
[
-
1
]
==
'@'
:
str
=
str
[:
-
1
]
return
str
def
Reset
(
self
)
:
self
.
sentence
=
''
def
Fragment
(
self
,
fragment
)
:
args
=
fragment
.
split
(
','
)
if
args
[
0
]
.
find
(
'!AIVDM'
)
>=
0
:
self
.
sentence
+=
args
[
5
]
if
args
[
1
]
==
args
[
2
]
:
return
self
.
_decode
()
return
None
def
_decode
(
self
)
:
print
'Decode '
+
self
.
sentence
type
=
self
.
read_uint
(
self
.
sentence
,
0
,
6
)
print
'Type '
+
str
(
type
)
repeat
=
self
.
read_uint
(
self
.
sentence
,
6
,
2
)
mmsi
=
self
.
read_uint
(
self
.
sentence
,
8
,
30
)
if
type
==
1
:
obj
=
AISmsg1
()
obj
.
repeat
=
repeat
obj
.
mmsi
=
mmsi
obj
.
_decode
(
self
.
sentence
)
elif
type
==
5
:
obj
=
AISmsg5
()
obj
.
repeat
=
repeat
obj
.
mmsi
=
mmsi
obj
.
_decode
(
self
.
sentence
)
elif
type
==
21
:
obj
=
AISmsg21
()
obj
.
repeat
=
repeat
obj
.
mmsi
=
mmsi
obj
.
_decode
(
self
.
sentence
)
else
:
obj
=
None
return
obj
class
AISmsg1
(
AISmsg
)
:
UNDERWAY_ENGINE
=
0
ANCHOR
=
1
NOT_UNDER_COMMAND
=
2
RESTRICTED_MANOEUVRABILITY
=
3
CONSTRAINED_DRAUGHT
=
4
MOORED
=
5
AGROUND
=
6
FISHING
=
7
SAILING
=
8
SART_ACTIVE
=
14
SART_TEST
=
15
NO_TURN_INFO_AVAILABLE
=
128
HDG_NOT_AVAILABLE
=
511
SPECIAL_MANOEUVRE_NOT_AVAIL
=
0
SPECIAL_MANOEUVRE_NOT_ENGAGED
=
1
SPECIAL_MANOEUVRE_ENGAGED
=
2
def
__init__
(
self
)
:
AISmsg
.
__init__
(
self
)
self
.
type
=
1
self
.
repeat
=
0
# SART MMSI : 970xxxxxx
# MOB MMSI : 972xxxxxx
# EPIRB MMSI : 974xxxxxx
self
.
mmsi
=
0
self
.
navStatus
=
AISmsg1
.
UNDERWAY_ENGINE
self
.
rot
=
AISmsg1
.
NO_TURN_INFO_AVAILABLE
self
.
sog
=
0.0
self
.
accuracy
=
0
self
.
lon
=
0.0
self
.
lat
=
0.0
self
.
cog
=
0.0
self
.
hdg
=
AISmsg1
.
HDG_NOT_AVAILABLE
self
.
timeStamp
=
0
self
.
specialManoeuvre
=
AISmsg1
.
SPECIAL_MANOEUVRE_NOT_AVAIL
self
.
RAIM
=
0
self
.
radioStatus
=
0
def
_encode
(
self
)
:
self
.
bb
=
bitBuf
()
self
.
aisframe
=
''
self
.
padding
=
0
self
.
bb
.
WriteByte
(
self
.
type
,
6
)
self
.
bb
.
WriteByte
(
self
.
repeat
,
2
)
self
.
bb
.
WriteInteger
(
self
.
mmsi
,
30
)
self
.
bb
.
WriteByte
(
self
.
navStatus
,
4
)
self
.
bb
.
WriteInteger
(
self
.
rot
,
8
)
self
.
bb
.
WriteInteger
(
int
(
self
.
sog
*
10
),
10
)
self
.
bb
.
WriteBit
(
self
.
accuracy
)
lon
=
int
((
self
.
lon
*
600000
)
+
0.5
)
if
self
.
lon
<
0
:
lon
=
(
lon
^
0x0fffffff
)
+
1
# 2-complement
self
.
bb
.
WriteInteger
(
lon
,
28
)
lat
=
int
((
self
.
lat
*
600000
)
+
0.5
)
if
self
.
lat
<
0
:
lat
=
(
lat
^
0x0fffffff
)
+
1
# 2-complement
self
.
bb
.
WriteInteger
(
lat
,
27
)
self
.
bb
.
WriteInteger
(
int
(
self
.
cog
*
10
),
12
)
self
.
bb
.
WriteInteger
(
int
(
self
.
hdg
),
9
)
self
.
bb
.
WriteByte
(
self
.
timeStamp
,
6
)
self
.
bb
.
WriteByte
(
self
.
specialManoeuvre
,
2
)
self
.
bb
.
WriteByte
(
0
,
3
)
# spare
self
.
bb
.
WriteBit
(
self
.
RAIM
)
self
.
bb
.
WriteInteger
(
self
.
radioStatus
,
19
)
self
.
aisframe
=
self
.
_bin2asc
()
self
.
padding
=
self
.
bb
.
Padding
()
def
_decode
(
self
,
sentence
)
:
self
.
sentence
=
sentence
self
.
navStatus
=
self
.
read_uint
(
self
.
sentence
,
38
,
4
)
self
.
rot
=
math
.
pow
(
self
.
read_uint
(
self
.
sentence
,
42
,
8
)
/
4.733
,
2.0
)
self
.
sog
=
self
.
read_uint
(
self
.
sentence
,
50
,
10
)
/
10.0
self
.
accuracy
=
self
.
read_uint
(
self
.
sentence
,
60
,
1
)
self
.
lon
=
self
.
read_int
(
self
.
sentence
,
61
,
28
)
/
600000.0
self
.
lat
=
self
.
read_int
(
self
.
sentence
,
89
,
27
)
/
600000.0
self
.
cog
=
self
.
read_uint
(
self
.
sentence
,
116
,
12
)
/
10.0
self
.
hdg
=
self
.
read_uint
(
self
.
sentence
,
128
,
9
)
/
10.0
self
.
timeStamp
=
self
.
read_uint
(
self
.
sentence
,
137
,
6
)
self
.
specialManoeuvre
=
self
.
read_uint
(
self
.
sentence
,
143
,
2
)
self
.
RAIM
=
self
.
read_uint
(
self
.
sentence
,
148
,
1
)
self
.
radioStatus
=
self
.
read_uint
(
self
.
sentence
,
149
,
19
)
class
AISmsg5
(
AISmsg
)
:
VERSION_M1371_1
=
0
VERSION_M1371_3
=
1
FISHING
=
30
TOWING
=
31
TOWING_200m
=
32
DREDGING
=
33
DIVING
=
34
MILITARY
=
35
SAILING
=
36
PLEASURE
=
37
HIGH_SPEED
=
40
PILOT_VESSEL
=
50
SAR_VESSEL
=
51
TUG
=
52
PORT_TENDER
=
53
PASSENGER
=
60
CARGO
=
70
TANKER
=
80
OTHER
=
90
DEVICE_UNDEFINED
=
0
DEVICE_GPS
=
1
DEVICE_GLONASS
=
2
DEVICE_LORANC
=
4
DEVICE_GALILEO
=
8
def
__init__
(
self
)
:
AISmsg
.
__init__
(
self
)
self
.
type
=
5
self
.
version
=
self
.
VERSION_M1371_1
self
.
imo
=
0
self
.
callSign
=
''
self
.
name
=
''
self
.
shipType
=
0
self
.
to_bow
=
0
self
.
to_stern
=
0
self
.
to_port
=
0
self
.
to_starboard
=
0
self
.
deviceType
=
self
.
DEVICE_UNDEFINED
self
.
ETAmonth
=
0
self
.
ETAday
=
0
self
.
ETAhour
=
0
self
.
ETAminute
=
0
self
.
draught
=
0
self
.
destination
=
''
self
.
dte
=
0
def
_encode
(
self
)
:
self
.
bb
=
bitBuf
()
self
.
aisframe
=
''
self
.
padding
=
0
self
.
bb
.
WriteByte
(
self
.
type
,
6
)
self
.
bb
.
WriteByte
(
self
.
repeat
,
2
)
self
.
bb
.
WriteInteger
(
self
.
mmsi
,
30
)
self
.
bb
.
WriteByte
(
self
.
version
,
2
)
self
.
bb
.
WriteInteger
(
self
.
imo
,
30
)
self
.
bb
.
WriteString
(
self
.
callSign
,
7
)
self
.
bb
.
WriteString
(
self
.
name
,
20
)
self
.
bb
.
WriteByte
(
self
.
shipType
,
8
)
self
.
bb
.
WriteInteger
(
self
.
to_bow
,
9
)
self
.
bb
.
WriteInteger
(
self
.
to_stern
,
9
)
self
.
bb
.
WriteByte
(
self
.
to_port
,
6
)
self
.
bb
.
WriteByte
(
self
.
to_starboard
,
6
)
self
.
bb
.
WriteByte
(
self
.
deviceType
,
4
)
self
.
bb
.
WriteInteger
(
self
.
ETAmonth
,
4
)
self
.
bb
.
WriteInteger
(
self
.
ETAday
,
5
)
self
.
bb
.
WriteInteger
(
self
.
ETAhour
,
5
)
self
.
bb
.
WriteInteger
(
self
.
ETAminute
,
6
)
self
.
bb
.
WriteByte
(
self
.
draught
*
10
,
8
)
self
.
bb
.
WriteString
(
self
.
destination
,
20
)
self
.
bb
.
WriteBit
(
self
.
dte
)
self
.
bb
.
WriteBit
(
0
)
# spare
self
.
aisframe
=
self
.
_bin2asc
()
self
.
padding
=
self
.
bb
.
Padding
()
def
_decode
(
self
,
sentence
)
:
self
.
sentence
=
sentence
self
.
version
=
self
.
read_uint
(
self
.
sentence
,
38
,
2
)
self
.
imo
=
self
.
read_uint
(
self
.
sentence
,
40
,
30
)
self
.
callSign
=
self
.
read_string
(
self
.
sentence
,
70
,
42
)
self
.
name
=
self
.
read_string
(
self
.
sentence
,
112
,
120
)
self
.
shipType
=
self
.
read_uint
(
self
.
sentence
,
232
,
8
)
self
.
to_bow
=
self
.
read_uint
(
self
.
sentence
,
240
,
9
)
self
.
to_stern
=
self
.
read_uint
(
self
.
sentence
,
249
,
9
)
self
.
to_port
=
self
.
read_uint
(
self
.
sentence
,
258
,
6
)
self
.
to_starboard
=
self
.
read_uint
(
self
.
sentence
,
264
,
6
)
self
.
ETAmonth
=
self
.
read_uint
(
self
.
sentence
,
274
,
4
)
self
.
ETAday
=
self
.
read_uint
(
self
.
sentence
,
278
,
5
)
self
.
ETAhour
=
self
.
read_uint
(
self
.
sentence
,
283
,
5
)
self
.
ETAminute
=
self
.
read_uint
(
self
.
sentence
,
288
,
6
)
self
.
draught
=
self
.
read_uint
(
self
.
sentence
,
294
,
8
)
/
10.0
self
.
destination
=
self
.
read_string
(
self
.
sentence
,
302
,
120
)
class
AISmsg21
(
AISmsg
)
:
NOT_SPECIFIED
=
0
REFERENCE_POINT
=
1
RACON
=
2
FIXED_STRUCTURE_OFFSHORE
=
3
LIGHT_WITHOUT_SECTORS
=
5
LIGHT_WITH_SECTORS
=
6
LEADING_LIGHT_FRONT
=
7
LEADING_LIGHT_REAR
=
8
BEACON_CARDINAL_N
=
9
BEACON_CARDINAL_E
=
10
BEACON_CARDINAL_S
=
11
BEACON_CARDINAL_W
=
12
BEACON_PORT
=
13
BEACON_STARBOARD
=
14
BEACON_PREF_PORT
=
15
BEACON_PREF_STARBOARD
=
16
BEACON_ISOLATED
=
17
BEACON_SAFE_WATER
=
18
BEACON_SPECIAL_MARK
=
19
CARDINAL_N
=
20
CARDINAL_E
=
21
CARDINAL_S
=
22
CARDINAL_W
=
23
PORT_HAND_MARK
=
24
STARBOARD_HAND_MARK
=
25
PREF_CHANNEL_PORT
=
26
PREF_CHANNEL_STARBOARD
=
27
ISOLATED_DANGER
=
28
SAFE_WATER
=
29
SPECIAL_MARK
=
30
LIGHT_VESSEL
=
31
def
__init__
(
self
)
:
AISmsg
.
__init__
(
self
)
self
.
type
=
21
self
.
AtoN_type
=
self
.
NOT_SPECIFIED
self
.
name
=
''
self
.
accuracy
=
1
self
.
lon
=
0.0
self
.
lat
=
0.0
self
.
to_bow
=
0
self
.
to_stern
=
0
self
.
to_port
=
0
self
.
to_starboard
=
0
self
.
deviceType
=
0
self
.
timeStamp
=
0
self
.
offPosition
=
0
self
.
AtoN_status
=
0
self
.
RAIM
=
0
self
.
virtual_AtoN
=
0
self
.
assigned
=
0
self
.
spare
=
0
self
.
extension
=
''
def
_encode
(
self
)
:
self
.
bb
=
bitBuf
()
self
.
aisframe
=
''
self
.
padding
=
0
self
.
bb
.
WriteByte
(
self
.
type
,
6
)
self
.
bb
.
WriteByte
(
self
.
repeat
,
2
)
self
.
bb
.
WriteInteger
(
self
.
mmsi
,
30
)
self
.
bb
.
WriteByte
(
self
.
AtoN_type
,
5
)
self
.
bb
.
WriteString
(
self
.
name
,
20
)
self
.
bb
.
WriteBit
(
self
.
accuracy
)
lon
=
int
((
self
.
lon
*
600000
)
+
0.5
)
if
self
.
lon
<
0
:
lon
=
(
lon
^
0x0fffffff
)
+
1
# 2-complement
self
.
bb
.
WriteInteger
(
lon
,
28
)
lat
=
int
((
self
.
lat
*
600000
)
+
0.5
)
if
self
.
lat
<
0
:
lat
=
(
lat
^
0x0fffffff
)
+
1
# 2-complement
self
.
bb
.
WriteInteger
(
lat
,
27
)
self
.
bb
.
WriteInteger
(
self
.
to_bow
,
9
)
self
.
bb
.
WriteInteger
(
self
.
to_stern
,
9
)
self
.
bb
.
WriteByte
(
self
.
to_port
,
6
)
self
.
bb
.
WriteByte
(
self
.
to_starboard
,
6
)
self
.
bb
.
WriteByte
(
self
.
deviceType
,
4
)
self
.
bb
.
WriteByte
(
self
.
timeStamp
,
6
)
self
.
bb
.
WriteBit
(
self
.
offPosition
)
self
.
bb
.
WriteByte
(
self
.
AtoN_status
,
8
)
self
.
bb
.
WriteBit
(
self
.
RAIM
)
self
.
bb
.
WriteBit
(
self
.
virtual_AtoN
)
self
.
bb
.
WriteBit
(
self
.
assigned
)
self
.
bb
.
WriteBit
(
self
.
spare
)
if
len
(
self
.
extension
)
>
0
:
self
.
bb
.
WriteString
(
self
.
extension
,
len
(
self
.
extension
))
self
.
bb
.
WriteInteger
(
self
.
spare2
,
6
)
self
.
aisframe
=
self
.
_bin2asc
()
self
.
padding
=
self
.
bb
.
Padding
()
def
_decode
(
self
,
sentence
)
:
self
.
sentence
=
sentence
self
.
AtoN_type
=
self
.
read_uint
(
self
.
sentence
,
38
,
5
)
self
.
name
=
self
.
read_string
(
self
.
sentence
,
43
,
120
)
self
.
accuracy
=
self
.
read_uint
(
self
.
sentence
,
163
,
1
)
self
.
lon
=
self
.
read_int
(
self
.
sentence
,
164
,
28
)
/
600000.0
self
.
lat
=
self
.
read_int
(
self
.
sentence
,
192
,
27
)
/
600000.0
self
.
to_bow
=
self
.
read_uint
(
self
.
sentence
,
219
,
9
)
self
.
to_stern
=
self
.
read_uint
(
self
.
sentence
,
228
,
9
)
self
.
to_port
=
self
.
read_uint
(
self
.
sentence
,
237
,
6
)
self
.
to_starboard
=
self
.
read_uint
(
self
.
sentence
,
243
,
6
)
self
.
deviceType
=
self
.
read_uint
(
self
.
sentence
,
249
,
4
)
self
.
timeStamp
=
self
.
read_uint
(
self
.
sentence
,
253
,
6
)
self
.
offPosition
=
self
.
read_uint
(
self
.
sentence
,
259
,
1
)
self
.
AtoN_status
=
self
.
read_uint
(
self
.
sentence
,
260
,
8
)
self
.
RAIM
=
self
.
read_uint
(
self
.
sentence
,
268
,
1
)
self
.
virtual_AtoN
=
self
.
read_uint
(
self
.
sentence
,
269
,
1
)
self
.
assigned
=
self
.
read_uint
(
self
.
sentence
,
270
,
1
)
self
.
spare
=
self
.
read_uint
(
self
.
sentence
,
271
,
1
)
#
# Code for testing classes
#
if
__name__
==
'__main__'
:
obj
=
AISmsg5
()
obj
.
mmsi
=
205344990
obj
.
callSign
=
'ATC'
obj
.
name
=
'PETIT BAIGNEUR'
obj
.
destination
=
'MARSEILLE'
obj
.
to_bow
=
50
obj
.
to_stern
=
20
obj
.
to_port
=
10
obj
.
to_starboard
=
10
obj
.
ETAmonth
=
12
obj
.
ETAday
=
12
obj
.
ETAhour
=
1
obj
.
ETAminute
=
30
obj
.
draught
=
10
multi
=
obj
.
Encode
()
for
aivdm
in
multi
:
print
aivdm
obj
=
AISmsg1
()
obj
.
mmsi
=
205344990
obj
.
navStatus
=
AISmsg1
.
UNDERWAY_ENGINE
obj
.
sog
=
20
obj
.
accuracy
=
1
obj
.
lat
=
43.01666
obj
.
lon
=
6.0
obj
.
cog
=
110.7
obj
.
hdg
=
AISmsg1
.
HDG_NOT_AVAILABLE
obj
.
timeStamp
=
40
obj
.
specialManoeuvre
=
AISmsg1
.
SPECIAL_MANOEUVRE_NOT_AVAIL
obj
.
RAIM
=
1
obj
.
state
=
0
multi
=
obj
.
Encode
()
for
aivdm
in
multi
:
print
aivdm
obj
=
AISmsg21
()
obj
.
mmsi
=
101010100
obj
.
AtoN_type
=
AISmsg21
.
BEACON_CARDINAL_N
obj
.
name
=
'Nord'
obj
.
accuracy
=
1
obj
.
lat
=
42.0
+
0.05
obj
.
lon
=
6.0
obj
.
virtual_AtoN
=
1
multi
=
obj
.
Encode
()
for
aivdm
in
multi
:
print
aivdm
# !AIVDM,1,1,,A,E1PE:e4W7a20000000000000000@=fr0<1uF0000000010,4*7D
decoder
=
AISmsg
()
decoder
.
Fragment
(
'!AIVDM,2,1,,A,533m@oP000005@<00010E@UB084TLpEE800000006@D::361NI3@DTiBC31@,0*4C'
)
ais
=
decoder
.
Fragment
(
'!AIVDM,2,2,,A,00000000000,2*14'
)
if
ais
!=
None
:
print
'Type : '
+
str
(
ais
.
type
)
print
'mmsi : '
+
str
(
ais
.
mmsi
)
print
ais
.
name
print
ais
.
destination
print
ais
.
__dict__
Event Timeline
Log In to Comment