Merge pull request #70 from s-allius/s-allius/issue69

S allius/issue69
This commit is contained in:
Stefan Allius
2024-05-13 23:05:34 +02:00
committed by GitHub
6 changed files with 307 additions and 53 deletions

View File

@@ -42,7 +42,6 @@ class Talent(Message):
self.contact_name = b''
self.contact_mail = b''
self.db = InfosG3()
self.mb = Modbus()
self.forward_modbus_resp = False
self.switch = {
0x00: self.msg_contact_info,
@@ -392,11 +391,11 @@ class Talent(Message):
self.header_len+self.data_len]
if self.ctrl.is_req():
if not self.mb.recv_req(data[hdr_len:]):
return
self.forward_modbus_resp = True
self.inc_counter('Modbus_Command')
if not self.remoteStream.mb.recv_req(data[hdr_len:]):
self.inc_counter('Invalid_Msg_Format')
else:
self.inc_counter('Modbus_Command')
self.remoteStream.forward_modbus_resp = True
elif self.ctrl.is_ind():
# logger.debug(f'Modbus Ind MsgLen: {modbus_len}')
self.modbus_elms = 0

View File

@@ -60,8 +60,8 @@ class SolarmanV5(Message):
self.snr = 0
self.db = InfosG3P()
self.time_ofs = 0
self.mb = Modbus()
self.forward_modbus_resp = False
self.forward_at_cmd_resp = False
self.switch = {
0x4210: self.msg_data_ind, # real time data
@@ -319,6 +319,7 @@ class SolarmanV5(Message):
async def send_at_cmd(self, AT_cmd: str) -> None:
if self.state != self.STATE_UP:
return
self.forward_at_cmd_resp = False
self.__build_header(0x4510)
self._send_buffer += struct.pack(f'<BHLLL{len(AT_cmd)}sc', self.AT_CMD,
2, 0, 0, 0, AT_cmd.encode('utf-8'),
@@ -372,14 +373,14 @@ class SolarmanV5(Message):
data = self._recv_buffer[self.header_len:]
result = struct.unpack_from('<BLLL', data, 0)
ftype = result[0] # always 2
total = result[1]
# total = result[1]
tim = result[2]
res = result[3] # always zero
logger.info(f'frame type:{ftype:02x}'
f' timer:{tim:08x}s null:{res}')
if self.time_ofs:
dt = datetime.fromtimestamp(total + self.time_ofs)
logger.info(f'ts: {dt.strftime("%Y-%m-%d %H:%M:%S")}')
# if self.time_ofs:
# dt = datetime.fromtimestamp(total + self.time_ofs)
# logger.info(f'ts: {dt.strftime("%Y-%m-%d %H:%M:%S")}')
self.__process_data(ftype)
self.__forward_msg()
@@ -389,7 +390,7 @@ class SolarmanV5(Message):
data = self._recv_buffer
result = struct.unpack_from('<BHLLLHL', data, self.header_len)
ftype = result[0] # 1 or 0x81
total = result[2]
# total = result[2]
tim = result[3]
if 1 == ftype:
self.time_ofs = result[4]
@@ -397,9 +398,9 @@ class SolarmanV5(Message):
cnt = result[6]
logger.info(f'ftype:{ftype:02x} timer:{tim:08x}s'
f' ??: {unkn:04x} cnt:{cnt}')
if self.time_ofs:
dt = datetime.fromtimestamp(total + self.time_ofs)
logger.info(f'ts: {dt.strftime("%Y-%m-%d %H:%M:%S")}')
# if self.time_ofs:
# dt = datetime.fromtimestamp(total + self.time_ofs)
# logger.info(f'ts: {dt.strftime("%Y-%m-%d %H:%M:%S")}')
self.__process_data(ftype)
self.__forward_msg()
@@ -426,11 +427,13 @@ class SolarmanV5(Message):
ftype = result[0]
if ftype == self.AT_CMD:
self.inc_counter('AT_Command')
self.forward_at_cmd_resp = True
elif ftype == self.MB_RTU_CMD:
if not self.mb.recv_req(data[15:]):
return
self.forward_modbus_resp = True
self.inc_counter('Modbus_Command')
if not self.remoteStream.mb.recv_req(data[15:]):
self.inc_counter('Invalid_Msg_Format')
else:
self.inc_counter('Modbus_Command')
self.remoteStream.forward_modbus_resp = True
self.__forward_msg()
# self.__send_ack_rsp(0x1510, ftype)
@@ -440,7 +443,8 @@ class SolarmanV5(Message):
self.header_len+self.data_len]
ftype = data[0]
if ftype == self.AT_CMD:
pass
if not self.forward_at_cmd_resp:
return
elif ftype == self.MB_RTU_CMD:
valid = data[1]
modbus_msg_len = self.data_len - 14

View File

@@ -3,8 +3,10 @@ import weakref
if __name__ == "app.src.messages":
from app.src.infos import Infos
from app.src.modbus import Modbus
else: # pragma: no cover
from infos import Infos
from modbus import Modbus
logger = logging.getLogger('msg')
@@ -58,6 +60,9 @@ class Message(metaclass=IterRegistry):
self._registry.append(weakref.ref(self))
self.server_side = server_side
if server_side:
self.mb = Modbus()
self.header_valid = False
self.header_len = 0
self.data_len = 0

View File

@@ -86,11 +86,11 @@ class Modbus():
# logging.info(f'recv_req: first byte modbus:{buf[0]} len:{len(buf)}')
if not self.check_crc(buf):
self.err = 1
logging.error('Modbus: CRC error')
logging.error('Modbus recv: CRC error')
return False
if buf[0] != self.INV_ADDR:
self.err = 2
logging.info(f'Modbus: Wrong addr{buf[0]}')
logging.info(f'Modbus recv: Wrong addr{buf[0]}')
return False
res = struct.unpack_from('>BHH', buf, 1)
self.last_fcode = res[0]
@@ -103,11 +103,11 @@ class Modbus():
Generator[tuple[str, bool], None, None]:
# logging.info(f'recv_resp: first byte modbus:{buf[0]} len:{len(buf)}')
if not self.check_crc(buf):
logging.error('Modbus: CRC error')
logging.error('Modbus resp: CRC error')
self.err = 1
return
if buf[0] != self.INV_ADDR:
logging.info(f'Modbus: Wrong addr {buf[0]}')
logging.info(f'Modbus resp: Wrong addr {buf[0]}')
self.err = 2
return
if buf[1] != self.last_fcode:

View File

@@ -63,6 +63,12 @@ class MemoryStream(SolarmanV5):
if self.test_exception_async_write:
raise RuntimeError("Peer closed.")
def createClientStream(self, msg, chunks = (0,)):
c = MemoryStream(msg, chunks, False)
self.remoteStream = c
c. remoteStream = self
return c
def _SolarmanV5__flush_recv_msg(self) -> None:
super()._SolarmanV5__flush_recv_msg()
self.msg_count += 1
@@ -350,6 +356,39 @@ def InverterIndMsg800(): # 0x4210 rated Power 800W
msg += b'\x15'
return msg
@pytest.fixture
def InverterIndMsg_81(): # 0x4210 fcode 0x81
msg = b'\xa5\x99\x01\x10\x42\x02\x03' +get_sn() +b'\x81\xb0\x02\xbc\xc8'
msg += b'\x24\x32\x6c\x1f\x00\x00\xa0\x07\x04\x03\x01\x00\x03\x08\x00\x00'
msg += b'\x59\x31\x37\x45\x37\x41\x30\x46\x30\x31\x30\x42\x30\x31\x33\x45'
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
msg += b'\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
msg += b'\x40\x10\x08\xc8\x00\x49\x13\x8d\x00\x36\x00\x00\x02\x58\x06\x7a'
msg += b'\x01\x61\x00\xa8\x02\x54\x01\x5a\x00\x8a\x01\xe4\x01\x5a\x00\xbd'
msg += b'\x02\x8f\x00\x11\x00\x01\x00\x00\x00\x0b\x00\x00\x27\x98\x00\x04'
msg += b'\x00\x00\x0c\x04\x00\x03\x00\x00\x0a\xe7\x00\x05\x00\x00\x0c\x75'
msg += b'\x00\x00\x00\x00\x06\x16\x02\x00\x00\x00\x55\xaa\x00\x01\x00\x00'
msg += b'\x00\x00\x00\x00\xff\xff\x07\xd0\x00\x03\x04\x00\x04\x00\x04\x00'
msg += b'\x04\x00\x00\x01\xff\xff\x00\x01\x00\x06\x00\x68\x00\x68\x05\x00'
msg += b'\x09\xcd\x07\xb6\x13\x9c\x13\x24\x00\x01\x07\xae\x04\x0f\x00\x41'
msg += b'\x00\x0f\x0a\x64\x0a\x64\x00\x06\x00\x06\x09\xf6\x12\x8c\x12\x8c'
msg += b'\x00\x10\x00\x10\x14\x52\x14\x52\x00\x10\x00\x10\x01\x51\x00\x05'
msg += b'\x04\x00\x00\x01\x13\x9c\x0f\xa0\x00\x4e\x00\x66\x03\xe8\x04\x00'
msg += b'\x09\xce\x07\xa8\x13\x9c\x13\x26\x00\x00\x00\x00\x00\x00\x00\x00'
msg += b'\x00\x00\x00\x00\x04\x00\x04\x00\x00\x00\x00\x00\xff\xff\x00\x00'
msg += b'\x00\x00\x00\x00'
msg += correct_checksum(msg)
msg += b'\x15'
return msg
@pytest.fixture
def InverterRspMsg(): # 0x1210
msg = b'\xa5\x0a\x00\x10\x12\x02\02' +get_sn() +b'\x01\x01'
@@ -359,6 +398,15 @@ def InverterRspMsg(): # 0x1210
msg += b'\x15'
return msg
@pytest.fixture
def InverterRspMsg_81(): # 0x1210 fcode 0x81
msg = b'\xa5\x0a\x00\x10\x12\x03\03' +get_sn() +b'\x81\x01'
msg += total()
msg += hb()
msg += correct_checksum(msg)
msg += b'\x15'
return msg
@pytest.fixture
def UnknownMsg(): # 0x5110
msg = b'\xa5\x0a\x00\x10\x51\x10\x84' +get_sn() +b'\x01\x01\x69\x6f\x09'
@@ -461,6 +509,15 @@ def MsgModbusCmd():
msg += b'\x15'
return msg
@pytest.fixture
def MsgModbusCmdCrcErr():
msg = b'\xa5\x17\x00\x10\x45\x03\x02' +get_sn() +b'\x02\xb0\x02'
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x06\x20\x08'
msg += b'\x00\x00\x04\xc8'
msg += correct_checksum(msg)
msg += b'\x15'
return msg
@pytest.fixture
def MsgModbusRsp(): # 0x1510
msg = b'\xa5\x3b\x00\x10\x15\x03\x03' +get_sn() +b'\x02\x01'
@@ -496,6 +553,19 @@ def MsgUnknownCmd():
msg += b'\x15'
return msg
@pytest.fixture
def MsgUnknownCmdRsp(): # 0x1510
msg = b'\xa5\x3b\x00\x10\x15\x03\x03' +get_sn() +b'\x03\x01'
msg += total()
msg += hb()
msg += b'\x0a\xe2\xfa\x33\x01\x03\x28\x40\x10\x08\xd8'
msg += b'\x00\x00\x13\x87\x00\x31\x00\x68\x02\x58\x00\x00\x01\x53\x00\x02'
msg += b'\x00\x00\x01\x52\x00\x02\x00\x00\x01\x53\x00\x03\x00\x00\x00\x04'
msg += b'\x00\x01\x00\x00\x6c\x68'
msg += correct_checksum(msg)
msg += b'\x15'
return msg
@pytest.fixture
def ConfigTsunAllowAll():
Config.config = {'solarman':{'enabled': True}, 'inverters':{'allow_all':True}}
@@ -779,6 +849,52 @@ def test_read_two_messages(ConfigTsunAllowAll, DeviceIndMsg, DeviceRspMsg, Inver
assert m._send_buffer==b''
m.close()
def test_read_two_messages2(ConfigTsunAllowAll, InverterIndMsg, InverterIndMsg_81, InverterRspMsg, InverterRspMsg_81):
ConfigTsunAllowAll
m = MemoryStream(InverterIndMsg, (0,))
m.append_msg(InverterIndMsg_81)
m.read() # read complete msg, and dispatch msg
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
assert m.msg_count == 1
assert m.header_len==11
assert m.snr == 2070233889
assert m.unique_id == '2070233889'
assert m.control == 0x4210
assert m.time_ofs == 0x33e447a0
assert str(m.seq) == '02:02'
assert m.data_len == 0x199
assert m.msg_count == 1
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
assert m._forward_buffer==InverterIndMsg
assert m._send_buffer==InverterRspMsg
m._send_buffer = bytearray(0) # clear send buffer for next test
m._init_new_client_conn()
assert m._send_buffer==b''
assert m._recv_buffer==InverterIndMsg_81
m._send_buffer = bytearray(0) # clear send buffer for next test
m._forward_buffer = bytearray(0) # clear forward buffer for next test
m.read() # read complete msg, and dispatch msg
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
assert m.msg_count == 2
assert m.header_len==11
assert m.snr == 2070233889
assert m.unique_id == '2070233889'
assert m.control == 0x4210
assert m.time_ofs == 0x33e447a0
assert str(m.seq) == '03:03'
assert m.data_len == 0x199
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
assert m._forward_buffer==InverterIndMsg_81
assert m._send_buffer==InverterRspMsg_81
m._send_buffer = bytearray(0) # clear send buffer for next test
m._init_new_client_conn()
assert m._send_buffer==b''
m.close()
def test_unkown_message(ConfigTsunInv1, UnknownMsg):
ConfigTsunInv1
m = MemoryStream(UnknownMsg, (0,))
@@ -1144,7 +1260,7 @@ async def test_AT_cmd(ConfigTsunAllowAll, DeviceIndMsg, DeviceRspMsg, InverterIn
assert m._send_buffer==b''
assert m._forward_buffer==b''
assert str(m.seq) == '02:04'
assert m.forward_at_cmd_resp == False
m.close()
def test_at_command_ind(ConfigTsunInv1, AtCommandIndMsg):
@@ -1172,25 +1288,93 @@ def test_at_command_ind(ConfigTsunInv1, AtCommandIndMsg):
assert m.forward_modbus_resp == False
m.close()
def test_msg_at_command_rsp1(ConfigTsunInv1, AtCommandRspMsg):
ConfigTsunInv1
m = MemoryStream(AtCommandRspMsg)
m.db.stat['proxy']['Unknown_Ctrl'] = 0
m.db.stat['proxy']['Modbus_Command'] = 0
m.forward_at_cmd_resp = True
m.read() # read complete msg, and dispatch msg
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
assert m.msg_count == 1
assert m.control == 0x1510
assert str(m.seq) == '03:03'
assert m.header_len==11
assert m.data_len==10
assert m._forward_buffer==AtCommandRspMsg
assert m._send_buffer==b''
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
assert m.db.stat['proxy']['Modbus_Command'] == 0
m.close()
def test_msg_at_command_rsp2(ConfigTsunInv1, AtCommandRspMsg):
ConfigTsunInv1
m = MemoryStream(AtCommandRspMsg)
m.db.stat['proxy']['Unknown_Ctrl'] = 0
m.db.stat['proxy']['Modbus_Command'] = 0
m.forward_at_cmd_resp = False
m.read() # read complete msg, and dispatch msg
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
assert m.msg_count == 1
assert m.control == 0x1510
assert str(m.seq) == '03:03'
assert m.header_len==11
assert m.data_len==10
assert m._forward_buffer==b''
assert m._send_buffer==b''
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
assert m.db.stat['proxy']['Modbus_Command'] == 0
m.close()
def test_msg_modbus_req(ConfigTsunInv1, MsgModbusCmd):
ConfigTsunInv1
m = MemoryStream(MsgModbusCmd, (0,), False)
m = MemoryStream(b'')
c = m.createClientStream(MsgModbusCmd)
m.forward_modbus_resp = False
m.db.stat['proxy']['Unknown_Ctrl'] = 0
m.db.stat['proxy']['AT_Command'] = 0
m.db.stat['proxy']['Modbus_Command'] = 0
m.read() # read complete msg, and dispatch msg
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
assert m.msg_count == 1
assert m.control == 0x4510
assert str(m.seq) == '03:02'
assert m.header_len==11
assert m.data_len==23
assert m._forward_buffer==MsgModbusCmd
assert m._send_buffer==b''
m.db.stat['proxy']['Invalid_Msg_Format'] = 0
c.read() # read complete msg, and dispatch msg
assert not c.header_valid # must be invalid, since msg was handled and buffer flushed
assert c.msg_count == 1
assert c.control == 0x4510
assert str(c.seq) == '03:02'
assert c.header_len==11
assert c.data_len==23
assert c._forward_buffer==MsgModbusCmd
assert c._send_buffer==b''
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
assert m.db.stat['proxy']['AT_Command'] == 0
assert m.db.stat['proxy']['Modbus_Command'] == 1
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
assert m.forward_modbus_resp == True
m.close()
def test_msg_modbus_req2(ConfigTsunInv1, MsgModbusCmdCrcErr):
ConfigTsunInv1
m = MemoryStream(b'')
c = m.createClientStream(MsgModbusCmdCrcErr)
m.forward_modbus_resp = False
m.db.stat['proxy']['Unknown_Ctrl'] = 0
m.db.stat['proxy']['AT_Command'] = 0
m.db.stat['proxy']['Modbus_Command'] = 0
m.db.stat['proxy']['Invalid_Msg_Format'] = 0
c.read() # read complete msg, and dispatch msg
assert not c.header_valid # must be invalid, since msg was handled and buffer flushed
assert c.msg_count == 1
assert c.control == 0x4510
assert str(c.seq) == '03:02'
assert c.header_len==11
assert c.data_len==23
assert c._forward_buffer==MsgModbusCmdCrcErr
assert c._send_buffer==b''
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
assert m.db.stat['proxy']['AT_Command'] == 0
assert m.db.stat['proxy']['Modbus_Command'] == 0
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
assert m.forward_modbus_resp == True
m.close()
@@ -1201,6 +1385,7 @@ def test_msg_unknown_cmd_req(ConfigTsunInv1, MsgUnknownCmd):
m.db.stat['proxy']['Unknown_Ctrl'] = 0
m.db.stat['proxy']['AT_Command'] = 0
m.db.stat['proxy']['Modbus_Command'] = 0
m.db.stat['proxy']['Invalid_Msg_Format'] = 0
m.read() # read complete msg, and dispatch msg
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
assert m.msg_count == 1
@@ -1213,12 +1398,13 @@ def test_msg_unknown_cmd_req(ConfigTsunInv1, MsgUnknownCmd):
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
assert m.db.stat['proxy']['AT_Command'] == 0
assert m.db.stat['proxy']['Modbus_Command'] == 0
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
assert m.forward_modbus_resp == False
m.close()
def test_msg_modbus_rsp1(ConfigTsunInv1, MsgModbusRsp):
ConfigTsunInv1
m = MemoryStream(MsgModbusRsp, (0,), False)
m = MemoryStream(MsgModbusRsp)
m.db.stat['proxy']['Unknown_Ctrl'] = 0
m.db.stat['proxy']['Modbus_Command'] = 0
m.forward_modbus_resp = False
@@ -1237,7 +1423,7 @@ def test_msg_modbus_rsp1(ConfigTsunInv1, MsgModbusRsp):
def test_msg_modbus_rsp2(ConfigTsunInv1, MsgModbusRsp):
ConfigTsunInv1
m = MemoryStream(MsgModbusRsp, (0,), False)
m = MemoryStream(MsgModbusRsp)
m.db.stat['proxy']['Unknown_Ctrl'] = 0
m.db.stat['proxy']['Modbus_Command'] = 0
m.forward_modbus_resp = True
@@ -1256,7 +1442,7 @@ def test_msg_modbus_rsp2(ConfigTsunInv1, MsgModbusRsp):
def test_msg_modbus_rsp3(ConfigTsunInv1, MsgModbusRsp):
ConfigTsunInv1
m = MemoryStream(MsgModbusRsp, (0,), False)
m = MemoryStream(MsgModbusRsp)
m.append_msg(MsgModbusRsp)
m.forward_modbus_resp = True
@@ -1289,6 +1475,25 @@ def test_msg_modbus_rsp3(ConfigTsunInv1, MsgModbusRsp):
m.close()
def test_msg_unknown_rsp(ConfigTsunInv1, MsgUnknownCmdRsp):
ConfigTsunInv1
m = MemoryStream(MsgUnknownCmdRsp)
m.db.stat['proxy']['Unknown_Ctrl'] = 0
m.db.stat['proxy']['Modbus_Command'] = 0
m.forward_modbus_resp = True
m.read() # read complete msg, and dispatch msg
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
assert m.msg_count == 1
assert m.control == 0x1510
assert str(m.seq) == '03:03'
assert m.header_len==11
assert m.data_len==59
assert m._forward_buffer==MsgUnknownCmdRsp
assert m._send_buffer==b''
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
assert m.db.stat['proxy']['Modbus_Command'] == 0
m.close()
def test_msg_modbus_invalid(ConfigTsunInv1, MsgModbusInvalid):
ConfigTsunInv1
m = MemoryStream(MsgModbusInvalid, (0,), False)

View File

@@ -51,6 +51,12 @@ class MemoryStream(Talent):
def _timestamp(self):
return 1700260990000
def createClientStream(self, msg, chunks = (0,)):
c = MemoryStream(msg, chunks, False)
self.remoteStream = c
c. remoteStream = self
return c
def _Talent__flush_recv_msg(self) -> None:
super()._Talent__flush_recv_msg()
self.msg_count += 1
@@ -188,6 +194,13 @@ def MsgModbusCmd():
msg += b'\x00\x00\x03\xc8'
return msg
@pytest.fixture
def MsgModbusCmdCrcErr():
msg = b'\x00\x00\x00\x20\x10R170000000000001'
msg += b'\x70\x77\x00\x01\xa3\x28\x08\x01\x06\x20\x08'
msg += b'\x00\x00\x04\xc8'
return msg
@pytest.fixture
def MsgModbusRsp():
msg = b'\x00\x00\x00\x20\x10R170000000000001'
@@ -789,27 +802,55 @@ def test_proxy_counter():
def test_msg_modbus_req(ConfigTsunInv1, MsgModbusCmd):
ConfigTsunInv1
m = MemoryStream(MsgModbusCmd, (0,), False)
m = MemoryStream(b'')
c = m.createClientStream(MsgModbusCmd)
m.db.stat['proxy']['Unknown_Ctrl'] = 0
m.db.stat['proxy']['Modbus_Command'] = 0
m.read() # read complete msg, and dispatch msg
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
assert m.msg_count == 1
assert m.id_str == b"R170000000000001"
assert m.unique_id == 'R170000000000001'
assert int(m.ctrl)==112
assert m.msg_id==119
assert m.header_len==23
assert m.data_len==13
assert m._forward_buffer==MsgModbusCmd
assert m._send_buffer==b''
m.db.stat['proxy']['Invalid_Msg_Format'] = 0
c.read() # read complete msg, and dispatch msg
assert not c.header_valid # must be invalid, since msg was handled and buffer flushed
assert c.msg_count == 1
assert c.id_str == b"R170000000000001"
assert c.unique_id == 'R170000000000001'
assert int(c.ctrl)==112
assert c.msg_id==119
assert c.header_len==23
assert c.data_len==13
assert c._forward_buffer==MsgModbusCmd
assert c._send_buffer==b''
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
assert m.db.stat['proxy']['Modbus_Command'] == 1
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
m.close()
def test_msg_modbus_req2(ConfigTsunInv1, MsgModbusCmdCrcErr):
ConfigTsunInv1
m = MemoryStream(b'')
c = m.createClientStream(MsgModbusCmdCrcErr)
m.db.stat['proxy']['Unknown_Ctrl'] = 0
m.db.stat['proxy']['Modbus_Command'] = 0
m.db.stat['proxy']['Invalid_Msg_Format'] = 0
c.read() # read complete msg, and dispatch msg
assert not c.header_valid # must be invalid, since msg was handled and buffer flushed
assert c.msg_count == 1
assert c.id_str == b"R170000000000001"
assert c.unique_id == 'R170000000000001'
assert int(c.ctrl)==112
assert c.msg_id==119
assert c.header_len==23
assert c.data_len==13
assert c._forward_buffer==MsgModbusCmdCrcErr
assert c._send_buffer==b''
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
assert m.db.stat['proxy']['Modbus_Command'] == 0
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
m.close()
def test_msg_modbus_rsp1(ConfigTsunInv1, MsgModbusRsp):
ConfigTsunInv1
m = MemoryStream(MsgModbusRsp, (0,), False)
m = MemoryStream(MsgModbusRsp)
m.db.stat['proxy']['Unknown_Ctrl'] = 0
m.db.stat['proxy']['Modbus_Command'] = 0
m.forward_modbus_resp = False
@@ -830,7 +871,7 @@ def test_msg_modbus_rsp1(ConfigTsunInv1, MsgModbusRsp):
def test_msg_modbus_rsp2(ConfigTsunInv1, MsgModbusRsp):
ConfigTsunInv1
m = MemoryStream(MsgModbusRsp, (0,), False)
m = MemoryStream(MsgModbusRsp)
m.db.stat['proxy']['Unknown_Ctrl'] = 0
m.db.stat['proxy']['Modbus_Command'] = 0
m.forward_modbus_resp = True
@@ -851,7 +892,7 @@ def test_msg_modbus_rsp2(ConfigTsunInv1, MsgModbusRsp):
def test_msg_modbus_rsp3(ConfigTsunInv1, MsgModbusResp20):
ConfigTsunInv1
m = MemoryStream(MsgModbusResp20, (0,), False)
m = MemoryStream(MsgModbusResp20)
m.append_msg(MsgModbusResp20)
m.forward_modbus_resp = True