实现设备自动发现规则管理系统,包含以下主要功能: 1. 新增规则管理页面和API,支持创建、编辑和删除主题匹配规则 2. 添加规则匹配引擎,支持+和#通配符匹配设备主题 3. 实现Broker设备注册表,自动发现并管理符合规则的设备 4. 扩展仪表盘显示Broker信息和活跃主题 5. 修改设备卡片和详情页以区分规则发现的设备 6. 添加相关测试用例确保功能稳定性
87 lines
3.0 KiB
Python
87 lines
3.0 KiB
Python
from types import SimpleNamespace
|
|
from mqtt_home.broker_devices import BrokerDevice, BrokerDeviceRegistry
|
|
|
|
|
|
def make_rule(id=1, topic_pattern="home/+/state", device_type="switch",
|
|
command_template="home/{device_id}/set", state_value_path="state",
|
|
is_enabled=True):
|
|
return SimpleNamespace(
|
|
id=id, topic_pattern=topic_pattern, device_type=device_type,
|
|
command_template=command_template, state_value_path=state_value_path,
|
|
is_enabled=is_enabled,
|
|
)
|
|
|
|
|
|
def test_create_device_on_match():
|
|
registry = BrokerDeviceRegistry()
|
|
rule = make_rule()
|
|
device = registry.update_or_create("home/fire/state", '{"state":"on"}', rule)
|
|
assert device is not None
|
|
assert device.id == "broker:fire"
|
|
assert device.name == "fire"
|
|
assert device.type == "switch"
|
|
assert device.state == "on"
|
|
assert device.command_topic == "home/fire/set"
|
|
assert device.is_online is True
|
|
assert device.rule_id == 1
|
|
|
|
|
|
def test_update_existing_device():
|
|
registry = BrokerDeviceRegistry()
|
|
rule = make_rule()
|
|
registry.update_or_create("home/fire/state", '{"state":"on"}', rule)
|
|
device = registry.update_or_create("home/fire/state", '{"state":"off"}', rule)
|
|
assert device.state == "off"
|
|
assert len(registry.get_all()) == 1
|
|
|
|
|
|
def test_different_topics_different_devices():
|
|
registry = BrokerDeviceRegistry()
|
|
rule = make_rule()
|
|
registry.update_or_create("home/fire/state", '{"state":"on"}', rule)
|
|
registry.update_or_create("home/servo/state", '{"state":"off"}', rule)
|
|
assert len(registry.get_all()) == 2
|
|
|
|
|
|
def test_no_match_returns_none():
|
|
registry = BrokerDeviceRegistry()
|
|
rule = make_rule(topic_pattern="home/+/state")
|
|
result = registry.update_or_create("living/light/status", '{"state":"on"}', rule)
|
|
assert result is None
|
|
|
|
|
|
def test_remove_by_rule():
|
|
registry = BrokerDeviceRegistry()
|
|
rule1 = make_rule(id=1)
|
|
rule2 = make_rule(id=2, topic_pattern="sensor/+/data")
|
|
registry.update_or_create("home/fire/state", '{"state":"on"}', rule1)
|
|
registry.update_or_create("sensor/temp/data", '{"value":25}', rule2)
|
|
assert len(registry.get_all()) == 2
|
|
removed = registry.remove_by_rule(1)
|
|
assert removed == ["broker:fire"]
|
|
assert len(registry.get_all()) == 1
|
|
assert registry.get("broker:fire") is None
|
|
|
|
|
|
def test_full_payload_as_state():
|
|
registry = BrokerDeviceRegistry()
|
|
rule = make_rule(state_value_path=None)
|
|
device = registry.update_or_create("home/fire/state", '{"state":"on","brightness":128}', rule)
|
|
assert device.state == '{"state":"on","brightness":128}'
|
|
|
|
|
|
def test_get_device():
|
|
registry = BrokerDeviceRegistry()
|
|
rule = make_rule()
|
|
registry.update_or_create("home/fire/state", '{"state":"on"}', rule)
|
|
assert registry.get("broker:fire") is not None
|
|
assert registry.get("broker:nonexistent") is None
|
|
|
|
|
|
def test_clear():
|
|
registry = BrokerDeviceRegistry()
|
|
rule = make_rule()
|
|
registry.update_or_create("home/fire/state", '{"state":"on"}', rule)
|
|
registry.clear()
|
|
assert len(registry.get_all()) == 0
|