M lazy-lock.json M lua/custom/configs/lspconfig.lua M lua/custom/init.lua A lua/custom/journal.lua A nvim_venv/bin/Activate.ps1 A nvim_venv/bin/activate A nvim_venv/bin/activate.csh A nvim_venv/bin/activate.fish
111 lines
3.1 KiB
Python
111 lines
3.1 KiB
Python
"""Modbus Utilities.
|
|
|
|
A collection of utilities for packing data, unpacking
|
|
data computing checksums, and decode checksums.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
# pylint: disable=missing-type-doc
|
|
import struct
|
|
|
|
|
|
def dict_property(store, index):
|
|
"""Create class properties from a dictionary.
|
|
|
|
Basically this allows you to remove a lot of possible
|
|
boilerplate code.
|
|
|
|
:param store: The store store to pull from
|
|
:param index: The index into the store to close over
|
|
:returns: An initialized property set
|
|
"""
|
|
if hasattr(store, "__call__"):
|
|
getter = lambda self: store( # pylint: disable=unnecessary-lambda-assignment
|
|
self
|
|
)[index]
|
|
setter = lambda self, value: store( # pylint: disable=unnecessary-lambda-assignment
|
|
self
|
|
).__setitem__(index, value)
|
|
elif isinstance(store, str):
|
|
getter = lambda self: self.__getattribute__( # pylint: disable=unnecessary-dunder-call,unnecessary-lambda-assignment
|
|
store
|
|
)[index]
|
|
setter = lambda self, value: self.__getattribute__( # pylint: disable=unnecessary-dunder-call,unnecessary-lambda-assignment
|
|
store
|
|
).__setitem__(index, value)
|
|
else:
|
|
getter = (
|
|
lambda self: store[index] # pylint: disable=unnecessary-lambda-assignment
|
|
)
|
|
setter = lambda self, value: store.__setitem__( # pylint: disable=unnecessary-lambda-assignment
|
|
index, value
|
|
)
|
|
|
|
return property(getter, setter)
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# Bit packing functions
|
|
# --------------------------------------------------------------------------- #
|
|
def pack_bitstring(bits: list[bool]) -> bytes:
|
|
"""Create a bytestring out of a list of bits.
|
|
|
|
:param bits: A list of bits
|
|
|
|
example::
|
|
|
|
bits = [False, True, False, True]
|
|
result = pack_bitstring(bits)
|
|
"""
|
|
ret = b""
|
|
i = packed = 0
|
|
for bit in bits:
|
|
if bit:
|
|
packed += 128
|
|
i += 1
|
|
if i == 8:
|
|
ret += struct.pack(">B", packed)
|
|
i = packed = 0
|
|
else:
|
|
packed >>= 1
|
|
if 0 < i < 8:
|
|
packed >>= 7 - i
|
|
ret += struct.pack(">B", packed)
|
|
return ret
|
|
|
|
|
|
def unpack_bitstring(data: bytes) -> list[bool]:
|
|
"""Create bit list out of a bytestring.
|
|
|
|
:param data: The modbus data packet to decode
|
|
|
|
example::
|
|
|
|
bytes = "bytes to decode"
|
|
result = unpack_bitstring(bytes)
|
|
"""
|
|
byte_count = len(data)
|
|
bits = []
|
|
for byte in range(byte_count):
|
|
value = int(data[byte])
|
|
for _ in range(8):
|
|
bits.append((value & 1) == 1)
|
|
value >>= 1
|
|
return bits
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# Error Detection Functions
|
|
# --------------------------------------------------------------------------- #
|
|
|
|
|
|
def hexlify_packets(packet):
|
|
"""Return hex representation of bytestring received.
|
|
|
|
:param packet:
|
|
:return:
|
|
"""
|
|
if not packet:
|
|
return ""
|
|
return " ".join([hex(int(x)) for x in packet])
|