Source code for nwp500.topic_builder

"""
MQTT topic building utilities for Navien devices.

All MQTT topic construction goes through this class so that the topic schema
is defined in exactly one place.

Topic schema:
  Device command (ctrl/query): cmd/{device_type}/navilink-{mac}/{suffix}
  Device subscribe (wildcard):  cmd/{device_type}/navilink-{mac}/#
  Response (control ack):       cmd/{device_type}/navilink-{mac}/{client_id}/res
  Response (query result):      cmd/{device_type}/{client_id}/res/{suffix}
  Event:                        evt/{device_type}/navilink-{mac}/{suffix}
"""

from __future__ import annotations


[docs] class MqttTopicBuilder: """Helper to construct standard MQTT topics for Navien devices."""
[docs] @staticmethod def device_topic(mac_address: str) -> str: """Get the navilink device path segment from MAC address.""" return f"navilink-{mac_address}"
[docs] @staticmethod def command_topic( device_type: str, mac_address: str, suffix: str = "ctrl" ) -> str: """Build a device command topic. Format: ``cmd/{device_type}/navilink-{mac}/{suffix}`` """ dt = MqttTopicBuilder.device_topic(mac_address) return f"cmd/{device_type}/{dt}/{suffix}"
[docs] @staticmethod def response_ack_topic( device_type: str, mac_address: str, client_id: str ) -> str: """Build the default response topic for control commands. The device sends its acknowledgement to this topic; the client subscribes via the ``command_topic(..., "#")`` wildcard. Format: ``cmd/{device_type}/navilink-{mac}/{client_id}/res`` """ dt = MqttTopicBuilder.device_topic(mac_address) return f"cmd/{device_type}/{dt}/{client_id}/res"
[docs] @staticmethod def response_topic(device_type: str, client_id: str, suffix: str) -> str: """Build a client-specific response topic for query commands. Used when the device should reply directly to a client-keyed topic rather than the device topic (e.g. reservation reads, TOU reads, energy queries). Format: ``cmd/{device_type}/{client_id}/res/{suffix}`` """ return f"cmd/{device_type}/{client_id}/res/{suffix}"
[docs] @staticmethod def event_topic(device_type: str, mac_address: str, suffix: str) -> str: """Build a device event topic. Format: ``evt/{device_type}/navilink-{mac}/{suffix}`` """ dt = MqttTopicBuilder.device_topic(mac_address) return f"evt/{device_type}/{dt}/{suffix}"