Dane Sabo 3299181c70 Auto sync: 2025-09-02 22:47:53 (10335 files changed)
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
2025-09-02 22:47:53 -04:00

208 lines
6.6 KiB
Python

"""Diagnostic record read/write."""
from __future__ import annotations
import struct
from pymodbus.constants import ModbusStatus
from pymodbus.datastore import ModbusSlaveContext
from pymodbus.device import DeviceInformationFactory, ModbusControlBlock
from pymodbus.pdu.pdu import ModbusPDU
_MCB = ModbusControlBlock()
class ReadExceptionStatusRequest(ModbusPDU):
"""ReadExceptionStatusRequest."""
function_code = 0x07
rtu_frame_size = 4
def encode(self) -> bytes:
"""Encode the message."""
return b""
def decode(self, _data: bytes) -> None:
"""Decode data part of the message."""
async def update_datastore(self, _context: ModbusSlaveContext) -> ModbusPDU:
"""Run a read exception status request against the store."""
status = _MCB.Counter.summary()
return ReadExceptionStatusResponse(status=status, dev_id=self.dev_id, transaction_id=self.transaction_id)
class ReadExceptionStatusResponse(ModbusPDU):
"""ReadExceptionStatusResponse."""
function_code = 0x07
rtu_frame_size = 5
def encode(self) -> bytes:
"""Encode the response."""
return struct.pack(">B", self.status)
def decode(self, data: bytes) -> None:
"""Decode a the response."""
self.status = int(data[0])
# Encapsulate interface transport 43, 14
# CANopen general reference 43, 13
class GetCommEventCounterRequest(ModbusPDU):
"""GetCommEventCounterRequest."""
function_code = 0x0B
rtu_frame_size = 4
def encode(self) -> bytes:
"""Encode the message."""
return b""
def decode(self, _data: bytes) -> None:
"""Decode data part of the message."""
async def update_datastore(self, _context) -> ModbusPDU:
"""Run a read exception status request against the store."""
count = _MCB.Counter.Event
return GetCommEventCounterResponse(count=count, dev_id=self.dev_id, transaction_id=self.transaction_id)
class GetCommEventCounterResponse(ModbusPDU):
"""GetCommEventCounterRequest."""
function_code = 0x0B
rtu_frame_size = 8
def encode(self) -> bytes:
"""Encode the response."""
ready = ModbusStatus.READY if self.status else ModbusStatus.WAITING
return struct.pack(">HH", ready, self.count)
def decode(self, data: bytes) -> None:
"""Decode a the response."""
ready, self.count = struct.unpack(">HH", data)
self.status = ready == ModbusStatus.READY
class GetCommEventLogRequest(ModbusPDU):
"""GetCommEventLogRequest."""
function_code = 0x0C
rtu_frame_size = 4
def encode(self) -> bytes:
"""Encode the message."""
return b""
def decode(self, _data: bytes) -> None:
"""Decode data part of the message."""
async def update_datastore(self, _context: ModbusSlaveContext) -> ModbusPDU:
"""Run a read exception status request against the store."""
return GetCommEventLogResponse(
status=True,
message_count=_MCB.Counter.BusMessage,
event_count=_MCB.Counter.Event,
events=_MCB.getEvents(),
dev_id=self.dev_id, transaction_id=self.transaction_id)
class GetCommEventLogResponse(ModbusPDU):
"""GetCommEventLogRequest."""
function_code = 0x0C
rtu_byte_count_pos = 2
def __init__(self, status: bool = True, message_count: int = 0, event_count: int = 0, events: list[int] | None = None, dev_id: int = 1, transaction_id: int = 0) -> None:
"""Initialize a new instance."""
super().__init__(transaction_id=transaction_id, dev_id=dev_id, status=status)
self.message_count = message_count
self.event_count = event_count
self.events = events or []
def encode(self) -> bytes:
"""Encode the response."""
if self.status:
ready = ModbusStatus.READY
else:
ready = ModbusStatus.WAITING
packet = struct.pack(">B", 6 + len(self.events))
packet += struct.pack(">H", ready)
packet += struct.pack(">HH", self.event_count, self.message_count)
packet += b"".join(struct.pack(">B", e) for e in self.events)
return packet
def decode(self, data: bytes) -> None:
"""Decode a the response."""
length = int(data[0])
status = struct.unpack(">H", data[1:3])[0]
self.status = status == ModbusStatus.READY
self.event_count = struct.unpack(">H", data[3:5])[0]
self.message_count = struct.unpack(">H", data[5:7])[0]
self.events = []
for i in range(7, length + 1):
self.events.append(int(data[i]))
class ReportSlaveIdRequest(ModbusPDU):
"""ReportSlaveIdRequest."""
function_code = 0x11
rtu_frame_size = 4
def encode(self) -> bytes:
"""Encode the message."""
return b""
def decode(self, _data: bytes) -> None:
"""Decode data part of the message."""
async def update_datastore(self, _context: ModbusSlaveContext) -> ModbusPDU:
"""Run a report slave id request against the store."""
information = DeviceInformationFactory.get(_MCB)
id_data = []
for v_item in information.values():
if isinstance(v_item, bytes):
id_data.append(v_item)
else:
id_data.append(v_item.encode())
identifier = b"-".join(id_data)
identifier = identifier or b"Pymodbus"
return ReportSlaveIdResponse(identifier=identifier, dev_id=self.dev_id, transaction_id=self.transaction_id)
class ReportSlaveIdResponse(ModbusPDU):
"""ReportSlaveIdRequeste."""
function_code = 0x11
rtu_byte_count_pos = 2
def __init__(self, identifier: bytes = b"\x00", status: bool = True, dev_id: int = 1, transaction_id: int = 0) -> None:
"""Initialize a new instance."""
super().__init__(transaction_id=transaction_id, dev_id=dev_id, status=status)
self.identifier = identifier
self.byte_count = 0
def encode(self) -> bytes:
"""Encode the response."""
status = ModbusStatus.SLAVE_ON if self.status else ModbusStatus.SLAVE_OFF
length = len(self.identifier) + 1
packet = struct.pack(">B", length)
packet += self.identifier # we assume it is already encoded
packet += struct.pack(">B", status)
return packet
def decode(self, data: bytes) -> None:
"""Decode a the response.
Since the identifier is device dependent, we just return the
raw value that a user can decode to whatever it should be.
"""
self.byte_count = int(data[0])
self.identifier = data[1 : self.byte_count + 1]
status = int(data[-1])
self.status = status == ModbusStatus.SLAVE_ON