218 lines
7.4 KiB
Python
218 lines
7.4 KiB
Python
"""SigMesh Gateway 服务定义(保留用于向后兼容)。
|
||
|
||
注意:配网功能已迁移到 Web UI,服务调用接口保留用于自动化脚本。
|
||
"""
|
||
|
||
import voluptuous as vol
|
||
from homeassistant.helpers import config_validation as cv
|
||
|
||
from .const import CONF_GROUP_ADDRESS, CONF_NETWORK_KEY, DOMAIN
|
||
|
||
# 服务常量
|
||
SERVICE_START_SCAN = "start_scan"
|
||
SERVICE_STOP_PROVISIONING = "stop_provisioning"
|
||
SERVICE_START_PROVISIONING = "start_provisioning"
|
||
SERVICE_BIND_APPKEY = "bind_appkey"
|
||
SERVICE_ADD_TO_GROUP = "add_to_group"
|
||
SERVICE_REMOVE_FROM_GROUP = "remove_from_group"
|
||
SERVICE_SEND_VENDOR_COMMAND = "send_vendor_command"
|
||
|
||
# 服务 Schema
|
||
SERVICE_SCHEMA_START_SCAN = {}
|
||
|
||
SERVICE_SCHEMA_STOP_PROVISIONING = {}
|
||
|
||
SERVICE_SCHEMA_START_PROVISIONING = {
|
||
vol.Required("device_address"): cv.string,
|
||
}
|
||
|
||
SERVICE_SCHEMA_BIND_APPKEY = {
|
||
vol.Required("device_address"): cv.string,
|
||
vol.Required("element_address", default=0): vol.Coerce(int),
|
||
}
|
||
|
||
SERVICE_SCHEMA_ADD_TO_GROUP = {
|
||
vol.Required("target_address"): cv.string,
|
||
vol.Required("element_address", default=0): vol.Coerce(int),
|
||
vol.Required("group_address"): cv.string,
|
||
vol.Required("model_id", default=4352): vol.Coerce(int),
|
||
vol.Optional("is_sig", default=True): cv.boolean,
|
||
}
|
||
|
||
SERVICE_SCHEMA_REMOVE_FROM_GROUP = {
|
||
vol.Required("target_address"): cv.string,
|
||
vol.Required("element_address", default=0): vol.Coerce(int),
|
||
vol.Required("group_address"): cv.string,
|
||
vol.Required("model_id", default=4352): vol.Coerce(int),
|
||
vol.Optional("is_sig", default=True): cv.boolean,
|
||
}
|
||
|
||
SERVICE_SCHEMA_SEND_VENDOR_COMMAND = {
|
||
vol.Required("target_address"): cv.string,
|
||
vol.Required("element_address", default=0): vol.Coerce(int),
|
||
vol.Required("opcode"): cv.string,
|
||
vol.Required("payload"): cv.string,
|
||
}
|
||
|
||
SERVICE_SCHEMA_SEND_RAW_COMMAND = {
|
||
vol.Required("hex_data"): cv.string,
|
||
}
|
||
|
||
|
||
def setup_services(hass, coordinators: dict) -> None:
|
||
"""设置 HA 服务。
|
||
|
||
注意:配网功能已迁移到 Web UI,服务调用接口保留用于自动化脚本。
|
||
推荐使用 Web UI 进行配网和分组管理操作。
|
||
|
||
Args:
|
||
hass: HomeAssistant 实例
|
||
coordinators: 协调器字典 {entry_id: coordinator}
|
||
"""
|
||
|
||
async def handle_start_scan(call) -> None:
|
||
"""处理开始扫描服务调用."""
|
||
for coordinator in coordinators.values():
|
||
await coordinator.start_scanning()
|
||
|
||
async def handle_stop_provisioning(call) -> None:
|
||
"""处理停止配网服务调用."""
|
||
for coordinator in coordinators.values():
|
||
await coordinator.stop_provisioning()
|
||
|
||
async def handle_start_provisioning(call) -> None:
|
||
"""处理开始配网服务调用."""
|
||
device_address = call.data.get("device_address")
|
||
for coordinator in coordinators.values():
|
||
await coordinator.start_provisioning(device_address)
|
||
|
||
async def handle_bind_appkey(call) -> None:
|
||
"""处理绑定 App Key 服务调用."""
|
||
device_address = call.data.get("device_address")
|
||
element_address = call.data.get("element_address", 0)
|
||
for coordinator in coordinators.values():
|
||
await coordinator.bind_app_key(device_address, element_address)
|
||
|
||
async def handle_add_to_group(call) -> None:
|
||
"""处理添加设备到组服务调用."""
|
||
target_address = call.data.get("target_address")
|
||
element_address = call.data.get("element_address", 0)
|
||
group_address = call.data.get("group_address")
|
||
model_id = call.data.get("model_id", 4352)
|
||
is_sig = call.data.get("is_sig", True)
|
||
|
||
# 解析组地址(支持 hex 字符串)
|
||
if isinstance(group_address, str):
|
||
group_address = int(group_address, 16)
|
||
|
||
for coordinator in coordinators.values():
|
||
await coordinator.add_device_to_group(
|
||
target_address, element_address, group_address, model_id, is_sig
|
||
)
|
||
|
||
async def handle_remove_from_group(call) -> None:
|
||
"""处理从组中移除设备服务调用."""
|
||
target_address = call.data.get("target_address")
|
||
element_address = call.data.get("element_address", 0)
|
||
group_address = call.data.get("group_address")
|
||
model_id = call.data.get("model_id", 4352)
|
||
is_sig = call.data.get("is_sig", True)
|
||
|
||
# 解析组地址(支持 hex 字符串)
|
||
if isinstance(group_address, str):
|
||
group_address = int(group_address, 16)
|
||
|
||
for coordinator in coordinators.values():
|
||
await coordinator.remove_device_from_group(
|
||
target_address, element_address, group_address, model_id, is_sig
|
||
)
|
||
|
||
async def handle_send_vendor_command(call) -> None:
|
||
"""处理发送 VENDOR 命令服务调用."""
|
||
target_address = call.data.get("target_address")
|
||
element_address = call.data.get("element_address", 0)
|
||
opcode = call.data.get("opcode")
|
||
payload = call.data.get("payload")
|
||
|
||
# 解析操作码和负载
|
||
if isinstance(opcode, str):
|
||
opcode = int(opcode, 16)
|
||
if isinstance(payload, str):
|
||
payload = bytes.fromhex(payload)
|
||
|
||
for coordinator in coordinators.values():
|
||
await coordinator.prov_manager.send_vendor_command(
|
||
target_address, element_address, opcode, payload
|
||
)
|
||
|
||
async def handle_send_raw_command(call) -> None:
|
||
"""处理发送原始串口命令服务调用."""
|
||
hex_data = call.data.get("hex_data")
|
||
try:
|
||
raw_data = bytes.fromhex(hex_data)
|
||
for coordinator in coordinators.values():
|
||
if coordinator.serial_reader.is_connected:
|
||
await coordinator.serial_reader.write(raw_data)
|
||
_LOGGER.info("已发送原始命令:%s", hex_data)
|
||
else:
|
||
_LOGGER.warning("串口未连接,无法发送命令")
|
||
except ValueError as e:
|
||
_LOGGER.error("无效的十六进制数据:%s, 错误:%s", hex_data, e)
|
||
|
||
# 注册服务
|
||
hass.services.async_register(
|
||
DOMAIN,
|
||
SERVICE_START_SCAN,
|
||
handle_start_scan,
|
||
schema=vol.Schema(SERVICE_SCHEMA_START_SCAN),
|
||
)
|
||
|
||
hass.services.async_register(
|
||
DOMAIN,
|
||
SERVICE_STOP_PROVISIONING,
|
||
handle_stop_provisioning,
|
||
schema=vol.Schema(SERVICE_SCHEMA_STOP_PROVISIONING),
|
||
)
|
||
|
||
hass.services.async_register(
|
||
DOMAIN,
|
||
SERVICE_START_PROVISIONING,
|
||
handle_start_provisioning,
|
||
schema=vol.Schema(SERVICE_SCHEMA_START_PROVISIONING),
|
||
)
|
||
|
||
hass.services.async_register(
|
||
DOMAIN,
|
||
SERVICE_BIND_APPKEY,
|
||
handle_bind_appkey,
|
||
schema=vol.Schema(SERVICE_SCHEMA_BIND_APPKEY),
|
||
)
|
||
|
||
hass.services.async_register(
|
||
DOMAIN,
|
||
SERVICE_ADD_TO_GROUP,
|
||
handle_add_to_group,
|
||
schema=vol.Schema(SERVICE_SCHEMA_ADD_TO_GROUP),
|
||
)
|
||
|
||
hass.services.async_register(
|
||
DOMAIN,
|
||
SERVICE_REMOVE_FROM_GROUP,
|
||
handle_remove_from_group,
|
||
schema=vol.Schema(SERVICE_SCHEMA_REMOVE_FROM_GROUP),
|
||
)
|
||
|
||
hass.services.async_register(
|
||
DOMAIN,
|
||
SERVICE_SEND_VENDOR_COMMAND,
|
||
handle_send_vendor_command,
|
||
schema=vol.Schema(SERVICE_SCHEMA_SEND_VENDOR_COMMAND),
|
||
)
|
||
|
||
hass.services.async_register(
|
||
DOMAIN,
|
||
"send_raw_command",
|
||
handle_send_raw_command,
|
||
schema=vol.Schema(SERVICE_SCHEMA_SEND_RAW_COMMAND),
|
||
)
|