Add duration and toggle setting types to YAML nodes #134

Merged
Claude merged 5 commits from feat/yaml-settings into feat/yaml-nodes 2026-10-16 09:23:26 +00:00
Collaborator

YN-15. Two new endpoint types, both a ctrl::SettingEndpoint on one ctrl::PreferencesStore per node. toggle is an Enablement setting (0 to 1, default a YAML bool, true by default). duration is a Duration setting in whole seconds in YAML (0 to 6553, min <= default <= max, default required), sent in deciseconds. The store's NVS namespace is the node label cut to 15 characters and keys are s<index>, so renaming a setting keeps its value; the README says so, and that changing the index or the first 15 characters of the label loses it. Settings take no pin, binds, disabled_modes or failsafe.

enabled_by: <label> on a switch or touch names a toggle on the same node. The generator emits a one-line predicate function reading it and sets it on every bind whose source is that input. ctrl::Bind gains bool (*enabled)() = nullptr: while the predicate returns false the bind skips its action (no toggle, no follow) but still tracks the source, so a latching switch flipped while disabled does not toggle on re-enabling. The check sits in OnOffStrategy::onSource beside the mode check. The input itself still reports to the bus, as the hand-written nodes' touch pads do; only the local action is skipped, which on a YAML node is the bind. hold on occupancy now takes an integer or the label of a duration on the same node, and then setHoldDs(setting.value()) runs at the top of loop. Cross-node references, and labels of the wrong type, are rejected.

Schema regenerated (hold is integer-or-string, enabled_by, per-type setting fields) and README gains the rows and a Settings section. The C3 fixture has a duration driving the PIR hold and the S3 fixture a toggle gating the touch pad's binds, so CI compiles both.

Tested: Python 75 (was 61) and native 616, none skipped locally. Native tests show a closed gate ignores a fresh press and an open one acts, and that a latching switch flipped while gated does not toggle on re-enabling; moving the check back before the tracking fails the second. A Python test shows the gate is set only on binds whose source has enabled_by. All three fixtures and pio run build.

YN-15. Two new endpoint types, both a `ctrl::SettingEndpoint` on one `ctrl::PreferencesStore` per node. `toggle` is an Enablement setting (0 to 1, `default` a YAML bool, true by default). `duration` is a Duration setting in whole seconds in YAML (0 to 6553, `min <= default <= max`, `default` required), sent in deciseconds. The store's NVS namespace is the node label cut to 15 characters and keys are `s<index>`, so renaming a setting keeps its value; the README says so, and that changing the index or the first 15 characters of the label loses it. Settings take no `pin`, `binds`, `disabled_modes` or `failsafe`. `enabled_by: <label>` on a `switch` or `touch` names a `toggle` on the same node. The generator emits a one-line predicate function reading it and sets it on every bind whose source is that input. `ctrl::Bind` gains `bool (*enabled)() = nullptr`: while the predicate returns false the bind skips its action (no toggle, no follow) but still tracks the source, so a latching switch flipped while disabled does not toggle on re-enabling. The check sits in `OnOffStrategy::onSource` beside the mode check. The input itself still reports to the bus, as the hand-written nodes' touch pads do; only the local action is skipped, which on a YAML node is the bind. `hold` on `occupancy` now takes an integer or the label of a `duration` on the same node, and then `setHoldDs(setting.value())` runs at the top of `loop`. Cross-node references, and labels of the wrong type, are rejected. Schema regenerated (`hold` is integer-or-string, `enabled_by`, per-type setting fields) and README gains the rows and a Settings section. The C3 fixture has a duration driving the PIR hold and the S3 fixture a toggle gating the touch pad's binds, so CI compiles both. Tested: Python 75 (was 61) and native 616, none skipped locally. Native tests show a closed gate ignores a fresh press and an open one acts, and that a latching switch flipped while gated does not toggle on re-enabling; moving the check back before the tracking fails the second. A Python test shows the gate is set only on binds whose source has `enabled_by`. All three fixtures and `pio run` build.
Add duration and toggle setting types to YAML nodes
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
6eb5c29dda
Claude left a comment

enabled_by is inert for every generated node, not just binds. The generator never calls setOnPress (grep scripts/yaml_node.py), and BinaryInput::pressed returns before the predicate unless onPress_ is set. The PR body undersells this. nodes/README.md says "The input is disabled while the toggle is off", which is false: events still broadcast and binds still fire. Either gate emission/binds in the runtime, or drop enabled_by from this PR and the README until it does something.

Two minor ones:

  • scripts/yaml_node.py, declare_endpoint: stray blank line added before the temperature return.
  • A duration with no default fails with "None is not between 0 and 6553", and a test pins that text. Raise a "default is required" error instead.
enabled_by is inert for every generated node, not just binds. The generator never calls setOnPress (grep scripts/yaml_node.py), and BinaryInput::pressed returns before the predicate unless onPress_ is set. The PR body undersells this. nodes/README.md says "The input is disabled while the toggle is off", which is false: events still broadcast and binds still fire. Either gate emission/binds in the runtime, or drop enabled_by from this PR and the README until it does something. Two minor ones: - scripts/yaml_node.py, declare_endpoint: stray blank line added before the temperature return. - A duration with no default fails with "None is not between 0 and 6553", and a test pins that text. Raise a "default is required" error instead.
Say when a duration default is missing and that enabled_by has no effect yet
All checks were successful
Build and test / build (pull_request) Successful in 5m12s
Build and test / release (pull_request) Has been skipped
21e4e14c6a
Gate binds on an input's enabled_by toggle
All checks were successful
Build and test / build (pull_request) Successful in 2m2s
Build and test / release (pull_request) Has been skipped
4e58d80719
Claude left a comment

lib/node-runtime/src/bind.cpp:92: the gate skips the whole onSource call, so sourceOn goes stale while the toggle is off. For a latching switch (ToggleOnChange) flipped while disabled, the first report after re-enabling sees sourceOn != event.on and toggles the light. A Follow bind has the same lag. If that is not intended, move the gate into OnOffStrategy::onSource so it still updates sourceOn but skips the action. If you want it as is, ignore this.

lib/node-runtime/src/bind.cpp:92: the gate skips the whole onSource call, so `sourceOn` goes stale while the toggle is off. For a latching switch (ToggleOnChange) flipped while disabled, the first report after re-enabling sees `sourceOn != event.on` and toggles the light. A Follow bind has the same lag. If that is not intended, move the gate into OnOffStrategy::onSource so it still updates `sourceOn` but skips the action. If you want it as is, ignore this.
Keep tracking a gated bind's source and skip only the action
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
eb5c84f0e8
Reset the gate between bind tests
All checks were successful
Build and test / build (pull_request) Successful in 2m49s
Build and test / release (pull_request) Has been skipped
1ad97076cf
Claude merged commit c77345f65a into feat/yaml-nodes 2026-10-16 09:23:26 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rob/CampervanControlSystems!134
No description provided.