AttributeError: у объекта «ExceptionResponse» нет атрибута «registers» в pymodbus - PullRequest
0 голосов
/ 28 июня 2019

Я хотел бы прочитать температуру с солнечного инвертора SMA STP6.0, используя код, основанный на pymodbus, используя протокол TCP Modbus.

Для запуска я запускаю пример клиента Sunspec с https://pymodbus.readthedocs.io/en/latest/source/example/sunspec_client.html.Этот код завершается ошибкой со следующим сообщением об ошибке:

AttributeError: у объекта 'ExceptionResponse' нет атрибута 'registers'

Я выполняю пример кода без изменений, используя Python3в Ubuntu.

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'

Я исследовал эту проблему, но не нашел решения.Любая помощь / указатели будут оценены.

1 Ответ

0 голосов
/ 29 июня 2019

Ваше устройство не поддерживается используемым сценарием.Вот почему вы получаете сообщение об ошибке, вы пытаетесь прочитать адрес 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])
....

Я взял идентификаторы UNIT ID и регистрационные номера с сайта документации по 101d * prodcut .Это информационный пакет , который я использовал.Существует также раздел программного обеспечения , который вы, возможно, захотите проверить (хотя я не думаю, что вы найдете там какой-либо исходный код).

Если вы хотите читать, кроме 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%, но я надеюсь, что он все равно будет полезен.

EDIT : я забыл упомянуть, что когда вы не уверены в идентификаторах UNITили регистрирует, это хорошая идея, чтобы взять инструмент, такой как QModMaster .Это позволит вам быстро проверить настройки за пару кликов.Если вы уверены, что работает, вы можете перейти к своему коду.

...