Skip to content

DRV-33: Add Update entity support#37

Open
svc-finitelabs[bot] wants to merge 38 commits into
mainfrom
agent/DRV-33-update-entity
Open

DRV-33: Add Update entity support#37
svc-finitelabs[bot] wants to merge 38 commits into
mainfrom
agent/DRV-33-update-entity

Conversation

@svc-finitelabs
Copy link
Copy Markdown
Contributor

@svc-finitelabs svc-finitelabs Bot commented Mar 28, 2026

Summary

Adds support for ESPHome update entities, enabling firmware version tracking and over-the-air update management from Control4.

What's included

Variables (per update entity):

  • {name} Current Version (STRING) — currently installed version
  • {name} Latest Version (STRING) — latest available version
  • {name} Update Available (BOOL) — 1 when an update is available
  • {name} Update Progress (NUMBER) — 0–100 during active updates, 0 otherwise

Properties:

  • Automatic Device Updates (Off/On, default Off) — when enabled, automatically installs device firmware updates when detected during periodic checks

Commands:

  • Update Device — checks for a firmware update on the selected entity, then installs it if available. If the Update Available boolean is already true, skips the check and installs directly. No-op if no update is available.

Periodic update checks:

  • Device update checks run in the heartbeat loop on the same 30-minute interval as driver update checks
  • When connected, all discovered update entities are checked via UPDATE_COMMAND_CHECK
  • If Automatic Device Updates is enabled, available updates are installed automatically after a 10-second delay (to allow check responses to arrive)

Implementation

  • New src/esphome/entities/update.lua following established entity patterns
  • checkAll() and installAll() methods on UpdateEntity for heartbeat integration
  • Registered in drivers/esphome/driver.lua entity table + heartbeat loop
  • Automatic Device Updates property with OPC handler and cross-instance sync
  • Uses existing proto schema (UpdateStateResponse, UpdateCommandRequest, UpdateCommand enum)
  • Updated CHANGELOG.md, README.md entity support table, variables table, and commands table

Resolves DRV-33

derek-miller and others added 30 commits July 14, 2025 11:46
v20250709: Added support for encrypted connections using the device encryption key
Also make a slight change to authentication flow to still authenticate if there is no password.
- Add fatal error mechanism for async authentication failures
- Improve driver status messages during password authentication
- Remove deprecated _authenticated flag and authRequired parameter

