Skip to content

Commit b7bdb17

Browse files
gratuxjmccrohan
authored andcommitted
fix/improve tcp proxy example
- `asyncio.StreamReader.readexactly` throws when not enough data can be read. - use proper logging.
1 parent 6770b92 commit b7bdb17

1 file changed

Lines changed: 31 additions & 29 deletions

File tree

‎utils/solarman_tcp_proxy.py‎

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,16 @@
1616
import argparse
1717
import asyncio
1818
import struct
19+
import logging
1920
from functools import partial
2021
from umodbus.client.serial.redundancy_check import get_crc
2122
from pysolarmanv5 import PySolarmanV5Async
2223

24+
logging.basicConfig(
25+
level=logging.INFO,
26+
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
27+
)
28+
log = logging.getLogger("solarman")
2329

2430
async def handle_client(
2531
reader: asyncio.StreamReader,
@@ -28,49 +34,49 @@ async def handle_client(
2834
logger_serial: int,
2935
):
3036
solarmanv5 = PySolarmanV5Async(
31-
logger_address, logger_serial, verbose=True, auto_reconnect=True
37+
address=logger_address, serial=logger_serial, verbose=True, auto_reconnect=True, logger=log
3238
)
3339
await solarmanv5.connect()
3440

3541
addr = writer.get_extra_info("peername")
3642

37-
print(f"{addr}: New connection")
43+
log.info(f"{addr}: New connection")
3844

3945
try:
4046
while True:
41-
# Convert TCP to RTU
42-
header = await reader.readexactly(6)
43-
if not header:
47+
try:
48+
# read Modbus TCP frame
49+
header = await reader.readexactly(6)
50+
# decode header
51+
trans_id, proto_id, length = struct.unpack(">HHH", header)
52+
unit_id = await reader.readexactly(1)
53+
pdu = await reader.readexactly(length - 1) # length includes unit_id
54+
except asyncio.IncompleteReadError:
55+
# connection closed
4456
break
4557

46-
trans_id, proto_id, length = struct.unpack(">HHH", header)
47-
unit_id = await reader.readexactly(1)
48-
pdu = await reader.readexactly(length - 1) # length includes unit_id
49-
58+
# create equivalent RTU frame
5059
slave_id = b"\x01"
5160
modbus_rtu = slave_id + pdu + get_crc(slave_id + pdu)
5261

53-
try:
54-
# Convert RTU back to TCP
55-
reply_rtu = await solarmanv5.send_raw_modbus_frame(modbus_rtu)
62+
reply_rtu = await solarmanv5.send_raw_modbus_frame(modbus_rtu)
5663

57-
slave_id_reply = reply_rtu[0:1]
58-
pdu_reply = reply_rtu[1:-2]
59-
crc_reply = reply_rtu[-2:]
64+
# slave_id_reply = reply_rtu[0:1]
65+
pdu_reply = reply_rtu[1:-2]
66+
# crc_reply = reply_rtu[-2:]
6067

61-
mbap = struct.pack(">HHH", trans_id, 0, len(pdu_reply) + 1)
62-
reply_tcp = mbap + unit_id + pdu_reply
68+
# Convert RTU back to TCP
69+
mbap = struct.pack(">HHH", trans_id, 0, len(pdu_reply) + 1)
70+
reply_tcp = mbap + unit_id + pdu_reply
6371

64-
writer.write(reply_tcp)
65-
except:
66-
pass
72+
writer.write(reply_tcp)
6773

6874
await writer.drain()
6975
except OSError:
7076
# https://github.com/python/cpython/issues/83037
7177
pass
7278

73-
print(f"{addr}: Connection closed")
79+
log.info(f"{addr}: Connection closed")
7480
await solarmanv5.disconnect()
7581

7682

@@ -85,14 +91,14 @@ async def run_proxy(
8591
port,
8692
)
8793
async with server:
88-
print(f"Listening on {bind_address}:{port}")
94+
log.info(f"Listening on {bind_address}:{port}")
8995
await server.serve_forever()
9096

9197

9298
def main():
9399
parser = argparse.ArgumentParser(
94-
prog="solarman rtu proxy",
95-
description="A Modbus RTU over TCP Proxy for Solarman loggers",
100+
prog="solarman-tcp-proxy",
101+
description="A Modbus TCP Proxy for Solarman loggers",
96102
)
97103
parser.add_argument(
98104
"-b", "--bind", default="0.0.0.0", help="The address to listen on"
@@ -104,11 +110,7 @@ def main():
104110
"-l", "--logger", required=True, help="The IP address of the logger"
105111
)
106112
parser.add_argument(
107-
"-s",
108-
"--serial",
109-
required=True,
110-
type=int,
111-
help="The serial number of the logger",
113+
"-s", "--serial", required=True, type=int, help="The serial number of the logger"
112114
)
113115
args = parser.parse_args()
114116

0 commit comments

Comments
 (0)