Skip to content

Commit 4af16bc

Browse files
authored
Merge pull request #28 from zeenix/poll-methods
Add poll_seconds, poll_millis & poll_micros attributes
2 parents f235672 + cbb3cc2 commit 4af16bc

File tree

6 files changed

+403
-92
lines changed

6 files changed

+403
-92
lines changed

CLAUDE.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,24 @@ Processes the controller impl block. Distinguishes between:
9393
* Creates `<StructName><MethodName>` stream type and `<StructName><MethodName>Args` struct.
9494
* Signal methods are NOT exposed in the client API (controller emits them directly).
9595

96+
**Poll methods** (marked with `#[controller(poll_*)]`):
97+
* Methods are called periodically at the specified interval.
98+
* Three time unit attributes are supported:
99+
* `#[controller(poll_seconds = N)]` - Poll every N seconds.
100+
* `#[controller(poll_millis = N)]` - Poll every N milliseconds.
101+
* `#[controller(poll_micros = N)]` - Poll every N microseconds.
102+
* Methods with the same timeout value (same unit and value) are grouped into a single ticker arm.
103+
* All methods in a group are called sequentially when the ticker fires (in declaration order).
104+
* Poll methods are NOT exposed in the client API (internal to the controller).
105+
* Uses `embassy_time::Ticker::every()` for timing.
106+
96107
**Getter/setter methods** (from struct field attributes):
97108
* Receives getter/setter field info from struct processing.
98109
* Generates client-side getter methods that request current field value.
99110
* Generates client-side setter methods that update field value (and broadcast if published).
100111

101112
The generated `run()` method contains a `select_biased!` loop that receives method calls from
102-
clients and dispatches them to the user's implementations.
113+
clients, dispatches them to the user's implementations, and handles periodic poll method calls.
103114

104115
### Utilities (`src/util.rs`)
105116
Case conversion functions (`pascal_to_snake_case`, `snake_to_pascal_case`) used for generating type and method names.
@@ -109,6 +120,7 @@ Case conversion functions (`pascal_to_snake_case`, `snake_to_pascal_case`) used
109120
User code must have these dependencies (per README):
110121
* `futures` with `async-await` feature.
111122
* `embassy-sync` for channels and synchronization.
123+
* `embassy-time` for poll method timing (only required if using poll methods).
112124

113125
Dev dependencies include `embassy-executor` and `embassy-time` for testing.
114126

Cargo.lock

Lines changed: 11 additions & 82 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,5 @@ embassy-sync = "0.7.2"
3030
embassy-executor = { version = "0.9.1", features = [
3131
"arch-std",
3232
"executor-thread",
33-
"defmt",
34-
] }
35-
embassy-time = { version = "0.5.0", features = [
36-
"defmt",
37-
"defmt-timestamp-uptime",
38-
"tick-hz-32_768",
3933
] }
34+
embassy-time = { version = "0.5.0", features = ["mock-driver"] }

README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,12 +185,72 @@ methods:
185185
signal events. The stream yields `<struct-name><method-name-in-pascal-case>Args` structs
186186
(e.g., `ControllerPowerErrorArgs`) containing all signal arguments as public fields.
187187

188+
## Poll Methods
189+
190+
Methods can be marked for periodic execution using poll attributes. These methods are called
191+
automatically by the controller's `run()` loop at the specified interval.
192+
193+
Three time unit attributes are supported:
194+
* `#[controller(poll_seconds = N)]` - Poll every N seconds.
195+
* `#[controller(poll_millis = N)]` - Poll every N milliseconds.
196+
* `#[controller(poll_micros = N)]` - Poll every N microseconds.
197+
198+
Example:
199+
```rust,no_run
200+
use firmware_controller::controller;
201+
202+
#[controller]
203+
mod sensor_controller {
204+
pub struct Controller {
205+
#[controller(publish)]
206+
temperature: f32,
207+
}
208+
209+
impl Controller {
210+
// Called every 5 seconds.
211+
#[controller(poll_seconds = 5)]
212+
pub async fn read_temperature(&mut self) {
213+
// Read from sensor and update state.
214+
self.set_temperature(42.0).await;
215+
}
216+
217+
// Called every 100ms.
218+
#[controller(poll_millis = 100)]
219+
pub async fn check_watchdog(&mut self) {
220+
// Pet the watchdog.
221+
}
222+
223+
// Both called every second (grouped together).
224+
#[controller(poll_seconds = 1)]
225+
pub async fn log_status(&self) {
226+
// Log current status.
227+
}
228+
229+
#[controller(poll_seconds = 1)]
230+
pub async fn blink_led(&mut self) {
231+
// Toggle LED.
232+
}
233+
}
234+
}
235+
236+
fn main() {}
237+
```
238+
239+
Key characteristics:
240+
* Poll methods are **not** exposed in the client API. They are internal periodic tasks managed
241+
entirely by the controller's `run()` loop.
242+
* Methods with the same timeout value (same unit and value) are grouped into a single timer arm
243+
and called sequentially when the timer fires (in declaration order).
244+
* Uses `embassy_time::Ticker` for timing, which ensures consistent intervals regardless of method
245+
execution time.
246+
188247
## Dependencies assumed
189248

190249
The `controller` macro assumes that you have the following dependencies in your `Cargo.toml`:
191250

192251
* `futures` with `async-await` feature enabled.
193252
* `embassy-sync`
253+
* `embassy-time` (only required if using poll methods)
194254

195255
## Known limitations & Caveats
196256

0 commit comments

Comments
 (0)