My application is including a board that talks with a host linux computer using Cyphal Serial.
Everything seems to work properly (Including publishers/subscribers/clients) but the servers do not seem to work.
Right now I am trying to develop firmware updates over Cyphal.
I am sending ExecCommand to the board with COMMAND_BEGIN_SOFTWARE_UPDATE, the board responds and then tries to use ReadFile to start reading the update file from the host but the ReadFile server never triggers.
Up to now I have tried in my Cyphal Class:
To set up a callback
self._node.get_server(uavcan.file.Read_1).serve_in_background(self._serve_file_read)
@staticmethod
async def _serve_file_read(
request: uavcan.file.Read_1.Request,
metadata: pycyphal.presentation.ServiceRequestMetadata,
) -> uavcan.file.Read_1.Response:
logging.info(" <-- Execute file read request %s from node %d", request, metadata.client_node_id)
if request.command == uavcan.file.Read_1.Request:
try:
path = request.patha
offset = request.offset
data = Path(path).read_bytes()
logging.info("Reading file: ")
logging.info(data)
except Exception as e: # Do nothing if already removed.
logging.error(e)
pass
return uavcan.file.Read_1.Response()
return uavcan.file.Read_1.Response()
To setup a file server
roots = [Path(), Path() ...]
self.fs = FileServer(self._node, roots)
I also tried yakut -v file-server --update-software NODE_ID
which hangs after the following log while the boards keeps sending ReadFile requests.
INF yakut.cmd.file_server: Node NODE_ID confirmed software update command uavcan.node.ExecuteCommand.Request.1.1(command=65533, parameter='PATH')
Do I need to set up any environmental variable for ReadFile? I guessed not since its a fixed port.
Is there any documentation for servers except the standard pycyphal demo ? (opencyphal-tutorial/docs/1-pc-demo/pycyphal.md at main · maksimdrachov/opencyphal-tutorial · GitHub)
Any help is appreciated
The most comprehensive demo is here:
https://pycyphal.readthedocs.io/en/stable/pages/demo.html
Your code looks correct (except for the condition if request.command == uavcan.file.Read_1.Request:
– it doesn’t make sense but it’s not related to your issues).
You need to enable verbose logging in PyCyphal (e.g., via the PYCYPHAL_LOGLEVEL
environment variable) to see what is happening at the time of request arrival. There will be a lot of output, so you will need to sift through that carefully (LLMs are usually helpful with that).
I also recommend dumping all serial port exchanges into a file, and then feeding that file into an analyzer tool like this: Postmortem dump analyzer tool. It does not support Cyphal Serial out of the box though, but the support is easy to add using CandumpCaptureLoader
as a reference – there is a todo comment about that on line 267. Let me know if you need practical help with that.
The point of using the analyzer tool is to see whether the request actually makes it to the server.
Hello Pavel, thanks for your response and your help.
I did not go into the postmortem tool, it was easier to inspect the packets raw.
Found the error which on my case was the PORT id.
I did not know that when calling a service I need to manually add 16384 to the PORT id but when i reply to a service I don’t.
Not sure if this documented somewhere but I was under the impression that is was the same for request/reply.
Maybe you could add a comment about this in the serial header example of the cyphal specification to make it clear.
Best Regards
Ah right its there, my bad thanks!
Hello Pavel, I am encountering a new problem with my application and I would like to ask for help.
I am using pycyphal and yakut’s FileServer to communicate with my board for firmware updates over UART and I noticed that logging messages from pycyphal are ported to UART. I receive all logging messages in my board’s UART Rx which at points breaks my application.
- Is this intended behavior?
- If yes is there a way to disable it and only send the logging messages to the cmd?
The behavior you described is enabled when you set uavcan.diagnostic.severity
to any value from 0 to 7 inclusive. More about it here: pycyphal.application.make_node() — PyCyphal 1.20.0 documentation
To disable it, set uavcan.diagnostic.severity
to 8, or remove this register completely.