Homepage GitHub

UAVCAN receiving files. Algorithm questions


When writing the code for receiving files, I set 400 ms emergency timeout for receiving UAVCAN_PROTOCOL_FILE_READ_ID.
After testing the reception of files for about a week, I thought that I coped with this task. But after half a year of work, errors began to appear when receiving files.
Due to the delay of the data transmission channel (PC-> USB-> CAN + internal optimization of the transmission systems for data caching), the response can sometimes come with a delay. After the timeout is triggered, I form a repeat of the UAVCAN_PROTOCOL_FILE_READ_ID command with the previous offset value and send the request again, I have 5 such repeats.
After a time when the system (PC-> USB) caching channels go back to normal, I get several responses from the system cache, at the same time, I get confused with the data received in a row, I cannot easily identify them, the response does not contain information about the current segment.
If each response had an additional offset field, then we can understand which part of the file came.
For the time being, I have fixed this by increasing the packet timeout sufficiently.

In this case, it would be nice to add an offset field in the response structure uavcan_protocol_file_ReadResponse, I think so.

typedef struct
// uint32_t offset; <- as a package identifier
uavcan_protocol_file_Error error;


uint16_t len;
uint8_t * data;
} data;

} uavcan_protocol_file_ReadResponse;

I also encountered the problem of transferring files to WINDOWS 10, with similar symptoms. Everything works well on WINDOWS 7.

Can you advise on the correct algorithm for receiving files ?!

Sounds like you are handling your service calls incorrectly. What you are looking for is the Transfer-ID – a numerical identifier that binds service request with its corresponding service response. When you send a request, store its transfer-ID somewhere locally along with the associated offset. When you receive a response, take its transfer-ID and look up the offset from that local storage.

The offset is not manifested in the response transfer precisely because the caller is expected to rely on its local state if such functionality is needed.

Also, you should migrate to UAVCAN v1.0.


Analyzing the code for sending packets, I was not sure that the Transfer-ID of the response would coincide with the Transfer-ID of my request, since I noticed in the code that it unconditionally increases (incrementTransferID (inout_transfer_id)) when sending any command.

Thanks for the affirmative answer to this question.

A small question on the further use of Transfer-ID. Let’s say there is a Lidar device, which additionally provides file server services (allows you to read the archived lidar record as a file). When transferring Lidar messages, the Transfer-ID will automatically increase. And if another subscriber of the network sent a request to the Lidar device to retrieve a file with its Transfer-ID (which must be sent in the response), which differs from the current Transfer-ID of Lidar, what to do with the Transfer-ID:

  1. Inherit Transfer-ID from a file request and make it current for all transfers, including lidar data?
  2. Save the current Transfer-ID of Lidar, respond to the file operation with the Transfer-ID of the subscriber (who sent the request for the file), after the transfer - restore the saved Transfer-ID of Lidar again?

What are the consequences when transferring data from the device to the network can duplication of Transfer-ID lead?

  1. Every session maintains a separate transfer-ID state.

  2. When responding to a service request, always reuse the transfer-ID from the corresponding request transfer.

Suppose your lidar publishes some measurement subjects and provides your file read service. It goes like this:

  • publish measurement message A with transfer-ID 0
  • publish measurement message A with transfer-ID 1
  • publish measurement message A with transfer-ID 2
  • publish measurement message B with transfer-ID 0 (not related to A)
  • having received a service C request with transfer-ID X, respond with transfer-ID X (no need to keep any local state, the client chooses the transfer-ID here)
  • publish measurement message A with transfer-ID 3
  • publish measurement message B with transfer-ID 1

More in the Specification.