2026-06-25 18:51:33 +02:00

121 lines
3.1 KiB
Python
Executable File

#!/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()