BlackZork / mqmgateway

MQTT gateway for modbus networks
GNU Affero General Public License v3.0
44 stars 20 forks source link

Add support for RPC to read/write Modbus register ranges #20

Closed lmartorella closed 1 year ago

lmartorella commented 1 year ago

The current gateway's declarative support for aggregating, converting and publishing register values as MQTT topic is great. However, for performance reason, in some situations it can be more useful to access Modbus registers on-demand. Some examples:

The idea is then to leverage the MQTT RPC protocol, exposing new object type like this:

modbus:
  networks:
    - name: tcptest
mqtt:
  objects:
    - topic: test_call
      remote_calls:
        - name: range
          register: tcptest.1.1024
          register_type: holding
          size: 16  # Read/write the [1024-1039] address range in one go
      availability: false

The PR doesn't cope with the converters, since the current converter infrastructure requires major overhaul to support range of registers.

The string format of the topic data is in plain istream bank-separated format (e.g. 23 45 67). I'm unsure if the JSON format should be used instead. New PR will probably follow to support full binary data, and to specify data endianness (at the moment the host machine endianness is used by libmodbus implementation). However, I'm not sure how to extend the support of such new "binary" format to state objects too, due to the converters support on top. Any suggestion on how to proceed are welcome!

Due to the amount of changes required, I've tried to arrange the changes in "atomic" commits, that adds one feature at a time.

All the proposed changes are compliant to the current LICENSE.

Thanks! L

BlackZork commented 1 year ago

Many thanks for your contribution!

I think that there are multiple features here that needs to be implemented in correct order:

  1. Add converter support for commands. Current converters should be able to covert data in both directions.
  2. Add support for reading state and writing commands from/to multiple registers at once (writing needs (1) ).
  3. Add support for converting non-string mqtt payload to single or multiple register values. (payload_type is alreay there, but only string is implemented and string is assumed if there is no converter defined).
  4. Add support for MQTT RPC (needs (1),(2) )

As for MQTT RPC, I think that we should declare request and response for RPC like this:

mqtt:
  objects:
    - topic: test_call
          commands:
          - name: set
              register: 273
              register_type: coil
              rpc_response:
                - register: 255
                - register_type: coil

This example uses single registers. When (1) and (2) will be implemented, then command and rpc_response register specification could be defined as a list of registers register address and a count, with converter that knows how to convert multiple uint_16 values to mqtt payload.

The MQTT v5 RPC call will be defined in exactly the same way as command with additional rpc_response section. This section should declare how to send rpc response: send some constant value or read some register data. If register data is used as in example above, then it should be defined in the same way as state is defined now. This section should be optional and if not defined, then gateway should respond with some reasonable default if client sends MQTT v5 response_topic. Eventually we could add rpc_response: no to disable parsing MQTT v5 properties attached to message.

Next thing is error handling. From a quick look into MQTT RPC I am not sure how gateway should respond when write fails or response data cannot be read from modbus device.

I am now focused to implement (1) and (2). (2) is especially important, there are many requests for this. I would like to postpone work on this PR at least until those features go into next version of mqmgateway.

BlackZork commented 1 year ago

Reading implemented in 5de54c8. See #16 for details.

BlackZork commented 1 year ago

I just finished making changes in master branch:

I am not able to work on MQTT RPC now due to other projects ongoing, but if you are able to add support for it on top of my changes, I will of course review it. In this case reopen this PR or create a new one. Thanks!