From 3649a33afb7874b6646106bce625f7fed1e49bd3 Mon Sep 17 00:00:00 2001 From: Jad Date: Wed, 26 Mar 2025 03:56:39 +0800 Subject: [PATCH] =?UTF-8?q?feat(plugin=5Ffunc):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=9F=B3=E9=87=8F=E6=8E=A7=E5=88=B6=E6=8F=92=E4=BB=B6=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BA=AE=E5=BA=A6=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 支持立创实战派等设备亮度调整 --- .../core/handle/functionHandler.py | 2 +- .../plugins_func/functions/handle_device.py | 105 ++++++++++++++++++ .../functions/raise_and_lower_the_volume.py | 64 ----------- 3 files changed, 106 insertions(+), 65 deletions(-) create mode 100644 main/xiaozhi-server/plugins_func/functions/handle_device.py delete mode 100644 main/xiaozhi-server/plugins_func/functions/raise_and_lower_the_volume.py diff --git a/main/xiaozhi-server/core/handle/functionHandler.py b/main/xiaozhi-server/core/handle/functionHandler.py index 2879ad6d..9cad9499 100644 --- a/main/xiaozhi-server/core/handle/functionHandler.py +++ b/main/xiaozhi-server/core/handle/functionHandler.py @@ -51,7 +51,7 @@ class FunctionHandler: self.function_registry.register_function("plugin_loader") self.function_registry.register_function("get_time") self.function_registry.register_function("get_lunar") - self.function_registry.register_function("raise_and_lower_the_volume") + self.function_registry.register_function("handle_device") def register_config_functions(self): """注册配置中的函数,可以不同客户端使用不同的配置""" diff --git a/main/xiaozhi-server/plugins_func/functions/handle_device.py b/main/xiaozhi-server/plugins_func/functions/handle_device.py new file mode 100644 index 00000000..d564562b --- /dev/null +++ b/main/xiaozhi-server/plugins_func/functions/handle_device.py @@ -0,0 +1,105 @@ +from config.logger import setup_logging +from plugins_func.register import register_function, ToolType, ActionResponse, Action +from core.handle.iotHandle import get_iot_status, send_iot_conn +import asyncio + +TAG = __name__ +logger = setup_logging() + +async def _get_device_status(conn, device_name, device_type, property_name): + """获取设备状态""" + status = await get_iot_status(conn, device_type, property_name) + if status is None: + raise Exception(f"你的设备不支持{device_name}控制") + return status + +async def _set_device_property(conn, device_name, device_type, method_name, property_name, new_value=None, action=None, step=10): + """设置设备属性""" + current_value = await _get_device_status(conn, device_name, device_type, property_name) + + if action == 'raise': + current_value += step + elif action == 'lower': + current_value -= step + elif action == 'set': + if new_value is None: + raise Exception(f"缺少{property_name}参数") + current_value = new_value + + # 限制属性范围在0到100之间 + current_value = max(0, min(100, current_value)) + + await send_iot_conn(conn, device_type, method_name, {property_name: current_value}) + return current_value + +def _handle_device_action(conn, func, success_message, error_message, *args, **kwargs): + """处理设备操作的通用函数""" + future = asyncio.run_coroutine_threadsafe(func(conn, *args, **kwargs), conn.loop) + try: + result = future.result() + logger.bind(tag=TAG).info(f"{success_message}: {result}") + response = f"{success_message}{result}" + return ActionResponse(action=Action.RESPONSE, result=result, response=response) + except Exception as e: + logger.bind(tag=TAG).error(f"{error_message}: {e}") + response = f"{error_message}: {e}" + return ActionResponse(action=Action.RESPONSE, result=None, response=response) + +# 设备控制 +handle_device_function_desc = { + "type": "function", + "function": { + "name": "handle_device", + "description": ( + "用户想要获取或者设置设备的音量/亮度大小,或者用户觉得声音/亮度过高或过低,或者用户想提高或降低音量/亮度。" + "比如用户说现在亮度多少,参数为:device_type:Backlight,action:get。" + "比如用户说设置音量为50,参数为:device_type:Speaker,action:set,value:50。" + "比如用户说亮度太高了,参数为:device_type:Backlight,action:lower。" + "比如用户说调大音量,参数为:device_type:Speaker,action:raise。" + ), + "parameters": { + "type": "object", + "properties": { + "device_type": { + "type": "string", + "description": "设备类型,可选值:Speaker(音量),Backlight(亮度)" + }, + "action": { + "type": "string", + "description": "动作名称,可选值:get(获取),set(设置),raise(提高),lower(降低)" + }, + "value": { + "type": "int", + "description": "值大小,可选值:0-100之间的整数" + } + }, + "required": ["device_type", "action"] + } + } +} + +@register_function('handle_device', handle_device_function_desc, ToolType.IOT_CTL) +def handle_device(conn, device_type: str, action: str, value: int = None): + if device_type == "Speaker": + method_name, property_name, device_name = "SetVolume", "volume", "音量" + elif device_type == "Backlight": + method_name, property_name, device_name = "SetBrightness", "brightness", "亮度" + else: + raise Exception(f"未识别的设备类型: {device_type}") + + if action not in ["get", "set", "raise", "lower"]: + raise Exception(f"未识别的动作名称: {action}") + + if action == "get": + # get + return _handle_device_action( + conn, _get_device_status, f"当前{device_name}", f"获取{device_name}失败", + device_name=device_name, device_type=device_type, property_name=property_name, + ) + else: + # set, raise, lower + return _handle_device_action( + conn, _set_device_property, f"{device_name}已调整到", f"{device_name}调整失败", + device_name=device_name, device_type=device_type, method_name=method_name, + property_name=property_name, new_value=value, action=action + ) diff --git a/main/xiaozhi-server/plugins_func/functions/raise_and_lower_the_volume.py b/main/xiaozhi-server/plugins_func/functions/raise_and_lower_the_volume.py deleted file mode 100644 index c77cb78b..00000000 --- a/main/xiaozhi-server/plugins_func/functions/raise_and_lower_the_volume.py +++ /dev/null @@ -1,64 +0,0 @@ -from config.logger import setup_logging -from plugins_func.register import register_function, ToolType, ActionResponse, Action -from core.handle.iotHandle import get_iot_status, send_iot_conn -import asyncio - -TAG = __name__ -logger = setup_logging() - -raise_and_lower_the_volume_function_desc = { - "type": "function", - "function": { - "name": "raise_and_lower_the_volume", - "description": "用户觉得声音过高或过低,或者用户想提高或降低音量。比如用户说太大声了,参数为:lower,比如用户说提高音量,参数为:raise", - "parameters": { - "type": "object", - "properties": { - "action": { - "type": "string", - "description": "动作名称,要么是raise,要么是lower" - } - }, - "required": ["action"] - } - } -} - - -@register_function('raise_and_lower_the_volume', raise_and_lower_the_volume_function_desc, ToolType.IOT_CTL) -def raise_and_lower_the_volume(conn, action: str): - """ - 获取当前设备音量 - """ - - future = asyncio.run_coroutine_threadsafe( - _raise_and_lower_the_volume(conn, action), - conn.loop - ) - - try: - new_volume = future.result() # 同步等待异步操作完成 - logger.bind(tag=TAG).info(f"音量操作完成: {new_volume}") - response = f"音量已调整到{new_volume}" - except Exception as e: - logger.bind(tag=TAG).error(f"音量操作失败: {e}") - response = f"音量调整失败: {e}" - - return ActionResponse(action=Action.RESPONSE, result="指令已接收", response=response) - - -async def _raise_and_lower_the_volume(conn, action): - volume = await get_iot_status(conn, "Speaker", "volume") - if volume is None: - raise Exception("你的设备不支持音量控制") - if action == 'raise': - volume += 10 - elif action == 'lower': - volume -= 10 - # 限制音量范围在0到100之间 - if volume < 0: - volume = 0 - elif volume > 100: - volume = 100 - await send_iot_conn(conn, "Speaker", "SetVolume", {"volume": volume}) - return volume