Modbus 家庭助手和 python 结构(小端序、大端序、uint16 中的负值)

Modbus home assistant and python struct (little endian, big endian, negative values from uint16)

提问人:tomdelahaba 提问时间:1/19/2023 更新时间:9/28/2023 访问量:317

问:

我有一个关于 modbus 设置的问题。我已经仔细阅读了文档,尝试搜索了一些主题,但不幸的是我没有找到问题的答案。

我有一个热泵,它能够通过modbus进行通信。过去,如果没有 HA,我在 ESP8266 上有自己的应用程序,读取数据、上传数据等。现在我想把它移到 HA 中。我发现 modbus 协议是在 HA 中实现的,这很棒。

现在,在我的自定义应用程序中,我必须读取注册表并修改每个值的响应,因为设备具有 MSB 实现,让我提供一个示例:

从设备文档中,我唯一知道的事情(似乎已经足够了,因为我能够实现该应用程序)是: 热泵在.....上通信IP 地址,在 ....港口。它使用 slave,slave ID 是 ....所有值都以 MSB(最高有效字节)表示。现在关于值,例如外部温度在地址 0 上,类型是只读的,刻度是 100(对于配置文件中的 modbus,它应该是 0.01 - 让我们暂时忽略它),单位是 °C。

所以,我的配置看起来像:

# Modbus configuration
modbus:
  - name: ...
    type: tcp
    host: ...
    port: ...
    delay: 5
    timeout: 5
    sensors:
      - name: Heat pump outside temperature
        address: 0
        slave: 1
        input_type: holding
        device_class: temperature
        state_class: measurement
        data_type: uint16
        unique_id: "ac_heating_outside_temp"

这导致该实体的值为 65436,这显然是错误的。此时的实际值是 -1。uint16 的最大值是 65535,65436-65535 = -99,乘以 0.01(或除以 100)是 -0.99,即(如果我们减去零)-1.00 度......这就是我需要的价值。好吧,在我的 C 应用程序中,我一直在自己(以字节为单位)进行重新计算。不幸的是,我不知道如何在“我们的”modbus yaml 描述中做到这一点。

我一直在寻找文档中的 SWAP、DATA_TYPE 和 STRUCTURE:DOCUMENTATION(文档链接)不幸的是,没有任何工作对我有用。我知道如果我想提供结构,我必须设置自定义data_type,但是在结构中定义自定义类型和“>I”需要读取 2 个注册表,但实体的地址是 0,即 1 个注册表。即使这样,我也尝试过,但我无法获得正确的值。将 uint16 的data_type与交换字节甚至交换字一起使用似乎不起作用。我尝试(出于必要)使用 uint8、2 个注册表一起玩并交换在一起,但没有组合导致正确的结果。Python 结构文档:https://docs.python.org/3.8/library/struct.html

谁能帮我解决这个问题?

python endianness modbus home-assistant uint16

评论


答:

0赞 balun 1/19/2023 #1

您可以考虑Modbus-to-MQTT桥接模式,使用一些专业的Modbus工具轮询设备数据并发布到MQTT,然后家庭助理可以通过MQTT集成轻松集成这些数据。

遵循上述解决方案至少有 3 个优点

  • Modbus 工具(例如 modpoll)为您提供了更多选项(大/小字/字节字节序、各种数据类型)来处理来自不同供应商的一些非标准实现
  • MQTT Broker 将 Modbus 工作负载与 HA 解耦,这有利于模块化设计原则
  • MQTT 代理使调试/故障排除变得更加容易,您可以随时订阅特定主题,而无需 HA 停机。
1赞 Lukasz 9/28/2023 #2

我专门为此目的创建了 mqmgateway。它可以转换从 mobus 寄存器读取的数据,并将其作为字符串值或 json 有效负载呈现给 HomeAssistant。

有 int16、uint16 转换和 MSB/LSB 配置。如果这还不够,您可以添加自己的转换器或使用 exprtk 插件进行更高级的数学运算。