0

我想使用基于 pymodbus 和 modbus TCP 协议的代码从 SMA STP6.0 太阳能逆变器读取温度。

首先,我从https://pymodbus.readthedocs.io/en/latest/source/example/sunspec_client.html运行 Sunspec 客户端示例。此代码失败并显示以下错误消息:

AttributeError:“ExceptionResponse”对象没有属性“registers”

我在 Ubuntu 上使用 Python3 未更改地运行示例代码。

DEBUG:__main__:reading device block[40000..40002]
Traceback (most recent call last):
  File "/home/pi/scripts/sma-modbus.py", line 301, in <module>
    client = create_sunspec_sync_client("192.168.178.110")
  File "/home/pi/scripts/sma-modbus.py", line 179, in create_sunspec_sync_client
    client.initialize()
  File "/home/pi/scripts/sma-modbus.py", line 225, in initialize
    decoder  = self.get_device_block(self.offset, 2)
  File "/home/pi/scripts/sma-modbus.py", line 266, in get_device_block
    return SunspecDecoder.fromRegisters(response.registers)
AttributeError: 'ExceptionResponse' object has no attribute 'registers'

我已经研究过这个问题,但没有找到解决方案。任何帮助/指针将不胜感激。

4

1 回答 1

0

您正在使用的脚本似乎不支持您的设备。这就是您收到错误的原因,您正在尝试读取尚未定义的 Modbus 地址(它实际上看起来您与您的设备根本没有连接,如果您正在读取错误的地址,您会是得到一个不同的错误,所以首先确保你与你的设备有连接,并且你的端口502是打开的并且没有被过滤)。

在任何情况下,Sunspec 客户端脚本只能从设备中读取信息,您应该能够回收大部分信息。

您可以尝试以下方法从设备读取内部温度:

# --------------------------------------------------------------------------- #
# import the various server implementations
# --------------------------------------------------------------------------- #
from pymodbus.client.sync import ModbusTcpClient as ModbusClient

# --------------------------------------------------------------------------- #
# configure the client logging
# --------------------------------------------------------------------------- #
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s '
          '%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)

# ------------------------------------------------------------------------#
# Define UNIT ID
# ------------------------------------------------------------------------#
UNIT = 126  # default according to the manual, see below

# ------------------------------------------------------------------------#
# Define client
# ------------------------------------------------------------------------#
client = ModbusClient('localhost', port=502)
client.connect()

# ----------------------------------------------------------------------- #
# Read temperature
# ----------------------------------------------------------------------- #
rr = client.read_holding_registers(219, 1, unit=UNIT) #see documentation linked below
print(rr.registers[0])

# ----------------------------------------------------------------------- #
# close the client
# ----------------------------------------------------------------------- #
client.close()

如果您有默认的设备 UNIT ID,这个脚本应该可以工作。

如果你得到一个error: Modbus address does not exist它意味着由于某种原因你的设备有一个不同的 UNIT ID。您可以使用相同的脚本更改以下行来读取地址:

...
# ------------------------------------------------------------------------#
# Define UNIT ID
# ------------------------------------------------------------------------#
UNIT = 1  # default according to the manual, used for reading actual DEVICE ID

...
# ----------------------------------------------------------------------- #
# Read UNIT ID
# ----------------------------------------------------------------------- #
rr = client.read_holding_registers(2112, 1, unit=UNIT) #see documentation linked below
print(rr.registers[0])
....

我从prodcut 文档站点获取了 UNIT ID 和注册号。这是我使用的信息包。还有一个您可能想要检查的软件部分(不过我认为您不会在其中找到任何源代码)。

如果您想读取值以外的int值(例如 Power Drawn,它是unsigned32类型),您应该能够class SunspecDecoder(BinaryPayloadDecoder):从 Sunspec 客户端进行回收。

请注意,根据这些设备的 Modbus 映射,您必须使用read_input_registers制造商所谓的 SMA Modbus 配置文件(默认 UNIT ID 3),但read_holding_registers用于 Sunspec Modbus 配置文件(默认 UNIT ID 126)。

作为最后的免责声明,我自己从未使用过任何这些逆变器,所以我的回答只是基于对文档的快速回顾。这意味着我不能保证我的答案是 100% 准确的,但我希望它仍然有用。

编辑:我忘了提到,当您不确定 UNIT ID 或寄存器时,最好使用QModMaster 之类的工具。这将使您只需单击几下即可快速检查设置。一旦你确定什么是有效的,你就可以继续你的代码。

于 2019-06-29T18:51:31.967 回答