-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStatic24.py
435 lines (352 loc) · 13.6 KB
/
Static24.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
import datetime
import AISData
import MyPreConfigs
import GlobalDefinitions
class STATIC24:
# because type 24 is made up of information from parts "A" and "B"
# cannot just throw data into the AIS_Data variable since to get complete information
# need to receive at least two information packets
# these variables are stored in a dictionary class using (string) MMSI as the key
# a boolean flag is used to indicate whether the information is complete
# a timestamp is used to allow garbage collection for items which have not been completed within a defined time
#
p_mmsi = 0
p_name = ""
p_type = 0 # not available
p_vendor = "" # 3 chars
p_model = 0
p_serial = 0
p_call = ""
p_d2bow = 0
p_d2stern = 0
p_d2port = 0
p_d2starboard = 0
p_mother = (
0 # this field is open to interpretation - definition is confused 30 bits
)
p_complete = (
False # used to indicate if all information has been collected and record valid
)
p_timestamp = (
datetime.datetime.now()
) # used to allow "garbage collection" for items not validated within given period
hasbeenDisposed = False
p_timeout = float(
180
) # defaults to 180 second timeout - adjustable using public (writeonly) Timeout variable
p_valid_a = False
p_valid_b = False
# dont need to store MMSI with the Type24 data since this is held as key in the dictionary
# ditto PartNumber - indicating either Part A or B value of this must be either 0 or 1 representing Part A or Part B
"""
def get_xxxx(self) -> zz:
return self.yyyy
def set_xxxx(self,value):
if isinstance(value, zz):
self.yyyy = value
else:
self.yyyy = ''
raise(ValueError, " Type error xxxx must be a zz")
xxxx = property(get_xxxx, set_xxxx)
"""
def __init__(self, aisobject):
# initialise a collection of parameters presumably held in the aisobject
# first
# print('Instantiating Type 24')
# aisobject.print_AIS()
if aisobject._Payload_ID == 5:
if GlobalDefinitions.Global.diagnostic3:
print(
"ín 5 aisobject Binary",
len(aisobject.AIS_Binary_Payload),
" ",
aisobject.AIS_Binary_Payload
)
# first stuff related to a Type 5 (Static and Voyage RElated)
aisobject.Version = aisobject.ExtractInt(38, 2)
aisobject.IMO = aisobject.ExtractInt(40, 30)
aisobject.Callsign = self.get_string(aisobject.AIS_Binary_Payload, 70, 42)
aisobject.Name = self.get_string(aisobject.AIS_Binary_Payload, 112, 120)
aisobject.ShipType = aisobject.ExtractInt(232, 8)
aisobject.Dim2Bow = aisobject.ExtractInt(240, 9)
aisobject.Dim2Stern = aisobject.ExtractInt(249, 9)
aisobject.Dim2Port = aisobject.ExtractInt(258, 6)
aisobject.Dim2StarBoard = aisobject.ExtractInt(264, 6)
aisobject.PositionFix = aisobject.ExtractInt(270, 4)
aisobject.ETAMonth = aisobject.ExtractInt(274, 4)
aisobject.ETADay = aisobject.ExtractInt(278, 5)
aisobject.ETAHour = aisobject.ExtractInt(283, 5)
aisobject.ETAMinute = aisobject.ExtractInt(288, 6)
aisobject.Draught = aisobject.ExtractInt(294, 8)
aisobject.Destination = self.get_string(
aisobject.AIS_Binary_Payload, 302, 120
)
aisobject.DTE = aisobject.ExtractInt(422, 1)
if aisobject._Payload_ID == 24:
# now we update the objrct just created -
# whether part A or part B will be chcked in update()
self.update(aisobject)
def update(self, aisobject):
# update the Static24 object with data from the AIS stream
# Type 24 can come as either TypeA or TypeB (0 or 1 in bits38-39)
if aisobject.ExtractInt(38, 2) == 0: # Type A
self.p_name = self.get_string(aisobject.AIS_Binary_Payload, 40, 120)
self.p_valid_a = True # indicates we have had valid part A data
else: # Type B
self.p_type = aisobject.ExtractInt(40, 8)
self.p_vendor = self.get_string(aisobject.AIS_Binary_Payload, 48, 18)
self.p_model = aisobject.ExtractInt(66, 4)
self.p_serial = aisobject.ExtractInt(70, 20)
self.p_call = self.get_string(aisobject.AIS_Binary_Payload, 90, 42)
self.p_d2bow = aisobject.ExtractInt(132, 9)
self.p_d2stern = aisobject.ExtractInt(141, 9)
self.p_d2port = aisobject.ExtractInt(150, 6)
self.p_d2starboard = aisobject.ExtractInt(156, 6)
self.p_mother = aisobject.ExtractInt(132, 30)
self.p_valid_b = True # indicates we have had valid part A data
def get_string(self, Binarystring, sstart, length) -> str:
diagnostic = GlobalDefinitions.Global.diagnostic
diagnostic2 = GlobalDefinitions.Global.diagnostic2
diagnostic3 = GlobalDefinitions.Global.diagnostic3
if diagnostic3:
print("in get string start = ", sstart, " length = ", length)
ba = bytearray()
st = Binarystring[sstart + 1: sstart + length + 1]
if diagnostic3:
print("length st =", len(st))
while len(st) < length:
st = st + "0"
for i in range(0, int(length / 6)):
if diagnostic3:
print(st[i * 6: (i * 6) + 6])
temp = int(st[i * 6: (i * 6) + 5], 2)
# print("temp = " + temp);
temp = temp & 0x3F
if temp < 31:
temp = temp + 0x40
ba.append(temp)
i += 1
thisstring = ba.decode("utf-8")
if diagnostic3:
print(thisstring)
# SUPRESS @
no_at = ""
strlength = len(thisstring) - 1
for i in range(0, strlength):
if thisstring[i] == "@":
no_at = no_at + " "
else:
no_at = no_at + thisstring[i]
# Suppress trailing Spaces
for i in range(len(no_at) - 1, 1):
if no_at[i] == " ":
no_at = no_at[0: i - 1]
else:
break
# safety check
if len(no_at) == 0:
no_at = " "
return no_at
def get_int(self, Binarystring, sstart, length) -> int:
diagnostic = GlobalDefinitions.Global.diagnostic
diagnostic2 = GlobalDefinitions.Global.diagnostic2
diagnostic3 = GlobalDefinitions.Global.diagnostic3
if diagnostic3:
print("in get int static24 start = ", sstart, " length = ", length)
st = Binarystring[sstart + 1: sstart + length + 1]
if diagnostic3:
print("in static24 length st =", len(st))
while len(st) < length:
st = st + "0"
# convert binary string to integer base 2
try:
my_int = int(st, 2)
except:
my_int = 0
return my_int
def get_Name(self) -> str:
return self.p_name
def set_Name(self, value):
if isinstance(value, str):
self.p_name = value
self.p_name = Remove_at(self.p_name)
self.p_name = Remove_space(self.p_name)
else:
self.p_name = ""
raise (ValueError, " Type error Name must be a str")
Name = property(get_Name, set_Name)
def get_ShipType(self) -> int:
return self.p_type
def set_ShipType(self, value):
if isinstance(value, int):
self.p_type = value
else:
self.p_type = 0
raise (ValueError, " Type error ShipType must be a int")
ShipType = property(get_ShipType, set_ShipType)
def get_Vendor(self) -> str:
return self.p_vendor
def set_Vendor(self, value):
if isinstance(value, str):
self.p_vendor = value
else:
self.p_vendor = ""
raise (ValueError, " Type error Vendor must be a str")
Vendor = property(get_Vendor, set_Vendor)
def get_Model(self) -> int:
return self.p_model
def set_Model(self, value):
if isinstance(value, int):
self.p_model = value
else:
self.p_model = 0
raise (ValueError, " Type error Model must be a int")
Model = property(get_Model, set_Model)
def get_SerialNo(self) -> int:
return self.p_serial
def set_SerialNo(self, value):
if isinstance(value, int):
self.p_serial = value
else:
self.p_serial = 0
raise (ValueError, " Type error SerialNo must be a int")
SerialNo = property(get_SerialNo, set_SerialNo)
def get_Callsign(self) -> str:
return self.p_call
def set_Callsign(self, value):
if isinstance(value, str):
p_call = value
p_call = Remove_at(p_call)
p_call = Remove_space(p_call)
else:
self.p_call = ""
raise (ValueError, " Type error Callsign must be a str")
Callsign = property(get_Callsign, set_Callsign)
def get_Dim2Bow(self) -> int:
return self.p_d2bow
def set_Dim2Bow(self, value):
if isinstance(value, int):
self.p_d2bow = value
else:
self.p_d2bow = 0
raise (ValueError, " Type error Dim2Bow must be a int")
Dim2Bow = property(get_Dim2Bow, set_Dim2Bow)
def get_Dim2Stern(self) -> int:
return self.p_d2stern
def set_Dim2Stern(self, value):
if isinstance(value, int):
self.p_d2stern = value
else:
self.p_d2stern = 0
raise (ValueError, " Type error Dim2Stern must be a int")
Dim2Stern = property(get_Dim2Stern, set_Dim2Stern)
def get_Dim2Port(self) -> int:
return self.p_d2port
def set_Dim2Port(self, value):
if isinstance(value, int):
self.p_d2port = value
else:
self.p_d2port = 0
raise (ValueError, " Type error Dim2Port must be a int")
Dim2Port = property(get_Dim2Port, set_Dim2Port)
def get_Dim2Starboard(self) -> int:
return self.p_d2starboard
def set_Dim2Starboard(self, value):
if isinstance(value, int):
self.p_d2starboard = value
else:
self.p_d2starboard = 0
raise (ValueError, " Type error Dim2Starboard must be a int")
Dim2Starboard = property(get_Dim2Starboard, set_Dim2Starboard)
def get_MotherMMSI(self) -> int:
return self.p_mother
def set_MotherMMSI(self, value):
if isinstance(value, int):
self.p_mother = value
else:
self.p_mother = 0
raise (ValueError, " Type error MotherMMSI must be a int")
MotherMMSI = property(get_MotherMMSI, set_MotherMMSI)
def get_Valid(self) -> bool:
return self.p_complete
def set_Valid(self, value):
if isinstance(value, bool):
self.p_complete = value
else:
self.p_complete = False
raise (ValueError, " Type error Valid must be a bool")
Valid = property(get_Valid, set_Valid)
def get_Timeout(self) -> float:
return self.p_timeout
def set_Timeout(self, value):
if isinstance(value, float):
self.p_timeout = value
else:
self.p_timeout = float(0)
raise (ValueError, " Type error Timeout must be a float")
Timeout = property(get_Timeout, set_Timeout)
def get_Outdated(self) -> bool:
now = datetime.datetime.now()
tester = self.p_timestamp
tester = tester.AddSeconds(self.p_timeout)
if tester.CompareTo(now) < 0: # if True the timeout period has expired
return True
else:
return False
Outdated = property(get_Outdated)
def get_ValidA(self) -> bool:
return self.p_valid_a
def set_ValidA(self, value):
if isinstance(value, bool):
self.p_valid_a = value
else:
self.p_valid_a = False
raise (ValueError, " Type error ValidA must be a bool")
Valid_A = property(get_ValidA, set_ValidA)
def get_ValidB(self) -> bool:
return self.p_valid_b
def set_ValidB(self, value):
if isinstance(value, bool):
self.p_valid_b = value
else:
self.p_valid_b = False
raise (ValueError, " Type error ValidB must be a bool")
Valid_B = property(get_ValidB, set_ValidB)
def Remove_at(p: str) -> str:
try:
if p.index("@") > 0:
p = p[0: p.index("@")]
return p
else:
if p.index("@") == 0:
return ""
else:
return p
except ValueError:
return p
except Exception as e:
print("Error T24 Remove_at string = " + p + " length = " + str(len(p)) + "\r\n")
raise RuntimeError("Error in Type 24 Remove_at", e) from e
def Remove_space(p: str) -> str:
try:
if p == "":
return ""
else:
if p[len(p) - 1: 1] == " ":
while p[len(p) - 1: 1] == " ":
if len(p) > 1:
p = p[0: len(p) - 1]
else:
return ""
return p
except ValueError:
return ""
except:
print(
"Error T24 Remove_Space string = " + p + " length = " + str(len(p)) + "\r\n"
)
raise RuntimeError("Error in TYpe 24 Remove_Space")
def main(self):
pass
if __name__ == 'main':
main()