1
0
mirror of https://github.com/mjg59/python-broadlink.git synced 2024-11-21 14:43:30 +01:00

Improve CRC-16 function (#565)

* Rename calculate_crc16 to crc16

* Apply PEP-8 naming conventions

* Remove unnecessary import

* Accept any sequence type

* Remove unnecessary conversions

* Expose polynomial and initial value as kwargs

* Remove unnecessary bitwise operations

* Store the CRC-16 table for performance

* Add missing type hints

* Update docstring

* General improvements
This commit is contained in:
Felipe Martins Diel 2021-04-01 12:19:16 -03:00 committed by Felipe Martins Diel
parent 1a8ee21a34
commit 86b5d0727c
2 changed files with 30 additions and 24 deletions

View File

@ -3,7 +3,7 @@ from typing import List
from . import exceptions as e
from .device import device
from .helpers import calculate_crc16
from .helpers import crc16
class hysen(device):
@ -19,7 +19,7 @@ class hysen(device):
def send_request(self, input_payload: bytes) -> bytes:
"""Send a request to the device."""
crc = calculate_crc16(input_payload)
crc = crc16(input_payload)
# first byte is length, +2 for CRC16
request_payload = bytearray([len(input_payload) + 2, 0x00])
@ -40,7 +40,7 @@ class hysen(device):
raise ValueError(
"hysen_response_error", "first byte of response is not length"
)
crc = calculate_crc16(response_payload[2:response_payload_len])
crc = crc16(response_payload[2:response_payload_len])
if (response_payload[response_payload_len] == crc & 0xFF) and (
response_payload[response_payload_len + 1] == (crc >> 8) & 0xFF
):

View File

@ -1,26 +1,32 @@
"""Helper functions."""
from ctypes import c_ushort
import typing as t
_crc16_cache = {}
def calculate_crc16(input_data: bytes) -> int:
"""Calculate the CRC-16 of a byte string."""
crc16_tab = []
crc16_constant = 0xA001
def crc16(
sequence: t.Sequence[int],
polynomial: int = 0xA001, # Default: Modbus CRC-16.
init_value: int = 0xFFFF,
) -> int:
"""Calculate the CRC-16 of a sequence of integers."""
global _crc16_cache
for i in range(0, 256):
crc = c_ushort(i).value
for j in range(0, 8):
if crc & 0x0001:
crc = c_ushort(crc >> 1).value ^ crc16_constant
else:
crc = c_ushort(crc >> 1).value
crc16_tab.append(hex(crc))
try:
crc_table = _crc16_cache[polynomial]
except KeyError:
crc_table = []
for dividend in range(0, 256):
remainder = dividend
for _ in range(0, 8):
if remainder & 1:
remainder = remainder >> 1 ^ polynomial
else:
remainder = remainder >> 1
crc_table.append(remainder)
_crc16_cache[polynomial] = crc_table
crcValue = 0xFFFF
for c in input_data:
tmp = crcValue ^ c
rotated = c_ushort(crcValue >> 8).value
crcValue = rotated ^ int(crc16_tab[(tmp & 0x00FF)], 0)
return crcValue
crc = init_value
for item in sequence:
crc = crc >> 8 ^ crc_table[(crc ^ item) & 0xFF]
return crc