@@ -40,10 +40,62 @@ class MessageRTU(MessageBase):
4040 neither when receiving nor when sending.
4141 """
4242
43+ @classmethod
44+ def generate_crc16_table (cls ) -> list [int ]:
45+ """Generate a crc16 lookup table.
46+
47+ .. note:: This will only be generated once
48+ """
49+ result = []
50+ for byte in range (256 ):
51+ crc = 0x0000
52+ for _ in range (8 ):
53+ if (byte ^ crc ) & 0x0001 :
54+ crc = (crc >> 1 ) ^ 0xA001
55+ else :
56+ crc >>= 1
57+ byte >>= 1
58+ result .append (crc )
59+ return result
60+ crc16_table : list [int ] = [0 ]
61+
4362 def decode (self , _data : bytes ) -> tuple [int , int , int , bytes ]:
4463 """Decode message."""
4564 return 0 , 0 , 0 , b''
4665
47- def encode (self , _data : bytes , _device_id : int , _tid : int ) -> bytes :
66+ def encode (self , data : bytes , device_id : int , _tid : int ) -> bytes :
4867 """Decode message."""
49- return b''
68+ packet = device_id .to_bytes (1 ,'big' ) + data
69+ return packet + MessageRTU .compute_CRC (packet ).to_bytes (2 ,'big' )
70+
71+ @classmethod
72+ def check_CRC (cls , data : bytes , check : int ) -> bool :
73+ """Check if the data matches the passed in CRC.
74+
75+ :param data: The data to create a crc16 of
76+ :param check: The CRC to validate
77+ :returns: True if matched, False otherwise
78+ """
79+ return cls .compute_CRC (data ) == check
80+
81+ @classmethod
82+ def compute_CRC (cls , data : bytes ) -> int :
83+ """Compute a crc16 on the passed in bytes.
84+
85+ For modbus, this is only used on the binary serial protocols (in this
86+ case RTU).
87+
88+ The difference between modbus's crc16 and a normal crc16
89+ is that modbus starts the crc value out at 0xffff.
90+
91+ :param data: The data to create a crc16 of
92+ :returns: The calculated CRC
93+ """
94+ crc = 0xFFFF
95+ for data_byte in data :
96+ idx = cls .crc16_table [(crc ^ int (data_byte )) & 0xFF ]
97+ crc = ((crc >> 8 ) & 0xFF ) ^ idx
98+ swapped = ((crc << 8 ) & 0xFF00 ) | ((crc >> 8 ) & 0x00FF )
99+ return swapped
100+
101+ MessageRTU .crc16_table = MessageRTU .generate_crc16_table ()
0 commit comments