feat: add AmbiSense presence support#1
Merged
Conversation
AmbiSense (radar presence + LED follow-me) advertises itself as a
SmartGhar hub with one virtual sub-device of kind="presence". Adding
this kind to the integration so HA renders the right entities for
each AmbiSense unit on the network — alongside any TankSync hubs.
Hub-model dispatch: pull `product` from /api/v1/info and pick the
device-registry model string accordingly. AmbiSense hubs now show as
"AmbiSense Hub" in Settings → Devices instead of "TankSync Hub".
Older firmware that doesn't include `product` in /api/v1/info falls
back to "TankSync Hub" — matches existing behaviour.
Entities added per `kind: "presence"` device:
- binary_sensor: occupancy (device_class=occupancy) with stationary,
target_count, nearest_cm, seconds_since_seen as attributes
- sensor: nearest_cm (device_class=distance, unit cm)
- sensor: target_count
- sensor: seconds_since_seen (diagnostic, duration)
- sensor: rssi_dbm (diagnostic, signal_strength, disabled by default)
Multi-device safe: hub_id (derived from MAC) is unique per device, so N
AmbiSense units on one network produce N separate HA devices with
zero entity-id collisions.
Tested against AmbiSense firmware v6.2.0-alpha.2 on ESP32-C3
(MAC d8:3b:da:35:06:f0). Discovery + entity creation + state updates
+ config writes (PUT /api/v1/devices/0) all behave as expected.
Spec: https://github.com/Techposts/AmbiSense/blob/v6-idf-rewrite/docs/SMARTGHAR-PROTOCOL.md
Co-existence test: TankSync Hub + AmbiSense both on same network →
two separate hubs in HA, both fully functional, no shared state.
Techposts
pushed a commit
to Techposts/AmbiSense
that referenced
this pull request
May 7, 2026
AmbiSense now speaks the smartghar device protocol so the smartghar-homeassistant custom integration auto-discovers it on the network. Same protocol TankSync (aqualevel) already uses; the integration PR adding presence-kind support is at Techposts/smartghar-homeassistant#1 Discovery (netmgr.c): - New mDNS service _smartghar._tcp on port 80 with TXT records (hub_id, product=ambisense, manufacturer=SmartGhar, schema=1.0, path=/api/v1/info). hub_id is ambisense_<MAC> so multiple AmbiSense units on one network show up as distinct HA devices. - Legacy _ambisense._http._tcp service kept for older tools. REST contract (webui.c, +152 lines): - GET /api/v1/info — hub identity (manufacturer, product, model, fw_version, hub_id, host, ip, uptime_s, wifi_rssi, free_heap, capabilities). Mirrors aqualevel hub schema so the integration treats AmbiSense as another smartghar hub. - GET /api/v1/devices — returns {devices: [...]} with one entry of kind="presence" for AmbiSense's standalone-hub topology (single-ESP32-doing-everything is exposed as a hub with one virtual sub-device). - PUT /api/v1/devices/0 — config writes (vacancy_secs, radar_kind); returns updated device object so the integration reflects changes immediately. Auth-gated by admin password cookie. - POST /api/v1/hub/identify — flash status LED for ~3 s at 5 Hz using status_led_oneshot(STATUS_LED_OTA, 3000). Auth-gated. - POST /api/v1/hub/reboot — alias to /api/reboot, kept under the contract path so future legacy /api refactors don't break the integration. Web UI (screens.tsx): - System tab: removed the MQTT card (we explicitly chose the WS+mDNS path over MQTT — see commit log) and replaced with a SmartGhar HA integration card explaining auto-discovery + linking the integration repo + the protocol doc. - Presence tab HA card: leads with smartghar integration as recommended; the RESTful /api/presence YAML recipe is moved behind a <details> as the no-MQTT-no-custom-component fallback. Cross-product spec (docs/SMARTGHAR-PROTOCOL.md, NEW): - Protocol contract every Techposts IoT device honors so future products (RidgeSync fingerprint lock, etc.) integrate with one small additive PR to smartghar-homeassistant. - Documents both topology models: standalone hub (AmbiSense, mains-powered single ESP32) and hub+TX (TankSync, multi-sensor with battery-powered TX nodes via short-range RF). - Wire details: mDNS TXT keys, all /api/v1 endpoints + JSON schemas, WS push contract, auth model, schema versioning rules. - Adding a new product checklist + entity-builder template patches for the integration repo. - Per-kind device JSON templates (presence, tank, lock for RidgeSync's design-ahead). Build: - ambisense.bin 0x1207a0 (~1.16 MB), 18% partition free. Recovered ~150 KB by dropping the MQTT component (was at 9% free in the v6.2.0-alpha.1 dev branch with mqtt + cJSON pulled in). - UI bundle 98.5 KB raw, 28.8 KB gzipped. Bench-tested clean-flash on ESP32-C3 d8:3b:da:35:06:f0: - mDNS _smartghar._tcp advertises with all 5 TXT records. - /api/v1/info, /api/v1/devices return valid JSON. - /api/v1/devices/0 PUT round-trips vacancy_secs. - /api/v1/hub/identify flashes the onboard LED visibly. - Existing /api/* (web UI) endpoints unchanged.
HACS validation rejected keys in hacs.json that belong in manifest.json (iot_class, documentation, issue_tracker) plus '_iot_class_note' which is a custom key not in HACS schema. The same fields are already correctly present in manifest.json; hacs.json just needs to be the schema-allowed subset (name, render_readme, homeassistant, country). Pre-existing config issue unrelated to the AmbiSense additions but clearing it in the same PR avoids a separate roundtrip.
custom_components/smartghar/brand/icon.png + icon@2x.png — copied from the existing assets/ directory (same source). HACS looks for brand assets in this exact path; absent, validation fails with 'repository does not provide brand assets and is not listed in HA brands repository'. This is the local-asset path; we can additionally register in the upstream home-assistant/brands repo later for the green checkmark in HA's device card.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AmbiSense (radar presence + LED follow-me) speaks the smartghar contract from firmware v6.2.0-alpha.2. Each unit advertises itself on
_smartghar._tcp.local.as a SmartGhar hub with one virtual sub-device ofkind: \"presence\". This PR teaches the integration to render the right HA entities for that kind — alongside any existing TankSync hubs in the same install.Spec the firmware implements: docs/SMARTGHAR-PROTOCOL.md.
What changed
const.py: newDEVICE_KIND_PRESENCE = \"presence\",MODEL_PRESENCE,hub_model_for_product()dispatcher (TankSync → "TankSync Hub", AmbiSense → "AmbiSense Hub", unknown → "SmartGhar Hub").binary_sensor.py: newSmartGharPresenceOccupancy(device_class=occupancy) per presence device. Stationary / target_count / nearest_cm / seconds_since_seen ride asextra_state_attributesso HA automations can react to combinations like "occupied AND stationary > 5 min" without separate binary sensors. Also: hub OTA-available now useshub_model_for_productso the device entry model matches the actual product.sensor.py:PRESENCE_SENSORSdescription tuple — nearest_cm (distance, cm), target_count, seconds_since_seen (diagnostic, duration), rssi_dbm (diagnostic, disabled by default).SmartGharPresenceSensorclass. nearest_cm reads -1 from firmware when vacant; this surfaces asNoneso HA renders "Unknown" instead of "-1 cm".SmartGharHubSensordevice_info now useshub_model_for_product.kind == DEVICE_KIND_PRESENCEand constructs the four sensor entities per device.strings.json+translations/en.json: translation keys foroccupancy,presence_nearest,presence_target_count,presence_seconds_since_seen,presence_rssi.manifest.json: version 0.6.1 → 0.7.0.Multi-device
hub_id(derived from MAC) is the integration's primary key. Two AmbiSense units on one network → two separate HA devices, two sets of entities, zero collisions. Same applies to AmbiSense + TankSync co-existing.Test plan
v6.2.0-alpha.2firmwarevacancy_secs(default 60) → occupancy flips offBackward compatibility
No breaking changes for TankSync. The
MODEL_HUBconstant is preserved as an alias toMODEL_HUB_TANKSYNC. Existing entity unique_ids and device identifiers are untouched. Older firmware (noproductfield in/api/v1/info) falls back to TankSync labelling — same as today.