diff --git a/gauge.py b/gauge.py index 2909e9b..72d8bd0 100644 --- a/gauge.py +++ b/gauge.py @@ -756,10 +756,10 @@ def connect_mqtt(): _mqtt_check_interval_ms = 30000 _last_mqtt_check = 0 -_discovery_phases = () -_discovery_phase_idx = 0 +_discovery_queue = [] +_discovery_idx = 0 _last_discovery_ms = 0 -_DISCOVERY_INTERVAL_MS = 500 +_DISCOVERY_INTERVAL_MS = 200 def check_mqtt(): @@ -809,237 +809,208 @@ def check_mqtt(): return False -def _discovery_pause(client, count=5, delay_ms=25): - for _ in range(count): - client.check_msg() - utime.sleep_ms(delay_ms) - gc.collect() - - def _publish_discovery_entity(client, topic, payload, log_msg): client.publish(topic, ujson.dumps(payload), retain=True) info(log_msg) -def _publish_gauge_discovery(client, dev_ref): +def _append_gauge_discovery(entries, dev_ref): for i, g in enumerate(gauges): gt = gauge_topics[i] - _publish_discovery_entity( - client, - gt["disc"], - { - "name": g["entity_name"], - "unique_id": f"{MQTT_CLIENT_ID}_g{i}", - "cmd_t": gt["set"], - "stat_t": gt["state"], - "avty_t": gt["status"], - "min": g["min"], - "max": g["max"], - "step": 1, - "unit_of_meas": g["unit"], - "icon": "mdi:gauge", - "dev": dev_ref, - }, - f"Discovery: gauge {i} ({g['name']})", + entries.append( + ( + gt["disc"], + { + "name": g["entity_name"], + "unique_id": f"{MQTT_CLIENT_ID}_g{i}", + "cmd_t": gt["set"], + "stat_t": gt["state"], + "avty_t": gt["status"], + "min": g["min"], + "max": g["max"], + "step": 1, + "unit_of_meas": g["unit"], + "icon": "mdi:gauge", + "dev": dev_ref, + }, + f"Discovery: gauge {i} ({g['name']})", + ) ) - _discovery_pause(client) -def _publish_speed_discovery(client, dev_ref): +def _append_speed_discovery(entries, dev_ref): for i, g in enumerate(gauges): gt = gauge_topics[i] - _publish_discovery_entity( - client, - gt["speed_disc"], - { - "name": f"{g['name']} Speed", - "unique_id": f"{MQTT_CLIENT_ID}_g{i}_speed", - "cmd_t": gt["speed"], - "stat_t": gt["speed_state"], - "avty_t": gt["status"], - "min": 1, - "max": 50000, - "step": 1, - "mode": "box", - "unit_of_meas": "steps/s", - "icon": "mdi:speedometer", - "entity_category": "config", - "dev": dev_ref, - }, - f"Discovery: gauge {i} speed", + entries.append( + ( + gt["speed_disc"], + { + "name": f"{g['name']} Speed", + "unique_id": f"{MQTT_CLIENT_ID}_g{i}_speed", + "cmd_t": gt["speed"], + "stat_t": gt["speed_state"], + "avty_t": gt["status"], + "min": 1, + "max": 50000, + "step": 1, + "mode": "box", + "unit_of_meas": "steps/s", + "icon": "mdi:speedometer", + "entity_category": "config", + "dev": dev_ref, + }, + f"Discovery: gauge {i} speed", + ) ) - _discovery_pause(client) -def _publish_acceleration_discovery(client, dev_ref): +def _append_acceleration_discovery(entries, dev_ref): for i, g in enumerate(gauges): gt = gauge_topics[i] - _publish_discovery_entity( - client, - gt["acceleration_disc"], - { - "name": f"{g['name']} Acceleration", - "unique_id": f"{MQTT_CLIENT_ID}_g{i}_acceleration", - "cmd_t": gt["acceleration"], - "stat_t": gt["acceleration_state"], - "avty_t": gt["status"], - "min": 1, - "max": 100000, - "step": 1, - "mode": "box", - "unit_of_meas": "steps/s2", - "icon": "mdi:chart-bell-curve-cumulative", - "entity_category": "config", - "dev": dev_ref, - }, - f"Discovery: gauge {i} acceleration", + entries.append( + ( + gt["acceleration_disc"], + { + "name": f"{g['name']} Acceleration", + "unique_id": f"{MQTT_CLIENT_ID}_g{i}_acceleration", + "cmd_t": gt["acceleration"], + "stat_t": gt["acceleration_state"], + "avty_t": gt["status"], + "min": 1, + "max": 100000, + "step": 1, + "mode": "box", + "unit_of_meas": "steps/s2", + "icon": "mdi:chart-bell-curve-cumulative", + "entity_category": "config", + "dev": dev_ref, + }, + f"Discovery: gauge {i} acceleration", + ) ) - _discovery_pause(client) -def _publish_indicator_led_discovery(client, dev_ref): +def _append_indicator_led_discovery(entries, dev_ref): for i, g in enumerate(gauges): gt = gauge_topics[i] - _publish_discovery_entity( - client, - gt["led_red_disc"], - { - "name": f"{g['name']} Dial Red LED", - "uniq_id": f"{MQTT_CLIENT_ID}_g{i}_red", - "cmd_t": gt["led_red"], - "stat_t": gt["led_red_state"], - "schema": "json", - "supported_color_modes": ["onoff"], - "effect": True, - "effect_list": _EFFECT_LIST, - "icon": "mdi:led-on", - "dev": dev_ref, - "ret": True, - }, - f"Discovery: gauge {i} red LED", + entries.append( + ( + gt["led_red_disc"], + { + "name": f"{g['name']} Dial Red LED", + "uniq_id": f"{MQTT_CLIENT_ID}_g{i}_red", + "cmd_t": gt["led_red"], + "stat_t": gt["led_red_state"], + "schema": "json", + "supported_color_modes": ["onoff"], + "effect": True, + "effect_list": _EFFECT_LIST, + "icon": "mdi:led-on", + "dev": dev_ref, + "ret": True, + }, + f"Discovery: gauge {i} red LED", + ) + ) + entries.append( + ( + gt["led_green_disc"], + { + "name": f"{g['name']} Dial Green LED", + "uniq_id": f"{MQTT_CLIENT_ID}_g{i}_green", + "cmd_t": gt["led_green"], + "stat_t": gt["led_green_state"], + "schema": "json", + "supported_color_modes": ["onoff"], + "effect": True, + "effect_list": _EFFECT_LIST, + "icon": "mdi:led-on", + "dev": dev_ref, + "ret": True, + }, + f"Discovery: gauge {i} green LED", + ) ) - _publish_discovery_entity( - client, - gt["led_green_disc"], - { - "name": f"{g['name']} Dial Green LED", - "uniq_id": f"{MQTT_CLIENT_ID}_g{i}_green", - "cmd_t": gt["led_green"], - "stat_t": gt["led_green_state"], - "schema": "json", - "supported_color_modes": ["onoff"], - "effect": True, - "effect_list": _EFFECT_LIST, - "icon": "mdi:led-on", - "dev": dev_ref, - "ret": True, - }, - f"Discovery: gauge {i} green LED", - ) - _discovery_pause(client) - -def _publish_backlight_status_discovery(client, dev_ref): +def _append_backlight_status_discovery(entries, dev_ref): for i, g in enumerate(gauges): gt = gauge_topics[i] - _publish_discovery_entity( - client, - gt["led_bl_disc"], - { - "name": f"{g['name']} Backlight", - "uniq_id": f"{MQTT_CLIENT_ID}_g{i}_bl", - "cmd_t": gt["led_bl"], - "stat_t": gt["led_bl_state"], - "schema": "json", - "supported_color_modes": ["rgb"], - "effect": True, - "effect_list": _EFFECT_LIST, - "icon": "mdi:led-strip", - "dev": dev_ref, - "ret": True, - }, - f"Discovery: gauge {i} backlight", + entries.append( + ( + gt["led_bl_disc"], + { + "name": f"{g['name']} Backlight", + "uniq_id": f"{MQTT_CLIENT_ID}_g{i}_bl", + "cmd_t": gt["led_bl"], + "stat_t": gt["led_bl_state"], + "schema": "json", + "supported_color_modes": ["rgb"], + "effect": True, + "effect_list": _EFFECT_LIST, + "icon": "mdi:led-strip", + "dev": dev_ref, + "ret": True, + }, + f"Discovery: gauge {i} backlight", + ) ) - - _publish_discovery_entity( - client, - gt["status_red_disc"], - { - "name": f"{g['name']} Channel Status Red", - "uniq_id": f"{MQTT_CLIENT_ID}_g{i}_status_red", - "cmd_t": gt["status_red"], - "stat_t": gt["status_red_state"], - "schema": "json", - "supported_color_modes": ["onoff"], - "effect": True, - "effect_list": _EFFECT_LIST, - "icon": "mdi:led-on", - "dev": dev_ref, - "ret": True, - }, - f"Discovery: gauge {i} status red", + entries.append( + ( + gt["status_red_disc"], + { + "name": f"{g['name']} Channel Status Red", + "uniq_id": f"{MQTT_CLIENT_ID}_g{i}_status_red", + "cmd_t": gt["status_red"], + "stat_t": gt["status_red_state"], + "schema": "json", + "supported_color_modes": ["onoff"], + "effect": True, + "effect_list": _EFFECT_LIST, + "icon": "mdi:led-on", + "dev": dev_ref, + "ret": True, + }, + f"Discovery: gauge {i} status red", + ) ) - - _publish_discovery_entity( - client, - gt["status_green_disc"], - { - "name": f"{g['name']} Channel Status Green", - "uniq_id": f"{MQTT_CLIENT_ID}_g{i}_status_green", - "cmd_t": gt["status_green"], - "stat_t": gt["status_green_state"], - "schema": "json", - "supported_color_modes": ["onoff"], - "effect": True, - "effect_list": _EFFECT_LIST, - "icon": "mdi:led-on", - "dev": dev_ref, - "ret": True, - }, - f"Discovery: gauge {i} status green", + entries.append( + ( + gt["status_green_disc"], + { + "name": f"{g['name']} Channel Status Green", + "uniq_id": f"{MQTT_CLIENT_ID}_g{i}_status_green", + "cmd_t": gt["status_green"], + "stat_t": gt["status_green_state"], + "schema": "json", + "supported_color_modes": ["onoff"], + "effect": True, + "effect_list": _EFFECT_LIST, + "icon": "mdi:led-on", + "dev": dev_ref, + "ret": True, + }, + f"Discovery: gauge {i} status green", + ) ) - _discovery_pause(client) - - -def publish_discovery(client): - """Publish all HA MQTT discovery payloads for gauges and LEDs.""" - _dev_ref = _DEVICE - - # Clear any previously registered switch entities (migration to light). - for i in range(num_gauges): - for old_t in [ - f"homeassistant/switch/{MQTT_CLIENT_ID}_g{i}_red/config", - f"homeassistant/switch/{MQTT_CLIENT_ID}_g{i}_green/config", - f"homeassistant/switch/{MQTT_CLIENT_ID}_g{i}_status_red/config", - f"homeassistant/switch/{MQTT_CLIENT_ID}_g{i}_status_green/config", - ]: - client.publish(old_t, b"", retain=True) - _discovery_pause(client, count=2, delay_ms=15) - - _publish_gauge_discovery(client, _dev_ref) - _publish_speed_discovery(client, _dev_ref) - _publish_acceleration_discovery(client, _dev_ref) - _publish_indicator_led_discovery(client, _dev_ref) - _publish_backlight_status_discovery(client, _dev_ref) def schedule_discovery(): - global _discovery_phases, _discovery_phase_idx, _last_discovery_ms + global _discovery_queue, _discovery_idx, _last_discovery_ms _dev_ref = _DEVICE - _discovery_phases = ( - lambda client: _clear_legacy_discovery(client), - lambda client: _publish_gauge_discovery(client, _dev_ref), - lambda client: _publish_speed_discovery(client, _dev_ref), - lambda client: _publish_acceleration_discovery(client, _dev_ref), - lambda client: _publish_indicator_led_discovery(client, _dev_ref), - lambda client: _publish_backlight_status_discovery(client, _dev_ref), - ) - _discovery_phase_idx = 0 + entries = [] + _append_legacy_discovery(entries) + _append_gauge_discovery(entries, _dev_ref) + _append_speed_discovery(entries, _dev_ref) + _append_acceleration_discovery(entries, _dev_ref) + _append_indicator_led_discovery(entries, _dev_ref) + _append_backlight_status_discovery(entries, _dev_ref) + _discovery_queue = entries + _discovery_idx = 0 _last_discovery_ms = 0 -def _clear_legacy_discovery(client): +def _append_legacy_discovery(entries): for i in range(num_gauges): for old_t in [ f"homeassistant/switch/{MQTT_CLIENT_ID}_g{i}_red/config", @@ -1047,22 +1018,27 @@ def _clear_legacy_discovery(client): f"homeassistant/switch/{MQTT_CLIENT_ID}_g{i}_status_red/config", f"homeassistant/switch/{MQTT_CLIENT_ID}_g{i}_status_green/config", ]: - client.publish(old_t, b"", retain=True) - _discovery_pause(client, count=2, delay_ms=15) + entries.append((old_t, b"", None)) def service_discovery(): - global _discovery_phase_idx, _last_discovery_ms - if client_ref is None or _discovery_phase_idx >= len(_discovery_phases): + global _discovery_idx, _last_discovery_ms + if client_ref is None or _discovery_idx >= len(_discovery_queue): return now = utime.ticks_ms() if _last_discovery_ms and utime.ticks_diff(now, _last_discovery_ms) < _DISCOVERY_INTERVAL_MS: return - _discovery_phases[_discovery_phase_idx](client_ref) - _discovery_phase_idx += 1 + topic, payload, log_msg = _discovery_queue[_discovery_idx] + if isinstance(payload, bytes): + client_ref.publish(topic, payload, retain=True) + else: + _publish_discovery_entity(client_ref, topic, payload, log_msg) + _discovery_idx += 1 _last_discovery_ms = utime.ticks_ms() + if (_discovery_idx & 3) == 0: + gc.collect() def publish_online(client):