Skip to content

Commit 281d652

Browse files
committed
Link meter devices to add-on via_device using supervisor slug
Resolve the add-on slug from the supervisor (`/store/addons/self`) in run.sh and forward it as `ADDON_SLUG` in the `[MQTT_INSIGHTS]` section. The MQTT Insights service then sets `via_device: <addon_slug>` on the CT002 and Shelly meter discovery payloads so Home Assistant nests them under the AstraMeter add-on device.
1 parent b70483d commit 281d652

5 files changed

Lines changed: 51 additions & 14 deletions

File tree

ha_addon/run.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,23 @@ else
143143
echo "POWER_MULTIPLIER=$power_multiplier"
144144
fi
145145

146+
# Fetch this add-on's slug from the supervisor so MQTT discovery can
147+
# link discovered meter devices to the add-on device via_device.
148+
addon_slug=""
149+
if addon_slug="$(bashio::api.supervisor GET '/store/addons/self' false '.slug')" && [ -n "$addon_slug" ]; then
150+
bashio::log.info "Resolved add-on slug for HA discovery: $addon_slug"
151+
else
152+
bashio::log.warning "Failed to resolve add-on slug from supervisor; meter devices will not be linked via_device"
153+
addon_slug=""
154+
fi
155+
146156
if bashio::config.has_value 'mqtt_uri'; then
147157
bashio::log.info "Using custom MQTT broker URL from configuration"
148158
echo ""
149159
echo "[MQTT_INSIGHTS]"
150160
echo "URI=$(bashio::config 'mqtt_uri')"
151161
echo "HA_DISCOVERY=True"
162+
[ -n "$addon_slug" ] && echo "ADDON_SLUG=$addon_slug"
152163
elif bashio::services.available "mqtt"; then
153164
bashio::log.info "Using Home Assistant's internal MQTT broker"
154165
echo ""
@@ -159,6 +170,7 @@ else
159170
echo "PASSWORD=$(bashio::services 'mqtt' 'password')"
160171
echo "TLS=$(bashio::services 'mqtt' 'ssl')"
161172
echo "HA_DISCOVERY=True"
173+
[ -n "$addon_slug" ] && echo "ADDON_SLUG=$addon_slug"
162174
fi
163175
} > "$CONFIG"
164176
fi

src/astrameter/config/config_loader.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,5 +570,6 @@ def read_mqtt_insights_config(
570570
section, "HA_DISCOVERY_PREFIX", fallback=""
571571
)
572572
or "homeassistant",
573+
addon_slug=config.get(section, "ADDON_SLUG", fallback="") or None,
573574
)
574575
return None

src/astrameter/mqtt_insights/discovery.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ def build_ct002_device_discovery(
239239
base_topic: str,
240240
device_id: str,
241241
ha_prefix: str,
242+
addon_slug: str | None = None,
242243
) -> tuple[str, dict]:
243244
safe_dev = _sanitize_id(device_id)
244245
node_id = f"astrameter_ct002_{safe_dev}"
@@ -283,12 +284,16 @@ def build_ct002_device_discovery(
283284
},
284285
}
285286

287+
device_info: dict = {
288+
"identifiers": node_id,
289+
"name": f"AstraMeter CT002 {device_id}",
290+
"manufacturer": "astrameter",
291+
}
292+
if addon_slug:
293+
device_info["via_device"] = addon_slug
294+
286295
payload = {
287-
"device": {
288-
"identifiers": node_id,
289-
"name": f"AstraMeter CT002 {device_id}",
290-
"manufacturer": "astrameter",
291-
},
296+
"device": device_info,
292297
"origin": _origin(),
293298
"components": components,
294299
"availability": [_system_availability(base_topic)],
@@ -403,6 +408,7 @@ def build_shelly_device_discovery(
403408
base_topic: str,
404409
device_id: str,
405410
ha_prefix: str,
411+
addon_slug: str | None = None,
406412
) -> tuple[str, dict]:
407413
safe_dev = _sanitize_id(device_id)
408414
node_id = f"astrameter_shelly_{safe_dev}"
@@ -420,12 +426,16 @@ def build_shelly_device_discovery(
420426
},
421427
}
422428

