add log_level support for modbus commands

This commit is contained in:
Stefan Allius
2024-05-28 19:32:20 +02:00
parent ab9e798152
commit 66657888dd
9 changed files with 52 additions and 36 deletions

View File

@@ -122,25 +122,25 @@ class Talent(Message):
f' Ctl: {int(self.ctrl):#02x} Msg: {fnc.__name__!r}')
return
def send_modbus_cb(self, modbus_pdu: bytearray, state: str):
def send_modbus_cb(self, modbus_pdu: bytearray, log_lvl: int, state: str):
if self.state != self.STATE_UP:
return
self.__build_header(0x70, 0x77)
self.__build_header(0x70, 0x77, log_lvl)
self._send_buffer += b'\x00\x01\xa3\x28' # fixme
self._send_buffer += struct.pack('!B', len(modbus_pdu))
self._send_buffer += modbus_pdu
self.__finish_send_msg()
hex_dump_memory(logging.INFO, f'Send Modbus {state}:{self.addr}:',
hex_dump_memory(log_lvl, f'Send Modbus {state}:{self.addr}:',
self._send_buffer, len(self._send_buffer))
self.writer.write(self._send_buffer)
self._send_buffer = bytearray(0) # self._send_buffer[sent:]
async def send_modbus_cmd(self, func, addr, val) -> None:
async def send_modbus_cmd(self, func, addr, val, log_lvl) -> None:
if self.state != self.STATE_UP:
return
self.mb.build_msg(Modbus.INV_ADDR, func, addr, val)
self.mb.build_msg(Modbus.INV_ADDR, func, addr, val, log_lvl)
def _init_new_client_conn(self) -> bool:
contact_name = self.contact_name
@@ -217,15 +217,16 @@ class Talent(Message):
self.header_valid = True
return
def __build_header(self, ctrl, msg_id=None) -> None:
def __build_header(self, ctrl, msg_id=None,
log_lvl: int = logging.INFO) -> None:
if not msg_id:
msg_id = self.msg_id
self.send_msg_ofs = len(self._send_buffer)
self._send_buffer += struct.pack(f'!l{len(self.id_str)+1}pBB',
0, self.id_str, ctrl, msg_id)
fnc = self.switch.get(msg_id, self.msg_unknown)
logger.info(self.__flow_str(self.server_side, 'tx') +
f' Ctl: {int(ctrl):#02x} Msg: {fnc.__name__!r}')
logger.log(log_lvl, self.__flow_str(self.server_side, 'tx') +
f' Ctl: {int(ctrl):#02x} Msg: {fnc.__name__!r}')
def __finish_send_msg(self) -> None:
_len = len(self._send_buffer) - self.send_msg_ofs

View File

@@ -248,15 +248,15 @@ class SolarmanV5(Message):
return True
def __build_header(self, ctrl) -> None:
def __build_header(self, ctrl, log_lvl: int = logging.INFO) -> None:
'''build header for new transmit message'''
self.send_msg_ofs = len(self._send_buffer)
self._send_buffer += struct.pack(
'<BHHHL', 0xA5, 0, ctrl, self.seq.get_send(), self.snr)
fnc = self.switch.get(ctrl, self.msg_unknown)
logger.info(self.__flow_str(self.server_side, 'tx') +
f' Ctl: {int(ctrl):#04x} Msg: {fnc.__name__!r}')
logger.log(log_lvl, self.__flow_str(self.server_side, 'tx') +
f' Ctl: {int(ctrl):#04x} Msg: {fnc.__name__!r}')
def __finish_send_msg(self) -> None:
'''finish the transmit message, set lenght and checksum'''
@@ -302,23 +302,23 @@ class SolarmanV5(Message):
self._heartbeat())
self.__finish_send_msg()
def send_modbus_cb(self, pdu: bytearray, state: str):
def send_modbus_cb(self, pdu: bytearray, log_lvl: int, state: str):
if self.state != self.STATE_UP:
return
self.__build_header(0x4510)
self.__build_header(0x4510, log_lvl)
self._send_buffer += struct.pack('<BHLLL', self.MB_RTU_CMD,
0x2b0, 0, 0, 0)
self._send_buffer += pdu
self.__finish_send_msg()
hex_dump_memory(logging.INFO, f'Send Modbus {state}:{self.addr}:',
hex_dump_memory(log_lvl, f'Send Modbus {state}:{self.addr}:',
self._send_buffer, len(self._send_buffer))
self.writer.write(self._send_buffer)
self._send_buffer = bytearray(0) # self._send_buffer[sent:]
async def send_modbus_cmd(self, func, addr, val) -> None:
async def send_modbus_cmd(self, func, addr, val, log_lvl) -> None:
if self.state != self.STATE_UP:
return
self.mb.build_msg(Modbus.INV_ADDR, func, addr, val)
self.mb.build_msg(Modbus.INV_ADDR, func, addr, val, log_lvl)
async def send_at_cmd(self, AT_cmd: str) -> None:
if self.state != self.STATE_UP:

View File

@@ -74,7 +74,8 @@ class Modbus():
0x3029: {'reg': Register.PV4_TOTAL_GENERATION, 'fmt': '!L', 'ratio': 0.01}, # noqa: E501
}
def __init__(self, snd_handler: Callable[[str], None], timeout: int = 1):
def __init__(self, snd_handler: Callable[[bytes, int, str], None],
timeout: int = 1):
if not len(self.__crc_tab):
self.__build_crc_tab(CRC_POLY)
self.que = asyncio.Queue(100)
@@ -94,6 +95,7 @@ class Modbus():
self.counter['retries'] = {}
for i in range(0, self.max_retries+1):
self.counter['retries'][f'{i}'] = 0
self.last_log_lvl = logging.DEBUG
self.last_addr = 0
self.last_fcode = 0
self.last_len = 0
@@ -106,7 +108,8 @@ class Modbus():
def __del__(self):
logging.debug(f'Modbus __del__:\n {self.counter}')
def build_msg(self, addr: int, func: int, reg: int, val: int) -> None:
def build_msg(self, addr: int, func: int, reg: int, val: int,
log_lvl=logging.DEBUG) -> None:
"""Build MODBUS RTU request frame and add it to the tx queue
Keyword arguments:
@@ -118,7 +121,8 @@ class Modbus():
msg = struct.pack('>BBHH', addr, func, reg, val)
msg += struct.pack('<H', self.__calc_crc(msg))
self.que.put_nowait({'req': msg,
'rsp_hdl': None})
'rsp_hdl': None,
'log_lvl': log_lvl})
if self.que.qsize() == 1:
self.__send_next_from_que()
@@ -140,7 +144,8 @@ class Modbus():
logger.error('Modbus recv: CRC error')
return False
self.que.put_nowait({'req': buf,
'rsp_hdl': rsp_handler})
'rsp_hdl': rsp_handler,
'log_lvl': logging.INFO})
if self.que.qsize() == 1:
self.__send_next_from_que()
@@ -245,7 +250,7 @@ class Modbus():
logger.debug(f'Modbus retrans {self}')
self.retry_cnt += 1
self.__start_timer()
self.snd_handler(self.last_req, state='Retrans')
self.snd_handler(self.last_req, self.last_log_lvl, state='Retrans')
else:
logger.info(f'Modbus timeout {self}')
self.counter['timeouts'] += 1
@@ -260,6 +265,7 @@ class Modbus():
req = item['req']
self.last_req = req
self.rsp_handler = item['rsp_hdl']
self.last_log_lvl = item['log_lvl']
self.last_addr = req[0]
self.last_fcode = req[1]
@@ -268,7 +274,7 @@ class Modbus():
self.last_len = res[1]
self.retry_cnt = 0
self.__start_timer()
self.snd_handler(self.last_req, state='Command')
self.snd_handler(self.last_req, self.last_log_lvl, state='Command')
except asyncio.QueueEmpty:
pass

View File

@@ -165,7 +165,7 @@ class Mqtt(metaclass=Singleton):
elif params == 2:
addr = int(res[0], base=16)
val = int(res[1]) # lenght
await fnc(func, addr, val)
await fnc(func, addr, val, logging.INFO)
async def at_cmd(self, message):
payload = message.payload.decode("UTF-8")

View File

@@ -40,8 +40,8 @@ class Schedule:
if m.server_side:
fnc = getattr(m, "send_modbus_cmd", None)
if callable(fnc):
await fnc(Modbus.READ_REGS, 0x3008, 21)
await fnc(Modbus.READ_REGS, 0x3008, 21, logging.DEBUG)
if 0 == (cls.count % 30):
# logging.info("Regular Modbus Status request")
await fnc(Modbus.READ_REGS, 0x2007, 2)
await fnc(Modbus.READ_REGS, 0x2007, 2, logging.DEBUG)
cls.count += 1

View File

@@ -14,7 +14,7 @@ class TestHelper(Modbus):
self.pdu = None
self.send_calls = 0
self.recv_responses = 0
def send_cb(self, pdu: bytearray, state: str):
def send_cb(self, pdu: bytearray, log_lvl: int, state: str):
self.pdu = pdu
self.send_calls += 1
def resp_handler(self):

View File

@@ -1,6 +1,7 @@
import pytest
import struct
import time
import logging
from datetime import datetime
from app.src.gen3plus.solarman_v5 import SolarmanV5
from app.src.config import Config
@@ -1200,7 +1201,7 @@ async def test_msg_build_modbus_req(ConfigTsunInv1, DeviceIndMsg, DeviceRspMsg,
m._send_buffer = bytearray(0) # clear send buffer for next test
m._forward_buffer = bytearray(0) # clear send buffer for next test
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0)
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
assert m._recv_buffer==InverterIndMsg # unhandled next message
assert 0 == m.send_msg_ofs
assert m._forward_buffer == b''
@@ -1216,7 +1217,7 @@ async def test_msg_build_modbus_req(ConfigTsunInv1, DeviceIndMsg, DeviceRspMsg,
m._send_buffer = bytearray(0) # clear send buffer for next test
m._forward_buffer = bytearray(0) # clear send buffer for next test
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0)
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
assert 0 == m.send_msg_ofs
assert m._forward_buffer == b''
assert m.writer.sent_pdu == MsgModbusCmd
@@ -1224,7 +1225,7 @@ async def test_msg_build_modbus_req(ConfigTsunInv1, DeviceIndMsg, DeviceRspMsg,
m._send_buffer = bytearray(0) # clear send buffer for next test
m.test_exception_async_write = True
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0)
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
assert 0 == m.send_msg_ofs
assert m._forward_buffer == b''
assert m._send_buffer == b''

View File

@@ -1091,14 +1091,14 @@ async def test_msg_build_modbus_req(ConfigTsunInv1, MsgModbusCmd):
ConfigTsunInv1
m = MemoryStream(b'', (0,), True)
m.id_str = b"R170000000000001"
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0)
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
assert 0 == m.send_msg_ofs
assert m._forward_buffer == b''
assert m._send_buffer == b''
assert m.writer.sent_pdu == b''
m.state = m.STATE_UP
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0)
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
assert 0 == m.send_msg_ofs
assert m._forward_buffer == b''
assert m._send_buffer == b''
@@ -1106,7 +1106,7 @@ async def test_msg_build_modbus_req(ConfigTsunInv1, MsgModbusCmd):
m.writer.sent_pdu = bytearray(0) # clear send buffer for next test
m.test_exception_async_write = True
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0)
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
assert 0 == m.send_msg_ofs
assert m._forward_buffer == b''
assert m._send_buffer == b''