mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 07:03:53 +08:00
* 2025-2-17-iot配置消息处理, 以及控制iot命令发送 (#40) * update:优化 * update:增加视频教程 * update:iot兼容性又问题,撤回 * fixed:iot boolean 参数接收bug --------- Co-authored-by: Jiao Haoyang <108573524+XuSenfeng@users.noreply.github.com> Co-authored-by: hrz <1710360675@qq.com>
153 lines
5.1 KiB
Python
153 lines
5.1 KiB
Python
import json
|
|
from config.logger import setup_logging
|
|
|
|
TAG = __name__
|
|
logger = setup_logging()
|
|
|
|
|
|
class IotDescriptor:
|
|
"""
|
|
A class to represent an IoT descriptor.
|
|
Attributes:
|
|
----------
|
|
name : str
|
|
The name of the IoT descriptor.
|
|
description : str
|
|
A brief description of the IoT descriptor.
|
|
properties : dict
|
|
A dictionary containing properties of the IoT descriptor.
|
|
methods : dict
|
|
A dictionary containing methods of the IoT descriptor.
|
|
-------
|
|
"""
|
|
|
|
def __init__(self, name, description, properties, methods):
|
|
self.name = name
|
|
self.description = description
|
|
self.properties = []
|
|
self.methods = []
|
|
|
|
# 根据描述创建属性
|
|
for key, value in properties.items():
|
|
# "volume":{"description":"当前音量 值","type":"number"}
|
|
"""
|
|
等价于
|
|
{
|
|
'name': 名字,
|
|
'description': 描述,
|
|
'value': 0
|
|
}
|
|
"""
|
|
# setattr(self, key, {}) # 创建一个空字典, 名字是属性名
|
|
property_item = globals()[key] = {} # 创建一个空字典, 名字是属性名
|
|
property_item['name'] = key
|
|
property_item["description"] = value["description"]
|
|
if value["type"] == "number":
|
|
property_item["value"] = 0
|
|
elif value["type"] == "boolean":
|
|
property_item["value"] = False
|
|
else:
|
|
property_item["value"] = ""
|
|
self.properties.append(property_item)
|
|
|
|
# 根据描述创建方法
|
|
for key, value in methods.items():
|
|
# "SetVolume": {"description":"设置音量","parameters":{"volume":{"description":"0到100之间的整数","type":"number"}}}
|
|
"""
|
|
等价于
|
|
SetVolume = {
|
|
`description`: 描述,
|
|
`volume`: {
|
|
`description`: 描述,
|
|
`value`: 0
|
|
}
|
|
}
|
|
"""
|
|
# setattr(self, key, {}) # 创建一个空字典, 名字是方法名
|
|
method = globals()[key] = {} # 创建一个空字典, 名字是方法名
|
|
method["description"] = value["description"]
|
|
method['name'] = key
|
|
for k, v in value["parameters"].items():
|
|
# 不同的参数解析
|
|
method[k] = {}
|
|
method[k]["description"] = v["description"]
|
|
if v["type"] == "number":
|
|
method[k]["value"] = 0
|
|
elif v["type"] == "boolean":
|
|
method[k]["value"] = False
|
|
else:
|
|
method[k]["value"] = ""
|
|
|
|
self.methods.append(method)
|
|
|
|
|
|
async def handleIotDescriptors(conn, descriptors):
|
|
"""
|
|
处理物联网描述
|
|
示例: [{
|
|
"name":"Speaker",
|
|
"description":"当前 AI 机器人的扬声器",
|
|
"properties":{
|
|
"volume":{"description":"当前音量 值","type":"number"} 可以有boolean, number, string三种类型
|
|
},
|
|
"methods":{
|
|
"SetVolume":{
|
|
"description":"设置音量","parameters":{"volume":{"description":"0到100之间的整数","type":"number"}}
|
|
}
|
|
}
|
|
}]
|
|
descriptors: 描述列表
|
|
"""
|
|
for descriptor in descriptors:
|
|
iot_descriptor = IotDescriptor(descriptor["name"], descriptor["description"], descriptor["properties"],
|
|
descriptor["methods"])
|
|
conn.iot_descriptors[descriptor["name"]] = iot_descriptor
|
|
|
|
# 暂时从配置文件中设置音量,后期通过意图识别控制音量
|
|
default_iot_volume = 100
|
|
if "iot" in conn.config:
|
|
default_iot_volume = conn.config["iot"]["Speaker"]["volume"]
|
|
logger.bind(tag=TAG).info(f"服务端设置音量为{default_iot_volume}")
|
|
await send_iot_conn(conn, "Speaker", "SetVolume", {"volume": default_iot_volume})
|
|
|
|
|
|
async def send_iot_conn(conn, name, method_name, parameters):
|
|
"""
|
|
发送物联网指令
|
|
name: 设备名称 "Speaker"
|
|
method: 方法 "SetVolume"
|
|
parameters: 参数, 是一个字典 {"volume": 100}
|
|
发送示例:
|
|
{
|
|
"type": "iot",
|
|
"commands": [
|
|
{
|
|
"name" : "Speaker",
|
|
"method": "SetVolume",
|
|
"parameters": {
|
|
"volume": 100
|
|
}
|
|
}
|
|
]
|
|
}
|
|
"""
|
|
|
|
for key, value in conn.iot_descriptors.items():
|
|
if key == name:
|
|
# 找到了设备
|
|
for method in value.methods:
|
|
# 找到了方法
|
|
if method["name"] == method_name:
|
|
await conn.websocket.send(json.dumps({
|
|
"type": "iot",
|
|
"commands": [
|
|
{
|
|
"name": name,
|
|
"method": method_name,
|
|
"parameters": parameters
|
|
}
|
|
]
|
|
}))
|
|
return
|
|
logger.bind(tag=TAG).error(f"未找到方法{method_name}")
|