Skip to content

Commit 545d94d

Browse files
author
Steven Ohmert
committed
Clarify and correct registration pattern psuedocode
1 parent d38be6b commit 545d94d

File tree

1 file changed

+38
-11
lines changed

1 file changed

+38
-11
lines changed

tracks/embedded_controller/src/service_registry.md

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,46 @@ This registration model allows each **policy domain** (e.g. power, thermal, char
88

99
## Registration Pattern
1010

11-
The `embedded_services` crate defines the services and their policy managers. A typical registration pattern looks like this:
11+
> **Pseudocode (concept only)**
12+
> The registration flow is: construct → init services → register.
13+
>
14+
> ```rust,ignore
15+
> let battery = BatteryDevice::new(DeviceId(1));
16+
> // ...
17+
> // in an async task function
18+
> embedded_services::init().await;
19+
> embedded_services::power::policy::register_device(&battery).await.unwrap();
20+
> ```
21+
>
22+
> This omits static allocation (`StaticCell`), executor wiring for async tasks, and controller setup, for clarity.
23+
24+
### Realistic skeleton (matches the sample projects)
25+
26+
Refer to the [Battery implementation example](../../guide/how/ec/battery/10-service_registry.html) or the [examples in the embedded-services repository](https://github.com/OpenDevicePartnership/embedded-services/blob/main/examples/std/src/bin/battery.rs#L474) for more concrete examples.
1227
1328
```rust
14-
let battery = BATTERY.init(BatteryDevice::new(...));
15-
let controller = BatteryController::new(battery.clone());
29+
// statically allocate single ownership
30+
static BATTERY: StaticCell<MockBatteryDevice> = StaticCell::new();
1631
17-
SERVICE_REGISTRY.register(controller);
18-
```
32+
// Construct a device handle
33+
let battery = BATTERY.init(MockBatteryDevice::new(DeviceId(1)));
1934
20-
- `BATTERY` is a `StaticCell` (or similar allocation) initialized at startup.
35+
// In an async context, initialize services once, then register the device
36+
embedded_services::init().await;
37+
embedded_services::power::policy::register_device(&battery).await.unwrap();
2138
22-
- `BatteryDevice` wraps the actual component (e.g., a `MockBattery`) and implements required traits.
39+
// Controller setup is covered in the next section.
40+
```
41+
_Semantics note_: In ODP, “Device” types are __handles__ to a single underlying component; the service runtime serializes access. Introducing the controller simply gives policy logic a dedicated handle to act on; it does not create a second owner of the hardware.
2342

24-
- `BatteryController` implements the `Service` trait and delegates operations to the device.
43+
### Bringing in the Controller
2544

26-
- `SERVICE_REGISTRY` stores the controller and makes it accessible to both the async executor and message routing infrastructure.
45+
``` rust
46+
let controller = CONTROLLER.init(
47+
MockBatteryController::<&'static mut MockBattery>::new(battery.inner_battery())
48+
);
49+
```
50+
The controller is given a handle to the inner `MockBattery` (`inner_battery()`), not a second owner of the hardware. All access is serialized through the service runtime.
2751

2852
### What Registration Enables
2953
| Feature | Enabled by Registration |
@@ -50,12 +74,15 @@ flowchart TD
5074
Once a controller is registered, the service registry allows the comms system to route incoming events to the correct service based on:
5175
- The __device ID__
5276
- The __message type__
53-
- The controller's implementation of the `handle()` function (_as defined by Service_)
77+
- The controller's implementation of the `handle()` function (_as defined by ServiceTraits_)
5478

5579
When a message is emitted (e.g. `BatteryEvent::UpdateStatus`), the comms channel looks up the appropriate service and dispatches the message.
5680

81+
Where `ServiceTraits` represent the service traits that define a Controller action,
82+
implementation may look something like this (in this case, `ServiceTraits` defines a function
83+
named `handle`, and it calls upon a local function defined in the device implementation):
5784
```rust
58-
impl Service for BatteryController {
85+
impl ServiceTraits for BatteryController {
5986
async fn handle(&mut self, msg: Message) -> Result<()> {
6087
match msg {
6188
Message::Battery(BatteryEvent::UpdateStatus) => {

0 commit comments

Comments
 (0)