Hi Janaka,
I thought about it some more. I notice that there are methodological similarities between the task of transfer bridging, as we are discussing here, and the monitoring mode discussed at:
I do not see a clear way of implementing transfer-level bridging using the means provided by the public API of the existing implementations. Although the task may seem similar to conventional node-to-node communication, bridging is actually different because it requires the bridge to operate in the promiscuous mode and operate on transfers that neither originate nor terminate at the local node. If you review the dataflow inside a bus monitor and a bridge, you see that they are, in essence, equivalent.
For now, I recommend you to implement bridging by modifying the transport reception logic in Libcanard v1 so that incoming frames are not filtered out based on the address mismatch and that new subscriptions are created automatically ad-hoc upon first reception of a matching frame.
By switching to Libcanard v1 you will also resolve your ROM footprint issues. You will be able to rely on direct manual field manipulation rather than auto-generating code. It’s tedious but ROM-efficient:
uint8_t mode = canardDSDLGetU8(heartbeat_transfer->payload, heartbeat_transfer->payload_size, 34, 3);
uint32_t uptime = canardDSDLGetU32(heartbeat_transfer->payload, heartbeat_transfer->payload_size, 0, 32);
uint32_t vssc = canardDSDLGetU32(heartbeat_transfer->payload, heartbeat_transfer->payload_size, 37, 19);
uint8_t health = canardDSDLGetU8(heartbeat_transfer->payload, heartbeat_transfer->payload_size, 32, 2);
uint8_t buffer[7];
// destination offset value bit-length
canardDSDLSetUxx(&buffer[0], 34, 2, 3); // mode
canardDSDLSetUxx(&buffer[0], 0, 0xDEADBEEF, 32); // uptime
canardDSDLSetUxx(&buffer[0], 37, 0x7FFFF, 19); // vssc
canardDSDLSetUxx(&buffer[0], 32, 2, 2); // health
// Now it can be transmitted:
my_transfer->payload = &buffer[0];
my_transfer->payload_size = sizeof(buffer);
result = canardTxPush(&ins, &my_transfer);