0

I have a Modbus server setup on a LAN with IP address 192.168.0.111 and Modbus map is this snip below where I am trying read the sensor highlighted yellow:

enter image description here

Can someone give me a tip on how to run a Modbus client script and read the sensor value?

from pymodbus.client import ModbusTcpClient

client = ModbusTcpClient('192.168.0.111')
result = client.read_coils(30500,1)
print(result.bits[0])

client.close()

This will error out:

print(result.bits[0])
AttributeError: 'ExceptionResponse' object has no attribute 'bits'

Experimenting a bit and changing the print to print(result) this will return without an exception

Exception Response(129, 1, IllegalFunction)
bbartling
  • 3,288
  • 9
  • 43
  • 88
  • It might be the case that the first address digit indicates the Modbus function code. Try `client.read_holding_registers(500, 2, unit=1)`. – Bosz Dec 31 '22 at 14:18
  • Thanks for the comment...same thing - `AttributeError: 'ExceptionResponse' object has no attribute 'bits'` – bbartling Dec 31 '22 at 14:29
  • Its one of these stand alone electrical meters: https://www.egauge.net/commercial-energy-monitor/ – bbartling Dec 31 '22 at 14:30
  • One thing I notice is when I use: `result = client.read_input_registers(500, 2, unit=1) print(result)` this doesnt return an `ExceptionResponse` from the device...this will just print `ReadInputRegistersResponse (2)` – bbartling Dec 31 '22 at 14:34
  • But I still cant get around the `print(result.bits[0]) AttributeError: 'ReadInputRegistersResponse' object has no attribute 'bits'` – bbartling Dec 31 '22 at 14:35
  • What does `print result.registers` return? – Bosz Dec 31 '22 at 14:43
  • If I do `result = client.read_input_registers(500,2,units=1)` and a `print(result.registers)` this returns `[17139, 29148]` – bbartling Dec 31 '22 at 16:47
  • the value I am looking for is 120 volts...and what returns makes no sense to me. What is also shown in the screenshot I posted is this which also makes no sense to me `Divide returned value by indicated Denominator to get quantity with the indicated unit` – bbartling Dec 31 '22 at 16:50
  • Combine the two values to a 32 bit float, see https://stackoverflow.com/questions/59883083/convert-two-raw-values-to-32-bit-ieee-floating-point-number – Bosz Dec 31 '22 at 19:43
  • Holy smokes that works....I still have to wrap my head around this but I get `123.0594253540039` which is definitely voltage. if you posted an answer I would hit the green check box – bbartling Dec 31 '22 at 20:18
  • I postend an answer but feel free to post something and ill give you the green check box points – bbartling Dec 31 '22 at 20:21

1 Answers1

1

In the chat for this question...this overstackoverflow question was referenced. Complete answer:

from pymodbus.client import ModbusTcpClient
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder


client = ModbusTcpClient('192.168.0.111')
result = client.read_input_registers(500,2,units=1)
print(result.registers)
decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big)
print(decoder.decode_32bit_float())
client.close()
bbartling
  • 3,288
  • 9
  • 43
  • 88