Skip to content

How to implement a custom server that can be busy? #2620

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

Closed
shyd opened this issue Mar 31, 2025 · 7 comments
Closed

How to implement a custom server that can be busy? #2620

shyd opened this issue Mar 31, 2025 · 7 comments

Comments

@shyd
Copy link

shyd commented Mar 31, 2025

Hi,
in my project, I have custom contexts that communicate with external hardware. Therefore I derive from ModbusSparseDataBlock and overwrite validate, setValues and getValues with my business logic.

For example I have a coil that takes several seconds to process data on the external hardware. A response look like this even the device is busy.

WriteSingleCoilResponse(dev_id=1, transaction_id=1, address=6, count=0, bits=[True], registers=[], status=1)

Now my question is how to use busy flag that the client gets the according response that the device is currently busy? If I use a lock the response would timeout because the lock cannot be acquired in time.

Thank you very much for this project!

@janiversen
Copy link
Collaborator

Modbus do not have a busy flag, please explain which message/flag you are referring to ?

@shyd
Copy link
Author

shyd commented Apr 1, 2025

Thanks for your quick answer! I am referring to

DEVICE_BUSY = 0x06

In my assumption this tells the client, that the device is busy an the client should retry later.

This is also stated in several modbus descriptions like https://www.simplymodbus.ca/exceptions.htm

06(06 hex) | Slave Device Busy | Specialized use in conjunction with programming commands.The slave is engaged in processing a long-duration program command.  The master should retransmit the message later when the slave is free..

@janiversen
Copy link
Collaborator

Yes, but that is received as an exception response, not a normal response. BUT the pymodbus server do not use this exception response.

If you receive that from the device in your datastore-client, you should pass it on...which is not very easy. It is something that is not foreseen in the current server implementation.

If you just need to wait the only option is a wait_for with timeout.

@janiversen
Copy link
Collaborator

janiversen commented Apr 1, 2025

The server context or datastores are designed to respond immediately, delays are not permitted. Also datastores are not designed to return anything but a value (or False in the validate function), so your point of attack seems wrong.

Did you look at the trace functions they allow you to generate/modify responses as you please, that in combination with the datastore might solve your problem.

But of course if you need the server to work differently Pull Requests are always welcome.

@shyd
Copy link
Author

shyd commented Apr 1, 2025

Thanks a lot, this is pointing in the right direction. I set up tracing like in your example.

For testing purposes I just want to return an Exception for all incoming requests. My tracing function looks like this

def my_trace_pdu(self, sending: bool, pdu: ModbusPDU) -> ModbusPDU:
    """Do dummy trace."""
    txt = "REQUEST pdu" if sending else "RESPONSE pdu"
    print(f"---> {txt}: {pdu}")
    if sending:
        return ExceptionResponse(function_code=pdu.function_code, exception_code=ExceptionResponse.SLAVE_BUSY, transaction=pdu.transaction_id)
    return pdu

The server log looks good I think:

---> REQUEST pdu: WriteSingleCoilResponse(dev_id=1, transaction_id=1, address=5, count=0, bits=[1], registers=[], status=1)
2025-04-01 15:04:11,817 ERROR pdu:128 Exception response 133 / 6

But the client doesn't seem to get the Exception number:

2025-04-01 15:04:11,797 ERROR pdu:128 Exception response 133 / 0
ExceptionResponse(dev_id=1, transaction_id=1, address=0, count=0, bits=[], registers=[], status=1)

notice 133 / 6 vs 133 / 0

Can you tell what I am doing wrong here?

@janiversen
Copy link
Collaborator

Did you check the ExceptionCode.

@janiversen
Copy link
Collaborator

Closing as this is not a pymodbus problem.

@janiversen janiversen closed this as not planned Won't fix, can't repro, duplicate, stale Apr 1, 2025
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