Skip to content

Commit 1d3a8cc

Browse files
committed
[geocom] added CRC checksum support
1 parent 396c50f commit 1d3a8cc

File tree

1 file changed

+32
-9
lines changed

1 file changed

+32
-9
lines changed

src/geocompy/geo/__init__.py

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@
4646
from serial import SerialException, SerialTimeoutException
4747

4848
from geocompy.data import Angle, Byte
49-
from geocompy.communication import Connection, DUMMYLOGGER
49+
from geocompy.communication import (
50+
Connection,
51+
DUMMYLOGGER,
52+
crc16_bytewise as crc16
53+
)
5054
from .gctypes import (
5155
GeoComCode,
5256
GeoComResponse,
@@ -120,16 +124,18 @@ class GeoCom(GeoComType):
120124
_R1P: re.Pattern[str] = re.compile(
121125
r"^%R1P,"
122126
r"(\d+)," # COM code
123-
r"(\d+):" # Transaction ID
124-
r"(\d+)" # RPC code
127+
r"(\d+)" # Transaction ID
128+
r"(?:,(\d+))?" # CRC checksum
129+
r":(\d+)" # RPC code
125130
r"(?:,(.*))?$" # parameters
126131
)
127132

128133
def __init__(
129134
self,
130135
connection: Connection,
131136
logger: Logger | None = None,
132-
retry: int = 2
137+
retry: int = 2,
138+
crc: bool = False
133139
):
134140
"""
135141
After the subsystems are initialized, the connection is tested by
@@ -229,6 +235,8 @@ def __init__(
229235
.. versionremoved:: GeoCOM-TPS1200
230236
"""
231237

238+
self._crc: bool = crc
239+
232240
for i in range(retry):
233241
try:
234242
self._conn.send("\n")
@@ -355,6 +363,11 @@ def request(
355363
trid = self.transaction_counter % _MAX_TRANSACTION
356364
self.transaction_counter += 1
357365
cmd = f"%R1Q,{rpc},{trid}:{','.join(strparams)}"
366+
367+
if self._crc:
368+
crc = crc16(cmd)
369+
cmd = f"%R1Q,{rpc},{trid},{crc}:{','.join(strparams)}"
370+
358371
try:
359372
answer = self._conn.exchange(cmd)
360373
except SerialTimeoutException:
@@ -432,7 +445,7 @@ def parse_response(
432445
433446
"""
434447
m = self._R1P.match(response)
435-
_, rpc, trid_expected = cmd.split(":")[0].split(",")
448+
rpc, trid_expected = cmd.split(":")[0].split(",")[1:3]
436449
rpcname = rpcnames.get(int(rpc), rpc)
437450
if not m:
438451
return GeoComResponse(
@@ -444,7 +457,20 @@ def parse_response(
444457
0
445458
)
446459

447-
com_field, tr_field, rpc_field, values = m.groups()
460+
com_field, tr_field, crc_field, rpc_field, values = m.groups()
461+
if crc_field is not None:
462+
crc = int(crc_field)
463+
beg, end = m.regs[3]
464+
if crc != crc16(response[:beg-1] + response[end:]):
465+
return GeoComResponse(
466+
rpcname,
467+
cmd,
468+
response,
469+
GeoComCode.COM_CLNT_RX_CHECKSUM_ERROR,
470+
GeoComCode.OK,
471+
0
472+
)
473+
448474
trid = int(tr_field)
449475
if trid != int(trid_expected):
450476
return GeoComResponse(
@@ -467,9 +493,6 @@ def parse_response(
467493
rpccode = GeoComCode.UNDEFINED
468494

469495
if values is None:
470-
values = ""
471-
472-
if values == "":
473496
return GeoComResponse(
474497
rpcname,
475498
cmd,

0 commit comments

Comments
 (0)