Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ All notable changes to Smart (Components) Toolkit for Homey will be documented i

---

## [1.10.38] - October 2026 (Test channel)

### Added
- Presence+: two new triggers wait until one selected person, or everyone, has remained away for a configurable number of minutes. Returning home cancels the pending trigger, and absence timers survive app restarts without firing the same threshold twice. See the [Presence+ guide](https://tiwas.github.io/SmartComponentsToolkit/docs/presence-plus.html).

### Fixed
- Presence+: a new Home → Away episode is now re-armed correctly even when the trigger call for the previous episode is still pending. Its delay remains anchored to the new Away time, and a Home event still cancels it.
- Circadian Light Group Collection: *Is paused* now returns yes when the Collection itself or at least one available member group is paused. Previously it only read the Collection's own pause flag, so an individually paused member group could be missed and an *All on* Flow could bypass Resume and skip every light in that group.
- Resume on a Collection continues to resume every member group. Together with the aggregate condition, a Flow can now reliably detect the mixed pause state, resume all groups, and then turn their lights on.

## [1.10.35] - October 2026 (Test channel)

### Fixed
Expand Down
14 changes: 11 additions & 3 deletions HOMEY_COMMUNITY_LISTING.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
URL: https://community.homey.app/t/app-smart-components-toolkit-was-boolean-toolbox-create-advanced-logic-with-simple-formulas-v1-10-16-store-v1-10-27-test-logic-device-reliability/143906

Title: [APP] Smart (Components) Toolkit (was: Boolean Toolbox) - Create advanced logic with simple formulas [v1.10.16 store / v1.10.35 test - Circadian cards no longer time out, Flow name card]
Title: [APP] Smart (Components) Toolkit (was: Boolean Toolbox) - Create advanced logic with simple formulas [v1.10.16 store / v1.10.38 test - Presence+, Collection pause detection]

Content:
![xlarge|690x483](upload://iSxhJPUltgcgPQ7gy4z5iisCv5F.jpeg)

# Smart (Components) Toolkit — store v1.10.16 / test v1.10.35
# Smart (Components) Toolkit — store v1.10.16 / test v1.10.38

> **📚 Full Documentation:** https://tiwas.github.io/SmartComponentsToolkit/

Expand All @@ -17,6 +17,13 @@ Replace complex flow networks with powerful logic devices controlled by dynamic

## What's new

### v1.10.38 (test channel)

- **New Presence+.** Trigger a Flow only after one selected person, or everyone, has remained away for a chosen number of minutes. A return before the delay expires cancels the pending trigger, filtering out brief Home/Away glitches. Countdown state survives an app restart. [Read the Presence+ guide](https://tiwas.github.io/SmartComponentsToolkit/docs/presence-plus.html).
- **Repeated departures are re-armed.** If someone returns Home and leaves again while the previous Presence+ trigger call is still finishing, the new absence keeps its own start time and triggers after the configured delay.
- **Collection pause detection fixed.** *Is paused* on a Circadian Light Group Collection now answers yes when the Collection itself or at least one available member group is paused.
- **Reliable All on after a partial pause.** An *All on* Flow can now take its Resume branch when one member group is paused. Resume still reaches every member group before the Flow continues to turn the lights on.

### v1.10.35 (test channel)

- **Circadian Light Group: no more "Timeout after 60000ms".** Homey stops an app's Flow card after 60 seconds, and the rest of the Flow then never runs. With a few lights that don't answer (an unplugged bulb, a Z-Wave module out of range), turning a group or Collection on could take almost that long, because the card waited for every retry. Now the card lets the Flow continue as soon as every light has its commands and has been checked, usually within a few seconds. Lights that haven't confirmed are retried in the background, and no Circadian card waits more than 50 seconds.
Expand Down Expand Up @@ -177,7 +184,7 @@ Together they cover both sides: Flow Doctor shows how your Flows are wired, and

## ✨ Circadian Light Group — now on stable

A virtual **light device** that adjusts brightness and color temperature for a group of real lights — automatically following a circadian rhythm. Store is currently v1.10.16; v1.10.35 is available on the test channel.
A virtual **light device** that adjusts brightness and color temperature for a group of real lights — automatically following a circadian rhythm. Store is currently v1.10.16; v1.10.38 is available on the test channel.

### Circadian Light Group highlights

Expand Down Expand Up @@ -249,6 +256,7 @@ Choose how the device knows how bright it is outside:
|------------------------------|---------|
| **Conditional Gates** | Simple GO/NO GO flow control without variables or devices. Short waits in the card, long waits in the background with a "wait finished" trigger. |
| **Waiter Gates** | Wait until a device capability reaches a target value — in the card (up to 55 s) or in the background with a "wait finished" trigger. |
| **Presence+** | Wait until one selected person, or everyone, has remained away for the configured minutes; any return cancels the pending trigger. |
| **Evaluate Expression** | Range checking and value mapping with AND/OR logic. |
| **Math Compare** | Compare a calculated number, e.g. `Temperature + 3` against a threshold. |
| **Gradient Map** | Map a number from one range to another and pass the `Mapped value` tag to the next card. |
Expand Down
8 changes: 7 additions & 1 deletion PROJECT_DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,18 @@
* **Collection:** `runAwaitedMemberGroups` merges the member groups' outcomes and reports group failures once their background retries have finished. The Collection queue is released when the card's part is done.
* **Key Files:** `drivers/circadian-light-group/device.js`, `drivers/circadian-light-group/driver.js`, `drivers/circadian-light-group-collection/device.js`, `CircadianLightGroupDevice.test.js`, `CircadianLightGroupCollectionDevice.test.js`, `CircadianLightGroupDriver.test.js`.

### 8. Presence+
* **Purpose:** Debounces Homey's user presence before starting a Flow. `presence_person_away_for` watches one selected person; `presence_everyone_away_for` starts when the last tracked person leaves.
* **Mechanism:** `lib/PresenceManager.js` subscribes to `ManagerUsers` events and reads enabled standard and Advanced Flows to discover the unique person/delay thresholds that need timers. A Home transition cancels the relevant pending timers.
* **Persistence:** Continuous-absence timestamps and fired thresholds are stored in Homey settings. An app restart resumes an active countdown and does not repeat a threshold that already fired in the same absence episode.
* **Key Files:** `lib/PresenceManager.js`, `.homeycompose/flow/triggers/presence_*.json`, `PresenceManager.test.js`, and `app.js` (lifecycle and card routing).

## Project Structure
* `no.tiwas.booleantoolbox/`: Main Homey app source.
* `app.js`: Application entry point and diagnostics collector.
* `api.js`: Private settings endpoint for generating diagnostic reports.
* `drivers/`: Device drivers (`composite-device`, `logic-device`, `logic-unit`, state and Circadian Light Group drivers).
* `lib/`: Core logic libraries (`CompositeAggregator.js`, `DiagnosticsReport.js`, `FlowIdentity.js`, `FormulaEvaluator.js`, `Logger.js`).
* `lib/`: Core logic libraries (`CompositeAggregator.js`, `DiagnosticsReport.js`, `FlowIdentity.js`, `FormulaEvaluator.js`, `Logger.js`, `PresenceManager.js`).
* `locales/`: Translation files.
* `docs/`: Documentation and web tools for the GitHub Pages site, published by `.github/workflows/pages.yml` on every push to `main` that changes `docs/` (Pages source: GitHub Actions).
* `.github/workflows/message-check.yml` with `.github/scripts/message-check.js`: checks commit messages, branch names, PR, issue and comment text against `AI_RULES.md` §7 on every pull request, push, issue, comment and review. Tests: `node --test .github/scripts/message-check.test.js`.
Expand Down
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Advanced logic and state management for your Homey automations. Create smart dev
[![Test](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapps-api.athom.com%2Fapi%2Fv1%2Fapp%2Fno.tiwas.booleantoolbox&query=%24.testVersion&label=test&color=orange)](https://homey.app/a/no.tiwas.booleantoolbox/test/)
[![Homey](https://img.shields.io/badge/Homey-5.0+-green.svg)](https://homey.app)

> **v1.10.35 test** — Circadian Light Group Flows no longer stop at Homey's 60-second card limit: a card lets the Flow continue once every light has its commands, lights that do not answer are retried in the background, and new Advanced Flow cards *Turn on / Turn off / Toggle and report the result* tell you whether every light confirmed. See the [Circadian Light Group guide](https://tiwas.github.io/SmartComponentsToolkit/docs/circadian-light-group.html#retries). Builds on **v1.10.34**: the app log now shows when a wait takes over a Waiter ID that is already waiting. Builds on **v1.10.33**: new Advanced Flow card *Get the name of [this Flow]* returns the Flow's own name, id and folder as tags, and follows when you rename the Flow. See the [Flow card reference](https://tiwas.github.io/SmartComponentsToolkit/docs/flow-cards.html#action-flow-name). Builds on **v1.10.32**: the Circadian Light Group schedule now follows your Homey's time zone (it ran 1–2 hours late on UTC), the outdoor light estimate follows the real sun, mornings can get their own optional profile, and the editors keep lux anchors and saved lux sensors. See the [Circadian Light Group guide](https://tiwas.github.io/SmartComponentsToolkit/docs/circadian-light-group.html). Builds on **v1.10.31** (Homey Web API library 3.20.0) and **v1.10.30**, which fixes app restarts and Logic Devices that stopped reacting, and adds background waits beyond Homey's 60-second Flow card limit. See the [Conditional Gates](https://tiwas.github.io/SmartComponentsToolkit/docs/conditional-gates.html) and [Waiter Gates](https://tiwas.github.io/SmartComponentsToolkit/docs/waiter-gates.html) guides.
> **v1.10.38 test** — New **Presence+** triggers start a Flow only after one selected person, or everyone, has remained away for a chosen number of minutes; returning home cancels the pending trigger, and a later departure is re-armed even if the previous trigger call is still finishing. Circadian Light Group Collections now also report *Is paused* when a member group is paused. See the [Presence+ guide](https://tiwas.github.io/SmartComponentsToolkit/docs/presence-plus.html) and [Circadian Light Group guide](https://tiwas.github.io/SmartComponentsToolkit/docs/circadian-light-group.html).

---

Expand Down Expand Up @@ -139,7 +139,7 @@ THEN: Pop state (restore previous) [Homey Flow delay: 5 minutes]

---

### Circadian Light Group *(stable v1.10.16 / test v1.10.35)*
### Circadian Light Group *(stable v1.10.16 / test v1.10.38)*

Virtual light device that adjusts brightness and color temperature for a group of real lights based on time, sun position or ambient lux.

Expand Down Expand Up @@ -230,6 +230,19 @@ Starting the wait again for the same gate (for example when the razor is turned

---

### Presence+

Homey's presence can briefly switch to Away and back. These triggers debounce that signal before a Flow is allowed to continue:

- **[Person] has been away for [minutes]** - starts when the selected person leaves and is cancelled if that person returns first
- **Everyone has been away for [minutes]** - starts when the last present person leaves and is cancelled as soon as anyone returns

The countdown runs in the background, survives an app restart, and fires once per continuous absence. No Flow card is kept open while it waits.

[📚 Read Presence+ guide →](https://tiwas.github.io/SmartComponentsToolkit/docs/presence-plus.html)

---

### Waiter Gates

Waiter Gates let your flows pause and wait for device states to change, with YES/NO outputs:
Expand Down Expand Up @@ -329,6 +342,8 @@ THEN: Turn on lights
- State was captured/applied *(State Capture Device)*
- Conditional Gate wait finished *(Conditional Gates)*
- Capability wait finished *(Waiter Gates)*
- Person has been away for a while *(Presence+)*
- Everyone has been away for a while *(Presence+)*

### Conditions (AND)
- Formula result is...
Expand Down
66 changes: 66 additions & 0 deletions WORKLOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,71 @@
# Worklog

## 2026-10-14 — Presence+ re-arm fix

### Requested
- Investigate why a person-specific Presence+ Flow triggered for the first absence, but did not trigger after the same person returned Home and then became Away again.
- Publish the corrected app as a new test version, update the website, README and Homey Community post source, and install it on the local Homey.

### Findings
- The normal completed sequence does reset correctly: an observed Away-to-Home transition clears the person's fired thresholds and the next Home-to-Away transition receives a new absence start time.
- Reproduced a race when the person returns and leaves again while the previous trigger call is still in flight. The new absence is observed, but schedule refresh skips it because the person/delay key is still marked in flight. When the previous trigger finishes, the in-flight marker is removed without another schedule refresh, so no timer is created for the new absence.
- Confirmed the race live with temporary diagnostics during `homey app run --remote`. The first one-minute timer fired at 14:47:01 local time. Home was received at 14:47:28, the fired threshold was cleared, and the next Away was received at 14:47:39 with a new absence timestamp. That second episode was skipped only because the first call was still marked in flight. The first `FlowCardTrigger.trigger()` promise did not settle until 14:48:31, almost exactly 90 seconds after it started; releasing the marker did not cause a schedule refresh.
- Homey's SDK contract says the trigger promise resolves when the Flow is triggered. The observed 90-second lifetime therefore looks like a Homey-side trigger timeout or hang, not the intended lifetime of the short downstream Flow. The scheduler must still tolerate a trigger promise that settles late.
- The same scheduling pattern is used by the everyone-away trigger, so it is vulnerable to the equivalent race.

### Implemented
- Presence events continue to update the current state immediately. When an older trigger call settles, the manager now detects a newer continuous-absence episode and schedules it using its original Away timestamp. If its deadline has already passed it fires immediately; otherwise only the remaining delay is scheduled.
- A Home event still cancels the episode naturally, so no explicit event queue is needed. A late completion also no longer restores the fired marker for an episode that has already ended.
- Applied the same re-arm behavior to the person-specific and everyone-away cards.
- Added regression tests for both trigger types with a deliberately unresolved first trigger call, a Home/Away cycle during that call, and exact scheduling of the second episode.
- Bumped the app to v1.10.38 and uploaded Build 67. Updated the GitHub Pages source with a Presence+ overview and dedicated guide, and updated the repository README, Store README, changelog and `HOMEY_COMMUNITY_LISTING.md` for the test release.

### Verification
- Focused PresenceManager suite: 9 tests passed.
- Live `homey app run --remote` reproduction: first Away at 14:56:21 triggered at 14:57:21. Home at 14:58:01 and a new Away at 14:58:11 arrived while the first trigger promise was still open. When it settled at 14:58:51, Presence+ scheduled the remaining 20 seconds and fired the second trigger at 14:59:11 exactly one minute after the new Away event.
- Temporary live diagnostics were removed after the successful run.
- Lars completed the Homey test-channel release; the public Homey app API reports `testVersion` v1.10.38.
- Full test suite: 25 suites and 427 tests passed. Publish-level package validation passed with 912 files, an 8.09 MB bundle and 17 verified manifest assets.
- `homey app install` installed v1.10.38 successfully on `Lars's New Homey`.

## 2026-10-13 — Debounced presence triggers

### Requested
- Add Flow triggers that fire only after one selected person, or everyone, has remained away for a configurable number of minutes, so brief Home/Away glitches do not directly drive automations.

### Implemented
- Added person-specific and everyone-away trigger cards with localized titles, hints, arguments, and output tags in all 11 app languages.
- Added an event-driven presence manager that observes Homey user updates, reads enabled standard and Advanced Flow configurations, and schedules exact background timers without keeping a Flow card open.
- Returning home cancels pending timers. Continuous-absence start times and fired thresholds are persisted so app restarts preserve countdowns and do not duplicate a trigger.
- Documented the new cards in the Store README and Flow-card reference.

### Verification
- Added regression coverage for timer expiry, cancellation on return, last-person semantics, restart deduplication, argument routing, and Compose card references.
- `npm test -- --runInBand --silent`: 25 suites, 425 tests passed.
- `npm run test:package`: publish-level Homey validation passed; both presence trigger cards were generated in the manifest (912-file bundle, 17 assets).
- `git diff --check`: passed.

## 2026-10-11 — Collection pause-state aggregation

### Requested
- Investigate issue #76 against the local Homey, including the Advanced Flow "All on - Toolbox", because some lights did not turn on and restarting the app in debug mode had helped before.

### Findings
- Reproduced the failure with `homey app run --remote` and the live Advanced Flow. The Collection's "Is paused" condition took the no branch while its main member group was paused.
- The subsequent Collection turn-on skipped all 11 lights in that paused group. The bedroom group ran, but its known unavailable member "Soverom: Nattbord v" could not be reached.
- Collection Pause and Resume already fan out to every member group. The inherited "Is paused" condition only read the Collection's own `clg_paused` capability, so it could return false while a member group was paused.

### Implemented
- Overrode the Collection's pause condition so it returns true when the Collection itself or at least one available member group is paused.
- Documented the aggregate Collection condition and added regression coverage for aggregate pause detection and Resume fan-out when only a member is paused.

### Verification
- Live retest on `Lars's New Homey`: the Collection condition took the true branch, Resume ran first for both member groups, and the formerly skipped main group then ran `turn_on_all_members`. Multiple previously off lights reported `onoff=true` and Lars confirmed that the lights came on.
- Remaining live failures are device-specific: `Smart Energy Illuminator` returned `TRANSMIT_COMPLETE_NO_ACK`, `Spisestue: Tunable White Bulb (E27)` was unreachable, and `Soverom: Nattbord v` was unreachable.
- `npm test -- --runInBand --silent`: 24 suites, 417 tests passed.
- `npm run test:package`: publish-level validation passed; 911-file bundle and 17 manifest assets verified.
- `git diff --check`: passed.

## 2026-10-08 — Test v1.10.35 released

### Implemented
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/circadian-light-group.html
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ <h3 class="text-lg font-semibold text-amber-700 mt-2 mb-3">Conditions</h3>
<ul class="text-gray-700 space-y-2 text-sm mb-4">
<li><span class="badge-condition">And</span> <strong>Is in phase</strong> — current phase is morning/day/evening/night (morning only with a morning profile).</li>
<li><span class="badge-condition">And</span> <strong>Red mode is active</strong>.</li>
<li><span class="badge-condition">And</span> <strong>Is paused</strong>.</li>
<li><span class="badge-condition">And</span> <strong>Is paused</strong> — for a Collection, yes when the Collection itself or at least one available member group is paused.</li>
<li><span class="badge-condition">And</span> <strong>Is on</strong>.</li>
</ul>

Expand Down
Loading
Loading