@@ -10,6 +10,7 @@ This document describes IPC contracts between various clients and corresponding
1010 - [ ` AccessRegisters ` ] ( #accessregisters )
1111- [ Relay services] ( #relay-services )
1212 - [ ` RawPublisher ` ] ( #rawpublisher )
13+ - [ ` RawRpcClient ` ] ( #rawrpcclient )
1314 - [ ` RawSubscriber ` ] ( #rawsubscriber )
1415- [ File Server services] ( #file-server-services )
1516 - [ ` ListRoots ` ] ( #listroots )
@@ -365,6 +366,155 @@ sequenceDiagram
365366 end
366367```
367368
369+ ## ` RawRpcClient `
370+
371+ ** DSDL definitions:**
372+ - ` RawRpcClient.0.1.dsdl `
373+ ```
374+ @union
375+ uavcan.primitive.Empty.1.0 empty
376+ RawRpcClientCreate.0.1 create
377+ RawRpcClientConfig.0.1 config
378+ RawRpcClientSend.0.1 send
379+ @sealed
380+ ---
381+ @union
382+ uavcan.primitive.Empty.1.0 empty
383+ RawRpcClientReceive.0.1 receive
384+ ocvsmd.common.Error.0.1 send_error
385+ ocvsmd.common.Error.0.1 receive_error
386+ @sealed
387+ ```
388+ - ` RawRpcClientCreate.0.1.dsdl `
389+ ```
390+ uint64 extent_size
391+ uint16 service_id
392+ uint16 server_node_id
393+ @extent 32 * 8
394+ ```
395+ - ` RawRpcClientConfig.0.1.dsdl `
396+ ```
397+ uint8[<=1] priority
398+ @extent 32 * 8
399+ ```
400+ - ` RawRpcClientSend.0.1.dsdl `
401+ ```
402+ uint64 request_timeout_us
403+ uint64 response_timeout_us
404+ uint64 payload_size
405+ @extent 64 * 8
406+ ```
407+ - ` RawRpcClientReceive.0.1.dsdl `
408+ ```
409+ uint8 priority
410+ uint16 remote_node_id
411+ uint64 payload_size
412+ @extent 32 * 8
413+ ```
414+
415+ ** Sequence diagram**
416+ ``` mermaid
417+ sequenceDiagram
418+ actor User
419+ participant RpcClient as RpcClient<br/><<sender>>>
420+ participant RawRpcClient as RawRpcClient<br/><<sender>>>
421+ participant RawRpcClientService
422+ participant CyServiceClient as LibCyphal<br/>RawServiceClient
423+ actor NodeX as NodeX<br/><<cyphal node>>
424+
425+ Note over RpcClient, CyServiceClient: Creating of a Cyphal Network RpcClient.
426+ User ->>+ RawRpcClient: submit(service_id, extent, srv_node_id)
427+ RawRpcClient --)+ RawRpcClientService: Route{ChMsg{}}<br/>RawRpcClient.Request_0_1{Create{service_id, extent, srv_node_id}}
428+ RawRpcClient ->>- User : return
429+
430+ RawRpcClientService ->> CyServiceClient: client = create.makeClient(srv_node_id, service_id, extent)
431+ activate RawRpcClient
432+ alt success
433+ RawRpcClientService --) RawRpcClient: Route{ChMsg{}}<br/>RawRpcClient.Response_0_1{empty}
434+ RawRpcClient ->> RpcClient: create(move(channel))
435+ Note right of RawRpcClient: The client has fulfilled its "factory" role, and<br/>now the RpcClient continues with the channel.
436+ else failure
437+ RawRpcClientService --) RawRpcClient: Route{ChEnd{alive=false, error}}
438+ end
439+ deactivate RawRpcClientService
440+ RawRpcClient -)- User: receiver(rpc_client_or_failure)
441+
442+ Note over RpcClient, CyServiceClient: Making requests to Cyphal Network, receiving responses, and changing request priorities.
443+ loop while keeping the rpc client alive
444+ alt making requests
445+
446+ %% Request
447+ %%
448+ Note over RawRpcClient, RawRpcClientService: Making a request
449+ User ->>+ RpcClient: request<Msg>(msg, timeouts)
450+ RpcClient ->> RpcClient: rawRequest(raw_payload, timeouts)
451+ RpcClient --)+ RawRpcClientService: Route{ChMsg{}}<br/>RawRpcClient.Request_0_1{Send{payload_size, timeouts}}<br/>raw_payload
452+ RpcClient ->>- User: return
453+ RawRpcClientService ->>+ CyServiceClient: promise = client.request(raw_payload, timeouts)
454+ CyServiceClient --) NodeX: SvcRequest<service_id>{}
455+ Note left of NodeX: Cyphal network servers(s)<br/>receive the service request.
456+ CyServiceClient ->>- RawRpcClientService: promise
457+ opt if error
458+ RawRpcClientService --)+ RpcClient: Route{ChMsg{}}<br/>RawRpcClient.Response_0_1{request_error}
459+ deactivate RawRpcClientService
460+ opt there is a receiver
461+ Note right of RpcClient: failure will be dropped<br/>if there is no receiver
462+ RpcClient -)- User: receiver<Result>(failure)
463+ end
464+ end
465+
466+ %% Response
467+ %%
468+ Note over RawRpcClient, RawRpcClientService: Waiting for response...
469+ alt
470+ NodeX --) CyServiceClient: SvcResponse<service_id>{}
471+ else
472+ CyServiceClient -) CyServiceClient: timeout or failure
473+ end
474+ CyServiceClient ->>+ RawRpcClientService: promise result
475+ alt success
476+ RawRpcClientService --)+ RpcClient: Route{ChMsg{}}<br/>RawRpcClient.Response_0_1{Receive{size, meta}}}<br/>raw_payload
477+ RpcClient ->> RpcClient: response.deserialize(raw_payload)
478+ else failure
479+ RawRpcClientService --) RpcClient: Route{ChMsg{}}<br/>RawRpcClient.Response_0_1{response_error}}
480+ end
481+ deactivate RawRpcClientService
482+ opt there is a receiver
483+ Note right of RpcClient: result will be dropped<br/>if there is no receiver
484+ RpcClient -)- User: receiver<Result>(result)
485+ end
486+ else configuring priority
487+ User ->>+ RpcClient: setPriority(priority)
488+ RpcClient --)+ RawRpcClientService: Route{ChMsg{}}<br/>RawRpcClient.Request_0_1{Config{priority}}
489+ RpcClient ->>- User: opt_error
490+ opt !priority.empty
491+ RawRpcClientService ->> CyServiceClient: client.setPriority(priority.front)
492+ end
493+ deactivate RawRpcClientService
494+ end
495+ end
496+
497+ Note over RpcClient, CyServiceClient: Releasing the Cyphal Network RpcClient.
498+ User -x+ RpcClient: release
499+ RpcClient --)+ RawRpcClientService: Route{ChEnd{alive=false}}
500+ deactivate RpcClient
501+ RawRpcClientService -x CyServiceClient: release client
502+ deactivate RawRpcClientService
503+
504+ box SDK Client
505+ actor User
506+ participant RpcClient
507+ participant RawRpcClient
508+ end
509+ box Daemon process<br/>《cyphal node》
510+ participant RawRpcClientService
511+ participant CyServiceClient
512+ end
513+ box Cyphal Network Nodes
514+ actor NodeX
515+ end
516+ ```
517+
368518## ` RawSubscriber `
369519
370520** DSDL definitions:**
0 commit comments