From 9ac1f6f46d5ddefa526e3a39dc363c4a2a51a729 Mon Sep 17 00:00:00 2001 From: Stefan Allius Date: Sun, 19 May 2024 21:17:16 +0200 Subject: [PATCH] add Modbus retrasmissions --- app/src/gen3/talent.py | 21 ++++++++++++++++----- app/src/gen3plus/solarman_v5.py | 10 ++++++++-- app/src/modbus.py | 32 +++++++++++++++++++++++++++----- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/app/src/gen3/talent.py b/app/src/gen3/talent.py index c9cf89d..94eec89 100644 --- a/app/src/gen3/talent.py +++ b/app/src/gen3/talent.py @@ -36,7 +36,7 @@ class Control: class Talent(Message): def __init__(self, server_side: bool, id_str=b''): - super().__init__(server_side, self.send_modbus_cb, 15) + super().__init__(server_side, self.send_modbus_cb, 11) self.await_conn_resp_cnt = 0 self.id_str = id_str self.contact_name = b'' @@ -122,13 +122,21 @@ class Talent(Message): f' Ctl: {int(self.ctrl):#02x} Msg: {fnc.__name__!r}') return - def send_modbus_cb(self, modbus_pdu: bytearray): + def send_modbus_cb(self, modbus_pdu: bytearray, retrans: bool): + if self.state != self.STATE_UP: + return + self.__build_header(0x70, 0x77) 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 Command:{self.addr}:', + if retrans: + cmd = 'Retrans' + else: + cmd = 'Command' + + hex_dump_memory(logging.INFO, f'Send Modbus {cmd}:{self.addr}:', self._send_buffer, len(self._send_buffer)) self.writer.write(self._send_buffer) self._send_buffer = bytearray(0) # self._send_buffer[sent:] @@ -392,11 +400,14 @@ class Talent(Message): self.header_len+self.data_len] if self.ctrl.is_req(): + # if (self.remoteStream.state != self.STATE_UP): + # logger.info('ignore Modbus Request in wrong state') + # return if self.remoteStream.mb.recv_req(data[hdr_len:], self.msg_forward): - self.remoteStream.inc_counter('Modbus_Command') + self.inc_counter('Modbus_Command') else: - self.remoteStream.inc_counter('Invalid_Msg_Format') + self.inc_counter('Invalid_Msg_Format') elif self.ctrl.is_ind(): # logger.debug(f'Modbus Ind MsgLen: {modbus_len}') self.modbus_elms = 0 diff --git a/app/src/gen3plus/solarman_v5.py b/app/src/gen3plus/solarman_v5.py index 80bcc8a..7ac8310 100644 --- a/app/src/gen3plus/solarman_v5.py +++ b/app/src/gen3plus/solarman_v5.py @@ -301,13 +301,19 @@ class SolarmanV5(Message): self._heartbeat()) self.__finish_send_msg() - def send_modbus_cb(self, pdu: bytearray): + def send_modbus_cb(self, pdu: bytearray, retrans: bool): + if self.state != self.STATE_UP: + return self.__build_header(0x4510) self._send_buffer += struct.pack(' None: if self.req_pend: @@ -106,6 +126,7 @@ class Modbus(): try: item = self.que.get_nowait() req = item['req'] + self.last_req = req self.rsp_handler = item['rsp_hdl'] self.last_addr = req[0] self.last_fcode = req[1] @@ -113,8 +134,9 @@ class Modbus(): res = struct.unpack_from('>HH', req, 2) self.last_reg = res[0] self.last_len = res[1] + self.retry_cnt = 0 self.start_timer() - self.snd_handler(req) + self.snd_handler(self.last_req, retrans=False) except asyncio.QueueEmpty: pass @@ -140,7 +162,7 @@ class Modbus(): return True def recv_resp(self, info_db, buf: bytearray, node_id: str) -> \ - Generator[tuple[str, bool], None, None]: + Generator[tuple[str, bool, any], None, None]: # logging.info(f'recv_resp: first byte modbus:{buf[0]} len:{len(buf)}') if not self.req_pend: self.err = 5 @@ -194,7 +216,7 @@ class Modbus(): f' : {result}{unit}') else: self.stop_timer() - + self.counter['retries'][self.retry_cnt] += 1 if self.rsp_handler: self.rsp_handler() self.get_next_req()