#!/usr/bin/env python3 import argparse import struct from pymodbus.client import ModbusSerialClient def regs_to_bytes(regs, mode): a = regs[0] b = regs[1] ab = a.to_bytes(2, "big") cd = b.to_bytes(2, "big") if mode == "ABCD": return ab + cd if mode == "CDAB": return cd + ab if mode == "BADC": return ab[::-1] + cd[::-1] if mode == "DCBA": return cd[::-1] + ab[::-1] raise ValueError(mode) def decode_float_candidates(regs): out = {} for mode in ["ABCD", "CDAB", "BADC", "DCBA"]: try: raw = regs_to_bytes(regs, mode) out[mode] = struct.unpack(">f", raw)[0] except Exception as exc: out[mode] = f"ERR: {exc}" return out def main(): parser = argparse.ArgumentParser() parser.add_argument("--port", default="/dev/ttyRS485") parser.add_argument("--slave", type=int, default=1) parser.add_argument("--baud", type=int, default=9600) parser.add_argument("--parity", default="N", choices=["N", "E", "O"]) parser.add_argument("--stopbits", type=int, default=1) parser.add_argument("--bytesize", type=int, default=8) parser.add_argument("--address", type=int, default=0) parser.add_argument("--count", type=int, default=2) parser.add_argument("--timeout", type=float, default=1.5) args = parser.parse_args() print("--- MODBUS RTU PROBE ---") print(f"port={args.port}") print(f"slave={args.slave}") print(f"baud={args.baud}") print(f"parity={args.parity}") print(f"address={args.address}") print(f"count={args.count}") client = ModbusSerialClient( port=args.port, baudrate=args.baud, parity=args.parity, stopbits=args.stopbits, bytesize=args.bytesize, timeout=args.timeout, ) if not client.connect(): print("[ERROR] Cannot open serial port") return 2 try: rr = client.read_input_registers( address=args.address, count=args.count, device_id=args.slave, ) if rr.isError(): print(f"[ERROR] Modbus error: {rr}") return 3 regs = rr.registers print(f"registers={regs}") print("float_candidates:") for mode, value in decode_float_candidates(regs).items(): print(f" {mode}: {value}") return 0 except Exception as exc: print(f"[ERROR] No Modbus response: {type(exc).__name__}: {exc}") return 3 finally: client.close() if __name__ == "__main__": raise SystemExit(main())