Skip to content

Feedback about the removal of broadcast_enable in 3.7.0+ #2378

@matesh

Description

@matesh

Versions

  • Python: 3.11
  • OS: Yocto Linux
  • Pymodbus: 3.7.x
  • Modbus Hardware (if used):

Pymodbus Specific

  • Client: tcp/rtu - sync

Description

The changes in the API introduced in 3.7.0 regarding broadcasting are in my opinion problematic. The below is some feedback of my experience with hundreds of different devices and complex systems using modbus TCP/RTU in the energy sector.

The change assumes that messages sent to slave==0 are intended to be broadcast, however, this is not always the case. I deal with several devices that act as a gateway into a system of multiple devices, which have slave==0 by default for their internal operational data, and all other unit IDs are devices addressed behind this gateway device. Previously, using the broadcast_enable flag upon instantiation of the client, it could be clearly defined how the client has to behave when slave==0:

  • When disabled, it was handled as if it was a standard device on the bus, expecting a response to any requests.
  • When enabled, requests were handled as a broadcast message, not expecting a response.

The behaviour is now solely determined by the slave ID which results in undesired behaviour in case when responses are indeed expected from slave==0. When sending a read request to slave==0, the client doesn't take timeout in consideration, not expecting a response and thus requests fail, even though these requests are legitimate.

The assumption made in the documentation, that "experience shows that modern devices do not allow broadcast, mostly because it is inheriently dangerous" is in my opinion incorrect. In industrial control, broadcasting is rather important. We need to write setpoints in the same registers of multiple identical devices on the same RS485 bus (or RS485 bus behind a TCP/RTU gateway), and writing registers individually into each device one by one takes too much time. Broadcasting is thus important in terms of timely delivery of register writes simultaneously into all devices on the same bus.

The assumption "With slave=0 the application can get upto 254 responses on a single request" is in my opinion incorrect: Devices (even modern ones) with modbus implemented properly, ignore read commands on slave==0, only receive write commands (if they support broadcasting at all, otherwise they ignore those messages too), and regardless whether they accepted broadcast write commands or not, they do not respond/confirm the failure or success of any write commands, not even by means of exceptions. I have not yet worked with a device that responded to write broadcast commands, and definitely not read commands on slave==0, unless of course as described above, when they had a slave==0 on purpose, in a well established case.

I believe, that because of the above reasons, the previous implementation, where the client behaviour for slave==0 could be set in the client for the specific use case, was a much more elegant and functional solution than what was introduced in 3.7.0 onwards, therefore I'd recommend either reinstating this option in the clients (more elegant) or handling slave==0 differently between read and write commands (less elegant). If the behaviour introduced in 3.7.0 is preferred to be the default, broadcast_enable could be set to True by default to maintain compatibility with 3.7.0 and above.

I won't be able to use 3.7.0 <= pymodbus on hundreds of systems because of this new behaviour. This is not a problem right now, but it might be in a few years time when I might have to move on to a more recent version due to python compatibility, etc. A small proportion of these gateways allow to be reconfigured to a different slave ID other than the default 0 for the internal data, but not all of them, and reconfiguring the ones that do allow, would require a site visit by a technician causing logistical difficulties. I'd also prefer not having to manage different versions of libraries on different installations based on what type of devices these systems need to interact with. I don't really see a reasonable/straightforward workaround to this without having to change code significantly, potentially causing backwards compatibility issues.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions