126 lines
4.4 KiB
Python
126 lines
4.4 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
from ha_deconz_bridge.ha import HomeAssistantBridge
|
|
from ha_deconz_bridge.lights import ChannelSpec, ControllerModeSpec, ControllerSpec, VirtualLightSpec
|
|
from ha_deconz_bridge.light import VirtualLightState
|
|
from ha_deconz_bridge.color import Color
|
|
|
|
|
|
class FakeMQTTClient:
|
|
def __init__(self) -> None:
|
|
self.connected = False
|
|
self.on_connect = None
|
|
self.on_message = None
|
|
self.published: list[tuple[str, str, bool]] = []
|
|
self.subscriptions: list[str] = []
|
|
|
|
def username_pw_set(self, username, password) -> None:
|
|
self.username = username
|
|
self.password = password
|
|
|
|
def connect(self, host: str, port: int, keepalive: int) -> None:
|
|
self.host = host
|
|
self.port = port
|
|
self.keepalive = keepalive
|
|
|
|
def loop_start(self) -> None:
|
|
self.connected = True
|
|
if self.on_connect is not None:
|
|
self.on_connect(self, None, None, 0)
|
|
|
|
def loop_stop(self) -> None:
|
|
self.connected = False
|
|
|
|
def disconnect(self) -> None:
|
|
self.connected = False
|
|
|
|
def publish(self, topic: str, payload: str, retain: bool = False):
|
|
if not self.connected:
|
|
raise RuntimeError("publish before MQTT connect")
|
|
self.published.append((topic, payload, retain))
|
|
|
|
def subscribe(self, topic: str) -> None:
|
|
if not self.connected:
|
|
raise RuntimeError("subscribe before MQTT connect")
|
|
self.subscriptions.append(topic)
|
|
|
|
|
|
def test_bridge_waits_for_connect_before_discovery(settings, rgb_light_spec) -> None:
|
|
mqtt = FakeMQTTClient()
|
|
bridge = HomeAssistantBridge(settings, mqtt_client=mqtt)
|
|
|
|
bridge.start(on_command=lambda event: None)
|
|
bridge.publish_discovery(rgb_light_spec)
|
|
bridge.publish_state(
|
|
rgb_light_spec,
|
|
VirtualLightState(
|
|
on=True,
|
|
color=rgb_light_spec.controllers["1"].modes["rgb"].channels["r"].color,
|
|
ha_mode="rgb",
|
|
brightness=128,
|
|
exact_chroma_match=True,
|
|
),
|
|
)
|
|
|
|
assert mqtt.published[0][0] == "homeassistant/light/rgb_light/config"
|
|
assert json.loads(mqtt.published[0][1])["schema"] == "json"
|
|
assert json.loads(mqtt.published[0][1])["name"] == "rgb_light"
|
|
assert mqtt.subscriptions == ["ha-deconz-bridge/light/rgb_light/set"]
|
|
|
|
|
|
def test_bridge_sanitizes_mqtt_object_id_for_discovery_topics(settings) -> None:
|
|
mqtt = FakeMQTTClient()
|
|
bridge = HomeAssistantBridge(settings, mqtt_client=mqtt)
|
|
bridge.start(on_command=lambda event: None)
|
|
|
|
spec = VirtualLightSpec(
|
|
name="Example Light North",
|
|
supported_color_modes=("brightness",),
|
|
controllers={
|
|
"example_controller": ControllerSpec(
|
|
zigbee_id="example_controller",
|
|
name="Example controller",
|
|
modes={
|
|
"brightness": ControllerModeSpec(
|
|
name="brightness",
|
|
channels={
|
|
"w": ChannelSpec(
|
|
"w",
|
|
Color.from_color_temp(182, brightness=1.0),
|
|
semantic_label="color_temp",
|
|
)
|
|
},
|
|
)
|
|
},
|
|
)
|
|
},
|
|
)
|
|
bridge.publish_discovery(spec)
|
|
|
|
assert mqtt.published[0][0] == "homeassistant/light/Example_Light_North/config"
|
|
payload = json.loads(mqtt.published[0][1])
|
|
assert payload["name"] == "Example Light North"
|
|
assert payload["unique_id"] == "Example_Light_North"
|
|
assert payload["device"]["identifiers"] == ["ha-deconz-bridge:Example_Light_North"]
|
|
assert payload["device"]["name"] == "HA deCONZ Bridge: Example Light North"
|
|
assert payload["command_topic"] == "ha-deconz-bridge/light/Example_Light_North/set"
|
|
assert payload["state_topic"] == "ha-deconz-bridge/light/Example_Light_North/state"
|
|
assert mqtt.subscriptions == ["ha-deconz-bridge/light/Example_Light_North/set"]
|
|
|
|
|
|
def test_bridge_resubscribes_to_command_topics_on_reconnect(settings, rgb_light_spec) -> None:
|
|
mqtt = FakeMQTTClient()
|
|
bridge = HomeAssistantBridge(settings, mqtt_client=mqtt)
|
|
bridge.start(on_command=lambda event: None)
|
|
bridge.publish_discovery(rgb_light_spec)
|
|
|
|
mqtt.loop_stop()
|
|
mqtt.loop_start()
|
|
|
|
assert mqtt.subscriptions == [
|
|
"ha-deconz-bridge/light/rgb_light/set",
|
|
"ha-deconz-bridge/light/rgb_light/set",
|
|
]
|