From 65792ccd893d3ad3cfb57d89ad8066d0ae35c857 Mon Sep 17 00:00:00 2001 From: Sucan126 <632190820@qq.com> Date: Sun, 28 Sep 2025 15:00:20 +0800 Subject: [PATCH] Update version to 0.1.21, enhance NavServer with user_id parameter for command functions, and improve error handling. Added new wheel and tar.gz distribution files. --- .../terminal_temi_mcp-0.1.21-py3-none-any.whl | Bin 0 -> 7227 bytes .../dist/terminal_temi_mcp-0.1.21.tar.gz | Bin 0 -> 6933 bytes terminal_temi_mcp/pyproject.toml | 2 +- terminal_temi_mcp/terminal_temi_mcp/main.py | 481 ++++++++---------- 4 files changed, 225 insertions(+), 258 deletions(-) create mode 100644 terminal_temi_mcp/dist/terminal_temi_mcp-0.1.21-py3-none-any.whl create mode 100644 terminal_temi_mcp/dist/terminal_temi_mcp-0.1.21.tar.gz diff --git a/terminal_temi_mcp/dist/terminal_temi_mcp-0.1.21-py3-none-any.whl b/terminal_temi_mcp/dist/terminal_temi_mcp-0.1.21-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..9b7b395813647c9ab4f1e8d1e695fee3894b253c GIT binary patch literal 7227 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 literal 0 HcmV?d00001 diff --git a/terminal_temi_mcp/dist/terminal_temi_mcp-0.1.21.tar.gz b/terminal_temi_mcp/dist/terminal_temi_mcp-0.1.21.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..809f31745de166b288c0c72a355a568f1ddd8731 GIT binary patch literal 6933 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 literal 0 HcmV?d00001 diff --git a/terminal_temi_mcp/pyproject.toml b/terminal_temi_mcp/pyproject.toml index 7095216..ac2080e 100644 --- a/terminal_temi_mcp/pyproject.toml +++ b/terminal_temi_mcp/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "terminal_temi_mcp" -version = "0.1.17" +version = "0.1.21" description = "MQTT-based navigation server for robot" requires-python = ">=3.10" dependencies = [ diff --git a/terminal_temi_mcp/terminal_temi_mcp/main.py b/terminal_temi_mcp/terminal_temi_mcp/main.py index b119b8e..1292f37 100644 --- a/terminal_temi_mcp/terminal_temi_mcp/main.py +++ b/terminal_temi_mcp/terminal_temi_mcp/main.py @@ -1,4 +1,4 @@ -from typing import Optional, Sequence +from typing import Optional, Sequence, List import logging from fastapi import FastAPI from pydantic import BaseModel @@ -27,268 +27,179 @@ class NavServer: def __init__(self, mmhandler=None): self.mmhandler = mmhandler or get_mcpmqtt_handler() - async def publish_Cmd(self, device_id: str, cmd: str, params: dict): + async def publish_Cmd(self, device_id: str, user_id: str, cmd: str, params: dict): try: payload = { "device_id": device_id, + "user_id": user_id, "cmd": cmd, "data": params["data"] } self.mmhandler.client.publish("robot/cmd", json.dumps(payload), qos=2) - return f"{cmd}工具执行成功" + return f"{cmd} 任务已经下达完成" except Exception as e: - logger.error(f"Failed to publish {cmd} command: {str(e)}", exc_info=True) - raise + logger.error(f"Failed to publish command: {str(e)}", exc_info=True) + return f"Failed to publish command: {str(e)}" - async def nav_to(self, location: str): - """ - 机器人导航去某个地方。 - Args: - - location (str): 目标地点名称 - Returns: - str: 命令执行结果消息 - - Raises: - ValueError: 如果参数无效或为空 - Exception: 如果MQTT发布失败 - """ - if location: - try: - if location == "充电桩": - location = "home base" + async def nav_to(self, user_id: str, location: str, flag: bool): + """轮足导航到指定位置""" + try: + if not location: + return "Location is not specified." + else: params = { - "data": {"location": location} + "data": {"location": location, "flag": flag} } - return await self.publish_Cmd("123456", "nav", params) - except Exception as e: - logger.error(f"Failed to call navigation mcp-tool: {str(e)} ", exc_info=True) - raise + return await self.publish_Cmd("123456", user_id, "nav", params) + except Exception as e: + logger.error(f"Failed to call navigation mcp-tool: {str(e)} ", exc_info=True) + return f"Failed to call navigation mcp-tool: {str(e)}" - async def speak(self, speech: str): - """ - 机器人说某些话。 - Args: - - speech (str): 说话内容 - Returns: - str: 命令执行结果消息 - - Raises: - ValueError: 如果参数无效或为空 - Exception: 如果MQTT发布失败 - """ - if speech: - try: + async def speak(self, user_id: str, speech: str): + """轮足机器人语音播报""" + try: + if not speech: + return "Speech content is not specified." + else: params = { "data": {"speech": speech} } - return await self.publish_Cmd("123456", "speak", params) - except Exception as e: - logger.error(f"Failed to call speak mcp-tool: {str(e)} ", exc_info=True) - raise + return await self.publish_Cmd("123456", user_id, "speak", params) + except Exception as e: + logger.error(f"Failed to call speak mcp-tool: {str(e)} ", exc_info=True) + return f"Failed to call speak mcp-tool: {str(e)}" - async def reception(self, location: str): - """ - 机器人接待客人。 - Args: - - location (str): 机器人接待客人到这个位置 - Returns: - str: 命令执行结果消息 - - Raises: - ValueError: 如果参数无效或为空 - Exception: 如果MQTT发布失败 - """ - if location : - try: + async def reception(self, user_id: str, location: str): + """轮足机器人移动到指定位置迎宾""" + try: + if not location: + return "Location is not specified." + else: params = { "data": { "location": location } } - return await self.publish_Cmd("123456", "reception", params) - except Exception as e: - logger.error(f"Failed to call reception mcp-tool: {str(e)} ", exc_info=True) - raise - - async def notification(self, location: str, text: str): - """ - 机器人通知事情。 - Args: - - location (str): 机器人去这个位置通知事情 - - text (str): 通知的内容 - Returns: - str: 命令执行结果消息 + return await self.publish_Cmd("123456", user_id, "reception", params) + except Exception as e: + logger.error(f"Failed to call reception mcp-tool: {str(e)} ", exc_info=True) + return f"Failed to call reception mcp-tool: {str(e)}" - Raises: - ValueError: 如果参数无效或为空 - Exception: 如果MQTT发布失败 - """ - if location : - try: + async def notification(self, user_id: str, location: str, text: str): + """轮足机器人移动到指定位置通知""" + try: + if not location or not text: + return "Location or text is not specified." + else: params = { "data": { "location": location, "text": text } } - return await self.publish_Cmd("123456", "notification", params) - except Exception as e: - logger.error(f"Failed to call notification mcp-tool: {str(e)} ", exc_info=True) - raise - async def repose(self): - """ - 机器人重新定位。 - """ + return await self.publish_Cmd("123456", user_id, "notification", params) + except Exception as e: + logger.error(f"Failed to call notification mcp-tool: {str(e)} ", exc_info=True) + return f"Failed to call notification mcp-tool: {str(e)}" + + async def repose(self, user_id: str): + """轮足机器人重新定位""" try: params = { "data": { "action": "repose" } } - return await self.publish_Cmd("123456", "map", params) + return await self.publish_Cmd("123456", user_id, "map", params) except Exception as e: logger.error(f"Failed to call repose mcp-tool: {str(e)} ", exc_info=True) - raise + return f"Failed to call repose mcp-tool: {str(e)}" - async def delivery(self, first_location: str, next_location: str): - """ - 机器人运送物品。 - Args: - - first_location (str): 机器人去这个位置取物品 - - next_location (str): 机器人将物品送到这个位置 - Returns: - str: 命令执行结果消息 - - Raises: - ValueError: 如果参数无效或为空 - Exception: 如果MQTT发布失败 - - """ - if first_location and next_location: - try: + async def delivery(self, user_id: str, first_location: str, next_location: str): + """轮足机器人配送""" + try: + if not first_location or not next_location: + return "first_location or next_location is not specified." + else: params = { "data": { "first_location": first_location, "next_location": next_location } } - return await self.publish_Cmd("123456", "delivery", params) - except Exception as e: - logger.error(f"Failed to call delivery mcp-tool: {str(e)} ", exc_info=True) - raise + return await self.publish_Cmd("123456", user_id, "delivery", params) + except Exception as e: + logger.error(f"Failed to call delivery mcp-tool: {str(e)} ", exc_info=True) + return f"Failed to call delivery mcp-tool: {str(e)}" - async def patrol(self, locations: list[str]): - """ - 机器人去巡逻。 - Args: - - locations (list[str]): 机器人巡逻经过的地点列表 - Returns: - str: 命令执行结果消息 - - Raises: - ValueError: 如果参数无效或为空 - Exception: 如果MQTT发布失败 - """ - if locations: - try: + async def patrol(self, user_id: str, locations: list): + """轮足机器人巡逻""" + try: + if not locations: + return "locations is not specified." + else: params = { "data": {"locations": locations} } - return await self.publish_Cmd("123456", "patrol", params) - except Exception as e: - logger.error(f"Failed to call patrol mcp-tool: {str(e)} ", exc_info=True) - raise + return await self.publish_Cmd("123456", user_id, "patrol", params) + except Exception as e: + logger.error(f"Failed to call patrol mcp-tool: {str(e)} ", exc_info=True) + return f"Failed to call patrol mcp-tool: {str(e)}" - async def startFaceRecognize(self, device_id: str): - """ - 机器人进行人脸识别。 - Args: - - device_id (str): 设备id - Returns: - str: 命令执行结果消息 - Raises: - ValueError: 如果参数无效或为空 - Exception: 如果MQTT发布失败 - """ - if device_id: - try: + async def startFaceRecognize(self, device_id: str, user_id: str): + """人脸识别""" + try: + if not device_id: + return "device_id is not specified." + else: params = { "data": {} } - return await self.publish_Cmd("123456", "face", params) - except Exception as e: - logger.error(f"Failed to call face recognize mcp-tool: {str(e)} ", exc_info=True) - raise + return await self.publish_Cmd("123456", user_id, "face", params) + except Exception as e: + logger.error(f"Failed to call face recognize mcp-tool: {str(e)} ", exc_info=True) + return f"Failed to call face recognize mcp-tool: {str(e)}" - async def scanQRCode(self, device_id: str): - """ - 机器人进行二维码扫描。 - Args: - - device_id (str): 设备id - Returns: - str: 命令执行结果消息 - Raises: - ValueError: 如果参数无效或为空 - Exception: 如果MQTT发布失败 - """ - if device_id: - try: + async def scanQRCode(self, device_id: str, user_id: str): + """扫描二维码""" + try: + if not device_id: + return "device_id is not specified." + else: params = { "data": {} } - return await self.publish_Cmd("123456", "qrcode", params) - except Exception as e: - logger.error(f"Failed to call QR code scan mcp-tool: {str(e)} ", exc_info=True) - raise + return await self.publish_Cmd("123456", user_id, "qrcode", params) + except Exception as e: + logger.error(f"Failed to call QR code scan mcp-tool: {str(e)} ", exc_info=True) + return f"Failed to call QR code scan mcp-tool: {str(e)}" - async def save_position(self, device_id: str, location_name: str): - """ - 机器人保存具体地点。 - Args: - - device_id (str): 设备id - - location_name (str): 地点名称 - Returns: - str: 命令执行结果消息 - Raises: - ValueError: 如果参数无效或为空 - Exception: 如果MQTT发布失败 - - """ - if device_id and location_name: - try: + async def save_position(self, user_id: str, location_name: str): + """保存当前位置""" + try: + if not location_name: + return "location is not specified." + else: params = { "data": {"location_name": location_name} } - return await self.publish_Cmd("123456", "saveLocation", params) - except Exception as e: - logger.error(f"Failed to call save_position mcp-tool: {str(e)} ", exc_info=True) - raise + return await self.publish_Cmd("123456", user_id, "saveLocation", params) + except Exception as e: + logger.error(f"Failed to call save_position mcp-tool: {str(e)} ", exc_info=True) + return f"Failed to call save_position mcp-tool: {str(e)}" - - async def guide(self): - """ - 机器人导览。 - Args: - Returns: - str: 命令执行结果消息 - - Raises: - ValueError: 如果参数无效或为空 - Exception: 如果MQTT发布失败 - """ + async def guide(self, user_id: str, datas: List[TourStop]): + """引导""" try: - datas = [ - TourStop(name="前台", text="欢迎来到我们的场所,这是入口区域"), - TourStop(name="灵泽万川展厅", text="这是我们的主大厅,提供接待服务"), - TourStop(name="爱易拍展厅", text="这里展示我们的主要产品和成果") - ] + if not datas: + return "datas is not specified." params = { "data": [data.model_dump() for data in datas] } - return await self.publish_Cmd("123456", "guide", params) + return await self.publish_Cmd("123456", user_id, "guide", params) except Exception as e: logger.error(f"Failed to call guide mcp-tool: {str(e)} ", exc_info=True) - raise + return f"Failed to call guide mcp-tool: {str(e)}" async def serve() -> None: server = Server("terminal_temi_mcp") @@ -301,7 +212,7 @@ async def serve() -> None: return [ Tool( name="nav_to", - description="数字员工、终端、具身机器人、前台机器人、助手、机器人导航带路到指定地点:带我去、去XX、请引路、导航去、我想去、能带我去吗、带路、送我去、在哪里、前往XX、去XX位置、带我过去、请带我到、我想前往、去那个地方、我要去、能不能去、带我导航、这个地方怎么走、我想找XX、导航带我去、请带路到、我要去那边、走一趟去、去下XX、到XX怎么走", + description="轮足机器人导航到指定地点为用户引路。支持普通引导和通知两种模式。普通引导用于一般带路场景;通知模式下,机器人到达后会播放提示。适用于带路、引路、前往某个位置等场景。触发关键词:带我去、导航、引路、带路、怎么走、在哪里。", inputSchema={ "type": "object", "properties": { @@ -309,14 +220,22 @@ async def serve() -> None: "type": "string", "description": "目标地点名称", "minLength": 1 + }, + "flag": { + "type": "boolean", + "description": "是否为通知类型的导航。True为通知,False为普通引导(默认)。" + }, + "user_id": { + "type": "string", + "description": "用户ID" } }, - "required": ["location"] + "required": ["location", "user_id"] } ), Tool( name="speak", - description="数字员工、终端、具身机器人、前台机器人、助手、机器人进行语音播报:告诉、提醒、告知、提示", + description="轮足机器人进行语音播报:告诉、提醒、告知、提示、通知", inputSchema={ "type": "object", "properties": { @@ -324,14 +243,18 @@ async def serve() -> None: "type": "string", "description": "要播报的语音内容", "minLength": 1 + }, + "user_id": { + "type": "string", + "description": "用户ID" } }, - "required": ["speech"] + "required": ["speech", "user_id"] } ), Tool( name="reception", - description="数字员工、终端、具身机器人、前台机器人、助手、机器人去接待客人:去接人、请迎接客人、去接待、迎接一下、带人过来、把客人带过来、去门口接人、去接一下、请接人、接客人、帮我迎接、去把人接过来、接待来访者、请去接一下客人、送客人过来、从XX接到YY、引导访客、带访客过来、请引领客人、去门口把人接进来、从入口接人、去接待处接人、带客人进来", + description="轮足机器人去接待客人:去接人、请迎接客人、去接待、迎接一下、带人过来、把客人带过来、去门口接人、去接一下、请接人、接客人、帮我迎接、去把人接过来、接待来访者、请去接一下客人、送客人过来、从XX接到YY、引导访客、带访客过来、请引领客人、去门口把人接进来、从入口接人、去接待处接人、带客人进来", inputSchema={ "type": "object", "properties": { @@ -340,42 +263,55 @@ async def serve() -> None: "description": "引导接待客人到这个位置", "minLength": 1 }, + "user_id": { + "type": "string", + "description": "用户ID" + } }, - "required": ["location"] + "required": ["location", "user_id"] } ), + # Tool( + # name="notification", + # description="轮足机器人去通知事情:通知、告诉、提醒、告知、提示", + # inputSchema={ + # "type": "object", + # "properties": { + # "location": { + # "type": "string", + # "description": "去这个位置通知事情", + # "minLength": 1 + # }, + # "text": { + # "type": "string", + # "description": "通知事情的内容", + # "minLength": 1 + # }, + # "user_id": { + # "type": "string", + # "description": "用户ID" + # } + # }, + # "required": ["location","text", "user_id"] + # } + # ), Tool( - name="notification", - description="数字员工、终端、具身机器人、前台机器人、助手、机器人去通知事情:通知、告诉、提醒、告知、提示", + name="repose", + description="轮足机器人、助手、机器人去重新定位", inputSchema={ "type": "object", "properties": { - "location": { + "user_id": { "type": "string", - "description": "去这个位置通知事情", - "minLength": 1 - }, - "text": { - "type": "string", - "description": "通知事情的内容", - "minLength": 1 + "description": "用户ID" } }, - "required": ["location","text"] - } - ), - Tool( - name="repose", - description="数字员工、终端、具身机器人、前台机器人、助手、机器人去重新定位", - inputSchema={ - "type": "object", - "properties": {}, - "required": [] + "required": ["user_id"] } ), Tool( name="delivery", - description="数字员工、终端、具身机器人、前台机器人、助手、机器人去运输物品:帮我送东西、去送一下、去送物品、帮我拿过去、送这个过去、去送快递、运送一下、帮我带东西、把东西送过去、物品配送、拿去给XX、去取个东西、取完送过去、帮我捎个东西、把这个拿去、请运过去、送过去给谁、请配送一下、帮我转交、帮我送到、从XX拿到YY、物品搬运", + description="轮足机器人去运输物品:帮我送东西、去送一下、去送物品、帮我拿过去、送这个过去、去送快递、运送一下、帮我带东西、把东西送过去、物品配送、拿去给XX、去取个东西、取完送过去、帮我捎个东西、把这个拿去、请运过去、送过去给谁、请配送一下、帮我转交、帮我送到、从XX拿到YY、物品搬运", inputSchema={ "type": "object", "properties": { @@ -388,14 +324,18 @@ async def serve() -> None: "type": "string", "description": "将物品运输、送到这个位置", "minLength": 1 + }, + "user_id": { + "type": "string", + "description": "用户ID" } }, - "required": ["first_location","next_location"] + "required": ["first_location","next_location", "user_id"] } ), Tool( name="patrol", - description="数字员工、终端、具身机器人、前台机器人、助手、机器人去巡逻:巡逻、巡查、去检查一下、去看看、去巡视", + description="轮足机器人、助手、机器人去巡逻:巡逻、巡查、去检查一下、去看看、去巡视", inputSchema={ "type": "object", "properties": { @@ -405,24 +345,32 @@ async def serve() -> None: "items": { "type": "string" } + }, + "user_id": { + "type": "string", + "description": "用户ID" } }, - "required": ["locations"] + "required": ["locations", "user_id"] } ), # Tool( # name="guide", - # description="数字员工、终端、具身机器人、前台机器人、助手、机器人进行导览服务:导览、介绍、参观、带领参观、导游、讲解、展示、演示、介绍场所、带我看看", + # description="轮足机器人进行导览服务:导览、介绍、参观、带领参观、导游、讲解、展示、演示、介绍场所、带我看看", # inputSchema={ # "type": "object", # "properties": { + # "user_id": { + # "type": "string", + # "description": "用户ID" + # } # }, - # "required": [] + # "required": ["user_id"] # } # ) # Tool( # name="face", - # description="数字员工、终端、具身机器人、前台机器人、助手、机器人进行人脸识别:识别人脸、人脸识别、脸部识别、面部识别、认脸、看看是谁、识别一下、看看这个人、辨识人脸、扫脸、人脸检测、看脸识别、脸部检测、识别面孔、看人脸、人脸扫描、脸识别、面孔识别、认人、识别身份、看看这是谁、人脸认证、脸部扫描、面部扫描", + # description="轮足机器人进行人脸识别:识别人脸、人脸识别、脸部识别、面部识别、认脸、看看是谁、识别一下、看看这个人、辨识人脸、扫脸、人脸检测、看脸识别、脸部检测、识别面孔、看人脸、人脸扫描、脸识别、面孔识别、认人、识别身份、看看这是谁、人脸认证、脸部扫描、面部扫描", # inputSchema={ # "type": "object", # "properties": { @@ -431,13 +379,17 @@ async def serve() -> None: # "description": "设备ID", # "minLength": 1 # }, + # "user_id": { + # "type": "string", + # "description": "用户ID" + # } # }, - # "required": ["device_id"] + # "required": ["device_id", "user_id"] # } # ), # Tool( # name="qrcode", - # description="数字员工、终端、具身机器人、前台机器人、助手、机器人进行二维码扫描:扫码、扫二维码、扫QR码、二维码识别、码扫描、扫一下码、读取二维码、识别二维码、二维码扫描、QR扫描、扫描条码、扫描编码、读码、解析二维码、扫描识别、码识别、条码扫描、扫描二维码、读取码、扫描条形码、二维码读取、码解析", + # description="轮足机器人进行二维码扫描:扫码、扫二维码、扫QR码、二维码识别、码扫描、扫一下码、读取二维码、识别二维码、二维码扫描、QR扫描、扫描条码、扫描编码、读码、解析二维码、扫描识别、码识别、条码扫描、扫描二维码、读取码、扫描条形码、二维码读取、码解析", # inputSchema={ # "type": "object", # "properties": { @@ -449,9 +401,13 @@ async def serve() -> None: # "task_id": { # "type": "string", # "description": "任务ID" + # }, + # "user_id": { + # "type": "string", + # "description": "用户ID" # } # }, - # "required": ["device_id"] + # "required": ["device_id", "user_id"] # } # ) ] @@ -462,56 +418,67 @@ async def serve() -> None: try: result = "" if name == "nav_to": - if "location" not in arguments: - raise ValueError("缺少必要参数: location") + if "location" not in arguments or "user_id" not in arguments: + raise ValueError("缺少必要参数: location or user_id") result = await nav_server.nav_to( - location=arguments["location"] + user_id=arguments["user_id"], + location=arguments["location"], + flag=arguments.get("flag", False) ) elif name == "speak": - if "speech" not in arguments: - raise ValueError("缺少必要参数: speech") + if "speech" not in arguments or "user_id" not in arguments: + raise ValueError("缺少必要参数: speech or user_id") result = await nav_server.speak( + user_id=arguments["user_id"], speech=arguments["speech"] ) elif name == "reception": - if "location" not in arguments: - raise ValueError("缺少必要参数: location") + if "location" not in arguments or "user_id" not in arguments: + raise ValueError("缺少必要参数: location or user_id") result = await nav_server.reception( - location=arguments["location"], - ) - elif name == "notification": - if "location" not in arguments or "text" not in arguments: - raise ValueError("缺少必要参数: location或text") - result = await nav_server.notification( - location=arguments["location"], - text=arguments["text"] + user_id=arguments["user_id"], + location=arguments["location"] ) + # elif name == "notification": + # if "location" not in arguments or "text" not in arguments or "user_id" not in arguments: + # raise ValueError("缺少必要参数: location、text or user_id") + # result = await nav_server.notification( + # user_id=arguments["user_id"], + # location=arguments["location"], + # text=arguments["text"] + # ) elif name == "repose": - result = await nav_server.repose() + if "user_id" not in arguments: + raise ValueError("缺少必要参数: user_id") + result = await nav_server.repose(user_id=arguments["user_id"]) elif name == "delivery": - if "first_location" not in arguments or "next_location" not in arguments: - raise ValueError("缺少必要参数: first_location或next_location") + if "first_location" not in arguments or "next_location" not in arguments or "user_id" not in arguments: + raise ValueError("缺少必要参数: first_location、next_location or user_id") result = await nav_server.delivery( + user_id=arguments["user_id"], first_location=arguments["first_location"], next_location=arguments["next_location"] ) elif name == "patrol": - if "locations" not in arguments: - raise ValueError("缺少必要参数: locations") + if "locations" not in arguments or "user_id" not in arguments: + raise ValueError("缺少必要参数: locations or user_id") result = await nav_server.patrol( + user_id=arguments["user_id"], locations=arguments["locations"] ) # elif name == "face": - # if "device_id" not in arguments: - # raise ValueError("缺少必要参数: device_id") + # if "device_id" not in arguments or "user_id" not in arguments: + # raise ValueError("缺少必要参数: device_id or user_id") # result = await nav_server.startFaceRecognize( # device_id=arguments["device_id"], + # user_id=arguments["user_id"] # ) # elif name == "qrcode": - # if "device_id" not in arguments: - # raise ValueError("缺少必要参数: device_id") + # if "device_id" not in arguments or "user_id" not in arguments: + # raise ValueError("缺少必要参数: device_id or user_id") # result = await nav_server.scanQRCode( # device_id=arguments["device_id"], + # user_id=arguments["user_id"] # ) else: raise ValueError(f"未知工具: {name}")