429+
device_info: dict = {
430+
"identifiers": node_id,
431+
"name": f"AstraMeter Shelly {device_id}",
432+
"manufacturer": "astrameter",
433+
}
434+
if addon_slug:
435+
device_info["via_device"] = addon_slug
436+
423437
payload = {
424-
"device": {
425-
"identifiers": node_id,
426-
"name": f"AstraMeter Shelly {device_id}",
427-
"manufacturer": "astrameter",
428-
},
438+
"device": device_info,
429439
"origin": _origin(),
430440
"components": components,
431441
"availability": [_system_availability(base_topic)],

src/astrameter/mqtt_insights/mqtt_insights_test.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,12 @@ def test_ct002_consumer_discovery_network_mac_and_ip():
152152

153153

154154
def test_ct002_device_discovery_structure():
155-
topic, payload = build_ct002_device_discovery("astrameter", "dev1", "homeassistant")
155+
topic, payload = build_ct002_device_discovery(
156+
"astrameter", "dev1", "homeassistant", addon_slug="34dea19a_astrameter"
157+
)
156158
_assert_discovery_structure(topic, payload)
157159
assert "AstraMeter" in payload["device"]["name"]
160+
assert payload["device"]["via_device"] == "34dea19a_astrameter"
158161
comps = payload["components"]
159162
assert "smooth_target" in comps
160163
assert "active_control" in comps
@@ -190,13 +193,21 @@ def test_shelly_battery_discovery_structure():
190193

191194
def test_shelly_device_discovery_structure():
192195
topic, payload = build_shelly_device_discovery(
193-
"astrameter", "shelly1", "homeassistant"
196+
"astrameter", "shelly1", "homeassistant", addon_slug="34dea19a_astrameter"
194197
)
195198
_assert_discovery_structure(topic, payload)
196199
assert "AstraMeter" in payload["device"]["name"]
200+
assert payload["device"]["via_device"] == "34dea19a_astrameter"
197201
assert "battery_count" in payload["components"]
198202

199203

204+
def test_meter_device_discovery_omits_via_device_without_addon_slug():
205+
_, ct002 = build_ct002_device_discovery("astrameter", "dev1", "homeassistant")
206+
assert "via_device" not in ct002["device"]
207+
_, shelly = build_shelly_device_discovery("astrameter", "shelly1", "homeassistant")
208+
assert "via_device" not in shelly["device"]
209+
210+
200211
def test_unique_ids_are_unique():
201212
"""All unique_ids within a single discovery payload must be distinct."""
202213
_, payload = build_ct002_consumer_discovery(
@@ -295,6 +306,7 @@ def test_read_mqtt_insights_config_present():
295306
BASE_TOPIC = my_topic
296307
HA_DISCOVERY = true
297308
HA_DISCOVERY_PREFIX = ha
309+
ADDON_SLUG = 34dea19a_astrameter
298310
"""
299311
)
300312
result = read_mqtt_insights_config(cfg)
@@ -307,6 +319,7 @@ def test_read_mqtt_insights_config_present():
307319
assert result.base_topic == "my_topic"
308320
assert result.ha_discovery is True
309321
assert result.ha_discovery_prefix == "ha"
322+
assert result.addon_slug == "34dea19a_astrameter"
310323

311324

312325
def test_read_mqtt_insights_config_defaults():

src/astrameter/mqtt_insights/service.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class MqttInsightsConfig:
5858
base_topic: str = "astrameter"
5959
ha_discovery: bool = True
6060
ha_discovery_prefix: str = "homeassistant"
61+
addon_slug: str | None = None
6162

6263

6364
@dataclass
@@ -341,7 +342,7 @@ async def _handle_ct002_event(
341342
if did not in self._discovered_ct002_devices:
342343
self._discovered_ct002_devices.add(did)
343344
topic, payload = build_ct002_device_discovery(
344-
base, did, cfg.ha_discovery_prefix
345+
base, did, cfg.ha_discovery_prefix, addon_slug=cfg.addon_slug
345346
)
346347
await client.publish(
347348
topic, payload=json.dumps(payload).encode(), retain=True
@@ -437,7 +438,7 @@ async def _handle_shelly_event(
437438
if did not in self._discovered_shelly_devices:
438439
self._discovered_shelly_devices.add(did)
439440
topic, payload = build_shelly_device_discovery(
440-
base, did, cfg.ha_discovery_prefix
441+
base, did, cfg.ha_discovery_prefix, addon_slug=cfg.addon_slug
441442
)
442443
await client.publish(
443444
topic, payload=json.dumps(payload).encode(), retain=True

0 commit comments

Comments
 (0)