Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Difficulties migrating from 3.5.2 to 3.8.6: is_active() is_closing() reset_frame() #2602

Closed
bsense-rius opened this issue Mar 9, 2025 · 6 comments

Comments

@bsense-rius
Copy link

bsense-rius commented Mar 9, 2025

Dear pymodbus community,

Please, please take this comment constructively. My aim is not to underestimate the great job the developers are putting in this library. And I assume that the comments I am about to make have been largely discussed.

I am an early user since the versions 2.X.X for the Serial Client. I tried to be following each new release as it enhances many features that I greatly appreciate. But it has been hard due to the multiple structure changes, that relocate features, change names, depreacte several functions etc. In fact I stopped trying to update till 3.5.2, because although I made the update to 3.6.4, when running with it from time to time there were port unavailabilities that I could not restore, something that did not happen with 3.5.2. I reported that issue. I understood that it was not possible to fix because there are so many things you are considering! I probably was not too clear to help either.

Anyway, I decided to update the library to the latest stable version 3.8.6, after some plumbing on the imports etc is saw that the ModbusProtocol was dropped from the ModbusBaseClient (inheritance). It formerly was in both server and client, but now it is not present in ModbusBaseClient anymore. I used the functions is_active and is_closing that are still present in ModbusProtocol class.

So my question are, if you are so kind:

  • Which were the reasons to remove the inheritance for ModbusBaseClient?

  • Is there any way for me to restore those features, specially is_active() and is_closing() in ModbusBaseClient (for the AsyncModbusSerialClient)

Finally the reset_frame() function has also vanished. I used it a lot to ensure that before any new command send the buffers were cleared. Otherwise, for down to earth industrial serial devices, in some cases the slave got out of sync (for EMI issues or who knows?) so that the input buffer received that dangling bytes that were added on top of the result of the next call. So by using the reset_frame() all these erroneous bytes were discarded. In the change log reset_frame() is mentioned but not in very explicit way I can understand (sorry for that, probably my bad).

So my questions are, if your are so generous to answer:

  • Which were the reasons to remove the reset_frame() function?
  • Is there any way for me to restore that function to be used AsyncModbusSerialClient

I would be really grateful if any of the greatest developers backing this fantastic library could steal a brief of time to answer the questions, even in a telegraphic way, so that you do not waste your time.

@janiversen
Copy link
Collaborator

janiversen commented Mar 9, 2025

The reason to remove/change/add functions is very simply that the library evolves. The changes from v2 to the current v3.8.6 are significant, it would not make sense to have all these versions without having changes !

One of the major changes is that asyncio not only works but is the main line. async in v2 barely worked and had a lot of caveats, meaning an app had to do a lot of tweaking.

E.g. reset() is no longer necessary since clearing the buffer is done with each send().

The server and the client have been divided for quite a long time to ease maintenance.

We now have a much better seperation between the layers, making maintenance a lot easier (transport - framer - pdu - transaction - client/server), alongside a better documentation...so nowadays you should not touch (or know about) the base client.

@janiversen
Copy link
Collaborator

And just for the record, ModbusProtocol is still present in both server and client, just not inherited.

@janiversen
Copy link
Collaborator

Closing, as this is more a question, than an actual bug in pymodbus.

@janiversen janiversen closed this as not planned Won't fix, can't repro, duplicate, stale Mar 9, 2025
@bsense-rius
Copy link
Author

bsense-rius commented Mar 9, 2025

The reason to remove/change/add functions is very simply that the library evolves. The changes from v2 to the current v3.8.6 are significant, it would not make sense to have all these versions without having changes !

Thank you very much. I guess that I made clear that I was running fine with 3.5.2. Just wanted to underline certain fidelity so that i followed this from earlier in time. I was not telling that I wanted to make the huge leap from 2.XX to 3.8.6. Even the title issue / quesrtion made it explicit enough.

One of the major changes is that asyncio not only works but is the main line. async in v2 barely worked and had a lot of caveats, meaning an app had to do a lot of tweaking.

E.g. reset() is no longer necessary since clearing the buffer is done with each send().

The server and the client have been divided for quite a long time to ease maintenance.

We now have a much better seperation between the layers, making maintenance a lot easier (transport - framer - pdu - transaction - client/server), alongside a better documentation...so nowadays you should not touch (or know about) the base client.

How should I access ModbusProtocol then from Client? I do not find the muy way to. I formerly used the modbusClient.client.is_active() / .is_closing() but after some attemps did not dinf that.

As I stated for real world serial modbus devices sometimes you have to tweak commands. For example the WriteSingeCoil() could accept other values than ON / OFF (for example for several board that use pulse timed ON / OFF. I tweaked myself the function easily: if parameter is a boolean use the ModbusStatus.ON / ModbusStatus.OFF, else just pass the 16 bit word value to the underlying write function.

Regards

@janiversen
Copy link
Collaborator

Well the title directly states "migrating from 3.5.2 to 3.8.6", and the same arguments applies to that as to a migration from v2 (to be fair, the changes are much less radical). E.g. between v3.5 and v3.8 the PDU layer was introduced.

ModbusProtocol is not part of the pymodbus API, so if you want to access it you have to dive into the source of pymodbus. Calling is_closing() will most likely not give the information you want, since the client now makes retries automatically, pymodbus offers a trace_connect() function to follow connect/disconnect. is_active() will basically always be true unless a reconnect takes place, so it covered by trace_connect().

I think I have sufficient years of experience (nearly a lifetime) to talk about deviations. Pymodbus support the modbus standard, so really the only reason to tweak commands is if you want to support non-standard devices, and for that pymodbus offers the possibility to add custom PDUs.

According to the standard WriteSingleCoil can only write ON/OFF, and of course it you want a timed or pulse version, you simply make a function WriteMyCoil or a custom PDU that calls WriteSingleCoil 2 times. Tweaking the commands means you have to dive into the source and make changes, which is something we do not recommend.

It seems to me you would benefit from reading about the API, instead of tweaking pymodbus where it really does not seem needed. But of course the choice is yours.

@bsense-rius
Copy link
Author

Thanks a alot!

An old dude here as well. Calling twice is not reliable enough because it depends on the availability of the calling device, so better let the RIOM to deal with pulses as they implement them on the firmware.

I will use the trace_connect() that seems to fit my use case instead of is_active().

Regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants