#!/usr/bin/env python3 import argparse import struct from pymodbus.client import ModbusTcpClient def call_with_unit(fn, unit, **kwargs): """ Compatible con varias versiones de pymodbus: - pymodbus 3.x usa device_id - versiones anteriores pueden usar slave o unit """ last_error = None for key in ("device_id", "slave", "unit"): try: return fn(**kwargs, **{key: unit}) except TypeError as e: last_error = e raise last_error def f32_abcd(reg_hi, reg_lo): raw = reg_hi.to_bytes(2, "big") + reg_lo.to_bytes(2, "big") return struct.unpack(">f", raw)[0] def print_holding(client, unit, start, count): print(f"\n=== HOLDING REGISTERS start={start}, count={count}, unit={unit} ===") try: rr = call_with_unit( client.read_holding_registers, unit, address=start, count=count ) except Exception as e: print("EXCEPTION:", repr(e)) return if rr.isError(): print("MODBUS ERROR:", rr) return regs = rr.registers for i, value in enumerate(regs): print(f"{start + i}: {value}") print("\nFloat ABCD por parejas:") for i in range(0, len(regs) - 1, 2): try: value = f32_abcd(regs[i], regs[i + 1]) print(f"{start + i}/{start + i + 1}: {value:.6f}") except Exception as e: print(f"{start + i}/{start + i + 1}: ERROR {e}") def print_bits(client, unit, kind, start, count): print(f"\n=== {kind.upper()} start={start}, count={count}, unit={unit} ===") fn = client.read_discrete_inputs if kind == "discrete" else client.read_coils try: rr = call_with_unit( fn, unit, address=start, count=count ) except Exception as e: print("EXCEPTION:", repr(e)) return if rr.isError(): print("MODBUS ERROR:", rr) return bits = rr.bits[:count] for i, value in enumerate(bits): print(f"{start + i}: {int(value)}") def main(): parser = argparse.ArgumentParser() parser.add_argument("--host", required=True) parser.add_argument("--port", type=int, default=502) parser.add_argument("--unit", type=int, default=1) args = parser.parse_args() client = ModbusTcpClient(args.host, port=args.port, timeout=3) if not client.connect(): print(f"ERROR: no conecta con {args.host}:{args.port}") return print(f"OK: conectado a {args.host}:{args.port}") try: # El WISE muestra Mapping Address(4X) 1001. # Probamos base cero y base uno. print_holding(client, args.unit, 1000, 20) print_holding(client, args.unit, 1001, 20) # Intentos tĂ­picos para DI por Modbus/TCP. # Luego afinamos segĂșn Bit Status del WISE. print_bits(client, args.unit, "discrete", 0, 16) print_bits(client, args.unit, "discrete", 1, 16) print_bits(client, args.unit, "coils", 0, 16) print_bits(client, args.unit, "coils", 1, 16) finally: client.close() if __name__ == "__main__": main()