Fixes #12
…e tracking (#15)

* Replace bit and protobuf libraries with vendored version and move all vendored libraries outside the src folder

* Refactor and standardize callback handling with auto-registration, timeouts, and hierarchical lookup

* Add device log forwarding feature to ESPHome driver

* Upgrade bitn and protobuf libraries to v0.2.0

* Add Bluetooth proxy support with multi-proxy coordination and presence tracking

Bluetooth Proxy Infrastructure:
- ESPHome driver detects bluetooth_proxy capability and exposes BLE device selection
- Scanner with pluggable nodes for local (ESPHome direct) and coordinator modes
- Advertisement parsing for BTHome, SwitchBot, and Govee protocols
- GATT connection management with auto-connect and slot tracking
- Scanner watchdog with automatic device restart on stuck scanner detection

Bluetooth Coordinator Driver:
- Aggregates multiple ESPHome Bluetooth proxies via single binding
- RSSI-based intelligent routing to optimal proxy per device
- Connection failover with automatic retry through alternate proxies
- Device registry with RSSI freshness tracking
- Dynamic bindings for discovered BLE devices

Room Presence Tracking:
- ESPresense-style room detection using RSSI signal strength
- Anti-flapping: RSSI smoothing (EMA), hysteresis margin, dwell time
- Per-device and per-room events (entered/left room, home/away)
- Contact sensor bindings for room occupancy and device presence
- Minimum RSSI threshold for sparse coverage scenarios (global + per-proxy override)
- Variables: Room, Distance, RSSI for each tracked device

Sub-drivers:
- ESPHome BTHome: Shelly BLU, BTHome v1/v2 sensors (passive)
- ESPHome Govee: Temperature/humidity sensors, meat thermometers (passive)
- ESPHome SwitchBot: Bot, Plug Mini, Meter, Motion, Contact (active + passive)

Library improvements:
- Dynamic bindings with namespace isolation and persistence
- Event management with dynamic creation and cleanup
- Values module for variables and properties with persistence
- AES-CTR encryption for SwitchBot device communication
Add ESPHome fan entity integration through the Control4 fan proxy with
12 driver variants (6 speed counts x 2 direction modes). Includes
preprocessor enhancements for variant-level #ifdef conditions,
cross-product dimension definitions, and consolidated PDF generation.
New Yale/August BLE lock driver with secure GATT handshake, lock/unlock
control, DoorSense contact sensor, battery monitoring, and Yale Cloud
API integration for offline key provisioning. Supports persistent and
poll connection modes.

Bluetooth proxy: V3 BLE CCCD descriptor write support, consistent BLE
address derivation via BLEAddress.fromString, improved GATT logging.

Replaced custom Lua AES-CTR implementation with native C4 crypto.

Documentation: Yale compatibility table with supported lock models,
DoorSense calibration note, key rotation troubleshooting, encryption
tip for BLE-only proxies to reduce controller CPU load, BTHome and
coordinator style corrections.

Normalize action command names to underscore format across all drivers.
- Add run_test.sh as general-purpose test runner that sets up LUA_PATH,
  loads C4 shim, and passes env vars to test files
- Add runEventLoop() to c4_shim so tests don't duplicate the event loop
- Remove hardcoded passwords and encryption keys from examples
- Normalize test files: consistent env var usage, 2-space indent,
  explicit dependency requires
JSON serialization of 48-bit BLE addresses via SerializeSafe loses
precision in scientific notation (e.g., 266846339488132 becomes
266846339488130, off by 2). This caused the coordinator to send wrong
addresses to ESP proxies, resulting in 20-second connection timeouts.

Refactored so numeric addresses only exist inside client.lua at the
protobuf boundary. All layers above (coordinator, router, bluetooth
proxy capability) now pass MAC strings exclusively. The client converts
MAC to number internally right before protobuf encoding.

Also switches gen-squishy from system Lua to LuaJIT to match the
Control4 runtime, and adds a generated-file header to README.md.
* Fix listEntities() never resolving due to callback registration order

ListEntitiesDoneResponse has no `ifdef` option in its proto schema.
The entity type check was evaluated before the DoneResponse check,
causing it to be skipped as "Unknown entity type". The Done callback
was never registered, so the deferred never resolved and entity
discovery silently failed. Sub-drivers (lights, fans, locks) stayed
Disconnected.

Fix: check for ListEntitiesDoneResponse first, before the entity type
lookup.

* Fix sub-drivers staying Disconnected after parent connects

ListEntitiesDoneResponse has no `ifdef` option in its proto schema.
The entity type check rejected it as unknown before reaching the Done
callback registration, so the deferred never resolved and entity
discovery silently failed.

Fix: check for ListEntitiesDoneResponse first, before the entity type
lookup. Also log unknown entity types at trace level instead of
silently skipping them.
Apply control4-driver-template to manage shared infrastructure via Copier.
Adds copier answers, Makefile, CONTRIBUTING, and syncs shared libs.

Co-authored-by: Derek Miller <derek@finitelabs.com>
* AGENT-30: Deduplicate DoorSense contact sensor notifications

Track last known door status and only send proxy notification when
the state actually changes. Previously, updateDoorStatus() fired
SendToProxy on every poll cycle regardless of state change, causing
Control4 to log repeated contact sensor events every ~1 minute.

Reset lastDoorStatus to nil on disconnect/reconnect and driver reset
so the first poll after reconnect always reports the current state.

* refactor: persist door status via values lib instead of local variable

Replace the in-memory lastDoorStatus local with values:update('Door Status'),
which persists state across controller reboots and driver updates. The values
lib's update() method returns false when the value hasn't changed, providing
the same deduplication behavior while also surviving isolate restarts.

- Remove lastDoorStatus local variable and all reset sites
- Use values:update() return value for change detection
- Property updates now handled by values lib (no manual UpdateProperty)
- values:reset() in EC.Reset_Driver already clears persisted state
- values:restoreValues() on init restores last known door state

---------

Co-authored-by: OpenClaw <openclaw@dmiller.me>
Added missing Unreleased section to CHANGELOG.md documenting the
DoorSense contact sensor deduplication fix. Rebuilt to embed updated
changelog in README.

Refs: AGENT-30

Co-authored-by: OpenClaw <openclaw@dmiller.me>
Co-authored-by: OpenClaw <openclaw@dmiller.me>
* TPL-2: copier update to v0.4.0 - add GitHub Actions CI

* fix: regenerate README.md to match pandoc output

The committed README.md had a trailing backslash line break that pandoc
converts to two trailing spaces, causing the dirty-tree CI check to fail.

* fix: remove trailing whitespace from README.md

* fix: remove trailing backslash line break in source doc

Applies the same fix from README.md to the source documentation.
Addresses review comment on PR #26.

* fix: join reflowed lines in source doc and README to match pandoc output

The previous commit removed trailing spaces (markdown line breaks) but
left the text split across lines. Pandoc reflows this into a single
paragraph, causing the dirty-tree CI check to fail. Join the lines
to match pandoc's expected output.

---------

Co-authored-by: OpenClaw <openclaw@dmiller.me>
Co-authored-by: openclaw[bot] <openclaw[bot]@users.noreply.github.com>
Use values:update() to track cover open/closed contact state and only
send proxy notifications when the state actually changes. Prevents
duplicate history agent entries during open/close operations when
ESPHome sends multiple position updates.
Automatically creates a GitHub release when a version tag is pushed.
Waits for the existing build workflow to complete, downloads the oss
artifacts, and publishes with auto-generated release notes.
Co-authored-by: OpenClaw <openclaw@dmiller.me>
…ks (#33)

- Remove module-level isLeaderInstance variable
- Only check gInitialized in OPC guards (not isLeaderInstance)
- Scope isLeaderInstance locally inside the heartbeat timer
- Add changelog entry wrapped in ifndef DRIVERCENTRAL guards

Co-authored-by: svc-finitelabs[bot] <269744575+svc-finitelabs[bot]@users.noreply.github.com>
@derek-miller derek-miller force-pushed the agent/DRV-33-update-entity branch from e3fe37e to 0b8edcb Compare March 28, 2026 03:35
@svc-finitelabs
Copy link
Copy Markdown
Contributor Author

Build was failing because README.md and the source documentation (drivers/esphome/www/documentation/index.md) were out of sync. The build generates README.md from the source docs via pandoc, so editing README.md directly gets overwritten.

Pushed a fix (3f05cdf) that updates the source documentation with the Update entity support (variables, commands, entity table). The build should now produce a clean git diff.

* DRV-25: Add Select entity support

- Create src/esphome/entities/select.lua (~130 lines)
- STRING variable with current option, writable via variable writes
- selectRegistry pattern for programming commands (matches button.lua)
- Add 'Set Select' command with dynamic Select and Option dropdowns
- Register SelectEntity in driver.lua entity table
- Add Set Select command definition to driver.xml
- Update README: entity support table, variables table, commands table
- Add CHANGELOG entry

* fix: update source documentation with Select entity support

The README was updated manually but the source documentation
(drivers/esphome/www/documentation/index.md) still had Select marked
as unsupported. The build regenerates README from source via pandoc,
causing 'Uncommitted changes after build' CI failure.

Updates source documentation to match:
- Mark Select entity as supported (✅)
- Add Select variable row to Variables table
- Add Set Select command to Commands table
- Update notes to mention Select entities

* chore: fix README.md formatting for dirty tree check

* fix: use nil check instead of IsEmpty for option value

An empty string is a valid select option. Using IsEmpty would
reject it, preventing the command from executing. Check for nil
instead to only guard against missing parameters.

---------

Co-authored-by: svc-finitelabs[bot] <269744575+svc-finitelabs[bot]@users.noreply.github.com>
Co-authored-by: OpenClaw <openclaw@dmiller.me>
Co-authored-by: svc-finitelabs[bot] <svc-finitelabs[bot]@users.noreply.github.com>
@derek-miller
Copy link
Copy Markdown
Contributor

Rebase and fix conflicts

@svc-finitelabs svc-finitelabs Bot force-pushed the agent/DRV-33-update-entity branch from 3f05cdf to a6b7567 Compare March 28, 2026 13:22
@svc-finitelabs
Copy link
Copy Markdown
Contributor Author

Rebased onto main and resolved conflicts. The merge conflicts were between the Select entity support (merged in v20260328) and the Update entity support from this PR — both touched the same sections in the docs and driver.xml commands.

Resolved by keeping both feature additions:

  • Variables table: includes Select + all Update variables
  • Commands: includes Set Select + Check for Updates + Install Update
  • Bindings note: lists Select + Update as non-binding entity types
  • CHANGELOG: Update entity entry placed in Unreleased, above Select's v20260328 release
  • driver.xml: all three new commands preserved (Set Select, Check for Updates, Install Update)

svc-finitelabs Bot and others added 2 commits March 28, 2026 08:40
* DRV-31: Add Event entity support

Implement ESPHome event entity handling for stateless triggers (button
presses, gestures, doorbell rings). Events create Control4 events for
programming and track the last event type in a variable.

Changes:
- Add src/esphome/entities/event.lua with discovered/updated handlers
- Register EventEntity in driver.lua entity table
- Fix client.lua subscribeStates to handle EventResponse (does not
  match *StateResponse pattern)
- Update README entity table, variables, and events documentation
- Add CHANGELOG entry

* fix: move event docs to source index.md so build doesn't produce uncommitted changes

README.md is generated from drivers/esphome/www/documentation/index.md
during the build. The event entity docs were added to README.md directly
but not the source doc, causing the build to overwrite them and fail the
uncommitted-changes check.

Also wraps long CHANGELOG.md line to satisfy prettier formatting.

* fix: align blockquote line wrap with pandoc output

---------

Co-authored-by: OpenClaw <openclaw@dmiller.me>
Co-authored-by: svc-finitelabs[bot] <svc-finitelabs[bot]@users.noreply.github.com>
* DRV-30: Add Date, Time, and Datetime entity support

- date.lua: formats as YYYY-MM-DD, writable (parses back to year/month/day)
- time.lua: formats as HH:MM:SS, writable (parses back to hour/minute/second)
- datetime.lua: converts epoch_seconds to YYYY-MM-DD HH:MM:SS, writable
- All three handle missing_state by setting variable to empty string
- Registered all three in driver.lua entity table
- Updated README, index.md, and CHANGELOG

* docs: alphabetically sort entity tables in documentation

* fix: re-sort documentation tables to match build output

The entity variable reference tables in README.md and the driver
documentation were manually ordered, but prettier --prose-wrap always
reformats them alphabetically during build. Commit the post-build
output so the dirty-tree CI check passes.

---------

Co-authored-by: svc-finitelabs[bot] <269744575+svc-finitelabs[bot]@users.noreply.github.com>
Co-authored-by: OpenClaw <openclaw@dmiller.me>
@derek-miller
Copy link
Copy Markdown
Contributor

Rebase and fix conflicts

@svc-finitelabs svc-finitelabs Bot force-pushed the agent/DRV-33-update-entity branch from bb3dd9d to 31e5878 Compare March 28, 2026 21:34
@svc-finitelabs
Copy link
Copy Markdown
Contributor Author

Rebased onto main and resolved conflicts. Changes merged cleanly with the Event, Date, Time, and Datetime entity work that landed since this branch was created:

  • CHANGELOG.md — added Update entry alongside Event/Date/Time/Datetime entries
  • README.md — merged variables table (alphabetical order with all new entity types), updated bindings note, merged changelog section
  • driver.lua — added UpdateEntity require + registration alongside TimeEntity
  • index.md — same table/note updates as README, plus Update ✅ in entity support table

The reformat commit was dropped since its changes were incorporated during conflict resolution. Two commits remain:

  1. feat: add Update entity support for ESPHome firmware updates (DRV-33)
  2. fix: update source docs with Update entity support

@derek-miller
Copy link
Copy Markdown
Contributor

A few things.

  1. I think we should be periodically checking for device updates (when supported) in the same loop as driver updates
  2. We should allow the user to turn on automatic updates
  3. The install update command should probably include the fact its for device updates, so like "Update Device". That command first checks for an update, then performs it if necessary, otherwise is a no-op.
  4. Since we will be checking in the same loop and to be consistent with the other actions, we probably dont need the command to check for updates. We will have the boolean to tell us and the command to do the update and the update command will always check unless the update available bool is true.

Feel free to adapt any of this to better fit the APIs if needed.

Add Voice Assistant footnote to entity table
@svc-finitelabs svc-finitelabs Bot force-pushed the agent/DRV-33-update-entity branch from 45750f1 to 672306e Compare March 28, 2026 22:01
@svc-finitelabs
Copy link
Copy Markdown
Contributor Author

Updated based on your feedback. Here's what changed:

  1. Periodic device update checks in heartbeat — runs on the same 30-minute interval as driver updates. When connected, sends UPDATE_COMMAND_CHECK to all discovered update entities. The state responses flow back through the existing subscribeStates callback and update the variables automatically.

  2. Automatic Device Updates property — new Off/On property (defaults to Off). When enabled, after each periodic check there's a 10-second delay to let check responses arrive, then installAll() installs any entity where Update Available is true. Property syncs across instances like the existing Automatic Updates property.

  3. "Update Device" command — replaces both "Check for Updates" and "Install Update". If Update Available is already true, it installs directly. Otherwise it sends a check first, then chains the install command. No-op if no update is available.

  4. Removed "Check for Updates" command — periodic heartbeat checks handle this, and the Update Device command does a check-then-install when invoked manually.

Squashed into a single clean commit, both builds pass.

- update.lua: tracks current/latest version, update available flag, progress
- Variables: Current Version, Latest Version, Update Available, Update Progress
- "Update Device" programming command with dynamic entity dropdown
- Automatic Device Updates property (default Off) with 30-min check interval
- checkAll/installAll methods for batch update operations
- Registered UpdateEntity in driver.lua entity table
- Updated README, index.md, driver.xml, CHANGELOG
@svc-finitelabs svc-finitelabs Bot force-pushed the agent/DRV-33-update-entity branch from 672306e to fa9d32c Compare March 28, 2026 23:22
@derek-miller
Copy link
Copy Markdown
Contributor

Updated based on your feedback. Here's what changed:

  1. Periodic device update checks in heartbeat — runs on the same 30-minute interval as driver updates. When connected, sends UPDATE_COMMAND_CHECK to all discovered update entities. The state responses flow back through the existing subscribeStates callback and update the variables automatically.
  2. Automatic Device Updates property — new Off/On property (defaults to Off). When enabled, after each periodic check there's a 10-second delay to let check responses arrive, then installAll() installs any entity where Update Available is true. Property syncs across instances like the existing Automatic Updates property.
  3. "Update Device" command — replaces both "Check for Updates" and "Install Update". If Update Available is already true, it installs directly. Otherwise it sends a check first, then chains the install command. No-op if no update is available.
  4. Removed "Check for Updates" command — periodic heartbeat checks handle this, and the Update Device command does a check-then-install when invoked manually.

Squashed into a single clean commit, both builds pass.

Don't use delays, when update available changes to true and the automatic device updates are on we would just send the command to update.

@svc-finitelabs
Copy link
Copy Markdown
Contributor Author

Good call — the delay is fragile and unnecessary. The state responses already flow through updated(), so I'll move the auto-install logic there: when Update Available transitions to true and Automatic Device Updates is on, send the install command immediately. No timer needed.

Changes:

  1. update.lua updated() — check the property and fire UPDATE_COMMAND_UPDATE when updateAvailable becomes true
  2. driver.lua heartbeat — remove the 10-second SetTimer auto-install block (periodic checkAll() stays, it just triggers state responses now)

Working on it.

Comment thread drivers/esphome/driver.lua Outdated
if not gInitialized then
return
end
syncPropertyToOtherInstances("Automatic Device Updates", propertyValue)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Device updates are device specific and shouldnt be synced to other instances.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct — the OPC handler intentionally does nothing since device updates are device-specific. No sync needed.

--#endif
end

function OPC.Automatic_Device_Updates(propertyValue)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, we should hide this property by default until we detect the UpdateEntity.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already handled — property is hidden by default in OnDriverLateInit() and only shown in discovered() when the first UpdateEntity is found.

Comment thread drivers/esphome/driver.lua Outdated
if not gInitialized then
return
end
syncPropertyToOtherInstances("Automatic Device Updates", propertyValue)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Device updates are device specific and shouldnt be synced to other instances of the driver.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, addressed — see reply above.

Comment thread drivers/esphome/driver.lua Outdated
else
-- Check for device updates on the same interval as driver updates (when connected)
local secondsSinceDeviceCheck = now - lastDeviceUpdateCheckTime
if secondsSinceDeviceCheck > (30 * 60) then
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a way to know if we have the UpdateEntity at all, then we can do if <has update entitiy> and secondsSinceDeviceCheck > (30 * 60)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already handled — the heartbeat check uses Entities[UpdateEntity.TYPE]:hasEntities() which returns true only when update entities have been discovered.

Comment thread drivers/esphome/driver.lua Outdated
-- If automatic device updates are enabled, install any available updates
if toboolean(Properties["Automatic Device Updates"]) then
-- Use a short delay to allow check responses to arrive before installing
SetTimer("autoDeviceUpdate", 10 * ONE_SECOND, function()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldnt this happen based on the response? Can checkAll() return a deferred and we can do this here based on the result?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. The deferred from checkAll() resolves when CHECK commands are sent, not when state responses arrive, so the .next() handler couldn't reliably know about available updates yet. Moved the auto-install logic into UpdateEntity:updated() instead — it now triggers reactively when a state response confirms an update is available and the Automatic Device Updates property is enabled. Removed installAll() entirely and simplified the heartbeat to just call checkAll().

</params>
</command>
<command>
<name>Update Device</name>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add this as an action too.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you do Update_Device as the command name for the action it can share the same EC handler.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already done — there's an action block with Update_Device as the command name, sharing the EC.Update_Device handler.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, already using Update_Device as the command name so it shares the EC handler.

Comment thread src/esphome/entities/update.lua Outdated

if state.in_progress and state.has_progress then
local progress = math.floor((state.progress or 0) * 100 + 0.5)
values:update(entity.name .. " Update Progress", tostring(progress), "NUMBER")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think we need the percentage, but it might be nice to have a boolean about there being an update in progress?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already handled — there's an "Update In Progress" boolean variable that gets set from state.in_progress. Percentage is not exposed.

Comment thread src/esphome/entities/update.lua Outdated
log:trace("UpdateEntity:installAll()")
for entityName, entry in pairs(updateRegistry) do
local updateAvailable = values:get(entityName .. " Update Available")
if updateAvailable == "1" then
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use our toboolean() helper here instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — changed state.missing_state check to use toboolean(state.missing_state).

Comment thread src/esphome/entities/update.lua Outdated
end

local updateAvailable = values:get(entityName .. " Update Available")
if updateAvailable == "1" then
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here with the toboolean usage

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — all state field boolean checks now use toboolean(). The state.in_progress check was already using it; updated state.missing_state to match.

@derek-miller
Copy link
Copy Markdown
Contributor

You are missing a bunch of unresolved comments in this PR @svc-finitelabs

@svc-finitelabs
Copy link
Copy Markdown
Contributor Author

You're right, sorry about that. Going through all the review comments now and addressing them.

OpenClaw and others added 2 commits March 30, 2026 19:29
- Remove syncPropertyToOtherInstances for Automatic Device Updates (device-specific)
- Hide Automatic Device Updates property by default, show when UpdateEntity discovered
- Add hasEntities() method to gate device update checks in heartbeat
- Make checkAll() return a Deferred; chain installAll() on its resolution instead of timer
- Replace Update Progress (NUMBER) with Update In Progress (BOOL)
- Use toboolean() helper for Update Available checks in installAll() and EC.Update_Device
- Add Update_Device as an action in driver.xml (shares EC handler with command)
- Update docs and changelog to reflect variable changes
- Move auto-install logic from heartbeat to UpdateEntity:updated() so
  updates install reactively when state confirms availability, not
  immediately after sending check commands
- Remove installAll() method (no longer needed)
- Use toboolean() for state.missing_state check
- Simplify heartbeat to just call checkAll() without .next() handler
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant