重构代码 led已经连接硬件,充电,状态都可显示,但是对话逻辑还需微调
authorSnickerSun <snickersun@163.com>
Thu, 7 May 2026 22:22:54 +0000 (06:22 +0800)
committerSnickerSun <snickersun@163.com>
Thu, 7 May 2026 22:22:54 +0000 (06:22 +0800)
35 files changed:
1.doc/AI吊坠LED状态优先级状态机.md [new file with mode: 0644]
1.doc/AI吊坠(双按键+三色指示灯)交互规范.md [new file with mode: 0644]
1.doc/v2_5.pdf [new file with mode: 0644]
2.sdk/project/7PIN_1_5/images/customer_fs.bin
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/Makefile
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/ai_VC.py
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_1_5/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK_EU/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK_coze/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_coze/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/G10/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/README.md [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/csh/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/jswm/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/jswm_BOX/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/momo/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/sjgq/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/szbst/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/constants.py
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/default_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/default_srv.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/main_init.py
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/protocol.py
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/README.md [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/beike.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/beike_dev.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/dev_type_url_backup.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/kxc.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/usr/ai_VC.py [deleted file]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/vc_config.py [new file with mode: 0644]
2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/versions.py
2.sdk/project/7PIN_1_5/sdk/system/platform/ASR_1606/boards/EG810MCN_GA_VOLTE/images/firmware_base_release_pack.zip

diff --git a/1.doc/AI吊坠LED状态优先级状态机.md b/1.doc/AI吊坠LED状态优先级状态机.md
new file mode 100644 (file)
index 0000000..151feb7
--- /dev/null
@@ -0,0 +1,53 @@
+# AI吊坠 LED 状态优先级状态机(实现用)\r
+#\r
+# 目标:只要输入四类状态(充电/电量/信号/AI对话),LED 自动按优先级显示,且同一时间只显示一种灯效。\r
+# 说明:AI 对话阶段优先级最高;其结束后才显示充电/电量/信号等基础状态。\r
+#\r
+# 输入状态域\r
+# - ai_state: idle / listening / thinking / playing\r
+# - charging: none / charging / full\r
+# - battery: normal(>=30%) / low(10~30%) / empty(<10%)\r
+# - signal: normal / weak\r
+#\r
+#\r
+## 1) 优先级总表(从高到低)\r
+#\r
+| 优先级 | 状态域 | 状态值 | LED显示 | 说明 |\r
+| ---: | --- | --- | --- | --- |\r
+| P1 | AI对话 | playing | 绿灯常亮 | 播放态最高优先级 |\r
+| P2 | AI对话 | thinking | 蓝绿交替慢闪(1秒切换一次) | 交互规范:思考模式 |\r
+| P3 | AI对话 | listening | 蓝色慢闪(1次/秒) | 交互规范:聆听模式 |\r
+| P4 | 充电 | full | 绿灯常亮 | 非对话阶段:满电提示 |\r
+| P5 | 充电 | charging | 红灯常亮 | 非对话阶段:充电中 |\r
+| P6 | 电量 | empty | 红色快闪3次(2次/秒)→熄灭 | 事件型提示;之后通常进入关机/熄灭 |\r
+| P7 | 电量 | low | 红色慢闪3次(1次/秒)→熄灭 | 事件型提示;建议 5 分钟节流一次 |\r
+| P8 | 信号 | weak | 蓝绿交替慢闪(1次/2秒) | 网络/信号弱提示(持续态) |\r
+| P9 | AI对话 | idle | 熄灭 | 交互规范:待机灯灭 |\r
+| P10 | 其它 | 默认 | 熄灭 | 兜底 |\r
+#\r
+#\r
+## 2) 决策表(输入 → 输出)\r
+#\r
+按顺序匹配,命中即返回:\r
+#\r
+| 顺序 | 条件(输入状态) | 输出 LED |\r
+| ---: | --- | --- |\r
+| 1 | ai_state == playing | 绿常亮 |\r
+| 2 | ai_state == thinking | 蓝绿交替慢闪(1秒切换) |\r
+| 3 | ai_state == listening | 蓝慢闪(1次/秒) |\r
+| 4 | charging == full | 绿常亮 |\r
+| 5 | charging == charging | 红常亮 |\r
+| 6 | battery == empty | 红快闪3次→熄灭(事件型) |\r
+| 7 | battery == low | 红慢闪3次→熄灭(事件型、建议节流) |\r
+| 8 | signal == weak | 蓝绿交替慢闪(1次/2秒) |\r
+| 9 | ai_state == idle | 熄灭 |\r
+| 10 | else | 熄灭 |\r
+#\r
+#\r
+## 3) 事件型 vs 状态型(工程建议)\r
+#\r
+| 类型 | 涵盖状态 | 特性 | 冲突处理建议 |\r
+| --- | --- | --- | --- |\r
+| 状态型(持续显示) | AI三阶段、充电中/满、信号弱 | 状态为真就一直显示 | 被 P1~P3 覆盖;结束后恢复 |\r
+| 事件型(播一次) | 低电提醒、耗尽提醒 | 播完即回到当前最高状态 | 若 AI 阶段中,延后或丢弃本次提示,避免抢占交互 |\r
+#\r
diff --git a/1.doc/AI吊坠(双按键+三色指示灯)交互规范.md b/1.doc/AI吊坠(双按键+三色指示灯)交互规范.md
new file mode 100644 (file)
index 0000000..883afa7
--- /dev/null
@@ -0,0 +1,112 @@
+# AI吊坠(双按键+三色指示灯)交互规范
+
+核心原则:**操作有反馈、状态有提示、逻辑不冲突**,适配吊坠随身佩戴、无屏操作场景,按键+灯光+提示音三者联动,让用户无需记忆,凭直观反馈即可判断设备状态。
+
+基础约定:
+
+*   按键:Power键(开关键)、AI键(语音交互键)
+    
+*   指示灯:红(R)、蓝(B)、绿(G)三色(遵循定义:绿=正常/电量/充满电;蓝=AI交互;红=低电/异常)
+    
+*   提示音:采用短促、清晰的单音/双音,区分不同操作,音量适中(避免刺耳,适配贴身佩戴),支持后续可调节(可选)
+    
+*   操作逻辑:长按=特殊功能(开关机、强制重启、连续对话);短按/双击=常用功能(唤醒、打断、复读),杜绝误触
+    
+
+## 备注
+
+聆听模式:蓝色慢闪
+
+思考模式:蓝绿交替慢闪
+
+播放模式:绿灯长亮
+
+进入聆听模式:单声“滴”(短促)
+
+[请至钉钉文档查看附件《start.mp3》。](https://alidocs.dingtalk.com/i/nodes/KGZLxjv9VGj15aBlU1wKrXGzW6EDybno?iframeQuery=anchorId%3DX02moo4wrj78r6ita1utoy&utm_scene=person_space)
+
+接入拾音/进入思考:单声“层”(短促,有尾音)
+
+[请至钉钉文档查看附件《5c893cf044bde33914.mp3》。](https://alidocs.dingtalk.com/i/nodes/KGZLxjv9VGj15aBlU1wKrXGzW6EDybno?iframeQuery=anchorId%3DX02moo4y0r5romh54qr1l&utm_scene=person_space)
+
+开机提示音
+
+[请至钉钉文档查看附件《开机.mp3》。](https://alidocs.dingtalk.com/i/nodes/KGZLxjv9VGj15aBlU1wKrXGzW6EDybno?iframeQuery=anchorId%3DX02moo4z0qlkd1hwu42as&utm_scene=person_space)
+
+## 第一部分:基础操作(Power键)+ 灯光+提示音联动
+
+| 操作动作 | 设备当前状态 | 指示灯状态 | 提示音 | 执行结果 |
+| --- | --- | --- | --- | --- |
+| Power键 长按3秒 | 关机状态 | 绿色灯常亮(持续3秒,同步长按时间),然后熄灭 | 现有设备开机提示音(后续视需求可修改) | 设备开机,进入正常待机状态 |
+| Power键 长按8秒 | 任何状态(死机/卡死/异常) | 红色快闪3次(1次/秒),然后熄灭 | “滴、滴、滴”(3声短促,与灯光同步) | 设备关机,切断所有电源 |
+| Power键 短按(单击) | 待机状态 | 无变化 | 无提示音 | 无操作 |
+| Power键 短按(单击) | AI交互中(聆听/处理/TTS) | 无变化(保持当前交互灯光) | 无提示音 | 停止对话,进入待机模式 |
+| Power键 短按(双击) | 待机状态 | 无变化 | 播报:单对话模式/长对话模式 | 切换对话模式 |
+
+## 第二部分:AI交互操作(AI键)+ 灯光+提示音联动
+
+| 操作动作 | 对话模式 | 设备当前状态 | 指示灯状态 | 提示音 | 执行结果 |
+| --- | --- | --- | --- | --- | --- |
+| AI键 短按1次 | 长对话模式 | 待机状态 | 立即切换为蓝色慢闪(1次/秒) | 单声“滴”(短促,清脆) | 唤醒AI,进入语音聆听状态,开始收音(用户可说话) |
+| AI键 短按1次 | 长对话模式 | 语音聆听中(蓝色慢闪) | 切换为蓝色慢闪 | 单声“滴”(短促) | 重新进入语音聆听状态,开始收音(用户可说话) |
+| AI键 短按1次 | 长对话模式 | TTS播报中(绿色常亮灯) | 切换为蓝色慢闪 | 单声“滴”(短促) | 进入语音聆听状态,开始收音(用户可说话) |
+| AI键 短按1次 | 长对话模式 | 思考中(蓝绿交替闪) | 切换为蓝色慢闪 | 单声“滴”(短促) | 进入语音聆听状态,开始收音(用户可说话) |
+| AI键 双击(两次短按,间隔≤1秒)-> 可选(根据可实现性而定) |  | 待机状态 & TTS播报结束后1分钟内 | 蓝色灯常亮(与正常TTS播报灯光一致) | “滴、滴”(2声短促,间隔0.5秒) | 复读上一次AI的TTS回复内容,复读结束后回到待机状态(蓝色灯灭) |
+| AI键 双击>>暂时无功能 |  |  |  |  |  |
+| AI键 长按(按下) | 单对话模式 | 待机状态/思考状态/播报状态 | 蓝色快闪(频率加快,2次/秒) | 单声“滴”(短促,清脆) | 进入收音状态 |
+| AI键 长按(松开) | 单对话模式 | 聆听中 | 蓝绿交替闪 | “曾——”(长音,持续1秒) | 进入思考模式 |
+
+## 第三部分:电量/充电状态 + 灯光+提示音联动
+
+| 设备状态 | 触发条件 | 指示灯状态 | 提示音 | 补充说明 |
+| --- | --- | --- | --- | --- |
+| 正常待机(电量≥30%) | 开机后无操作、交互结束后 | 指示灯灭(AI交互过程遵循如上第二部分的定义) | 无提示音 |  |
+| 低电量提醒(10%≤电量<30%) | 电量降至阈值、每5分钟触发1次 | 红色慢闪(1次/1秒),每次闪3次 | “滴、滴”(2声短促,与灯光同步) | 提醒用户尽快充电,不频繁打扰 |
+| 电量耗尽(电量<10%) | 电量降至关机阈值 | 红色快闪3次(2次/秒)→ 熄灭 | “滴、滴、滴”(3声短促,与灯光同步) | 快闪结束后设备自动关机 |
+| 充电中(电量<100%) | 连接充电器,接触正常 | 红色常亮 | 单声“滴”(短促) | 充电期间,按键操作仍有效(开关机、AI交互) |
+| 充电满(电量=100%) | 充电至满电阈值 | 红色常亮→切换为绿色常亮(延迟1秒) | “滴——”(长音,持续1秒) | 绿色常亮保持,提醒用户可拔下充电器(晚上不打扰) |
+
+## 第四部分:AI交互异常状态 + 灯光+提示音联动 
+
+| 异常场景 | 指示灯状态 | 提示音 | 处理方式 |
+| --- | --- | --- | --- |
+| 语音识别失败(未听清/无法识别) | 红蓝快闪2次(2次/秒)→ 回到待机状态(灯灭) | “滴、滴”(2声短促,与灯光同步) | 用户可再次短按AI键,重新唤醒聆听 |
+| 网络异常(无法请求AI) | 蓝绿交替慢闪(1次/2秒),持续闪烁 | “网络异常信号弱”(每5秒1次,循环) | 检查网络连接,恢复网络后自动回到待机状态 |
+| AI处理超时 | 蓝色常亮→红蓝快闪2次→回到待机状态(灯灭) | “滴、滴”(2声短促) | 处理失败,用户可重新发起语音请求 |
+
+## 第五部分:补充规范(工程&用户体验)
+
+### 1. 提示音规范
+
+*   音量:默认中等(约50dB),避免贴身佩戴时刺耳,支持后续通过APP调节(可选)
+    
+*   音色:统一采用清脆的电子音,避免复杂音效,确保不同场景的提示音可区分(短滴=操作确认,长滴=状态切换,多滴=提醒/异常)
+    
+*   优先级:异常提示音(网络异常)>操作提示音(唤醒、打断)>状态提示音(充电满、低电)
+    
+
+### 2. 灯光规范
+
+*   亮度:柔和不刺眼(≤100cd/m²),适配夜间、贴身佩戴场景,避免强光照射皮肤
+    
+*   响应速度:按键操作后,灯光和提示音同步触发(延迟≤100ms),无卡顿
+    
+*   冲突规避:同一时间仅显示一种状态灯光(如充电中触发AI交互,优先显示AI交互灯光,充电状态暂停显示,交互结束后恢复)
+    
+
+### 3. 工程可实现性说明
+
+*   按键逻辑:长按时间(3秒/8秒/2秒)可通过MCU精准控制,避免误判(如长按2秒切换进入连续对话模式,需持续检测按键按压时间,不足3秒不执行)
+    
+*   灯光控制:三色灯采用单灯三色设计,无需额外硬件,逻辑简单易实现
+    
+*   提示音:喇叭播放,无需额外蜂鸣器
+    
+
+### 4. 用户易用性补充
+
+*   所有操作均有“灯光+提示音”双重反馈,无屏状态下也能清晰判断设备状态
+    
+*   避免复杂操作,核心功能(唤醒、开关机)仅需1种按键动作,老人、儿童可快速上手
+    
+*   误触防护:短按Power键无操作、双击AI键仅在待机/播报后有效,减少误操作带来的困扰
\ No newline at end of file
diff --git a/1.doc/v2_5.pdf b/1.doc/v2_5.pdf
new file mode 100644 (file)
index 0000000..29dbc44
Binary files /dev/null and b/1.doc/v2_5.pdf differ
index c347d98..fc08043 100644 (file)
Binary files a/2.sdk/project/7PIN_1_5/images/customer_fs.bin and b/2.sdk/project/7PIN_1_5/images/customer_fs.bin differ
index 51994be..013850e 100644 (file)
-# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved.\r
-#\r
-# Licensed under the Apache License, Version 2.0 (the "License");\r
-# you may not use this file except in compliance with the License.\r
-# You may obtain a copy of the License at\r
-#\r
-#     http://www.apache.org/licenses/LICENSE-2.0\r
-#\r
-# Unless required by applicable law or agreed to in writing, software\r
-# distributed under the License is distributed on an "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-# See the License for the specific language governing permissions and\r
-# limitations under the License.\r
-\r
-#env\r
-TOP := ../../..\r
-ROOT := $(TOP)/../..\r
-\r
-KCONFIG_CONFIG_DIR := ../../../../..\r
-include $(KCONFIG_CONFIG_DIR)/config/$(KCONFIG_CONFIG)\r
-\r
-ifeq ("$(origin V)", "command line")\r
-BUILD_VERBOSE=$(V)\r
-endif\r
-ifndef BUILD_VERBOSE\r
-BUILD_VERBOSE = 0\r
-endif\r
-# ifeq ($(BUILD_VERBOSE),0)\r
-# Q = @\r
-# else\r
-# Q =\r
-# endif\r
-\r
-BUILD ?= build\r
-FROZEN_MPY_DIR ?= .\r
-\r
-RM = rm\r
-ECHO = echo\r
-CP = cp\r
-MKDIR = mkdir\r
-SED = sed\r
-CAT = cat\r
-TOUCH = touch\r
-\r
-MAKE_MANIFEST = $(PYTHON) $(TOP)/tools/makemanifest.py\r
-MAKE_FROZEN = $(PYTHON) $(TOP)/tools/make-frozen.py\r
-#because E-safeNet, mpy-cross could not read the py file, rename as notepad++\r
-ifeq ($(strip $(HOST)),linux)\r
-MPY_CROSS = $(TOP)/ports/quectel/tools/mpy-cross\r
-else\r
-MPY_CROSS = $(TOP)/ports/quectel/tools/notepad++.exe\r
-endif\r
-MPY_TOOL = $(PYTHON) $(TOP)/tools/mpy-tool.py\r
-\r
-QSTR_DEFS = source/qstrdefsport.h\r
-#py\r
-PY_SRC ?= $(TOP)/py\r
-HEADER_BUILD = $(TOP)/genhdr\r
-PY_QSTR_DEFS = $(PY_SRC)/qstrdefs.h\r
-ifneq ($(QSTR_AUTOGEN_DISABLE),1)\r
-QSTR_DEFS_COLLECTED = $(HEADER_BUILD)/qstrdefs.collected.h\r
-endif\r
-QSTR_GLOBAL_DEPENDENCIES += $(PY_SRC)/mpconfig.h source/mpconfigport.h\r
-CSUPEROPT = -O3\r
-ifeq ($(strip $(PLAT)),ECR6600)\r
-MPY_CROSS_FLAGS += -march=xtensa\r
-else\r
-MPY_CROSS_FLAGS += -march=armv7m\r
-endif\r
-# Enable building 32-bit code on 64-bit host.\r
-ifeq ($(MICROPY_FORCE_32BIT),1)\r
-CC += -m32\r
-CXX += -m32\r
-LD += -m32\r
-endif\r
-\r
-# External modules written in C.\r
-ifneq ($(USER_C_MODULES),)\r
-# pre-define USERMOD variables as expanded so that variables are immediate\r
-# expanded as they're added to them\r
-SRC_USERMOD :=\r
-C_FLAGS_USERMOD :=\r
-LD_FLAGS_USERMOD :=\r
-$(foreach module, $(wildcard $(USER_C_MODULES)/*/micropython.mk), \\r
-    $(eval USERMOD_DIR = $(patsubst %/,%,$(dir $(module))))\\r
-    $(info Including User C Module from $(USERMOD_DIR))\\r
-       $(eval include $(module))\\r
-)\r
-\r
-SRC_MOD += $(patsubst $(USER_C_MODULES)/%.c,%.c,$(SRC_USERMOD))\r
-C_FLAGS_MOD += $(C_FLAGS_USERMOD)\r
-LD_FLAGS_MOD += $(LD_FLAGS_USERMOD)\r
-endif\r
-\r
-# py object files\r
-PY_CORE_O_BASENAME = $(addprefix py/,\\r
-       mpstate.o \\r
-       nlr.o \\r
-       nlrx86.o \\r
-       nlrx64.o \\r
-       nlrthumb.o \\r
-       nlrpowerpc.o \\r
-       nlrxtensa.o \\r
-       nlrsetjmp.o \\r
-       malloc.o \\r
-       gc.o \\r
-       pystack.o \\r
-       qstr.o \\r
-       vstr.o \\r
-       mpprint.o \\r
-       unicode.o \\r
-       mpz.o \\r
-       reader.o \\r
-       lexer.o \\r
-       parse.o \\r
-       scope.o \\r
-       compile.o \\r
-       emitcommon.o \\r
-       emitbc.o \\r
-       asmbase.o \\r
-       asmx64.o \\r
-       emitnx64.o \\r
-       asmx86.o \\r
-       emitnx86.o \\r
-       asmthumb.o \\r
-       emitnthumb.o \\r
-       emitinlinethumb.o \\r
-       asmarm.o \\r
-       emitnarm.o \\r
-       asmxtensa.o \\r
-       emitnxtensa.o \\r
-       emitinlinextensa.o \\r
-       emitnxtensawin.o \\r
-       formatfloat.o \\r
-       parsenumbase.o \\r
-       parsenum.o \\r
-       emitglue.o \\r
-       persistentcode.o \\r
-       runtime.o \\r
-       runtime_utils.o \\r
-       scheduler.o \\r
-       nativeglue.o \\r
-       pairheap.o \\r
-       ringbuf.o \\r
-       stackctrl.o \\r
-       argcheck.o \\r
-       warning.o \\r
-       profile.o \\r
-       map.o \\r
-       obj.o \\r
-       objarray.o \\r
-       objattrtuple.o \\r
-       objbool.o \\r
-       objboundmeth.o \\r
-       objcell.o \\r
-       objclosure.o \\r
-       objcomplex.o \\r
-       objdeque.o \\r
-       objdict.o \\r
-       objenumerate.o \\r
-       objexcept.o \\r
-       objfilter.o \\r
-       objfloat.o \\r
-       objfun.o \\r
-       objgenerator.o \\r
-       objgetitemiter.o \\r
-       objint.o \\r
-       objint_longlong.o \\r
-       objint_mpz.o \\r
-       objlist.o \\r
-       objmap.o \\r
-       objmodule.o \\r
-       objobject.o \\r
-       objpolyiter.o \\r
-       objproperty.o \\r
-       objnone.o \\r
-       objnamedtuple.o \\r
-       objrange.o \\r
-       objreversed.o \\r
-       objset.o \\r
-       objsingleton.o \\r
-       objslice.o \\r
-       objstr.o \\r
-       objstrunicode.o \\r
-       objstringio.o \\r
-       objtuple.o \\r
-       objtype.o \\r
-       objzip.o \\r
-       opmethods.o \\r
-       sequence.o \\r
-       stream.o \\r
-       binary.o \\r
-       builtinimport.o \\r
-       builtinevex.o \\r
-       builtinhelp.o \\r
-       modarray.o \\r
-       modbuiltins.o \\r
-       modcollections.o \\r
-       modgc.o \\r
-       modio.o \\r
-       modmath.o \\r
-       modcmath.o \\r
-       modmicropython.o \\r
-       modstruct.o \\r
-       modsys.o \\r
-       moduerrno.o \\r
-       modthread.o \\r
-       vm.o \\r
-       bc.o \\r
-       showbc.o \\r
-       repl.o \\r
-       smallint.o \\r
-       frozenmod.o \\r
-       )\r
-\r
-PY_EXTMOD_O_BASENAME = \\r
-       extmod/moductypes.o \\r
-       extmod/modujson.o \\r
-       extmod/modure.o \\r
-       extmod/moduzlib.o \\r
-       extmod/moduheapq.o \\r
-       extmod/modutimeq.o \\r
-       extmod/modubinascii.o \\r
-       extmod/virtpin.o \\r
-       extmod/machine_mem.o \\r
-       extmod/machine_pinbase.o \\r
-       extmod/machine_signal.o \\r
-       extmod/machine_pulse.o \\r
-       extmod/machine_i2c.o \\r
-       extmod/machine_spi.o \\r
-       extmod/modbluetooth.o \\r
-       extmod/modurandom.o \\r
-       extmod/moduselect.o \\r
-       extmod/moduasyncio.o \\r
-       extmod/moduwebsocket.o \\r
-       extmod/modwebrepl.o \\r
-       extmod/modframebuf.o \\r
-       extmod/vfs.o \\r
-       extmod/vfs_blockdev.o \\r
-       extmod/vfs_reader.o \\r
-       extmod/vfs_posix.o \\r
-       extmod/vfs_posix_file.o \\r
-       extmod/vfs_fat.o \\r
-       extmod/vfs_fat_file.o \\r
-       extmod/vfs_lfs.o \\r
-       extmod/utime_mphal.o \\r
-       extmod/uos_dupterm.o \\r
-       extmod/modussl_mbedtls.o \\r
-       extmod/moduhashlib.o \\r
-       extmod/moducryptolib.o \\r
-       lib/embed/abort_.o \\r
-       lib/utils/printf.o \\r
-       lib/utils/sys_stdio_mphal.o\r
-\r
-ifeq ($(strip $(PLAT)),Qualcomm)\r
-PY_EXTMOD_O_BASENAME += \\r
-       extmod/vfs_efs.o \\r
-       extmod/vfs_efs_file.o\r
-endif\r
-\r
-ifeq ($(strip $(PLAT)), $(filter $(PLAT),Unisoc Unisoc_8910_R05))\r
-PY_EXTMOD_O_BASENAME += \\r
-       extmod/vfs_temp.o \\r
-       extmod/vfs_temp_file.o\r
-endif\r
-\r
-# Sources that may contain qstrings\r
-SRC_QSTR_IGNORE = py/nlr%\r
-SRC_QSTR += $(SRC_MOD) $(filter-out $(SRC_QSTR_IGNORE),$(PY_CORE_O_BASENAME:.o=.c)) $(PY_EXTMOD_O_BASENAME:.o=.c)\r
-SRC_QSTR += \\r
-                       source/modalipay.c \\r
-                       source/audio_audio.c \\r
-                       source/audio_queue.c \\r
-                       source/audio_record.c \\r
-                       source/audio_tts.c \\r
-                       source/audiocodec_rt5616.c \\r
-                       source/callbackdeal.c \\r
-                       source/camera_capture.c \\r
-                       source/camera_preview.c \\r
-                       source/camera_scandecode.c \\r
-                       source/devreport.c \\r
-                       source/machine_extint.c \\r
-                       source/machine_hw_spi.c \\r
-                       source/machine_iic.c \\r
-                       source/machine_iic_simulation.c \\r
-                       source/machine_keypad.c \\r
-                       source/machine_lcd.c \\r
-                       source/machine_nandflash.c \\r
-                       source/machine_pin.c \\r
-                       source/machine_rtc.c \\r
-                       source/machine_timer.c \\r
-                       source/machine_uart.c \\r
-                       source/machine_wdt.c \\r
-                       source/misc_adc.c \\r
-                       source/misc_power.c \\r
-                       source/misc_powerkey.c \\r
-                       source/misc_pwm.c \\r
-                       source/misc_temperature.c \\r
-                       source/misc_usb.c \\r
-                       source/misc_usbnet.c \\r
-                       source/modatcmd.c \\r
-                       source/modaudio.c \\r
-                       source/modaudiocodec.c \\r
-                       source/modble.c \\r
-                       source/modbt.c \\r
-                       source/modcamera.c \\r
-                       source/modcelllocator.c \\r
-                       source/modcelllocator_qpy.c \\r
-                       source/locator.c \\r
-                       source/modcsd.c \\r
-                       source/moddatacall.c \\r
-                       source/moddev.c \\r
-                       source/modethernet.c \\r
-                       source/modethernet_dm9051.c \\r
-                       source/modethernet_w5500.c \\r
-                       source/modethernet_ch395.c \\r
-                       source/modexample.c \\r
-                       source/modfota.c \\r
-                       source/modgnss.c \\r
-                       source/modlpm.c \\r
-                       source/modlvgl.c \\r
-                       source/modlwm2m.c \\r
-                       source/modmachine.c \\r
-                       source/modmisc.c \\r
-                       source/modnb.c \\r
-                       source/modnet.c \\r
-                       source/modostimer.c \\r
-                       source/modpoc.c \\r
-                       source/modqrcode.c \\r
-                       source/modrtmp.c \\r
-                       source/modsecuredata.c \\r
-                       source/modsensor.c \\r
-                       source/modsha1.c \\r
-                       source/modsim.c \\r
-                       source/modslipif.c \\r
-                       source/modsms.c \\r
-                       source/modsocket.c \\r
-                       source/modtp.c \\r
-                       source/moduos.c \\r
-                       source/modutils.c \\r
-                       source/modutime.c \\r
-                       source/modvoicecall.c \\r
-                       source/modwifilocator.c \\r
-                       source/modwifiscan.c \\r
-                       source/nb_aep.c \\r
-                       source/nb_oc.c \\r
-                       source/nb_onenet.c \\r
-                       source/quecpython.c \\r
-                       source/sensor_sn95500.c \\r
-                       source/sensor_icckey.c \\r
-                       source/sensor_gnss.c \\r
-                       source/tp_gt9xx.c \\r
-                       source/tp_xpt2046.c \\r
-                       source/tp_cst816.c \\r
-                       source/modGsensor.c \\r
-                       source/modGsensor_SC7A20.c \\r
-                       source/modHsensor.c \\r
-                       source/modHsensor_GH3018.c \\r
-                       source/modVideoCall.c \\r
-                       source/modVideoCall_juphoon.c \\r
-                       source/modHsensor_HX3918.c \\r
-                       source/modrsa.c \\r
-                       source/utils_crc32.c \\r
-                       source/http_parser.c \\r
-                       source/modwebserver.c \\r
-                       source/modethernet_yt8512h.c \\r
-                       source/sim_esim.c \\r
-                       source/modG711.c \\r
-                       source/modG729.c \\r
-                       source/modcan_mcp2515.c \\r
-                       source/modextuart_wk2114.c \\r
-                       source/modextgpio_aw9523.c \\r
-                       source/machine_key.c \\r
-                       source/lpm_wakeup.c \\r
-                       source/sensor_handmic_key.c     \\r
-                       source/modnetwork.c     \\r
-                       source/modwlan_ASR5803.c \\r
-                       source/machine_soft_spi.c \\r
-                       source/code128_p.c \\r
-                       source/modwlan.c\\r
-                       source/modwlan.c \\r
-                       source/modmask.c \\r
-                       source/modVad.c \\r
-                       source/machine_one_wire.c\r
-\r
-\r
-ifeq ($(strip $(PLAT)),RDA)\r
-SRC_QSTR += $(ROOT)/components/quecsdk/cloud/python/modquecIot-BC25old.c\r
-else\r
-SRC_QSTR += $(ROOT)/components/quecsdk/cloud/python/modquecIot.c\r
-endif\r
-\r
-ifeq ($(CONFIG_USQLITE), y)\r
-SRC_QSTR += lib/usqlite/usqlite_connection.c \\r
-                       lib/usqlite/usqlite_cursor.c \\r
-                       lib/usqlite/usqlite_row.c \\r
-                       lib/usqlite/usqlite_file.c \\r
-                       lib/usqlite/usqlite_mem.c \\r
-                       lib/usqlite/usqlite_vfs.c \\r
-                       lib/usqlite/usqlite_utils.c \\r
-                       lib/usqlite/usqlite.c \\r
-                       lib/usqlite/usqlite_module.c\r
-\r
-INC += -Ilib/usqlite\r
-endif\r
-\r
-$(BUILD)/%.pp: %.c\r
-       @$(ECHO) "PreProcess $<"\r
-       $(Q)$(CPP) $(C_FLAGS) -Wp,-C,-dD,-dI -o $@ $<\r
-\r
-# Anything that depends on FORCE will be considered out-of-date\r
-FORCE:\r
-.PHONY: FORCE\r
-\r
-$(HEADER_BUILD):\r
-       $(MKDIR) -p $@\r
-\r
-#$(HEADER_BUILD)/mpversion.h: FORCE | $(HEADER_BUILD)\r
-#      $(Q)$(PYTHON) $(PY_SRC)/makeversionhdr.py $@\r
-# mpconfigport.mk is optional, but changes to it may drastically change\r
-# overall config, so they need to be caught\r
-MPCONFIGPORT_MK = $(wildcard mpconfigport.mk)\r
-\r
-# qstr data\r
-# Adding an order only dependency on $(HEADER_BUILD) causes $(HEADER_BUILD) to get\r
-# created before we run the script to generate the .h\r
-# Note: we need to protect the qstr names from the preprocessor, so we wrap\r
-# the lines in "" and then unwrap after the preprocessor is finished.\r
-# See more information about this process in docs/develop/qstr.rst.\r
-$(HEADER_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) $(PY_SRC)/makeqstrdata.py source/mpconfigport.h $(MPCONFIGPORT_MK) $(PY_SRC)/mpconfig.h | $(HEADER_BUILD)\r
-       @$(ECHO) "GEN $@"\r
-       $(Q)$(CAT) $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) | $(SED) 's/^Q(.*)/"&"/' | $(CPP) $(C_FLAGS) - | $(SED) 's/^\"\(Q(.*)\)\"/\1/' > $(HEADER_BUILD)/qstrdefs.preprocessed.h\r
-       $(Q)$(PYTHON) $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/qstrdefs.preprocessed.h > $@\r
-\r
-# Compressed error strings.\r
-$(HEADER_BUILD)/compressed.split: $(HEADER_BUILD)/qstr.i.last\r
-       @$(ECHO) "GEN $@"\r
-       $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py split compress $< $(HEADER_BUILD)/compress _\r
-       $(Q)$(TOUCH) $@\r
-       \r
-$(HEADER_BUILD)/compressed.collected: $(HEADER_BUILD)/compressed.split\r
-       @$(ECHO) "GEN $@"\r
-       $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py $(CAT) compress _ $(HEADER_BUILD)/compress $@\r
-       \r
-$(HEADER_BUILD)/compressed.data.h: $(HEADER_BUILD)/compressed.collected\r
-       @$(ECHO) "GEN $@"\r
-       $(Q)$(PYTHON) $(PY_SRC)/makecompresseddata.py $< > $@\r
-       \r
-# build a list of registered modules for py/objmodule.c.\r
-$(HEADER_BUILD)/moduledefs.h: $(SRC_QSTR) $(QSTR_GLOBAL_DEPENDENCIES) | $(HEADER_BUILD)\r
-       @$(ECHO) "GEN $@"\r
-       $(Q)$(PYTHON) $(PY_SRC)/makemoduledefs.py --vpath="., $(TOP), $(USER_C_MODULES)" $(SRC_QSTR) > $@\r
-\r
-SRC_QSTR += $(HEADER_BUILD)/moduledefs.h\r
-\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/config\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/include\r
-\r
-ifeq ($(strip $(PLAT)),Qualcomm)\r
-INC += -I$(COMPILER_PATH)/armv7m-none-eabi/libc/include\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/inc\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/inc/azure_c_shared_utility\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/pal\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/pal/generic\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client/inc\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client/inc/internal\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/serializer\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/serializer/inc\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt/inc\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt/inc/azure_umqtt_c\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/qapi\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/threadx_api\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include\r
-INC += -I$(ROOT)/system/at\r
-INC += -I$(ROOT)/system/esim\r
-endif\r
-\r
-INC += -I.\r
-INC += -I$(HEADER_BUILD)\r
-INC += -I$(TOP)\r
-INC += -I$(TOP)/py\r
-INC += -I$(TOP)/extmod\r
-INC += -I$(TOP)/lib/utils\r
-INC += -I$(TOP)/lib/mp-readline\r
-INC += -I$(TOP)/lib/littlefs\r
-INC += -I$(TOP)/lib/netutils\r
-INC += -I$(TOP)/lib/timeutils\r
-INC += -I$(TOP)/ports/quectel/core\r
-INC += -I$(TOP)/ports/quectel/core/source\r
-INC += -I$(TOP)/ports/quectel/core/py\r
-INC += -I$(ROOT)/peripheral\r
-INC += -I$(ROOT)/system/include\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/include\r
-INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include\r
-INC += -I$(ROOT)/system/debug\r
-INC += -I$(ROOT)/system/dev\r
-INC += -I$(ROOT)/system/fs\r
-INC += -I$(ROOT)/system/hal\r
-INC += -I$(ROOT)/system/gnss\r
-INC += -I$(ROOT)/system/network\r
-INC += -I$(ROOT)/system/at\r
-INC += -I$(ROOT)/system/aliiot\r
-\r
-ifeq ($(strip $(PLAT)),ASR_1803s)\r
-INC += -I$(ROOT)/system/csd\r
-INC += -I$(ROOT)/system/esim\r
-endif\r
-ifeq ($(strip $(PLAT)),ASR_1606)\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include\r
-endif\r
-\r
-ifeq ($(strip $(PLAT)),Unisoc)\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/arpa\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/net\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/netinet\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/sys\r
-INC += -I$(ROOT)/system/at\r
-endif\r
-\r
-ifeq ($(strip $(PLAT)),Unisoc_8910_R05)\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp/polarssl\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/arpa\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/net\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/netinet\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/sys\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/stdc\r
-endif\r
-\r
-ifeq ($(strip $(PLAT)),EIGEN)\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/apps\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/priv\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/prot\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/arch\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/netif\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/posix\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/posix/sys\r
-endif\r
-\r
-ifeq ($(strip $(PLAT)),Unisoc_8850)\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp/polarssl\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/arpa\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/net\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/netinet\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/sys\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/stdc\r
-endif\r
-\r
-ifeq ($(strip $(PLAT)),RDA)\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/arch\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/arpa\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/net\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/netinet\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/sys\r
-endif\r
-\r
-ifeq ($(strip $(PLAT)), $(filter $(PLAT),ASR ASR_1803s))\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include\r
-INC += -I$(ROOT)/system/at\r
-endif\r
-\r
-ifeq ($(strip $(PLAT)),ECR6600)\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))\r
-INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include\r
-endif\r
-\r
-ifeq (y, $(CONFIG_MBEDTLS))\r
-INC += -I$(ROOT)/system/mbedtls\r
-INC += -I$(ROOT)/system/mbedtls/include\r
-INC += -I$(ROOT)/system/mbedtls/include/mbedtls\r
-INC += -I$(ROOT)/system/mbedtls/library\r
-INC += -I$(ROOT)/system/mbedtls/port/helios/inc\r
-endif\r
-INC += -I$(ROOT)/system/network\r
-INC += -I$(ROOT)/system/os\r
-INC += -I$(ROOT)/system/startup\r
-INC += -I$(ROOT)/system/fota\r
-INC += -I$(ROOT)/system/bt\r
-INC += -I$(ROOT)/system/at\r
-ifeq (y, $(CONFIG_LVGL))\r
-INC += -I$(TOP)/lib/lvgl\r
-INC += -I$(TOP)/lib/lvgl/src\r
-INC += -I$(TOP)/lib/lvgl/src/core\r
-INC += -I$(TOP)/lib/lvgl/src/draw\r
-INC += -I$(TOP)/lib/lvgl/src/extra\r
-INC += -I$(TOP)/lib/lvgl/src/font\r
-INC += -I$(TOP)/lib/lvgl/src/gpu\r
-INC += -I$(TOP)/lib/lvgl/src/hal\r
-INC += -I$(TOP)/lib/lvgl/src/misc\r
-INC += -I$(TOP)/lib/lvgl/src/widgts\r
-endif\r
-INC += -I$(ROOT)/driver\r
-INC += -I$(ROOT)/driver/lcd\r
-ifeq (y, $(CONFIG_QRCODE))\r
-INC += -I$(ROOT)/components/qrcode\r
-endif\r
-ifeq (y, $(CONFIG_QUECTHING))\r
-INC += -I$(ROOT)/components/quecsdk/cloud\r
-INC += -I$(ROOT)/components/quecsdk/driverLayer\r
-INC += -I$(ROOT)/components/quecsdk/thirdLib/mqtt\r
-INC += -I$(ROOT)/components/quecsdk/thirdLib/cJSON\r
-INC += -I$(ROOT)/components/quecsdk/kernel\r
-endif\r
-ifeq ($(CONFIG_SPINAND), y)\r
-INC += -I$(ROOT)/components/fs/include\r
-INC += -I$(ROOT)/components/fs/yaffs/src/direct\r
-INC += -I$(ROOT)/components/fs/yaffs/src/port\r
-INC += -I$(ROOT)/components/fs/yaffs/src\r
-INC += -I$(ROOT)/components/fs/yaffs\r
-endif\r
-ifeq ($(CONFIG_RTMP), y)\r
-INC += -I$(ROOT)/components/rtmpdump/librtmp/inc\r
-INC += -I$(ROOT)/components/rtmpdump/libz/inc\r
-endif\r
-INC += -I$(ROOT)/utilities\r
-ifeq ($(CONFIG_JPEG), y)\r
-INC += -I$(ROOT)/components/jpeg/jpeg-9c\r
-INC += -I$(ROOT)/components/jpeg\r
-endif\r
-ifeq ($(CONFIG_HX3918), y)\r
-INC += -I$(ROOT)/components/HX3918\r
-endif\r
-ifeq ($(CONFIG_GH301x), y)\r
-INC += -I$(ROOT)/components/GH301x\r
-endif\r
-ifeq ($(CONFIG_SC7A20), y)\r
-INC += -I$(ROOT)/components/SC7A20\r
-endif\r
-ifeq ($(CONFIG_juphoon), y)\r
-INC += -I$(ROOT)/components/juphoon\r
-endif\r
-ifeq ($(CONFIG_POC_BND), y)\r
-INC += -I$(ROOT)/components/poc\r
-INC += -I$(ROOT)/components/poc/bnd/inc\r
-endif\r
-ifeq ($(CONFIG_POC_BND_XIN), y)\r
-INC += -I$(ROOT)/components/poc\r
-INC += -I$(ROOT)/components/poc/bnd_xin/inc\r
-endif\r
-ifeq ($(CONFIG_POC_SL), y)\r
-INC += -I$(ROOT)/components/poc\r
-INC += -I$(ROOT)/components/poc/sl/inc\r
-endif\r
-ifeq ($(CONFIG_POC_QS), y)\r
-INC += -I$(ROOT)/components/poc\r
-INC += -I$(ROOT)/components/poc/qs/inc\r
-endif\r
-#Stephen.Gao add 2022/11/23\r
-ifeq ($(CONFIG_POC_ZZD), y)\r
-INC += -I$(ROOT)/components/poc\r
-INC += -I$(ROOT)/components/poc/zzd/inc\r
-endif\r
-#Stephen.Gao add 2023/01/06\r
-ifeq ($(CONFIG_POC_YDWL), y)\r
-INC += -I$(ROOT)/components/poc\r
-INC += -I$(ROOT)/components/poc/ydwl/inc\r
-endif\r
-\r
-ifeq ($(CONFIG_POC_SLPOC), y)\r
-INC += -I$(ROOT)/components/poc  -I$(ROOT)/components/poc/slpoc/src\r
-INC += -I$(ROOT)/components/poc/slpoc/inc\r
-SRC_QSTR += $(ROOT)/components/poc/slpoc/src/modpoc_slpoc.c\r
-endif\r
-\r
-ifeq ($(CONFIG_POC_RDA_BND), y)\r
-INC += -I$(ROOT)/components/poc  -I$(ROOT)/components/poc/rda_bnd/src\r
-INC += -I$(ROOT)/components/poc/rda_bnd/inc\r
-SRC_QSTR += $(ROOT)/components/poc/rda_bnd/src/modpocrda.c\r
-endif\r
-\r
-\r
-ifeq (y,$(CONFIG_DECODE_ZBAR))\r
-INC += -I$(ROOT)/components/decode/ZBar/zbar\r
-INC += -I$(ROOT)/components/decode/ZBar/include\r
-INC += -I$(ROOT)/components/decode/ZBar/zbar/decoder\r
-INC += -I$(ROOT)/components/decode/ZBar/zbar/qrcode\r
-endif\r
-ifeq (y,$(CONFIG_DECODE_QUECTEL))\r
-INC += -I$(ROOT)/components/decode/quectel/inc\r
-endif\r
-\r
-ifeq (y,$(CONFIG_DECODE_QINGYA))\r
-ifneq ($(strip $(PLAT)),ASR)\r
-ifneq ($(strip $(PLAT)),ASR_1606)\r
-INC += -I$(ROOT)/components/decode/qingya\r
-endif\r
-endif\r
-endif\r
-\r
-ifeq ($(CONFIG_SPI_SDCARD), y)\r
-INC += -I$(ROOT)/components/fs/fatfs/include\r
-endif\r
-\r
-ifeq ($(CONFIG_AUDIO_G711_COMPRESS), y)\r
-INC += -I$(ROOT)/components/audio/G711\r
-endif\r
-ifeq ($(strip $(PLAT)),EIGEN)\r
-INC += -I$(ROOT)/components/audio\r
-endif\r
-\r
-ifeq ($(CONFIG_GMSSL), y)\r
-INC += -I$(ROOT)/components/GMSSL/include\r
-INC += -I$(ROOT)/components/GMSSL/include/gmssl\r
-endif\r
-\r
-ifeq ($(CONFIG_AUDIO_G729_COMPRESS), y)\r
-INC += -I$(ROOT)/components/audio/G729\r
-INC += -I$(ROOT)/components/audio/G729/src\r
-INC += -I$(ROOT)/components/audio/G729/include\r
-endif\r
-\r
-# compiler settings\r
-CWARN = -Wall -Werror\r
-CWARN += -Wpointer-arith -Wuninitialized\r
-C_FLAGS = $(INC) $(CWARN) -std=gnu99 $(C_FLAGS_MOD) $(COPT) $(C_FLAGS_EXTRA)\r
-C_FLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables --include=../../../../../../config/autoconf.h\r
-\r
-LD_FLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections\r
-LD_FLAGS = $(LD_FLAGS_MOD) $(LD_FLAGS_ARCH) -lm $(LD_FLAGS_EXTRA)\r
-\r
-D_FLAGS += $(foreach dflag, $(DFLAGS), -D$(dflag))\r
-D_FLAGS += -DMP_CONFIGFILE="\"ports/quectel/core/source/mpconfigport.h\"" \\r
-                 -DMICROPY_MPTHREADPORT_H="\"ports/quectel/core/source/mpthreadport.h\"" \\r
-                 -DMICROPY_MPHALPORT_H="\"ports/quectel/core/source/mphalport.h\""\r
-\r
-vpath %.S . $(TOP) $(USER_C_MODULES)\r
-$(BUILD)/%.o: %.S\r
-       @$(ECHO) "CC $<"\r
-       $(Q)$(CC) $(C_FLAGS) $(D_FLAGS) -c -o $@ $<\r
-\r
-vpath %.s . $(TOP) $(USER_C_MODULES)\r
-$(BUILD)/%.o: %.s\r
-       @$(ECHO) "AS $<"\r
-       $(Q)$(AS) -o $@ $<\r
-QSTR_GEN_EXTRA_C_FLAGS += -DNO_QSTR\r
-vpath %.c . $(TOP) $(USER_C_MODULES)\r
-$(BUILD)/%.pp: %.c\r
-       @$(ECHO) "PreProcess $<"\r
-       $(Q)$(CPP) $(C_FLAGS) $(D_FLAGS) -Wp,-C,-dD,-dI -o $@ $<\r
-\r
-#$(OBJ): | $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/mpversion.h\r
-\r
-\r
-$(HEADER_BUILD)/qstr.i.last: $(SRC_QSTR) $(QSTR_GLOBAL_DEPENDENCIES) | $(QSTR_GLOBAL_REQUIREMENTS)\r
-       @$(ECHO) "GEN $@"\r
-       @rm -f $@ $@.dep\r
-       @for src in $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)); \\r
-       do \\r
-               echo $$src >> $@.dep; \\r
-       done\r
-       @while read -r src; \\r
-               do \\r
-                       echo processing on $$src ...; \\r
-                       $(CPP) $(QSTR_GEN_EXTRA_C_FLAGS) $(C_FLAGS) $(D_FLAGS) $$src >> $@; \\r
-       done < $@.dep\r
-\r
-$(HEADER_BUILD)/qstr.split: $(HEADER_BUILD)/qstr.i.last\r
-       @$(ECHO) "GEN $@"\r
-       $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py split qstr $(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED)\r
-       $(Q)$(TOUCH) $@\r
-\r
-$(QSTR_DEFS_COLLECTED): $(HEADER_BUILD)/qstr.split\r
-       @$(ECHO) "GEN $@"\r
-       $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py cat qstr $(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED)\r
-\r
-\r
-$(BUILD)/%.mpy: $(FROZEN_MPY_DIR)/%.py\r
-       @$(ECHO) "MPY $<"\r
-       $(Q)$(MKDIR) -p $(dir $@)\r
-       $(Q)$(MPY_CROSS) -o $@ -s $(<:$(FROZEN_MPY_DIR)/%=%) $(MPY_CROSS_FLAGS) $<\r
-\r
-ifeq ($(strip $(PLAT)),RDA)\r
-frozen_mpy_list =      $(BUILD)/_boot_RDA.mpy \\r
-                                       $(BUILD)/system.mpy \\r
-                                       $(BUILD)/dataCall.mpy \\r
-                                       $(BUILD)/umqtt.mpy \\r
-                                       $(BUILD)/sys_bus.mpy \\r
-                                       $(BUILD)/queue.mpy \\r
-                                       $(BUILD)/log.mpy \\r
-                                       $(BUILD)/request.mpy \\r
-                                       $(BUILD)/ql_fs.mpy \\r
-                                       $(BUILD)/app_fota_mount.mpy \\r
-                                       $(BUILD)/app_fota_download.mpy \\r
-                                       $(BUILD)/checksum.mpy \\r
-                                       $(BUILD)/file_crc32.mpy \\r
-                                       $(BUILD)/app_fota_updater.mpy \\r
-                                       $(BUILD)/app_fota.mpy \\r
-                                       $(BUILD)/backup_restore.mpy \\r
-                                       $(BUILD)/event_message.mpy \\r
-                                       $(BUILD)/ntptime.mpy \\r
-                                       $(BUILD)/checkNet.mpy \\r
-                                       $(BUILD)/uping.mpy \\r
-                                       $(BUILD)/ymodem.mpy \\r
-\r
-ifeq ($(strip $(BOARD)),$(filter $(strip $(BOARD)),BC25B8PA_LBS))\r
-       frozen_mpy_list +=      $(BUILD)/cellLocator.mpy \r
-endif\r
-\r
-else ifeq ($(strip $(PLAT)),ASR_1803s)\r
-frozen_mpy_list =      $(BUILD)/_boot.mpy \\r
-                                       $(BUILD)/system.mpy \\r
-                                       $(BUILD)/checkNet.mpy \\r
-                                       $(BUILD)/ntptime.mpy \\r
-                                       $(BUILD)/dataCall.mpy \\r
-                                       $(BUILD)/log.mpy \\r
-                                       $(BUILD)/request.mpy \\r
-                                       $(BUILD)/umqtt.mpy \\r
-                                       $(BUILD)/ql_fs.mpy \\r
-                                       $(BUILD)/app_fota_mount.mpy \\r
-                                       $(BUILD)/app_fota_download.mpy \\r
-                                       $(BUILD)/checksum.mpy \\r
-                                       $(BUILD)/file_crc32.mpy \\r
-                                       $(BUILD)/app_fota_updater.mpy \\r
-                                       $(BUILD)/app_fota.mpy \\r
-                                       $(BUILD)/backup_restore.mpy \\r
-                                       $(BUILD)/queue.mpy \\r
-                                       $(BUILD)/sys_bus.mpy \\r
-                                       $(BUILD)/event_message.mpy \\r
-                                       $(BUILD)/bak_util.mpy \\r
-                                       $(BUILD)/cellLocator.mpy \\r
-                                       $(BUILD)/ftplib.mpy \\r
-                                       $(BUILD)/ftplibtls.mpy \\r
-                                       $(BUILD)/uwebsocket.mpy \\r
-                                       $(BUILD)/uping.mpy \\r
-                                       $(BUILD)/ymodem.mpy \\r
-\r
-else ifeq ($(strip $(PLAT)),Qualcomm)\r
-frozen_mpy_list =      $(BUILD)/_boot_Qualcomm.mpy \\r
-                                       $(BUILD)/system.mpy \\r
-                                       $(BUILD)/checkNet.mpy \\r
-                                       $(BUILD)/ntptime.mpy \\r
-                                       $(BUILD)/dataCall.mpy \\r
-                                       $(BUILD)/umqtt.mpy \\r
-                                       $(BUILD)/log.mpy \\r
-                                       $(BUILD)/request.mpy \\r
-                                       $(BUILD)/ql_fs.mpy \\r
-                                       $(BUILD)/app_fota_download.mpy \\r
-                                       $(BUILD)/checksum.mpy \\r
-                                       $(BUILD)/file_crc32.mpy \\r
-                                       $(BUILD)/app_fota_mount.mpy \\r
-                                       $(BUILD)/app_fota_updater.mpy \\r
-                                       $(BUILD)/app_fota.mpy \\r
-                                       $(BUILD)/backup_restore.mpy \\r
-                                       $(BUILD)/queue.mpy \\r
-                                       $(BUILD)/sys_bus.mpy \\r
-                                       $(BUILD)/event_message.mpy \\r
-                                       $(BUILD)/bak_util.mpy \\r
-                                       $(BUILD)/uwebsocket.mpy \\r
-                                       $(BUILD)/uping.mpy \\r
-                                       $(BUILD)/ymodem.mpy \\r
-\r
-else ifeq ($(strip $(PLAT)),ASR_1606)\r
-ifeq ($(strip $(BOARD)),$(filter $(strip $(BOARD)),EC600MCN_CC EC800MCN_CC EC600MCN_CC_EXT EC600MCN_LF_SLPOC))\r
-frozen_mpy_list =      $(BUILD)/_boot.mpy \\r
-                                       $(BUILD)/system.mpy \\r
-                                       $(BUILD)/dataCall.mpy \\r
-                                       $(BUILD)/umqtt.mpy \\r
-                                       $(BUILD)/queue.mpy \\r
-                                       $(BUILD)/log.mpy \\r
-                                       $(BUILD)/request.mpy \\r
-                                       $(BUILD)/ql_fs.mpy \\r
-                                       $(BUILD)/app_fota_mount.mpy \\r
-                                       $(BUILD)/app_fota_download.mpy \\r
-                                       $(BUILD)/checksum.mpy \\r
-                                       $(BUILD)/file_crc32.mpy \\r
-                                       $(BUILD)/app_fota_updater.mpy \\r
-                                       $(BUILD)/app_fota.mpy \\r
-                                       $(BUILD)/backup_restore.mpy \\r
-                                       $(BUILD)/ntptime.mpy \\r
-                                       $(BUILD)/checkNet.mpy \\r
-                                       $(BUILD)/ymodem.mpy\r
-\r
-else ifeq ($(strip $(BOARD)),$(filter $(strip $(BOARD)),EC600MCN_CC_EXT_TTS))\r
-frozen_mpy_list =      $(BUILD)/_boot.mpy \\r
-                                       $(BUILD)/dataCall.mpy \\r
-                                       $(BUILD)/file_crc32.mpy \\r
-                                       $(BUILD)/ntptime.mpy \\r
-                                       $(BUILD)/ymodem.mpy\r
-else\r
-frozen_mpy_list =      $(BUILD)/_boot.mpy \\r
-                                       $(BUILD)/umqtt.mpy \\r
-                                       $(BUILD)/ntptime.mpy \\r
-                                       $(BUILD)/request.mpy \\r
-                                       $(BUILD)/log.mpy \\r
-                                       $(BUILD)/hmac.mpy \\r
-                                       $(BUILD)/hashlib.mpy \\r
-                                       $(BUILD)/base64.mpy \\r
-                                       $(BUILD)/file_sha256.mpy \\r
-                                       $(BUILD)/checksum.mpy \\r
-                                       $(BUILD)/checkNet.mpy \\r
-                                       $(BUILD)/dataCall.mpy \\r
-                                       $(BUILD)/ql_fs.mpy \\r
-                                       $(BUILD)/app_fota_mount.mpy \\r
-                                       $(BUILD)/app_fota_download.mpy\\r
-                                       $(BUILD)/app_fota_updater.mpy \\r
-                                       $(BUILD)/app_fota.mpy \\r
-                                       $(BUILD)/backup_restore.mpy \\r
-                                       $(BUILD)/file_crc32.mpy \\r
-                                       $(BUILD)/system.mpy \\r
-                                       $(BUILD)/gnss.mpy \\r
-                                       $(BUILD)/unzip.mpy \\r
-                                       $(BUILD)/queue.mpy \\r
-                                       $(BUILD)/sys_bus.mpy \\r
-                                       $(BUILD)/event_message.mpy \\r
-                                       $(BUILD)/hls.mpy \\r
-                                       $(BUILD)/wifilocator.mpy \\r
-                                       $(BUILD)/cellLocator.mpy \\r
-                                       $(BUILD)/bak_util.mpy \\r
-                                       $(BUILD)/uwebsocket.mpy \\r
-                                       $(BUILD)/uping.mpy \\r
-                                       $(BUILD)/ymodem.mpy \\r
-                                       $(BUILD)/common.mpy \\r
-                                       $(BUILD)/constants.mpy \\r
-                                       $(BUILD)/EventMesh.mpy \\r
-                                       $(BUILD)/mgr.mpy \\r
-                                       $(BUILD)/protocol.mpy \\r
-                                       $(BUILD)/ui.mpy \\r
-                                       $(BUILD)/main_init.mpy \\r
-                                       $(BUILD)/versions.mpy \\r
-                                       $(BUILD)/motor.mpy \\r
-                                       $(BUILD)/ai_VC.mpy \\r
-                                       $(BUILD)/ai_alarm.mpy \\r
-                                       $(BUILD)/voice_record.mpy \\r
-\r
-endif\r
-\r
-else ifeq ($(strip $(PLAT)),Unisoc_8850)\r
-ifeq ($(strip $(BOARD)),$(filter $(strip $(BOARD)),EC600GCN_LD EC600GCN_LD_YM EC800GCN_LD EC800GCN_LD_HRXM))\r
-frozen_mpy_list =      $(BUILD)/_boot.mpy \\r
-                                       $(BUILD)/umqtt.mpy \\r
-                                       $(BUILD)/ntptime.mpy \\r
-                                       $(BUILD)/request.mpy \\r
-                                       $(BUILD)/log.mpy \\r
-                                       $(BUILD)/checksum.mpy \\r
-                                       $(BUILD)/checkNet.mpy \\r
-                                       $(BUILD)/dataCall.mpy \\r
-                                       $(BUILD)/ql_fs.mpy \\r
-                                       $(BUILD)/app_fota_mount.mpy \\r
-                                       $(BUILD)/app_fota_download.mpy\\r
-                                       $(BUILD)/app_fota_updater.mpy \\r
-                                       $(BUILD)/app_fota.mpy \\r
-                                       $(BUILD)/backup_restore.mpy \\r
-                                       $(BUILD)/file_crc32.mpy \\r
-                                       $(BUILD)/system.mpy \\r
-                                       $(BUILD)/queue.mpy \\r
-                                       $(BUILD)/sys_bus.mpy \\r
-                                       $(BUILD)/event_message.mpy \\r
-                                       $(BUILD)/bak_util.mpy \\r
-                                       $(BUILD)/ymodem.mpy \\r
-                                       \r
-else\r
-frozen_mpy_list =      $(BUILD)/_boot.mpy \\r
-                                       $(BUILD)/umqtt.mpy \\r
-                                       $(BUILD)/ntptime.mpy \\r
-                                       $(BUILD)/request.mpy \\r
-                                       $(BUILD)/log.mpy \\r
-                                       $(BUILD)/hmac.mpy \\r
-                                       $(BUILD)/hashlib.mpy \\r
-                                       $(BUILD)/base64.mpy \\r
-                                       $(BUILD)/file_sha256.mpy \\r
-                                       $(BUILD)/checksum.mpy \\r
-                                       $(BUILD)/checkNet.mpy \\r
-                                       $(BUILD)/dataCall.mpy \\r
-                                       $(BUILD)/ql_fs.mpy \\r
-                                       $(BUILD)/app_fota_mount.mpy \\r
-                                       $(BUILD)/app_fota_download.mpy\\r
-                                       $(BUILD)/app_fota_updater.mpy \\r
-                                       $(BUILD)/app_fota.mpy \\r
-                                       $(BUILD)/backup_restore.mpy \\r
-                                       $(BUILD)/file_crc32.mpy \\r
-                                       $(BUILD)/system.mpy \\r
-                                       $(BUILD)/gnss.mpy \\r
-                                       $(BUILD)/unzip.mpy \\r
-                                       $(BUILD)/queue.mpy \\r
-                                       $(BUILD)/sys_bus.mpy \\r
-                                       $(BUILD)/event_message.mpy \\r
-                                       $(BUILD)/hls.mpy \\r
-                                       $(BUILD)/wifilocator.mpy \\r
-                                       $(BUILD)/bak_util.mpy \\r
-                                       $(BUILD)/ftplib.mpy \\r
-                                       $(BUILD)/ftplibtls.mpy \\r
-                                       $(BUILD)/uwebsocket.mpy \\r
-                                       $(BUILD)/uping.mpy \\r
-                                       $(BUILD)/ymodem.mpy \\r
-                                       \r
-endif\r
-\r
-else ifeq ($(strip $(PLAT)),EIGEN)\r
-ifeq ($(strip $(BOARD)),$(filter $(strip $(BOARD)),EC800ECN_LC_WDF))\r
-frozen_mpy_list =      $(BUILD)/_boot_WDF.mpy \\r
-                                       $(BUILD)/umqtt.mpy \\r
-                                       $(BUILD)/dataCall.mpy \\r
-                                       $(BUILD)/log.mpy \\r
-                                       $(BUILD)/request.mpy \\r
-                                       $(BUILD)/hmac.mpy \\r
-                                       $(BUILD)/hashlib.mpy \\r
-                                       $(BUILD)/ntptime.mpy \\r
-                                       $(BUILD)/checksum.mpy \\r
-                                       $(BUILD)/checkNet.mpy \\r
-                                       $(BUILD)/ql_fs.mpy \\r
-                                       $(BUILD)/app_fota_mount.mpy \\r
-                                       $(BUILD)/app_fota_download.mpy\\r
-                                       $(BUILD)/app_fota_updater.mpy \\r
-                                       $(BUILD)/app_fota.mpy \\r
-                                       $(BUILD)/backup_restore.mpy \\r
-                                       $(BUILD)/file_crc32.mpy \\r
-                                       $(BUILD)/system.mpy \\r
-                                       $(BUILD)/queue.mpy \\r
-                                       $(BUILD)/sys_bus.mpy \\r
-                                       $(BUILD)/event_message.mpy \\r
-                                       $(BUILD)/bak_util.mpy \\r
-                                       $(BUILD)/ftplib.mpy \\r
-                                       $(BUILD)/ftplibtls.mpy \\r
-                                       $(BUILD)/ymodem.mpy \\r
-\r
-else\r
-frozen_mpy_list =      $(BUILD)/_boot.mpy \\r
-                                       $(BUILD)/umqtt.mpy \\r
-                                       $(BUILD)/dataCall.mpy \\r
-                                       $(BUILD)/log.mpy \\r
-                                       $(BUILD)/request.mpy \\r
-                                       $(BUILD)/hmac.mpy \\r
-                                       $(BUILD)/hashlib.mpy \\r
-                                       $(BUILD)/ntptime.mpy \\r
-                                       $(BUILD)/checksum.mpy \\r
-                                       $(BUILD)/checkNet.mpy \\r
-                                       $(BUILD)/ql_fs.mpy \\r
-                                       $(BUILD)/app_fota_mount.mpy \\r
-                                       $(BUILD)/app_fota_download.mpy\\r
-                                       $(BUILD)/app_fota_updater.mpy \\r
-                                       $(BUILD)/app_fota.mpy \\r
-                                       $(BUILD)/backup_restore.mpy \\r
-                                       $(BUILD)/file_crc32.mpy \\r
-                                       $(BUILD)/system.mpy \\r
-                                       $(BUILD)/queue.mpy \\r
-                                       $(BUILD)/sys_bus.mpy \\r
-                                       $(BUILD)/event_message.mpy \\r
-                                       $(BUILD)/bak_util.mpy \\r
-                                       $(BUILD)/ftplib.mpy \\r
-                                       $(BUILD)/ftplibtls.mpy \\r
-                                       $(BUILD)/cellLocator.mpy \\r
-                                       $(BUILD)/ymodem.mpy \\r
-                                       \r
-endif\r
-\r
-else ifeq ($(strip $(PLAT)),ECR6600)\r
-frozen_mpy_list =      $(BUILD)/_boot_WIFI.mpy \\r
-                                       $(BUILD)/umqtt.mpy \\r
-                                       $(BUILD)/request.mpy \\r
-                                       $(BUILD)/ql_fs.mpy \\r
-                                       $(BUILD)/queue.mpy \\r
-                                       $(BUILD)/sys_bus.mpy \\r
-\r
-else\r
-ifeq ($(strip $(BOARD)),$(filter $(strip $(BOARD)),EC600UEU_AB_POC))\r
-frozen_mpy_list =      $(BUILD)/_boot.mpy \\r
-                                       $(BUILD)/ntptime.mpy \\r
-                                       $(BUILD)/log.mpy \\r
-                                       $(BUILD)/file_sha256.mpy \\r
-                                       $(BUILD)/checksum.mpy \\r
-                                       $(BUILD)/checkNet.mpy \\r
-                                       $(BUILD)/dataCall.mpy \\r
-                                       $(BUILD)/ql_fs.mpy \\r
-                                       $(BUILD)/app_fota_mount.mpy \\r
-                                       $(BUILD)/app_fota_download.mpy\\r
-                                       $(BUILD)/app_fota_updater.mpy \\r
-                                       $(BUILD)/app_fota.mpy \\r
-                                       $(BUILD)/backup_restore.mpy \\r
-                                       $(BUILD)/file_crc32.mpy \\r
-                                       $(BUILD)/system.mpy \\r
-                                       $(BUILD)/queue.mpy \\r
-                                       $(BUILD)/bak_util.mpy \\r
-                                       $(BUILD)/ymodem.mpy \r
-else\r
-frozen_mpy_list =      $(BUILD)/_boot.mpy \\r
-                                       $(BUILD)/umqtt.mpy \\r
-                                       $(BUILD)/ntptime.mpy \\r
-                                       $(BUILD)/request.mpy \\r
-                                       $(BUILD)/log.mpy \\r
-                                       $(BUILD)/hmac.mpy \\r
-                                       $(BUILD)/hashlib.mpy \\r
-                                       $(BUILD)/base64.mpy \\r
-                                       $(BUILD)/file_sha256.mpy \\r
-                                       $(BUILD)/checksum.mpy \\r
-                                       $(BUILD)/checkNet.mpy \\r
-                                       $(BUILD)/dataCall.mpy \\r
-                                       $(BUILD)/ql_fs.mpy \\r
-                                       $(BUILD)/app_fota_mount.mpy \\r
-                                       $(BUILD)/app_fota_download.mpy\\r
-                                       $(BUILD)/app_fota_updater.mpy \\r
-                                       $(BUILD)/app_fota.mpy \\r
-                                       $(BUILD)/backup_restore.mpy \\r
-                                       $(BUILD)/file_crc32.mpy \\r
-                                       $(BUILD)/system.mpy \\r
-                                       $(BUILD)/gnss.mpy \\r
-                                       $(BUILD)/unzip.mpy \\r
-                                       $(BUILD)/queue.mpy \\r
-                                       $(BUILD)/sys_bus.mpy \\r
-                                       $(BUILD)/event_message.mpy \\r
-                                       $(BUILD)/hls.mpy \\r
-                                       $(BUILD)/wifilocator.mpy \\r
-                                       $(BUILD)/bak_util.mpy \\r
-                                       $(BUILD)/ftplib.mpy \\r
-                                       $(BUILD)/ftplibtls.mpy \\r
-                                       $(BUILD)/uwebsocket.mpy \\r
-                                       $(BUILD)/uping.mpy \\r
-                                       $(BUILD)/ymodem.mpy \r
-endif\r
-endif\r
-\r
-$(BUILD)/_frozen_mpy.c: $(frozen_mpy_list) $(HEADER_BUILD)/qstrdefs.generated.h\r
-       @$(ECHO) "MISC freezing bytecode"\r
-       $(Q)$(MPY_TOOL) -f -q $(HEADER_BUILD)/qstrdefs.preprocessed.h $(frozen_mpy_list) > $@\r
-\r
-$(BUILD):\r
-       $(Q)echo creating directory: $@\r
-       -$(Q)$(MKDIR) $@\r
-\r
-all:$(BUILD) $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/moduledefs.h  $(HEADER_BUILD)/compressed.data.h $(BUILD)/_frozen_mpy.c\r
-\r
-clean:\r
-       @echo ----- cleaning microPython private target\r
-       @rm -rf $(HEADER_BUILD)\r
-       @rm -rf $(BUILD)\r
-       @echo ----- done.\r
+# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#env
+TOP := ../../..
+ROOT := $(TOP)/../..
+
+KCONFIG_CONFIG_DIR := ../../../../..
+include $(KCONFIG_CONFIG_DIR)/config/$(KCONFIG_CONFIG)
+
+ifeq ("$(origin V)", "command line")
+BUILD_VERBOSE=$(V)
+endif
+ifndef BUILD_VERBOSE
+BUILD_VERBOSE = 0
+endif
+# ifeq ($(BUILD_VERBOSE),0)
+# Q = @
+# else
+# Q =
+# endif
+
+BUILD ?= build
+FROZEN_MPY_DIR ?= .
+
+RM = rm
+ECHO = echo
+CP = cp
+MKDIR = mkdir
+SED = sed
+CAT = cat
+TOUCH = touch
+
+MAKE_MANIFEST = $(PYTHON) $(TOP)/tools/makemanifest.py
+MAKE_FROZEN = $(PYTHON) $(TOP)/tools/make-frozen.py
+#because E-safeNet, mpy-cross could not read the py file, rename as notepad++
+ifeq ($(strip $(HOST)),linux)
+MPY_CROSS = $(TOP)/ports/quectel/tools/mpy-cross
+else
+MPY_CROSS = $(TOP)/ports/quectel/tools/notepad++.exe
+endif
+MPY_TOOL = $(PYTHON) $(TOP)/tools/mpy-tool.py
+
+QSTR_DEFS = source/qstrdefsport.h
+#py
+PY_SRC ?= $(TOP)/py
+HEADER_BUILD = $(TOP)/genhdr
+PY_QSTR_DEFS = $(PY_SRC)/qstrdefs.h
+ifneq ($(QSTR_AUTOGEN_DISABLE),1)
+QSTR_DEFS_COLLECTED = $(HEADER_BUILD)/qstrdefs.collected.h
+endif
+QSTR_GLOBAL_DEPENDENCIES += $(PY_SRC)/mpconfig.h source/mpconfigport.h
+CSUPEROPT = -O3
+ifeq ($(strip $(PLAT)),ECR6600)
+MPY_CROSS_FLAGS += -march=xtensa
+else
+MPY_CROSS_FLAGS += -march=armv7m
+endif
+# Enable building 32-bit code on 64-bit host.
+ifeq ($(MICROPY_FORCE_32BIT),1)
+CC += -m32
+CXX += -m32
+LD += -m32
+endif
+
+# External modules written in C.
+ifneq ($(USER_C_MODULES),)
+# pre-define USERMOD variables as expanded so that variables are immediate
+# expanded as they're added to them
+SRC_USERMOD :=
+C_FLAGS_USERMOD :=
+LD_FLAGS_USERMOD :=
+$(foreach module, $(wildcard $(USER_C_MODULES)/*/micropython.mk), \
+    $(eval USERMOD_DIR = $(patsubst %/,%,$(dir $(module))))\
+    $(info Including User C Module from $(USERMOD_DIR))\
+       $(eval include $(module))\
+)
+
+SRC_MOD += $(patsubst $(USER_C_MODULES)/%.c,%.c,$(SRC_USERMOD))
+C_FLAGS_MOD += $(C_FLAGS_USERMOD)
+LD_FLAGS_MOD += $(LD_FLAGS_USERMOD)
+endif
+
+# py object files
+PY_CORE_O_BASENAME = $(addprefix py/,\
+       mpstate.o \
+       nlr.o \
+       nlrx86.o \
+       nlrx64.o \
+       nlrthumb.o \
+       nlrpowerpc.o \
+       nlrxtensa.o \
+       nlrsetjmp.o \
+       malloc.o \
+       gc.o \
+       pystack.o \
+       qstr.o \
+       vstr.o \
+       mpprint.o \
+       unicode.o \
+       mpz.o \
+       reader.o \
+       lexer.o \
+       parse.o \
+       scope.o \
+       compile.o \
+       emitcommon.o \
+       emitbc.o \
+       asmbase.o \
+       asmx64.o \
+       emitnx64.o \
+       asmx86.o \
+       emitnx86.o \
+       asmthumb.o \
+       emitnthumb.o \
+       emitinlinethumb.o \
+       asmarm.o \
+       emitnarm.o \
+       asmxtensa.o \
+       emitnxtensa.o \
+       emitinlinextensa.o \
+       emitnxtensawin.o \
+       formatfloat.o \
+       parsenumbase.o \
+       parsenum.o \
+       emitglue.o \
+       persistentcode.o \
+       runtime.o \
+       runtime_utils.o \
+       scheduler.o \
+       nativeglue.o \
+       pairheap.o \
+       ringbuf.o \
+       stackctrl.o \
+       argcheck.o \
+       warning.o \
+       profile.o \
+       map.o \
+       obj.o \
+       objarray.o \
+       objattrtuple.o \
+       objbool.o \
+       objboundmeth.o \
+       objcell.o \
+       objclosure.o \
+       objcomplex.o \
+       objdeque.o \
+       objdict.o \
+       objenumerate.o \
+       objexcept.o \
+       objfilter.o \
+       objfloat.o \
+       objfun.o \
+       objgenerator.o \
+       objgetitemiter.o \
+       objint.o \
+       objint_longlong.o \
+       objint_mpz.o \
+       objlist.o \
+       objmap.o \
+       objmodule.o \
+       objobject.o \
+       objpolyiter.o \
+       objproperty.o \
+       objnone.o \
+       objnamedtuple.o \
+       objrange.o \
+       objreversed.o \
+       objset.o \
+       objsingleton.o \
+       objslice.o \
+       objstr.o \
+       objstrunicode.o \
+       objstringio.o \
+       objtuple.o \
+       objtype.o \
+       objzip.o \
+       opmethods.o \
+       sequence.o \
+       stream.o \
+       binary.o \
+       builtinimport.o \
+       builtinevex.o \
+       builtinhelp.o \
+       modarray.o \
+       modbuiltins.o \
+       modcollections.o \
+       modgc.o \
+       modio.o \
+       modmath.o \
+       modcmath.o \
+       modmicropython.o \
+       modstruct.o \
+       modsys.o \
+       moduerrno.o \
+       modthread.o \
+       vm.o \
+       bc.o \
+       showbc.o \
+       repl.o \
+       smallint.o \
+       frozenmod.o \
+       )
+
+PY_EXTMOD_O_BASENAME = \
+       extmod/moductypes.o \
+       extmod/modujson.o \
+       extmod/modure.o \
+       extmod/moduzlib.o \
+       extmod/moduheapq.o \
+       extmod/modutimeq.o \
+       extmod/modubinascii.o \
+       extmod/virtpin.o \
+       extmod/machine_mem.o \
+       extmod/machine_pinbase.o \
+       extmod/machine_signal.o \
+       extmod/machine_pulse.o \
+       extmod/machine_i2c.o \
+       extmod/machine_spi.o \
+       extmod/modbluetooth.o \
+       extmod/modurandom.o \
+       extmod/moduselect.o \
+       extmod/moduasyncio.o \
+       extmod/moduwebsocket.o \
+       extmod/modwebrepl.o \
+       extmod/modframebuf.o \
+       extmod/vfs.o \
+       extmod/vfs_blockdev.o \
+       extmod/vfs_reader.o \
+       extmod/vfs_posix.o \
+       extmod/vfs_posix_file.o \
+       extmod/vfs_fat.o \
+       extmod/vfs_fat_file.o \
+       extmod/vfs_lfs.o \
+       extmod/utime_mphal.o \
+       extmod/uos_dupterm.o \
+       extmod/modussl_mbedtls.o \
+       extmod/moduhashlib.o \
+       extmod/moducryptolib.o \
+       lib/embed/abort_.o \
+       lib/utils/printf.o \
+       lib/utils/sys_stdio_mphal.o
+
+ifeq ($(strip $(PLAT)),Qualcomm)
+PY_EXTMOD_O_BASENAME += \
+       extmod/vfs_efs.o \
+       extmod/vfs_efs_file.o
+endif
+
+ifeq ($(strip $(PLAT)), $(filter $(PLAT),Unisoc Unisoc_8910_R05))
+PY_EXTMOD_O_BASENAME += \
+       extmod/vfs_temp.o \
+       extmod/vfs_temp_file.o
+endif
+
+# Sources that may contain qstrings
+SRC_QSTR_IGNORE = py/nlr%
+SRC_QSTR += $(SRC_MOD) $(filter-out $(SRC_QSTR_IGNORE),$(PY_CORE_O_BASENAME:.o=.c)) $(PY_EXTMOD_O_BASENAME:.o=.c)
+SRC_QSTR += \
+                       source/modalipay.c \
+                       source/audio_audio.c \
+                       source/audio_queue.c \
+                       source/audio_record.c \
+                       source/audio_tts.c \
+                       source/audiocodec_rt5616.c \
+                       source/callbackdeal.c \
+                       source/camera_capture.c \
+                       source/camera_preview.c \
+                       source/camera_scandecode.c \
+                       source/devreport.c \
+                       source/machine_extint.c \
+                       source/machine_hw_spi.c \
+                       source/machine_iic.c \
+                       source/machine_iic_simulation.c \
+                       source/machine_keypad.c \
+                       source/machine_lcd.c \
+                       source/machine_nandflash.c \
+                       source/machine_pin.c \
+                       source/machine_rtc.c \
+                       source/machine_timer.c \
+                       source/machine_uart.c \
+                       source/machine_wdt.c \
+                       source/misc_adc.c \
+                       source/misc_power.c \
+                       source/misc_powerkey.c \
+                       source/misc_pwm.c \
+                       source/misc_temperature.c \
+                       source/misc_usb.c \
+                       source/misc_usbnet.c \
+                       source/modatcmd.c \
+                       source/modaudio.c \
+                       source/modaudiocodec.c \
+                       source/modble.c \
+                       source/modbt.c \
+                       source/modcamera.c \
+                       source/modcelllocator.c \
+                       source/modcelllocator_qpy.c \
+                       source/locator.c \
+                       source/modcsd.c \
+                       source/moddatacall.c \
+                       source/moddev.c \
+                       source/modethernet.c \
+                       source/modethernet_dm9051.c \
+                       source/modethernet_w5500.c \
+                       source/modethernet_ch395.c \
+                       source/modexample.c \
+                       source/modfota.c \
+                       source/modgnss.c \
+                       source/modlpm.c \
+                       source/modlvgl.c \
+                       source/modlwm2m.c \
+                       source/modmachine.c \
+                       source/modmisc.c \
+                       source/modnb.c \
+                       source/modnet.c \
+                       source/modostimer.c \
+                       source/modpoc.c \
+                       source/modqrcode.c \
+                       source/modrtmp.c \
+                       source/modsecuredata.c \
+                       source/modsensor.c \
+                       source/modsha1.c \
+                       source/modsim.c \
+                       source/modslipif.c \
+                       source/modsms.c \
+                       source/modsocket.c \
+                       source/modtp.c \
+                       source/moduos.c \
+                       source/modutils.c \
+                       source/modutime.c \
+                       source/modvoicecall.c \
+                       source/modwifilocator.c \
+                       source/modwifiscan.c \
+                       source/nb_aep.c \
+                       source/nb_oc.c \
+                       source/nb_onenet.c \
+                       source/quecpython.c \
+                       source/sensor_sn95500.c \
+                       source/sensor_icckey.c \
+                       source/sensor_gnss.c \
+                       source/tp_gt9xx.c \
+                       source/tp_xpt2046.c \
+                       source/tp_cst816.c \
+                       source/modGsensor.c \
+                       source/modGsensor_SC7A20.c \
+                       source/modHsensor.c \
+                       source/modHsensor_GH3018.c \
+                       source/modVideoCall.c \
+                       source/modVideoCall_juphoon.c \
+                       source/modHsensor_HX3918.c \
+                       source/modrsa.c \
+                       source/utils_crc32.c \
+                       source/http_parser.c \
+                       source/modwebserver.c \
+                       source/modethernet_yt8512h.c \
+                       source/sim_esim.c \
+                       source/modG711.c \
+                       source/modG729.c \
+                       source/modcan_mcp2515.c \
+                       source/modextuart_wk2114.c \
+                       source/modextgpio_aw9523.c \
+                       source/machine_key.c \
+                       source/lpm_wakeup.c \
+                       source/sensor_handmic_key.c     \
+                       source/modnetwork.c     \
+                       source/modwlan_ASR5803.c \
+                       source/machine_soft_spi.c \
+                       source/code128_p.c \
+                       source/modwlan.c\
+                       source/modwlan.c \
+                       source/modmask.c \
+                       source/modVad.c \
+                       source/machine_one_wire.c
+
+
+ifeq ($(strip $(PLAT)),RDA)
+SRC_QSTR += $(ROOT)/components/quecsdk/cloud/python/modquecIot-BC25old.c
+else
+SRC_QSTR += $(ROOT)/components/quecsdk/cloud/python/modquecIot.c
+endif
+
+ifeq ($(CONFIG_USQLITE), y)
+SRC_QSTR += lib/usqlite/usqlite_connection.c \
+                       lib/usqlite/usqlite_cursor.c \
+                       lib/usqlite/usqlite_row.c \
+                       lib/usqlite/usqlite_file.c \
+                       lib/usqlite/usqlite_mem.c \
+                       lib/usqlite/usqlite_vfs.c \
+                       lib/usqlite/usqlite_utils.c \
+                       lib/usqlite/usqlite.c \
+                       lib/usqlite/usqlite_module.c
+
+INC += -Ilib/usqlite
+endif
+
+$(BUILD)/%.pp: %.c
+       @$(ECHO) "PreProcess $<"
+       $(Q)$(CPP) $(C_FLAGS) -Wp,-C,-dD,-dI -o $@ $<
+
+# Anything that depends on FORCE will be considered out-of-date
+FORCE:
+.PHONY: FORCE
+
+$(HEADER_BUILD):
+       $(MKDIR) -p $@
+
+#$(HEADER_BUILD)/mpversion.h: FORCE | $(HEADER_BUILD)
+#      $(Q)$(PYTHON) $(PY_SRC)/makeversionhdr.py $@
+# mpconfigport.mk is optional, but changes to it may drastically change
+# overall config, so they need to be caught
+MPCONFIGPORT_MK = $(wildcard mpconfigport.mk)
+
+# qstr data
+# Adding an order only dependency on $(HEADER_BUILD) causes $(HEADER_BUILD) to get
+# created before we run the script to generate the .h
+# Note: we need to protect the qstr names from the preprocessor, so we wrap
+# the lines in "" and then unwrap after the preprocessor is finished.
+# See more information about this process in docs/develop/qstr.rst.
+$(HEADER_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) $(PY_SRC)/makeqstrdata.py source/mpconfigport.h $(MPCONFIGPORT_MK) $(PY_SRC)/mpconfig.h | $(HEADER_BUILD)
+       @$(ECHO) "GEN $@"
+       $(Q)$(CAT) $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) | $(SED) 's/^Q(.*)/"&"/' | $(CPP) $(C_FLAGS) - | $(SED) 's/^\"\(Q(.*)\)\"/\1/' > $(HEADER_BUILD)/qstrdefs.preprocessed.h
+       $(Q)$(PYTHON) $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/qstrdefs.preprocessed.h > $@
+
+# Compressed error strings.
+$(HEADER_BUILD)/compressed.split: $(HEADER_BUILD)/qstr.i.last
+       @$(ECHO) "GEN $@"
+       $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py split compress $< $(HEADER_BUILD)/compress _
+       $(Q)$(TOUCH) $@
+       
+$(HEADER_BUILD)/compressed.collected: $(HEADER_BUILD)/compressed.split
+       @$(ECHO) "GEN $@"
+       $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py $(CAT) compress _ $(HEADER_BUILD)/compress $@
+       
+$(HEADER_BUILD)/compressed.data.h: $(HEADER_BUILD)/compressed.collected
+       @$(ECHO) "GEN $@"
+       $(Q)$(PYTHON) $(PY_SRC)/makecompresseddata.py $< > $@
+       
+# build a list of registered modules for py/objmodule.c.
+$(HEADER_BUILD)/moduledefs.h: $(SRC_QSTR) $(QSTR_GLOBAL_DEPENDENCIES) | $(HEADER_BUILD)
+       @$(ECHO) "GEN $@"
+       $(Q)$(PYTHON) $(PY_SRC)/makemoduledefs.py --vpath="., $(TOP), $(USER_C_MODULES)" $(SRC_QSTR) > $@
+
+SRC_QSTR += $(HEADER_BUILD)/moduledefs.h
+
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/config
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/include
+
+ifeq ($(strip $(PLAT)),Qualcomm)
+INC += -I$(COMPILER_PATH)/armv7m-none-eabi/libc/include
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/inc
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/inc/azure_c_shared_utility
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/pal
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/pal/generic
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client/inc
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client/inc/internal
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/serializer
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/serializer/inc
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt/inc
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt/inc/azure_umqtt_c
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/qapi
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/threadx_api
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include
+INC += -I$(ROOT)/system/at
+INC += -I$(ROOT)/system/esim
+endif
+
+INC += -I.
+INC += -I$(HEADER_BUILD)
+INC += -I$(TOP)
+INC += -I$(TOP)/py
+INC += -I$(TOP)/extmod
+INC += -I$(TOP)/lib/utils
+INC += -I$(TOP)/lib/mp-readline
+INC += -I$(TOP)/lib/littlefs
+INC += -I$(TOP)/lib/netutils
+INC += -I$(TOP)/lib/timeutils
+INC += -I$(TOP)/ports/quectel/core
+INC += -I$(TOP)/ports/quectel/core/source
+INC += -I$(TOP)/ports/quectel/core/py
+INC += -I$(ROOT)/peripheral
+INC += -I$(ROOT)/system/include
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/include
+INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include
+INC += -I$(ROOT)/system/debug
+INC += -I$(ROOT)/system/dev
+INC += -I$(ROOT)/system/fs
+INC += -I$(ROOT)/system/hal
+INC += -I$(ROOT)/system/gnss
+INC += -I$(ROOT)/system/network
+INC += -I$(ROOT)/system/at
+INC += -I$(ROOT)/system/aliiot
+
+ifeq ($(strip $(PLAT)),ASR_1803s)
+INC += -I$(ROOT)/system/csd
+INC += -I$(ROOT)/system/esim
+endif
+ifeq ($(strip $(PLAT)),ASR_1606)
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include
+endif
+
+ifeq ($(strip $(PLAT)),Unisoc)
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/arpa
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/net
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/netinet
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/sys
+INC += -I$(ROOT)/system/at
+endif
+
+ifeq ($(strip $(PLAT)),Unisoc_8910_R05)
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp/polarssl
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/arpa
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/net
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/netinet
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/sys
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/stdc
+endif
+
+ifeq ($(strip $(PLAT)),EIGEN)
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/apps
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/priv
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/prot
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/arch
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/netif
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/posix
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/posix/sys
+endif
+
+ifeq ($(strip $(PLAT)),Unisoc_8850)
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp/polarssl
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/arpa
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/net
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/netinet
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/sys
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/stdc
+endif
+
+ifeq ($(strip $(PLAT)),RDA)
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/arch
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/arpa
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/net
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/netinet
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/sys
+endif
+
+ifeq ($(strip $(PLAT)), $(filter $(PLAT),ASR ASR_1803s))
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include
+INC += -I$(ROOT)/system/at
+endif
+
+ifeq ($(strip $(PLAT)),ECR6600)
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))
+INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include
+endif
+
+ifeq (y, $(CONFIG_MBEDTLS))
+INC += -I$(ROOT)/system/mbedtls
+INC += -I$(ROOT)/system/mbedtls/include
+INC += -I$(ROOT)/system/mbedtls/include/mbedtls
+INC += -I$(ROOT)/system/mbedtls/library
+INC += -I$(ROOT)/system/mbedtls/port/helios/inc
+endif
+INC += -I$(ROOT)/system/network
+INC += -I$(ROOT)/system/os
+INC += -I$(ROOT)/system/startup
+INC += -I$(ROOT)/system/fota
+INC += -I$(ROOT)/system/bt
+INC += -I$(ROOT)/system/at
+ifeq (y, $(CONFIG_LVGL))
+INC += -I$(TOP)/lib/lvgl
+INC += -I$(TOP)/lib/lvgl/src
+INC += -I$(TOP)/lib/lvgl/src/core
+INC += -I$(TOP)/lib/lvgl/src/draw
+INC += -I$(TOP)/lib/lvgl/src/extra
+INC += -I$(TOP)/lib/lvgl/src/font
+INC += -I$(TOP)/lib/lvgl/src/gpu
+INC += -I$(TOP)/lib/lvgl/src/hal
+INC += -I$(TOP)/lib/lvgl/src/misc
+INC += -I$(TOP)/lib/lvgl/src/widgts
+endif
+INC += -I$(ROOT)/driver
+INC += -I$(ROOT)/driver/lcd
+ifeq (y, $(CONFIG_QRCODE))
+INC += -I$(ROOT)/components/qrcode
+endif
+ifeq (y, $(CONFIG_QUECTHING))
+INC += -I$(ROOT)/components/quecsdk/cloud
+INC += -I$(ROOT)/components/quecsdk/driverLayer
+INC += -I$(ROOT)/components/quecsdk/thirdLib/mqtt
+INC += -I$(ROOT)/components/quecsdk/thirdLib/cJSON
+INC += -I$(ROOT)/components/quecsdk/kernel
+endif
+ifeq ($(CONFIG_SPINAND), y)
+INC += -I$(ROOT)/components/fs/include
+INC += -I$(ROOT)/components/fs/yaffs/src/direct
+INC += -I$(ROOT)/components/fs/yaffs/src/port
+INC += -I$(ROOT)/components/fs/yaffs/src
+INC += -I$(ROOT)/components/fs/yaffs
+endif
+ifeq ($(CONFIG_RTMP), y)
+INC += -I$(ROOT)/components/rtmpdump/librtmp/inc
+INC += -I$(ROOT)/components/rtmpdump/libz/inc
+endif
+INC += -I$(ROOT)/utilities
+ifeq ($(CONFIG_JPEG), y)
+INC += -I$(ROOT)/components/jpeg/jpeg-9c
+INC += -I$(ROOT)/components/jpeg
+endif
+ifeq ($(CONFIG_HX3918), y)
+INC += -I$(ROOT)/components/HX3918
+endif
+ifeq ($(CONFIG_GH301x), y)
+INC += -I$(ROOT)/components/GH301x
+endif
+ifeq ($(CONFIG_SC7A20), y)
+INC += -I$(ROOT)/components/SC7A20
+endif
+ifeq ($(CONFIG_juphoon), y)
+INC += -I$(ROOT)/components/juphoon
+endif
+ifeq ($(CONFIG_POC_BND), y)
+INC += -I$(ROOT)/components/poc
+INC += -I$(ROOT)/components/poc/bnd/inc
+endif
+ifeq ($(CONFIG_POC_BND_XIN), y)
+INC += -I$(ROOT)/components/poc
+INC += -I$(ROOT)/components/poc/bnd_xin/inc
+endif
+ifeq ($(CONFIG_POC_SL), y)
+INC += -I$(ROOT)/components/poc
+INC += -I$(ROOT)/components/poc/sl/inc
+endif
+ifeq ($(CONFIG_POC_QS), y)
+INC += -I$(ROOT)/components/poc
+INC += -I$(ROOT)/components/poc/qs/inc
+endif
+#Stephen.Gao add 2022/11/23
+ifeq ($(CONFIG_POC_ZZD), y)
+INC += -I$(ROOT)/components/poc
+INC += -I$(ROOT)/components/poc/zzd/inc
+endif
+#Stephen.Gao add 2023/01/06
+ifeq ($(CONFIG_POC_YDWL), y)
+INC += -I$(ROOT)/components/poc
+INC += -I$(ROOT)/components/poc/ydwl/inc
+endif
+
+ifeq ($(CONFIG_POC_SLPOC), y)
+INC += -I$(ROOT)/components/poc  -I$(ROOT)/components/poc/slpoc/src
+INC += -I$(ROOT)/components/poc/slpoc/inc
+SRC_QSTR += $(ROOT)/components/poc/slpoc/src/modpoc_slpoc.c
+endif
+
+ifeq ($(CONFIG_POC_RDA_BND), y)
+INC += -I$(ROOT)/components/poc  -I$(ROOT)/components/poc/rda_bnd/src
+INC += -I$(ROOT)/components/poc/rda_bnd/inc
+SRC_QSTR += $(ROOT)/components/poc/rda_bnd/src/modpocrda.c
+endif
+
+
+ifeq (y,$(CONFIG_DECODE_ZBAR))
+INC += -I$(ROOT)/components/decode/ZBar/zbar
+INC += -I$(ROOT)/components/decode/ZBar/include
+INC += -I$(ROOT)/components/decode/ZBar/zbar/decoder
+INC += -I$(ROOT)/components/decode/ZBar/zbar/qrcode
+endif
+ifeq (y,$(CONFIG_DECODE_QUECTEL))
+INC += -I$(ROOT)/components/decode/quectel/inc
+endif
+
+ifeq (y,$(CONFIG_DECODE_QINGYA))
+ifneq ($(strip $(PLAT)),ASR)
+ifneq ($(strip $(PLAT)),ASR_1606)
+INC += -I$(ROOT)/components/decode/qingya
+endif
+endif
+endif
+
+ifeq ($(CONFIG_SPI_SDCARD), y)
+INC += -I$(ROOT)/components/fs/fatfs/include
+endif
+
+ifeq ($(CONFIG_AUDIO_G711_COMPRESS), y)
+INC += -I$(ROOT)/components/audio/G711
+endif
+ifeq ($(strip $(PLAT)),EIGEN)
+INC += -I$(ROOT)/components/audio
+endif
+
+ifeq ($(CONFIG_GMSSL), y)
+INC += -I$(ROOT)/components/GMSSL/include
+INC += -I$(ROOT)/components/GMSSL/include/gmssl
+endif
+
+ifeq ($(CONFIG_AUDIO_G729_COMPRESS), y)
+INC += -I$(ROOT)/components/audio/G729
+INC += -I$(ROOT)/components/audio/G729/src
+INC += -I$(ROOT)/components/audio/G729/include
+endif
+
+# compiler settings
+CWARN = -Wall -Werror
+CWARN += -Wpointer-arith -Wuninitialized
+C_FLAGS = $(INC) $(CWARN) -std=gnu99 $(C_FLAGS_MOD) $(COPT) $(C_FLAGS_EXTRA)
+C_FLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables --include=../../../../../../config/autoconf.h
+
+LD_FLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections
+LD_FLAGS = $(LD_FLAGS_MOD) $(LD_FLAGS_ARCH) -lm $(LD_FLAGS_EXTRA)
+
+D_FLAGS += $(foreach dflag, $(DFLAGS), -D$(dflag))
+D_FLAGS += -DMP_CONFIGFILE="\"ports/quectel/core/source/mpconfigport.h\"" \
+                 -DMICROPY_MPTHREADPORT_H="\"ports/quectel/core/source/mpthreadport.h\"" \
+                 -DMICROPY_MPHALPORT_H="\"ports/quectel/core/source/mphalport.h\""
+
+vpath %.S . $(TOP) $(USER_C_MODULES)
+$(BUILD)/%.o: %.S
+       @$(ECHO) "CC $<"
+       $(Q)$(CC) $(C_FLAGS) $(D_FLAGS) -c -o $@ $<
+
+vpath %.s . $(TOP) $(USER_C_MODULES)
+$(BUILD)/%.o: %.s
+       @$(ECHO) "AS $<"
+       $(Q)$(AS) -o $@ $<
+QSTR_GEN_EXTRA_C_FLAGS += -DNO_QSTR
+vpath %.c . $(TOP) $(USER_C_MODULES)
+$(BUILD)/%.pp: %.c
+       @$(ECHO) "PreProcess $<"
+       $(Q)$(CPP) $(C_FLAGS) $(D_FLAGS) -Wp,-C,-dD,-dI -o $@ $<
+
+#$(OBJ): | $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/mpversion.h
+
+
+$(HEADER_BUILD)/qstr.i.last: $(SRC_QSTR) $(QSTR_GLOBAL_DEPENDENCIES) | $(QSTR_GLOBAL_REQUIREMENTS)
+       @$(ECHO) "GEN $@"
+       @rm -f $@ $@.dep
+       @for src in $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)); \
+       do \
+               echo $$src >> $@.dep; \
+       done
+       @while read -r src; \
+               do \
+                       echo processing on $$src ...; \
+                       $(CPP) $(QSTR_GEN_EXTRA_C_FLAGS) $(C_FLAGS) $(D_FLAGS) $$src >> $@; \
+       done < $@.dep
+
+$(HEADER_BUILD)/qstr.split: $(HEADER_BUILD)/qstr.i.last
+       @$(ECHO) "GEN $@"
+       $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py split qstr $(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED)
+       $(Q)$(TOUCH) $@
+
+$(QSTR_DEFS_COLLECTED): $(HEADER_BUILD)/qstr.split
+       @$(ECHO) "GEN $@"
+       $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py cat qstr $(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED)
+
+
+$(BUILD)/%.mpy: $(FROZEN_MPY_DIR)/%.py
+       @$(ECHO) "MPY $<"
+       $(Q)$(MKDIR) -p $(dir $@)
+       $(Q)$(MPY_CROSS) -o $@ -s $(<:$(FROZEN_MPY_DIR)/%=%) $(MPY_CROSS_FLAGS) $<
+
+ifeq ($(strip $(PLAT)),RDA)
+frozen_mpy_list =      $(BUILD)/_boot_RDA.mpy \
+                                       $(BUILD)/system.mpy \
+                                       $(BUILD)/dataCall.mpy \
+                                       $(BUILD)/umqtt.mpy \
+                                       $(BUILD)/sys_bus.mpy \
+                                       $(BUILD)/queue.mpy \
+                                       $(BUILD)/log.mpy \
+                                       $(BUILD)/request.mpy \
+                                       $(BUILD)/ql_fs.mpy \
+                                       $(BUILD)/app_fota_mount.mpy \
+                                       $(BUILD)/app_fota_download.mpy \
+                                       $(BUILD)/checksum.mpy \
+                                       $(BUILD)/file_crc32.mpy \
+                                       $(BUILD)/app_fota_updater.mpy \
+                                       $(BUILD)/app_fota.mpy \
+                                       $(BUILD)/backup_restore.mpy \
+                                       $(BUILD)/event_message.mpy \
+                                       $(BUILD)/ntptime.mpy \
+                                       $(BUILD)/checkNet.mpy \
+                                       $(BUILD)/uping.mpy \
+                                       $(BUILD)/ymodem.mpy \
+
+ifeq ($(strip $(BOARD)),$(filter $(strip $(BOARD)),BC25B8PA_LBS))
+       frozen_mpy_list +=      $(BUILD)/cellLocator.mpy 
+endif
+
+else ifeq ($(strip $(PLAT)),ASR_1803s)
+frozen_mpy_list =      $(BUILD)/_boot.mpy \
+                                       $(BUILD)/system.mpy \
+                                       $(BUILD)/checkNet.mpy \
+                                       $(BUILD)/ntptime.mpy \
+                                       $(BUILD)/dataCall.mpy \
+                                       $(BUILD)/log.mpy \
+                                       $(BUILD)/request.mpy \
+                                       $(BUILD)/umqtt.mpy \
+                                       $(BUILD)/ql_fs.mpy \
+                                       $(BUILD)/app_fota_mount.mpy \
+                                       $(BUILD)/app_fota_download.mpy \
+                                       $(BUILD)/checksum.mpy \
+                                       $(BUILD)/file_crc32.mpy \
+                                       $(BUILD)/app_fota_updater.mpy \
+                                       $(BUILD)/app_fota.mpy \
+                                       $(BUILD)/backup_restore.mpy \
+                                       $(BUILD)/queue.mpy \
+                                       $(BUILD)/sys_bus.mpy \
+                                       $(BUILD)/event_message.mpy \
+                                       $(BUILD)/bak_util.mpy \
+                                       $(BUILD)/cellLocator.mpy \
+                                       $(BUILD)/ftplib.mpy \
+                                       $(BUILD)/ftplibtls.mpy \
+                                       $(BUILD)/uwebsocket.mpy \
+                                       $(BUILD)/uping.mpy \
+                                       $(BUILD)/ymodem.mpy \
+
+else ifeq ($(strip $(PLAT)),Qualcomm)
+frozen_mpy_list =      $(BUILD)/_boot_Qualcomm.mpy \
+                                       $(BUILD)/system.mpy \
+                                       $(BUILD)/checkNet.mpy \
+                                       $(BUILD)/ntptime.mpy \
+                                       $(BUILD)/dataCall.mpy \
+                                       $(BUILD)/umqtt.mpy \
+                                       $(BUILD)/log.mpy \
+                                       $(BUILD)/request.mpy \
+                                       $(BUILD)/ql_fs.mpy \
+                                       $(BUILD)/app_fota_download.mpy \
+                                       $(BUILD)/checksum.mpy \
+                                       $(BUILD)/file_crc32.mpy \
+                                       $(BUILD)/app_fota_mount.mpy \
+                                       $(BUILD)/app_fota_updater.mpy \
+                                       $(BUILD)/app_fota.mpy \
+                                       $(BUILD)/backup_restore.mpy \
+                                       $(BUILD)/queue.mpy \
+                                       $(BUILD)/sys_bus.mpy \
+                                       $(BUILD)/event_message.mpy \
+                                       $(BUILD)/bak_util.mpy \
+                                       $(BUILD)/uwebsocket.mpy \
+                                       $(BUILD)/uping.mpy \
+                                       $(BUILD)/ymodem.mpy \
+
+else ifeq ($(strip $(PLAT)),ASR_1606)
+ifeq ($(strip $(BOARD)),$(filter $(strip $(BOARD)),EC600MCN_CC EC800MCN_CC EC600MCN_CC_EXT EC600MCN_LF_SLPOC))
+frozen_mpy_list =      $(BUILD)/_boot.mpy \
+                                       $(BUILD)/system.mpy \
+                                       $(BUILD)/dataCall.mpy \
+                                       $(BUILD)/umqtt.mpy \
+                                       $(BUILD)/queue.mpy \
+                                       $(BUILD)/log.mpy \
+                                       $(BUILD)/request.mpy \
+                                       $(BUILD)/ql_fs.mpy \
+                                       $(BUILD)/app_fota_mount.mpy \
+                                       $(BUILD)/app_fota_download.mpy \
+                                       $(BUILD)/checksum.mpy \
+                                       $(BUILD)/file_crc32.mpy \
+                                       $(BUILD)/app_fota_updater.mpy \
+                                       $(BUILD)/app_fota.mpy \
+                                       $(BUILD)/backup_restore.mpy \
+                                       $(BUILD)/ntptime.mpy \
+                                       $(BUILD)/checkNet.mpy \
+                                       $(BUILD)/ymodem.mpy
+
+else ifeq ($(strip $(BOARD)),$(filter $(strip $(BOARD)),EC600MCN_CC_EXT_TTS))
+frozen_mpy_list =      $(BUILD)/_boot.mpy \
+                                       $(BUILD)/dataCall.mpy \
+                                       $(BUILD)/file_crc32.mpy \
+                                       $(BUILD)/ntptime.mpy \
+                                       $(BUILD)/ymodem.mpy
+else
+frozen_mpy_list =      $(BUILD)/_boot.mpy \
+                                       $(BUILD)/umqtt.mpy \
+                                       $(BUILD)/ntptime.mpy \
+                                       $(BUILD)/request.mpy \
+                                       $(BUILD)/log.mpy \
+                                       $(BUILD)/hmac.mpy \
+                                       $(BUILD)/hashlib.mpy \
+                                       $(BUILD)/base64.mpy \
+                                       $(BUILD)/file_sha256.mpy \
+                                       $(BUILD)/checksum.mpy \
+                                       $(BUILD)/checkNet.mpy \
+                                       $(BUILD)/dataCall.mpy \
+                                       $(BUILD)/ql_fs.mpy \
+                                       $(BUILD)/app_fota_mount.mpy \
+                                       $(BUILD)/app_fota_download.mpy\
+                                       $(BUILD)/app_fota_updater.mpy \
+                                       $(BUILD)/app_fota.mpy \
+                                       $(BUILD)/backup_restore.mpy \
+                                       $(BUILD)/file_crc32.mpy \
+                                       $(BUILD)/system.mpy \
+                                       $(BUILD)/gnss.mpy \
+                                       $(BUILD)/unzip.mpy \
+                                       $(BUILD)/queue.mpy \
+                                       $(BUILD)/sys_bus.mpy \
+                                       $(BUILD)/event_message.mpy \
+                                       $(BUILD)/hls.mpy \
+                                       $(BUILD)/wifilocator.mpy \
+                                       $(BUILD)/cellLocator.mpy \
+                                       $(BUILD)/bak_util.mpy \
+                                       $(BUILD)/uwebsocket.mpy \
+                                       $(BUILD)/uping.mpy \
+                                       $(BUILD)/ymodem.mpy \
+                                       $(BUILD)/common.mpy \
+                                       $(BUILD)/constants.mpy \
+                                       $(BUILD)/default_config.mpy \
+                                       $(BUILD)/vc_config.mpy \
+                                       $(BUILD)/default_srv.mpy \
+                                       $(BUILD)/srv_config.mpy \
+                                       $(BUILD)/EventMesh.mpy \
+                                       $(BUILD)/protocol.mpy \
+                                       $(BUILD)/ui.mpy \
+                                       $(BUILD)/main_init.mpy \
+                                       $(BUILD)/versions.mpy \
+                                       $(BUILD)/motor.mpy \
+                                       $(BUILD)/ai_VC.mpy \
+                                       $(BUILD)/ai_alarm.mpy \
+                                       $(BUILD)/voice_record.mpy \
+
+endif
+
+else ifeq ($(strip $(PLAT)),Unisoc_8850)
+ifeq ($(strip $(BOARD)),$(filter $(strip $(BOARD)),EC600GCN_LD EC600GCN_LD_YM EC800GCN_LD EC800GCN_LD_HRXM))
+frozen_mpy_list =      $(BUILD)/_boot.mpy \
+                                       $(BUILD)/umqtt.mpy \
+                                       $(BUILD)/ntptime.mpy \
+                                       $(BUILD)/request.mpy \
+                                       $(BUILD)/log.mpy \
+                                       $(BUILD)/checksum.mpy \
+                                       $(BUILD)/checkNet.mpy \
+                                       $(BUILD)/dataCall.mpy \
+                                       $(BUILD)/ql_fs.mpy \
+                                       $(BUILD)/app_fota_mount.mpy \
+                                       $(BUILD)/app_fota_download.mpy\
+                                       $(BUILD)/app_fota_updater.mpy \
+                                       $(BUILD)/app_fota.mpy \
+                                       $(BUILD)/backup_restore.mpy \
+                                       $(BUILD)/file_crc32.mpy \
+                                       $(BUILD)/system.mpy \
+                                       $(BUILD)/queue.mpy \
+                                       $(BUILD)/sys_bus.mpy \
+                                       $(BUILD)/event_message.mpy \
+                                       $(BUILD)/bak_util.mpy \
+                                       $(BUILD)/ymodem.mpy \
+                                       
+else
+frozen_mpy_list =      $(BUILD)/_boot.mpy \
+                                       $(BUILD)/umqtt.mpy \
+                                       $(BUILD)/ntptime.mpy \
+                                       $(BUILD)/request.mpy \
+                                       $(BUILD)/log.mpy \
+                                       $(BUILD)/hmac.mpy \
+                                       $(BUILD)/hashlib.mpy \
+                                       $(BUILD)/base64.mpy \
+                                       $(BUILD)/file_sha256.mpy \
+                                       $(BUILD)/checksum.mpy \
+                                       $(BUILD)/checkNet.mpy \
+                                       $(BUILD)/dataCall.mpy \
+                                       $(BUILD)/ql_fs.mpy \
+                                       $(BUILD)/app_fota_mount.mpy \
+                                       $(BUILD)/app_fota_download.mpy\
+                                       $(BUILD)/app_fota_updater.mpy \
+                                       $(BUILD)/app_fota.mpy \
+                                       $(BUILD)/backup_restore.mpy \
+                                       $(BUILD)/file_crc32.mpy \
+                                       $(BUILD)/system.mpy \
+                                       $(BUILD)/gnss.mpy \
+                                       $(BUILD)/unzip.mpy \
+                                       $(BUILD)/queue.mpy \
+                                       $(BUILD)/sys_bus.mpy \
+                                       $(BUILD)/event_message.mpy \
+                                       $(BUILD)/hls.mpy \
+                                       $(BUILD)/wifilocator.mpy \
+                                       $(BUILD)/bak_util.mpy \
+                                       $(BUILD)/ftplib.mpy \
+                                       $(BUILD)/ftplibtls.mpy \
+                                       $(BUILD)/uwebsocket.mpy \
+                                       $(BUILD)/uping.mpy \
+                                       $(BUILD)/ymodem.mpy \
+                                       
+endif
+
+else ifeq ($(strip $(PLAT)),EIGEN)
+ifeq ($(strip $(BOARD)),$(filter $(strip $(BOARD)),EC800ECN_LC_WDF))
+frozen_mpy_list =      $(BUILD)/_boot_WDF.mpy \
+                                       $(BUILD)/umqtt.mpy \
+                                       $(BUILD)/dataCall.mpy \
+                                       $(BUILD)/log.mpy \
+                                       $(BUILD)/request.mpy \
+                                       $(BUILD)/hmac.mpy \
+                                       $(BUILD)/hashlib.mpy \
+                                       $(BUILD)/ntptime.mpy \
+                                       $(BUILD)/checksum.mpy \
+                                       $(BUILD)/checkNet.mpy \
+                                       $(BUILD)/ql_fs.mpy \
+                                       $(BUILD)/app_fota_mount.mpy \
+                                       $(BUILD)/app_fota_download.mpy\
+                                       $(BUILD)/app_fota_updater.mpy \
+                                       $(BUILD)/app_fota.mpy \
+                                       $(BUILD)/backup_restore.mpy \
+                                       $(BUILD)/file_crc32.mpy \
+                                       $(BUILD)/system.mpy \
+                                       $(BUILD)/queue.mpy \
+                                       $(BUILD)/sys_bus.mpy \
+                                       $(BUILD)/event_message.mpy \
+                                       $(BUILD)/bak_util.mpy \
+                                       $(BUILD)/ftplib.mpy \
+                                       $(BUILD)/ftplibtls.mpy \
+                                       $(BUILD)/ymodem.mpy \
+
+else
+frozen_mpy_list =      $(BUILD)/_boot.mpy \
+                                       $(BUILD)/umqtt.mpy \
+                                       $(BUILD)/dataCall.mpy \
+                                       $(BUILD)/log.mpy \
+                                       $(BUILD)/request.mpy \
+                                       $(BUILD)/hmac.mpy \
+                                       $(BUILD)/hashlib.mpy \
+                                       $(BUILD)/ntptime.mpy \
+                                       $(BUILD)/checksum.mpy \
+                                       $(BUILD)/checkNet.mpy \
+                                       $(BUILD)/ql_fs.mpy \
+                                       $(BUILD)/app_fota_mount.mpy \
+                                       $(BUILD)/app_fota_download.mpy\
+                                       $(BUILD)/app_fota_updater.mpy \
+                                       $(BUILD)/app_fota.mpy \
+                                       $(BUILD)/backup_restore.mpy \
+                                       $(BUILD)/file_crc32.mpy \
+                                       $(BUILD)/system.mpy \
+                                       $(BUILD)/queue.mpy \
+                                       $(BUILD)/sys_bus.mpy \
+                                       $(BUILD)/event_message.mpy \
+                                       $(BUILD)/bak_util.mpy \
+                                       $(BUILD)/ftplib.mpy \
+                                       $(BUILD)/ftplibtls.mpy \
+                                       $(BUILD)/cellLocator.mpy \
+                                       $(BUILD)/ymodem.mpy \
+                                       
+endif
+
+else ifeq ($(strip $(PLAT)),ECR6600)
+frozen_mpy_list =      $(BUILD)/_boot_WIFI.mpy \
+                                       $(BUILD)/umqtt.mpy \
+                                       $(BUILD)/request.mpy \
+                                       $(BUILD)/ql_fs.mpy \
+                                       $(BUILD)/queue.mpy \
+                                       $(BUILD)/sys_bus.mpy \
+
+else
+ifeq ($(strip $(BOARD)),$(filter $(strip $(BOARD)),EC600UEU_AB_POC))
+frozen_mpy_list =      $(BUILD)/_boot.mpy \
+                                       $(BUILD)/ntptime.mpy \
+                                       $(BUILD)/log.mpy \
+                                       $(BUILD)/file_sha256.mpy \
+                                       $(BUILD)/checksum.mpy \
+                                       $(BUILD)/checkNet.mpy \
+                                       $(BUILD)/dataCall.mpy \
+                                       $(BUILD)/ql_fs.mpy \
+                                       $(BUILD)/app_fota_mount.mpy \
+                                       $(BUILD)/app_fota_download.mpy\
+                                       $(BUILD)/app_fota_updater.mpy \
+                                       $(BUILD)/app_fota.mpy \
+                                       $(BUILD)/backup_restore.mpy \
+                                       $(BUILD)/file_crc32.mpy \
+                                       $(BUILD)/system.mpy \
+                                       $(BUILD)/queue.mpy \
+                                       $(BUILD)/bak_util.mpy \
+                                       $(BUILD)/ymodem.mpy 
+else
+frozen_mpy_list =      $(BUILD)/_boot.mpy \
+                                       $(BUILD)/umqtt.mpy \
+                                       $(BUILD)/ntptime.mpy \
+                                       $(BUILD)/request.mpy \
+                                       $(BUILD)/log.mpy \
+                                       $(BUILD)/hmac.mpy \
+                                       $(BUILD)/hashlib.mpy \
+                                       $(BUILD)/base64.mpy \
+                                       $(BUILD)/file_sha256.mpy \
+                                       $(BUILD)/checksum.mpy \
+                                       $(BUILD)/checkNet.mpy \
+                                       $(BUILD)/dataCall.mpy \
+                                       $(BUILD)/ql_fs.mpy \
+                                       $(BUILD)/app_fota_mount.mpy \
+                                       $(BUILD)/app_fota_download.mpy\
+                                       $(BUILD)/app_fota_updater.mpy \
+                                       $(BUILD)/app_fota.mpy \
+                                       $(BUILD)/backup_restore.mpy \
+                                       $(BUILD)/file_crc32.mpy \
+                                       $(BUILD)/system.mpy \
+                                       $(BUILD)/gnss.mpy \
+                                       $(BUILD)/unzip.mpy \
+                                       $(BUILD)/queue.mpy \
+                                       $(BUILD)/sys_bus.mpy \
+                                       $(BUILD)/event_message.mpy \
+                                       $(BUILD)/hls.mpy \
+                                       $(BUILD)/wifilocator.mpy \
+                                       $(BUILD)/bak_util.mpy \
+                                       $(BUILD)/ftplib.mpy \
+                                       $(BUILD)/ftplibtls.mpy \
+                                       $(BUILD)/uwebsocket.mpy \
+                                       $(BUILD)/uping.mpy \
+                                       $(BUILD)/ymodem.mpy 
+endif
+endif
+
+$(BUILD)/_frozen_mpy.c: $(frozen_mpy_list) $(HEADER_BUILD)/qstrdefs.generated.h
+       @$(ECHO) "MISC freezing bytecode"
+       $(Q)$(MPY_TOOL) -f -q $(HEADER_BUILD)/qstrdefs.preprocessed.h $(frozen_mpy_list) > $@
+
+$(BUILD):
+       $(Q)echo creating directory: $@
+       -$(Q)$(MKDIR) $@
+
+all:$(BUILD) $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/moduledefs.h  $(HEADER_BUILD)/compressed.data.h $(BUILD)/_frozen_mpy.c
+
+clean:
+       @echo ----- cleaning microPython private target
+       @rm -rf $(HEADER_BUILD)
+       @rm -rf $(BUILD)
+       @echo ----- done.
index 476d06a..7ba05ab 100644 (file)
@@ -31,6 +31,10 @@ import dataCall
 import constants
 import versions
 from machine import UART
+try:
+    import vc_config
+except Exception as e:
+    usys.print_exception(e)
 try:
     import VAD
 except Exception as e:
@@ -46,7 +50,7 @@ PRESS_AUDIO_MODE = 0 #是按键音 0 是使用音频文件
 #dev_type = "7PIN_BK_coze"#k扣子小瑞
 #dev_type = "7PIN_BK_EU"#英文小瑞
 #dev_type = "7PIN_coze"#柒牌扣子
-dev_type = "7PIN"#柒牌
+dev_type = "7PIN"#柒牌(默认值,实际优先从 usr/default_config.py 覆盖)
 # dev_type = "7PIN_1_5"#柒牌1.5
 #dev_type = 'momo'#食梦貘
 #dev_type = 'sjgq'#四季甘泉
@@ -55,6 +59,13 @@ dev_type = "7PIN"#柒牌
 #dev_type = 'jswm_BOX'#金三完美柒牌盒子
 #dev_type = 'csh'#慈善会
 
+# 统一从配置加载 DEV_TYPE(usr 覆盖优先)
+try:
+    if "vc_config" in globals() and vc_config:
+        dev_type = vc_config.get_dev_type(dev_type)
+except Exception:
+    pass
+
 # 1=打印 VC 周期性保活专用行「VC: ping ping」;默认 0(WS send 明细里已跳过 ping,无需再开此项)
 VC_HEARTBEAT_LOG = 0
 # 1=打印音频帧级日志:Record_len / send_data len / 下发音频长度;默认 0(只看 uplink START/END)
@@ -62,28 +73,22 @@ VC_HEARTBEAT_LOG = 0
 # 1=启用我们新增的协议层“严格门控/缓冲/兜底”行为;0=临时排除这些改动(用于定位协议影响)
 # 受控项(与对端 V2.5+ 能力对齐;关=回退旧端行为):
 # - 上行:收到 started 前缓冲/丢弃 PCM;PTT 模式下 audio.create 前禁发 PCM
-# - 兜底:llm.completed 后若久无 tts.started,端侧 force_tts 主动发 synthesis
+# - 兜底:llm.completed 后若久无 tts.started,端侧可重启会话(不做 force_tts)
 # 注意:audio.played 不受此开关控制——金三 V2.5 服务端依赖端侧播完后上报才能进入下一轮 ASR;
 #       若误关会导致问候结束后首轮用户说话无 vad/asr。
 VC_PROTO_GUARDS = 0
 # 1=打印 VC WebSocket 每条收发的完整文本(流量大、易刷屏);0 仅一行 event 摘要(llm.delta 省略)
-VC_WS_IO_LOG = 1
-
-# 用于现场确认设备实际运行的 ai_VC 版本(只打印一次,不影响业务)
-VC_BUILD_TAG = "fsm_tts_actions_2026-05-06"
+VC_WS_IO_LOG = 0
 
 
 class AI_led(Abstract):
     def __init__(self):
-        if dev_type == "G10" or dev_type == 'jswm':
-            r_gpio, g_gpio, b_gpio = Pin.GPIO36, Pin.GPIO44, Pin.GPIO21
-        elif dev_type == "7PIN_BK_EU":
-            r_gpio, g_gpio, b_gpio = Pin.GPIO36, Pin.GPIO8, Pin.GPIO19
-        elif dev_type == "7PIN_1_5":
-            r_gpio, g_gpio, b_gpio = Pin.GPIO28, Pin.GPIO44, Pin.GPIO30
-        elif dev_type == "7PIN":
-            r_gpio, g_gpio, b_gpio = Pin.GPIO36, Pin.GPIO44, Pin.GPIO43
-        else:
+        try:
+            if "vc_config" in globals() and vc_config:
+                r_gpio, g_gpio, b_gpio = vc_config.led_gpio_tuple()
+            else:
+                r_gpio, g_gpio, b_gpio = Pin.GPIO36, Pin.GPIO21, Pin.GPIO19
+        except Exception:
             r_gpio, g_gpio, b_gpio = Pin.GPIO36, Pin.GPIO21, Pin.GPIO19
         self._led_gpio_r = r_gpio
         self._led_gpio_g = g_gpio
@@ -94,211 +99,459 @@ class AI_led(Abstract):
         print("AI_led GPIO dev_type={} red={} green={} blue={}".format(
             dev_type, r_gpio, g_gpio, b_gpio))
 
-        #=1 红灯闪,=2蓝灯闪,=3绿灯闪,=4全部灯闪,=5 思考:蓝绿交替
-        self.led_flicker_flag = 0
-        self.led_flicker_on_off_flag = 0
-        self.led_think_phase = 0
-        self.led_flicker_timer = osTimer()
-        
-        EventMesh.subscribe("open_led_red",self.open_led_red)
-        EventMesh.subscribe("open_led_blue",self.open_led_blue)
-        EventMesh.subscribe("open_led_green",self.open_led_green)
-        EventMesh.subscribe("open_led_all",self.open_led_all)
-        EventMesh.subscribe("open_led_red_blue",self.open_led_red_blue)
-        EventMesh.subscribe("open_led_red_green",self.open_led_red_green)
-        EventMesh.subscribe("flicker_led_red",self.flicker_led_red)
-        EventMesh.subscribe("flicker_led_blue",self.flicker_led_blue)
-        EventMesh.subscribe("flicker_led_green",self.flicker_led_green)
-        EventMesh.subscribe("flicker_led_all",self.flicker_led_all)
-        EventMesh.subscribe("flicker_led_blue_green",self.flicker_led_blue_green)
-        EventMesh.subscribe("close_led",self.close_led)
-        EventMesh.publish("open_led_red")
-
-        # 开机演示:每秒切换一次 LED,红->绿->蓝 为一轮,共 2 轮后停止
-        self._boot_led_demo_timer = osTimer()
-        self._boot_led_demo_step = 0
-        self._boot_led_demo_left = 3 * 2  # 3 色 * 2 轮
-        self._boot_led_demo_timer.start(1000, 1, self._boot_led_demo_timer_cb)
-
-    def _boot_led_demo_timer_cb(self, *args, **kwargs):
-        EventMesh.publish("publish_AI_btnInfo", {"func": self._boot_led_demo_timer_cb_})
-
-    def _boot_led_demo_timer_cb_(self):
-        try:
-            if self._boot_led_demo_left <= 0:
-                self._boot_led_demo_timer.stop()
-                return
-            # 不与闪烁抢占:演示期强制关掉闪烁
-            self.led_flicker_flag = 0
-            self._led_stop_flicker_timer()
-
-            if (self._boot_led_demo_step % 3) == 0:
-                print("boot_led_demo: RED (gpio={})".format(
-                    self._led_gpio_r))
-                self.open_led_red(None, None)
-            elif (self._boot_led_demo_step % 3) == 1:
-                print("boot_led_demo: GREEN (gpio={})".format(
-                    self._led_gpio_g))
-                self.open_led_green(None, None)
+        # 统一输入状态(充电/电量/信号/AI对话),按优先级表输出
+        self._st_ai = "idle"         # idle/listening/thinking/playing
+        self._st_charging = "none"   # none/charging/full
+        self._st_battery = "normal"  # normal/low/empty
+        self._st_signal = "normal"   # normal/weak
+
+        self._timer = osTimer()
+        self._mode = "off"  # off/red_on/green_on/blue_blink/red_blink/bg_alt
+        self._blink_on = 0
+        self._bg_phase = 0
+        self._period_ms = 1000
+
+        EventMesh.subscribe("set_led_state", self.set_led_state)
+        EventMesh.subscribe("get_led_debug_state", self.get_led_debug_state)
+        try:
+            self._set_off()
+        except Exception:
+            pass
+        # 1=打印每次 set_led_state 后的最终生效模式(默认关闭,避免刷屏)
+        try:
+            if "vc_config" in globals() and vc_config:
+                self._dbg = 1 if vc_config.get_bool("LED_DEBUG", False) else 0
             else:
-                print("boot_led_demo: BLUE (gpio={})".format(
-                    self._led_gpio_b))
-                self.open_led_blue(None, None)
-
-            self._boot_led_demo_step += 1
-            self._boot_led_demo_left -= 1
-            if self._boot_led_demo_left <= 0:
-                self._boot_led_demo_timer.stop()
-        except Exception as e:
-            try:
-                self._boot_led_demo_timer.stop()
-            except Exception:
-                pass
-            print("_boot_led_demo_timer_cb_ fail: {}".format(e))
+                self._dbg = 0
+        except Exception:
+            self._dbg = 0
+        try:
+            if "vc_config" in globals() and vc_config:
+                self._key_dbg = 1 if vc_config.get_bool("KEY_LED_DEBUG", False) else 0
+            else:
+                self._key_dbg = 0
+        except Exception:
+            self._key_dbg = 0
+        # LED 电平极性:有些板子是低电平点亮(active-low),也可能仅某一路反相
+        self._inv_r = 0
+        self._inv_g = 0
+        self._inv_b = 0
+        try:
+            if "vc_config" in globals() and vc_config:
+                inv = vc_config.get_attr("LED_ACTIVE_LOW_RGB", None)
+                if isinstance(inv, (tuple, list)) and len(inv) == 3:
+                    self._inv_r = 1 if inv[0] else 0
+                    self._inv_g = 1 if inv[1] else 0
+                    self._inv_b = 1 if inv[2] else 0
+                else:
+                    all_inv = 1 if vc_config.get_bool("LED_ACTIVE_LOW", False) else 0
+                    self._inv_r = all_inv
+                    self._inv_g = all_inv
+                    self._inv_b = all_inv
+        except Exception:
+            pass
+
+    def _timer_stop(self):
+        try:
+            self._timer.stop()
+        except Exception:
+            pass
 
-    def _led_stop_flicker_timer(self):
+    def _set_rgb(self, r, g, b):
         try:
-            self.led_flicker_timer.stop()
+            rr = 1 if r else 0
+            gg = 1 if g else 0
+            bb = 1 if b else 0
+            if self._inv_r:
+                rr = 0 if rr else 1
+            if self._inv_g:
+                gg = 0 if gg else 1
+            if self._inv_b:
+                bb = 0 if bb else 1
+            self.led_red.write(rr)
+            self.led_green.write(gg)
+            self.led_blue.write(bb)
         except Exception:
             pass
 
-    def flicker_led_red(self,event,msg):
-        self._led_stop_flicker_timer()
-        self.led_flicker_flag = 1
-        self.led_flicker_timer.start(1500, 1, self.led_flicker_timer_cb)
-
-    def flicker_led_blue(self,event,msg):
-        self._led_stop_flicker_timer()
-        self.led_flicker_flag = 2
-        self.led_flicker_timer.start(1500, 1, self.led_flicker_timer_cb)
-
-    def flicker_led_green(self,event,msg):
-        self._led_stop_flicker_timer()
-        self.led_flicker_flag = 3
-        self.led_flicker_timer.start(1500, 1, self.led_flicker_timer_cb)
-
-    def flicker_led_all(self,event,msg):
-        self._led_stop_flicker_timer()
-        self.led_flicker_flag = 4
-        self.led_flicker_timer.start(1500, 1, self.led_flicker_timer_cb)
-
-    def flicker_led_blue_green(self,event,msg):
-        # 思考态:蓝/绿交替亮(各占半个周期),红灯关闭
-        self._led_stop_flicker_timer()
-        self.led_flicker_flag = 5
-        self.led_think_phase = 0
-        self.led_red.write(0)
-        self.led_blue.write(1)
-        self.led_green.write(0)
-        self.led_think_phase = 1
-        self.led_flicker_timer.start(400, 1, self.led_flicker_timer_cb)
-
-    def led_flicker_timer_cb(self, *args, **kwargs):
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.led_flicker_timer_cb_})  
-    def led_flicker_timer_cb_(self):
-        if self.led_flicker_flag == 0:
-            self._led_stop_flicker_timer()
+    def _set_off(self):
+        self._mode = "off"
+        self._timer_stop()
+        self._set_rgb(0, 0, 0)
+
+    def _set_red_on(self):
+        self._mode = "red_on"
+        self._timer_stop()
+        self._set_rgb(1, 0, 0)
+
+    def _set_green_on(self):
+        self._mode = "green_on"
+        self._timer_stop()
+        self._set_rgb(0, 1, 0)
+
+    def _set_blue_blink(self, period_ms=1000):
+        self._mode = "blue_blink"
+        self._period_ms = period_ms or 1000
+        self._blink_on = 1
+        self._timer_stop()
+        self._set_rgb(0, 0, 1)
+        self._timer.start(self._period_ms, 1, self._timer_cb)
+
+    def _set_red_blink(self, period_ms=1000):
+        self._mode = "red_blink"
+        self._period_ms = period_ms or 1000
+        self._blink_on = 1
+        self._timer_stop()
+        self._set_rgb(1, 0, 0)
+        self._timer.start(self._period_ms, 1, self._timer_cb)
+
+    def _set_bg_alt(self, period_ms=1000):
+        self._mode = "bg_alt"
+        self._period_ms = period_ms or 1000
+        self._bg_phase = 0
+        self._timer_stop()
+        self._set_rgb(0, 0, 1)
+        self._timer.start(self._period_ms, 1, self._timer_cb)
+
+    def _timer_cb(self, *args, **kwargs):
+        EventMesh.publish("publish_AI_btnInfo", {"func": self._timer_cb_})
+
+    def _timer_cb_(self):
+        if self._mode == "blue_blink":
+            self._blink_on = 0 if self._blink_on else 1
+            self._set_rgb(0, 0, 1 if self._blink_on else 0)
+            return
+        if self._mode == "red_blink":
+            self._blink_on = 0 if self._blink_on else 1
+            self._set_rgb(1 if self._blink_on else 0, 0, 0)
             return
-        if self.led_flicker_flag == 5:
-            self.led_red.write(0)
-            if self.led_think_phase == 0:
-                self.led_blue.write(1)
-                self.led_green.write(0)
-                self.led_think_phase = 1
+        if self._mode == "bg_alt":
+            if self._bg_phase == 0:
+                self._set_rgb(0, 1, 0)
+                self._bg_phase = 1
             else:
-                self.led_blue.write(0)
-                self.led_green.write(1)
-                self.led_think_phase = 0
+                self._set_rgb(0, 0, 1)
+                self._bg_phase = 0
             return
-        if self.led_flicker_on_off_flag == 0:
-            self.led_red.write(0)
-            self.led_blue.write(0)
-            self.led_green.write(0)
-            self.led_flicker_on_off_flag = 1
-        else:
-            self.led_flicker_on_off_flag = 0
-            if self.led_flicker_flag == 1:
-                self.led_blue.write(0)
-                self.led_green.write(0)
-                self.led_red.write(1)
-            elif self.led_flicker_flag == 2:
-                self.led_red.write(0)
-                self.led_green.write(0)
-                self.led_blue.write(1)
-            elif self.led_flicker_flag == 3:
-                self.led_red.write(0)
-                self.led_blue.write(0)
-                self.led_green.write(1)
-            elif self.led_flicker_flag == 4:
-                self.led_blue.write(1)
-                self.led_green.write(1)
-                self.led_red.write(1)
-
-    def open_led_red(self,event,msg):
-        #print("open_led_red")
-        self.led_flicker_flag = 0
-        self._led_stop_flicker_timer()
-        #self.led_red.write(0)
-        self.led_blue.write(0)
-        self.led_green.write(0)
-        self.led_red.write(1)
-
-    def open_led_blue(self,event,msg):
-        #print("open_led_blue")
-        self.led_flicker_flag = 0
-        self._led_stop_flicker_timer()
-        self.led_red.write(0)
-        #self.led_blue.write(0)
-        self.led_green.write(0)
-        self.led_blue.write(1)
-
-    def open_led_green(self,event,msg):
-        #print("open_led_green")
-        self.led_flicker_flag = 0
-        self._led_stop_flicker_timer()
-        self.led_red.write(0)
-        self.led_blue.write(0)
-        #self.led_green.write(0)
-        self.led_green.write(1)
-
-    def open_led_red_blue(self,event,msg):
-        #print("open_led_blue")
-        self.led_flicker_flag = 0
-        self._led_stop_flicker_timer()
-        self.led_red.write(1)
-        #self.led_blue.write(0)
-        self.led_green.write(0)
-        self.led_blue.write(1)
-
-    def open_led_red_green(self,event,msg):
-        #print("open_led_blue")
-        self.led_flicker_flag = 0
-        self._led_stop_flicker_timer()
-        self.led_red.write(1)
-        #self.led_blue.write(0)
-        self.led_green.write(1)
-        self.led_blue.write(0)
-
-    def open_led_all(self,event,msg):
-        #print("open_led_all")
-        self.led_flicker_flag = 0
-        self._led_stop_flicker_timer()
-        #self.led_red.write(0)
-        self.led_blue.write(1)
-        self.led_green.write(1)
-        self.led_red.write(1)
-
-    def close_led(self,event,msg):
-        #print("close_led")
-        self.led_flicker_flag = 0
-        self._led_stop_flicker_timer()
-        try:
-            self._boot_led_demo_timer.stop()
+
+    def set_led_state(self, event=None, msg=None):
+        # msg: dict {ai_state, charging, battery, signal}
+        try:
+            if isinstance(msg, dict):
+                if "ai_state" in msg:
+                    self._st_ai = msg.get("ai_state") or "idle"
+                if "charging" in msg:
+                    self._st_charging = msg.get("charging") or "none"
+                if "battery" in msg:
+                    self._st_battery = msg.get("battery") or "normal"
+                if "signal" in msg:
+                    self._st_signal = msg.get("signal") or "normal"
+        except Exception:
+            pass
+        self._apply_by_table(msg)
+
+    def _apply_by_table(self, _msg=None):
+        prev_mode = self._mode
+        # P1~P3:AI 阶段(播放 > 思考 > 聆听)
+        try:
+            if self._st_ai == "playing":
+                self._set_green_on()
+                return self._dbg_print(prev_mode, _msg)
+            if self._st_ai == "thinking":
+                self._set_bg_alt(1000)
+                return self._dbg_print(prev_mode, _msg)
+            if self._st_ai == "listening":
+                self._set_blue_blink(1000)
+                return self._dbg_print(prev_mode, _msg)
+        except Exception:
+            pass
+        # 基础态:充电/电量/信号
+        try:
+            if self._st_charging == "full":
+                self._set_green_on()
+                return self._dbg_print(prev_mode, _msg)
+            if self._st_charging == "charging":
+                self._set_red_on()
+                return self._dbg_print(prev_mode, _msg)
+            if self._st_battery in ("empty", "low"):
+                self._set_red_blink(1000)
+                return self._dbg_print(prev_mode, _msg)
+            if self._st_signal == "weak":
+                self._set_bg_alt(2000)
+                return self._dbg_print(prev_mode, _msg)
+        except Exception:
+            pass
+        self._set_off()
+        return self._dbg_print(prev_mode, _msg)
+
+    def _dbg_print(self, prev_mode, _msg):
+        if getattr(self, "_dbg", 0) != 1:
+            return
+        try:
+            # 仅在模式变化或本次携带 ai_state 时打印,减少刷屏
+            if prev_mode != self._mode:
+                print("[LED] msg={} st(ai={},chg={},bat={},sig={}) mode:{}->{}".format(
+                    _msg,
+                    self._st_ai, self._st_charging, self._st_battery, self._st_signal,
+                    prev_mode, self._mode))
+            else:
+                try:
+                    if isinstance(_msg, dict) and ("ai_state" in _msg or "charging" in _msg):
+                        print("[LED] msg={} st(ai={},chg={},bat={},sig={}) mode={}".format(
+                            _msg,
+                            self._st_ai, self._st_charging, self._st_battery, self._st_signal,
+                            self._mode))
+                except Exception:
+                    pass
+        except Exception:
+            pass
+
+    def get_led_debug_state(self, event=None, msg=None):
+        # 供按键/状态机打印当前 LED 聚合状态与最终模式
+        try:
+            return {
+                "ai": self._st_ai,
+                "charging": self._st_charging,
+                "battery": self._st_battery,
+                "signal": self._st_signal,
+                "mode": self._mode,
+                "period_ms": self._period_ms,
+            }
+        except Exception:
+            return {"mode": getattr(self, "_mode", "?")}
+
+
+class AI_hw_status(Abstract):
+    # 精简硬件状态采集:仅维护 LED 状态机所需的 charging/battery/signal
+    def __init__(self):
+        # 无条件首行:确认是否进入初始化(避免被异常/注册顺序误判)
+        try:
+            print("[HW] __init__ enter")
+        except Exception:
+            pass
+        # 参考 mgr.py 的 BATTERY_OCV_TABLE(nix_coy_mnzo2),按电压插值换算 SoC
+        # 仅保留 LED 状态机所需:>=20 正常;<20 低电;<5 极低/空电
+        self._ocv_map = {
+            4290: 100, 4237: 95, 4179: 90, 4123: 85, 4070: 80, 4020: 75, 3963: 70, 3919: 65, 3882: 60, 3847: 55,
+            3818: 50, 3794: 45, 3772: 40, 3752: 35, 3733: 30, 3716: 25, 3699: 20, 3677: 15, 3652: 10, 3629: 5, 3400: 0,
+        }
+        self._ocv_volts = None
+        try:
+            self._ocv_volts = sorted(self._ocv_map.keys(), reverse=True)
+        except Exception:
+            self._ocv_volts = None
+        # cached state (avoid repeat publish)
+        self._chg = None
+        self._bat = None
+        self._sig = None
+        self._usb = None
+        self._timer = osTimer()
+        self._period_ms = 10000
+        self._weak_csq = 10
+        self._dbg = 0
+        try:
+            if "vc_config" in globals() and vc_config:
+                self._period_ms = vc_config.get_int("HW_STATUS_PERIOD_MS", 10000) or 10000
+                self._weak_csq = vc_config.get_int("SIGNAL_WEAK_CSQ", 10) or 10
+                self._dbg = 1 if vc_config.get_bool("HW_STATUS_DEBUG", False) else 0
+                # 允许覆盖 OCV 表(用电压门限的方式降级兼容)
+                try:
+                    if vc_config.get_bool("USE_SIMPLE_VBATT_THRESH", False):
+                        cf = vc_config.get_int("VBATT_CHARGE_FULL_MV", 4300)
+                        v20 = vc_config.get_int("VBATT_LOW_MV", 3699)
+                        v5 = vc_config.get_int("VBATT_EMPTY_MV", 3629)
+                        self._vbatt_simple = (int(cf), int(v20), int(v5))
+                    else:
+                        self._vbatt_simple = None
+                except Exception:
+                    self._vbatt_simple = None
+        except Exception:
+            pass
+        # 若开启了 LED/按键调试,也一并打开硬件监控打印,便于关联分析
+        try:
+            if "vc_config" in globals() and vc_config:
+                if vc_config.get_bool("LED_DEBUG", False) or vc_config.get_bool("KEY_LED_DEBUG", False):
+                    self._dbg = 1
+        except Exception:
+            pass
+
+        # 注意:AI_dev 也会注册 USB callback;USB 模块通常只支持一个 callback,后注册会覆盖先注册。
+        # 为避免“刚开始有效,后面失效”,这里不直接 setCallback,改为订阅 AI_dev 转发的 USB 状态事件,
+        # 并在 10 秒轮询中再读一次 GET_USB_STATE 作兜底。
+        try:
+            EventMesh.subscribe("hw_usb_state", self._on_usb_state)
+        except Exception:
+            pass
+
+        # 初始化:先立即刷新一次,再开启周期轮询(避免 one-shot/覆盖差异导致只跑一次)
+        try:
+            self._update()
+        except Exception:
+            pass
+        try:
+            self._timer.start(self._period_ms, 1, self._tick_cb)
+        except Exception:
+            pass
+        # 初始化打印(一次)
+        try:
+            print("[HW] init ok period_ms={} weak_csq={} usb_init={} algo={}".format(
+                self._period_ms,
+                self._weak_csq,
+                self._usb,
+                "simple" if getattr(self, "_vbatt_simple", None) else "ocv"))
+            if self._dbg == 1:
+                print("[HW] init detail vbatt_simple={}".format(getattr(self, "_vbatt_simple", None)))
+        except Exception:
+            pass
+
+    def _on_usb_state(self, event=None, msg=None):
+        try:
+            state = msg
+            self._usb = 1 if state == 1 else 0
         except Exception:
             pass
-        self.led_red.write(0)
-        self.led_blue.write(0)
-        self.led_green.write(0)
+        try:
+            if self._dbg == 1:
+                print("[HW] usb_evt state={} usb={}".format(state, self._usb))
+        except Exception:
+            pass
+        try:
+            self._update()
+        except Exception:
+            pass
+
+    def _tick_cb(self, *args, **kwargs):
+        # 定时器回调直接刷新(不依赖 AI_dev 的事件线程)
+        try:
+            self._tick()
+        except Exception:
+            pass
+
+    def _tick(self, *args, **kwargs):
+        self._update()
+
+    def _update(self):
+        # 每次刷新都“同步推送一次”当前硬件基础态到 LED(不依赖变化检测)
+        # 目的:保证 10 秒轮询和 USB callback 都能及时刷新充电/电量/信号的基础态显示
+        # charging/battery
+        try:
+            v = Power.getVbatt()
+        except Exception:
+            v = None
+        soc = None
+        csq = None
+        rssi = None
+        chg = "none"
+        bat = "normal"
+        sig = "normal"
+        try:
+            usb_status = self._usb
+            if usb_status is None:
+                try:
+                    usb_status = EventMesh.publish("GET_USB_STATE")
+                    if usb_status is None:
+                        usb_status = 0
+                except Exception:
+                    usb_status = 0
+            # charging
+            if usb_status == 1:
+                # 充满:默认用 4290mV 对齐 mgr OCV 100%,也允许用 simple 门限覆盖
+                full_mv = 4290
+                try:
+                    if getattr(self, "_vbatt_simple", None):
+                        full_mv = int(self._vbatt_simple[0])
+                except Exception:
+                    full_mv = 4290
+                if v is not None and v >= full_mv:
+                    chg = "full"
+                else:
+                    chg = "charging"
+            # battery level for LED table
+            if usb_status != 1 and v is not None:
+                soc = self._soc_from_vbatt(v)
+                if soc is not None:
+                    if soc < 5:
+                        bat = "empty"
+                    elif soc < 20:
+                        bat = "low"
+            self._chg = chg
+            self._bat = bat
+        except Exception:
+            pass
+
+        # signal
+        try:
+            csq = net.csqQueryPoll()
+            # csqQueryPoll 返回 (rssi, ber) 或 int,按保守取 rssi
+            try:
+                if isinstance(csq, (tuple, list)) and len(csq) > 0:
+                    rssi = csq[0]
+                else:
+                    rssi = csq
+            except Exception:
+                rssi = csq
+            sig = "weak" if (rssi is not None and int(rssi) >= 0 and int(rssi) < int(self._weak_csq)) else "normal"
+            self._sig = sig
+        except Exception:
+            pass
+
+        # 统一推送一次当前基础态(一次调用带齐字段,减少来回切换)
+        try:
+            EventMesh.publish("set_led_state", {"charging": chg, "battery": bat, "signal": sig})
+        except Exception:
+            pass
+
+        # 轮询调试打印(每次 10s tick 一次)
+        try:
+            if self._dbg == 1:
+                print("[HW] usb={} vbatt_mv={} soc={} chg={} bat={} csq={} rssi={} sig={} period_ms={}".format(
+                    usb_status, v, soc, self._chg, self._bat, csq, rssi, self._sig, self._period_ms))
+        except Exception:
+            pass
+
+    def _soc_from_vbatt(self, volt_mv):
+        # 返回 0~100;异常返回 None
+        try:
+            v = int(volt_mv)
+        except Exception:
+            return None
+        # 若启用 simple 门限,直接按门限输出近似 soc(仅用于 LED 分级)
+        try:
+            if getattr(self, "_vbatt_simple", None):
+                _full, _v20, _v5 = self._vbatt_simple
+                if v >= _full:
+                    return 100
+                if v <= _v5:
+                    return 0
+                if v <= _v20:
+                    return 10
+                return 60
+        except Exception:
+            pass
+        try:
+            volts = self._ocv_volts
+            if not volts:
+                return None
+            pre_volt = 0
+            volt_not_under = 0
+            soc1 = 0
+            soc2 = 0
+            for vv in volts:
+                if v > vv:
+                    volt_not_under = 1
+                    soc1 = self._ocv_map.get(vv, 0)
+                    soc2 = self._ocv_map.get(pre_volt, 0)
+                    break
+                else:
+                    pre_volt = vv
+            if pre_volt == 0:
+                return soc1
+            if volt_not_under == 0:
+                return 0
+            # 线性插值(对齐 mgr.__get_soc_from_dict)
+            return int(soc2 - (soc2 - soc1) * (pre_volt - v) // (pre_volt - vv))
+        except Exception:
+            return None
 def set_ipv4_datacall():
        # 获取第一路的APN,ipType 等信息
        pdpCtx = dataCall.getPDPContext(1)
@@ -357,7 +610,13 @@ class AI_UART():
         self.ping_json_str_tmp =""
         self.read_uart_data = ""
         self.bt_versions=""
-        if dev_type == "7PIN_1_5":
+        try:
+            uart_ok = False
+            if "vc_config" in globals() and vc_config:
+                uart_ok = vc_config.uart_supported()
+        except Exception:
+            uart_ok = False
+        if uart_ok:
             self.uart_send_queue = Queue(100)
             self.uart_send_queue_thread_id = _thread.start_new_thread(self.uart_send_queue_thread, ())
 
@@ -840,7 +1099,10 @@ class AI_UART():
 
         print("bt_send_end")
     def send_data(self,str_data,need_resend = None,ACK_time =None):
-        if dev_type != "7PIN_1_5": #不是1.5代不能发串口数据
+        try:
+            if not ("vc_config" in globals() and vc_config and vc_config.uart_supported()):
+                return
+        except Exception:
             return
         if self.bt_ota_flag == 1:
             print("ota 中不需要上传")
@@ -1086,19 +1348,43 @@ class AI_dev(Abstract):
         #     set_ipv4_datacall()
         self.is_wdt = 0 #是否开启看门狗
         #AT+QDAI=1,0,0,1,0,0,1,1PCM音频输出设置为主模式、短同步、16 kHz采样率和256 kHz时钟频率,采样位深为16bit,使用的时间间隙数量为1,并且使用第一个时间间隙。
-        if dev_type == "7PIN_1_5" : 
-            #蓝牙电源
-            self.PIN_BT_ON =Pin(Pin.GPIO31, Pin.OUT, Pin.PULL_DISABLE, 0)
-            #马达
-            self.PIN_MOT=Pin(Pin.GPIO36, Pin.OUT, Pin.PULL_DISABLE, 1)
-            
-            # #马达
-            # self.PIN_MOT.write(1)
-            
-            utime.sleep_ms(200)
-            self.PIN_MOT.write(0)
-            self.PIN_BT_ON.write(1)
-            audio.set_qdai_cfg(1,0,0,2,0,1,1,1)#用iis做音频输入输出
+        try:
+            bt_pm_en = False
+            pin_bt_on = None
+            pin_mot = None
+            qdai_cfg = None
+            if "vc_config" in globals() and vc_config:
+                bt_pm_en = bool(vc_config.get_attr("BT_POWER_MOTOR_ENABLED", False))
+                pin_bt_on = vc_config.get_attr("PIN_BT_ON_GPIO", None)
+                pin_mot = vc_config.get_attr("PIN_MOT_GPIO", None)
+                qdai_cfg = vc_config.get_attr("AUDIO_QDAI_CFG", None)
+        except Exception:
+            bt_pm_en = False
+            pin_bt_on = None
+            pin_mot = None
+            qdai_cfg = None
+
+        if bt_pm_en:
+            try:
+                if pin_bt_on:
+                    self.PIN_BT_ON = Pin(getattr(Pin, pin_bt_on), Pin.OUT, Pin.PULL_DISABLE, 0)
+                if pin_mot:
+                    self.PIN_MOT = Pin(getattr(Pin, pin_mot), Pin.OUT, Pin.PULL_DISABLE, 1)
+            except Exception:
+                pass
+            try:
+                utime.sleep_ms(200)
+                if hasattr(self, "PIN_MOT"):
+                    self.PIN_MOT.write(0)
+                if hasattr(self, "PIN_BT_ON"):
+                    self.PIN_BT_ON.write(1)
+            except Exception:
+                pass
+            try:
+                if isinstance(qdai_cfg, (tuple, list)) and len(qdai_cfg) == 8:
+                    audio.set_qdai_cfg(*qdai_cfg)  # 用iis做音频输入输出
+            except Exception:
+                pass
         self.VBATT_tab = {"charge_full":4300,"100" :4250 ,  "90":4179 , "80":4070, "60": 3883, "40":3770, "20":3699,  "10":3652,"5":3600,}
         self.KeyAI_status = 0
         self.KeyAI_timer_count = 0
@@ -1129,32 +1415,39 @@ class AI_dev(Abstract):
         self.play_imei_timer_count=0
         self.KeySOS_timer_count = 0
         self.KeySOS_timer_flag = 0
-        if dev_type == "G10" :
-            self.extint_AI = ExtInt(ExtInt.GPIO19,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb)
-            self.pwk_key = ExtInt(ExtInt.GPIO26, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb)
-        elif dev_type == 'jswm':
-            self.extint_AI = ExtInt(ExtInt.GPIO26,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb)
-            self.pwk_key = ExtInt(ExtInt.GPIO19, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb)
-        elif dev_type == "7PIN_BK_EU":
-            self.pwk_key = ExtInt(ExtInt.GPIO41, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb)
-            self.extint_AI = ExtInt(ExtInt.GPIO5,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb)
-        #蓝牙唤醒4G中断
-        elif dev_type == "7PIN_1_5":
-            self.pwk_key = ExtInt(ExtInt.GPIO41, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb)
-            self.extint_AI = ExtInt(ExtInt.GPIO43,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb)
-
-            self.extint_wakeup_cta1 = ExtInt(ExtInt.GPIO22,ExtInt.IRQ_RISING, ExtInt.PULL_DISABLE, self.wakeup_extint_cb)
-            #4G唤醒蓝牙中断
-            self.PIN_wakeup_bt =Pin(Pin.GPIO21, Pin.OUT, Pin.PULL_DISABLE, 0)
-            
-            
-            
-            self.extint_wakeup_cta1_timer = osTimer()
-            self.extint_wakeup_cta1.enable()
-        else:
-            # self.pwk_key = ExtInt(ExtInt.GPIO41, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb)
-            self.pwk_key = ExtInt(ExtInt.GPIO26, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb)
-            self.extint_AI = ExtInt(ExtInt.GPIO22,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb)
+        try:
+            ai_gpio = "GPIO22"
+            pwk_gpio = "GPIO26"
+            bt_wakeup_en = False
+            wakeup_cta1_gpio = None
+            wakeup_bt_gpio = None
+            if "vc_config" in globals() and vc_config:
+                ai_gpio = vc_config.get_attr("EXTINT_AI_GPIO", "GPIO22") or "GPIO22"
+                pwk_gpio = vc_config.get_attr("PWK_KEY_GPIO", "GPIO26") or "GPIO26"
+                bt_wakeup_en = bool(vc_config.get_attr("BT_WAKEUP_4G_ENABLED", False))
+                wakeup_cta1_gpio = vc_config.get_attr("EXTINT_WAKEUP_CTA1_GPIO", None)
+                wakeup_bt_gpio = vc_config.get_attr("PIN_WAKEUP_BT_GPIO", None)
+        except Exception:
+            ai_gpio = "GPIO22"
+            pwk_gpio = "GPIO26"
+            bt_wakeup_en = False
+            wakeup_cta1_gpio = None
+            wakeup_bt_gpio = None
+
+        self.extint_AI = ExtInt(getattr(ExtInt, ai_gpio), ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb)
+        self.pwk_key = ExtInt(getattr(ExtInt, pwk_gpio), ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb)
+
+        if bt_wakeup_en:
+            try:
+                if wakeup_cta1_gpio:
+                    self.extint_wakeup_cta1 = ExtInt(getattr(ExtInt, wakeup_cta1_gpio), ExtInt.IRQ_RISING, ExtInt.PULL_DISABLE, self.wakeup_extint_cb)
+                if wakeup_bt_gpio:
+                    self.PIN_wakeup_bt = Pin(getattr(Pin, wakeup_bt_gpio), Pin.OUT, Pin.PULL_DISABLE, 0)
+                self.extint_wakeup_cta1_timer = osTimer()
+                if hasattr(self, "extint_wakeup_cta1"):
+                    self.extint_wakeup_cta1.enable()
+            except Exception:
+                pass
 
         self.extint_AI.enable()
         self.pwk_key_status = 0
@@ -1213,8 +1506,11 @@ class AI_dev(Abstract):
         #EventMesh.publish("audio_montage_play",["xianyikaiji.mp3"])
         #EventMesh.publish("publish_AI_btnInfo",{"func":self.ntptime_cb})
         self.check_rest_timer_count = 0
-        if dev_type == "7PIN_1_5": #不是1.5代不能发串口数据
-            self.ai_uart = AI_UART()
+        try:
+            if "vc_config" in globals() and vc_config and vc_config.uart_supported():
+                self.ai_uart = AI_UART()
+        except Exception:
+            pass
 
         self.Keycall1_press_count = 0
         self.ble_switch_flag_time = osTimer()
@@ -1242,6 +1538,11 @@ class AI_dev(Abstract):
         #ntptime.settime(8)
         print("timer:{}!!!!!!!!\r\n".format(utime.localtime()))
     def usb_event_cb(self, state):
+        # 转发给精简硬件监控(AI_hw_status),避免 USB callback 被覆盖导致“后面失效”
+        try:
+            EventMesh.publish("hw_usb_state", state)
+        except Exception:
+            pass
         EventMesh.publish("publish_AI_btnInfo",{"func":self.usb_event,"data":state})
 
     def usb_event(self, state):    
@@ -1261,7 +1562,11 @@ class AI_dev(Abstract):
                 self.aud.stop()
                 #EventMesh.publish("flicker_led_red")#充电闪灯
                 #self.aud.play(1,1,'U:/static/R_CHARGE_IN.mp3')
-                EventMesh.publish("open_led_red")#充电红灯常亮
+                try:
+                    if not ("vc_config" in globals() and vc_config and vc_config.get_bool("USE_MIN_HW_STATUS", True)):
+                        EventMesh.publish("set_led_state", {"charging": "charging"})
+                except Exception:
+                    pass
                 EventMesh.publish("audio_montage_play",["R_CHARGE_IN.mp3"])
             self.Low_power_warning_flag  = 0
             pass
@@ -1275,7 +1580,11 @@ class AI_dev(Abstract):
                 voice_record_satrt_flag = 0
             if VC_satrt_flag == 0 and voice_record_satrt_flag == 0:
                 self.aud.stop()
-                EventMesh.publish("close_led")
+                try:
+                    if not ("vc_config" in globals() and vc_config and vc_config.get_bool("USE_MIN_HW_STATUS", True)):
+                        EventMesh.publish("set_led_state", {"charging": "none"})
+                except Exception:
+                    pass
                 EventMesh.publish("audio_montage_play",["R_CHARGE_OUT.mp3"])
                 #self.aud.play(1,1,'U:/static/R_CHARGE_OUT.mp3')
     def get_usb_state(self,event,msg):
@@ -1335,13 +1644,19 @@ class AI_dev(Abstract):
         #print("publish_AI_btnInfo 2")
     
     def sys_sleep_cb(self,event=None,msg=None):#休眠前回调
-        if dev_type != "7PIN_1_5": #不是1.5代不能发串口数据
+        try:
+            if not ("vc_config" in globals() and vc_config and vc_config.get_bool("BT_WAKEUP_4G_ENABLED", False)):
+                return
+        except Exception:
             return
         print("sys_sleep_cb!!!!!!!!!!!!!!!")
         EventMesh.publish("sleep_BT")#休眠蓝牙
         self.PIN_wakeup_bt.write(0)
     def sys_up_cb(self,event=None,msg=None):#唤醒前回调
-        if dev_type != "7PIN_1_5": #不是1.5代不能发串口数据
+        try:
+            if not ("vc_config" in globals() and vc_config and vc_config.get_bool("BT_WAKEUP_4G_ENABLED", False)):
+                return
+        except Exception:
             return
         print("sys_up_cb!!!!!!!!!!!!!!!")
         self.wakeup_BT()
@@ -1352,7 +1667,10 @@ class AI_dev(Abstract):
         utime.sleep_ms(100)
         self.PIN_BT_ON.write(1)
     def wakeup_BT(self,event=None,msg=None):#4G唤醒蓝牙
-        if dev_type != "7PIN_1_5": #不是1.5代不能发串口数据
+        try:
+            if not ("vc_config" in globals() and vc_config and vc_config.get_bool("BT_WAKEUP_4G_ENABLED", False)):
+                return
+        except Exception:
             return
         print("wakeup_BT!!!!!!!!!!!!!!!")
         wakeup_cta1_io = self.extint_wakeup_cta1.read_level()
@@ -1377,7 +1695,10 @@ class AI_dev(Abstract):
 
         
     def sleep_BT(self,event=None,msg=None):#使蓝牙休眠
-        if dev_type != "7PIN_1_5": #不是1.5代不能发串口数据
+        try:
+            if not ("vc_config" in globals() and vc_config and vc_config.get_bool("BT_WAKEUP_4G_ENABLED", False)):
+                return
+        except Exception:
             return
         print("sleep_BT!!!!!")
         print("sleep_BT!!!!!")
@@ -1395,7 +1716,10 @@ class AI_dev(Abstract):
    
    
     def wakeup_extint_cb(self,args):#蓝牙唤醒4g
-        if dev_type != "7PIN_1_5": #不是1.5代不能发串口数据
+        try:
+            if not ("vc_config" in globals() and vc_config and vc_config.get_bool("BT_WAKEUP_4G_ENABLED", False)):
+                return
+        except Exception:
             return
         print("wakeup_extint_cb:!!!!!!!!!")
         EventMesh.publish(constants.EVENT.SYSTEM_UP)#唤醒休眠
@@ -1517,7 +1841,7 @@ class AI_dev(Abstract):
                         #EventMesh.publish("AI_key_long_press")
                         # EventMesh.publish("audio_montage_play",["zhengzaiguanji.mp3"])
                         self.aud.play(1,0,'U:/static/zhengzaiguanji.mp3')#关机音频
-                        EventMesh.publish("open_led_red")
+                        EventMesh.publish("set_led_state", {"battery": "empty"})
                         utime.sleep_ms(2000)
                         self.aud.stopPlayStream()
                         self.aud.stopAll()
@@ -1527,9 +1851,10 @@ class AI_dev(Abstract):
                         #EventMesh.publish("publish_AI_btnInfo",{"func":self.pwk_key_Long_Press})  
             if self.pwk_key_status == 1:#松开
                 #print("pwk_key_timer_cb:{}".format(self.pwk_key_timer_count))
-                key_count = 5
-                if dev_type == "7PIN_BK" or dev_type == "7PIN_BK_EU"or dev_type == "7PIN_BK_coze":
-                    key_count = 3
+                try:
+                    key_count = vc_config.get_int("KEY_RELEASE_DEBOUNCE_COUNT", 5)
+                except Exception:
+                    key_count = 5
                 if self.pwk_key_timer_count >= key_count: #防抖200ms
                     #EventMesh.publish("AI_key_release")
                     EventMesh.publish("publish_AI_btnInfo",{"func":self.pwk_key_release})
@@ -1614,10 +1939,14 @@ class AI_dev(Abstract):
                     pass
 
             elif self.KeyAI_timer_count >= 10*8:#关机
-                if dev_type == 'jswm' or dev_type == 'jswm_BOX':
+                try:
+                    allow_power_off = vc_config.get_bool("AI_LONG_PRESS_POWER_OFF_ENABLED", False)
+                except Exception:
+                    allow_power_off = False
+                if allow_power_off:
                     EventMesh.publish("audio_montage_play",["zhengzaiguanji.mp3"])
                     #self.aud.play(1,0,'U:/static/zhengzaiguanji.mp3')#关机音频
-                    EventMesh.publish("open_led_red")
+                    EventMesh.publish("set_led_state", {"battery": "empty"})
                     utime.sleep_ms(2000)
                     self.aud.stopPlayStream()
                     print("stopAll:8")
@@ -1625,9 +1954,10 @@ class AI_dev(Abstract):
                     Power.powerDown()
             if self.KeyAI_status == 1:#松开
                 #print("KeyAI_timer_cb:{}".format(self.KeyAI_timer_count))
-                key_count = 5
-                if dev_type == "7PIN_BK"or dev_type == "7PIN_BK_EU"or dev_type == "7PIN_BK_coze":
-                    key_count = 3
+                try:
+                    key_count = vc_config.get_int("KEY_RELEASE_DEBOUNCE_COUNT", 5)
+                except Exception:
+                    key_count = 5
                 if self.KeyAI_timer_count >= key_count: #防抖200ms
                     if self.KeySOS_timer_flag == 1:
                         self.KeySOS_timer_flag = 0
@@ -1713,7 +2043,7 @@ class AI_dev(Abstract):
         # return
         EventMesh.publish("audio_montage_play",["zhengzaiguanji.mp3"])
         #self.aud.play(1,0,'U:/static/zhengzaiguanji.mp3')#关机音频
-        EventMesh.publish("open_led_red")
+        EventMesh.publish("set_led_state", {"battery": "empty"})
         utime.sleep_ms(3000)
         self.aud.stopPlayStream()
         self.aud.stopAll()
@@ -1747,23 +2077,39 @@ class AI_dev(Abstract):
             voice_record_satrt_flag = 0
         Vbatt = Power.getVbatt()
         if self.usb_status == 1 and VC_satrt_flag == 0 and voice_record_satrt_flag == 0:
-            EventMesh.publish("open_led_red")#充电红灯常亮
+            try:
+                if not ("vc_config" in globals() and vc_config and vc_config.get_bool("USE_MIN_HW_STATUS", True)):
+                    EventMesh.publish("set_led_state", {"charging": "charging"})#充电红灯常亮
+            except Exception:
+                pass
         if  self.usb_status == 1 and Vbatt>=self.VBATT_tab["charge_full"]and VC_satrt_flag == 0 and voice_record_satrt_flag == 0:#充电充满
-            EventMesh.publish("open_led_green")
+            try:
+                if not ("vc_config" in globals() and vc_config and vc_config.get_bool("USE_MIN_HW_STATUS", True)):
+                    EventMesh.publish("set_led_state", {"charging": "full"})
+            except Exception:
+                pass
             if self.usb_charge_flag == 0 :
                 EventMesh.publish("audio_montage_play",["R_CHARGE_FULL.mp3"])
                 #self.aud.play(1,0,'U:/static/R_CHARGE_FULL.mp3')#充电已满
                 self.usb_charge_flag = 1
         if  self.usb_status == 0 and Vbatt<self.VBATT_tab["20"]and VC_satrt_flag == 0 and self.Low_power_warning_flag ==0 and voice_record_satrt_flag == 0:#低电报警
             self.Low_power_warning_flag  = 1
-            EventMesh.publish("flicker_led_red")
+            try:
+                if not ("vc_config" in globals() and vc_config and vc_config.get_bool("USE_MIN_HW_STATUS", True)):
+                    EventMesh.publish("set_led_state", {"battery": "low"})
+            except Exception:
+                pass
             #self.aud.play(1,0,'Low_power_warning.mp3')
             # self.Low_power_warning_timer+=1
             # if self.Low_power_warning_timer >= 2:
             #     self.Low_power_warning_timer = 0
             EventMesh.publish("audio_montage_play",["Low_power_warning.mp3"])
         if  self.usb_status == 0 and Vbatt>=self.VBATT_tab["20"]and VC_satrt_flag == 0:#没有充电,电量又正常,关灯
-            EventMesh.publish("close_led")
+            try:
+                if not ("vc_config" in globals() and vc_config and vc_config.get_bool("USE_MIN_HW_STATUS", True)):
+                    EventMesh.publish("set_led_state", {"charging": "none", "battery": "normal"})
+            except Exception:
+                pass
 
         if  self.usb_status == 0 and Vbatt<self.VBATT_tab["5"]:    
             EventMesh.publish("audio_montage_play",["didianguanji.mp3"])
@@ -1995,11 +2341,7 @@ class device_res_author(Abstract):
         response = None
         try:
             print("dev_NTP1")
-            url =None
-            if dev_type == "7PIN_BK_EU":#英文小瑞
-                url = "http://dmp-global.raisound.com/bz-api/dev/time"
-            else:
-                url = constants.DMP_BASE + "/dev/time"
+            url = constants.DMP_BASE + "/dev/time"
             print("dev_NTP:{}".format(url))
             response = request.get(url,timeout=5)
             data = response.json()
@@ -2126,11 +2468,7 @@ class device_res_author(Abstract):
                 }
                 print(ujson.dumps(data))
                 headers_T ={"Content-Type":"application/json"}
-                url =None
-                if dev_type == "7PIN_BK_EU":#英文小瑞
-                    url = "http://dmp-global.raisound.com/bz-api/dev/auth/active"
-                else:
-                    url = constants.DMP_BASE + "/dev/auth/active"
+                url = constants.DMP_BASE + "/dev/auth/active"
                 print("dev_active:{}".format(url))
                 data =ujson.dumps(data)
                 response = None
@@ -2240,10 +2578,7 @@ class device_res_author(Abstract):
                 }
                 print(ujson.dumps(sign_in_data))
                 sign_url =None
-                if dev_type == "7PIN_BK_EU":#英文小瑞
-                    sign_url = "http://dmp-global.raisound.com/bz-api/dev/auth/sign_in" #登入地址
-                else:
-                    sign_url = constants.DMP_BASE + "/dev/auth/sign_in"
+                sign_url = constants.DMP_BASE + "/dev/auth/sign_in"
                 #获取验证码
                 #url = "http://dmp.qipai.com.cn:30461/dev/device/bind-code/860132066060377"
                 # token = EventMesh.publish("get_dev_token")
@@ -2313,10 +2648,7 @@ class device_res_author(Abstract):
                     headers_T = {"qp-dt":"{}".format(token)}
                 #http://dmp.raisound.com/bz-api/dev/iccid?deviceId=866610001099679&iccid=89860002192307889057
                 url =None
-                if dev_type == "7PIN_BK_EU":#英文小瑞
-                    url = "http://dmp-global.raisound.com/bz-api/dev/iccid?deviceId={}&iccid={}".format(modem.getDevImei(),iccid)
-                else:
-                    url = (constants.DMP_BASE + "/dev/iccid?deviceId={}&iccid={}").format(modem.getDevImei(),iccid)
+                url = (constants.DMP_BASE + "/dev/iccid?deviceId={}&iccid={}").format(modem.getDevImei(),iccid)
                 print("{} H:{}".format(url,headers_T))
                 response = request.post(url,headers = headers_T)
                 if response.status_code == 200:
@@ -2351,10 +2683,7 @@ class device_res_author(Abstract):
                 #self.dev_sign_in()
                 EventMesh.publish("dev_sign_in")
             dev_tokenip =None
-            if dev_type == "7PIN_BK_EU":#英文小瑞
-                dev_tokenip = "http://dmp-global.raisound.com/bz-api/dev/auth/token" #设备新令牌更新地址
-            else:
-                dev_tokenip = constants.DMP_BASE + "/dev/auth/token"
+            dev_tokenip = constants.DMP_BASE + "/dev/auth/token"
                      
             token = self.dev_token
             if token == None:
@@ -2424,11 +2753,6 @@ class OTA():
             print("bt_versions:{}".format(bt_versions))
             #url = "http://iot.api.thisiot.com/ota/task?deviceId=860132060348836&sourceVersion=2024-12-20-15:35-1"
             url =None
-            # if dev_type == "7PIN_BK_EU":#英文小瑞
-            #     url = "http://dmp-global.raisound.com/bz-api/ota/task?deviceId={}&sourceVersion={}".format(modem.getDevImei(),sourceVersion)
-            # if dev_type == "7PIN" or dev_type == "7PIN_coze":#柒牌
-            #     url = "http://ota.qipai.com/bz-cmp-api/api/task?deviceId={}&sourceVersion={}".format(modem.getDevImei(),sourceVersion)
-            # else:
             url = "https://dmp-api.qipai.com/qp-dmp-api/ota/task?deviceId={}&sourceVersion={}".format(modem.getDevImei(),sourceVersion)
             print(url)
             response = request.get(url,timeout=5)
@@ -2493,11 +2817,6 @@ class OTA():
             print("sourceVersion2:{}".format(sourceVersion))
             #url = "http://iot.api.thisiot.com/ota/task?deviceId=860132060348836&sourceVersion=2024-12-20-15:35-1"
             url =None
-            # if dev_type == "7PIN_BK_EU":#英文小瑞
-            #     url = "http://dmp-global.raisound.com/bz-api/ota/task?deviceId={}&sourceVersion={}".format(modem.getDevImei(),sourceVersion)
-            # if dev_type == "7PIN" or dev_type == "7PIN_coze":#柒牌
-            #     url = "http://ota.qipai.com/bz-cmp-api/api/task?deviceId={}&sourceVersion={}".format(modem.getDevImei(),sourceVersion)
-            # else:
             url = "https://dmp-api.qipai.com/qp-dmp-api/ota/task?deviceId={}&sourceVersion={}".format(modem.getDevImei(),sourceVersion)
             print(url)
             response = request.get(url,timeout=5)
@@ -2589,12 +2908,6 @@ class OTA():
             print("currentVersion1:{}".format(currentVersion))
             currentVersion = currentVersion.replace(" ", "0")
             print("currentVersion2:{}".format(currentVersion))
-            url =None
-            if dev_type == "7PIN_BK_EU":#英文小瑞
-                url = "http://dmp-global.raisound.com/bz-api/ota/result?deviceId={}&currentVersion={}".format(modem.getDevImei(),currentVersion)
-            # if dev_type == "7PIN" or dev_type == "7PIN_1_5" or dev_type == "7PIN_coze":#柒牌
-            #     url = "http://ota.qipai.com/bz-cmp-api/api/result?deviceId={}&currentVersion={}".format(modem.getDevImei(),currentVersion)
-            # else:
             url = (constants.DMP_BASE + "/ota/result?deviceId={}&currentVersion={}").format(modem.getDevImei(),currentVersion)
             print(url)
             response = request.post(url,timeout=5)
@@ -2624,10 +2937,7 @@ class OTA():
                     headers_T = {"bz-dt":"{}".format(token)}
                 #http://dmp.raisound.com/bz-api/dev/iccid?deviceId=866610001099679&iccid=89860002192307889057
                 url =None
-                if dev_type == "7PIN_BK_EU":#英文小瑞
-                    url = "http://dmp-global.raisound.com/bz-api/dev/iccid?deviceId={}&iccid={}".format(modem.getDevImei(),iccid)
-                else:
-                    url = (constants.DMP_BASE + "/dev/iccid?deviceId={}&iccid={}").format(modem.getDevImei(),iccid)
+                url = (constants.DMP_BASE + "/dev/iccid?deviceId={}&iccid={}").format(modem.getDevImei(),iccid)
                 print("{} H:{}".format(url,headers_T))
                 response = request.post(url,headers = headers_T,timeout=5)
                 if response.status_code == 200:
@@ -2710,7 +3020,6 @@ class VCStateMachine:
         self.turn = VCTurnState.Idle
         self.last_llm_ms = 0
         self.last_tts_pending_ms = 0
-        self.last_force_tts_ms = 0
         self.await_played = False
         self.last_tts_completed_ms = 0
 
@@ -2858,14 +3167,22 @@ class VCStateMachine:
                 return actions
             if event == "canceled":
                 self.on_server_canceled()
-                # canceled:若处于长对话,立刻回到聆听并尝试开麦(由 _uplink_request_start 的门控保证安全)
-                actions.append(("uplink_start", "canceled"))
+                # canceled:仅长对话允许“立刻回到聆听并尝试开麦”(由 _uplink_request_start 门控保证安全幂等)
+                try:
+                    if self.mode() == VCMode.Realtime and getattr(self.vc, "Close_flag", 0) == 0:
+                        actions.append(("uplink_start", "canceled"))
+                except Exception:
+                    pass
                 return actions
             if event == "completed":
                 self.on_server_completed()
-                # completed:若不在等待 audio.played(说明本轮无 TTS),长对话可直接进入下一轮聆听
-                if (not getattr(self, "await_played", False)) and self.turn != VCTurnState.AwaitPlayedAck:
-                    actions.append(("uplink_start", "completed"))
+                # completed:若不在等待 audio.played(说明本轮无 TTS),仅长对话可直接进入下一轮聆听
+                try:
+                    if self.mode() == VCMode.Realtime and getattr(self.vc, "Close_flag", 0) == 0:
+                        if (not getattr(self, "await_played", False)) and self.turn != VCTurnState.AwaitPlayedAck:
+                            actions.append(("uplink_start", "completed"))
+                except Exception:
+                    pass
                 return actions
         except Exception:
             pass
@@ -2897,12 +3214,18 @@ class VCStateMachine:
                 return actions
             if self.await_played:
                 actions.append(("send_audio_played", "local.play_end"))
-                # 当前策略:长对话模式不做“播完自动开麦”,避免静音时持续占用麦克/上行、误触发和隐私争议。
-                # 因此这里不追加 uplink_start。
+                # 长对话模式:对话过程中的 TTS 播完后,自动开麦继续当前对话。
+                # 例外:
+                # - 刚切到长对话模式的提示音(mode_switch_long)不应自动开麦
+                # - 其它提示/提醒(prompt)不应自动开麦
+                # 实际开麦是否允许由 _uplink_request_start 的门控(FSM.turn / record_state 等)保证安全幂等。
                 try:
-                    k = getattr(self.vc, "_last_tts_kind", "") or ""
+                    if self.mode() == VCMode.Realtime and getattr(self.vc, "Close_flag", 0) == 0:
+                        k = getattr(self.vc, "_last_tts_kind", "") or ""
+                        if k == "dialog":
+                            actions.append(("uplink_start", "local.play_end"))
                 except Exception:
-                    k = ""
+                    pass
             self.on_local_audio_played()
         except Exception:
             pass
@@ -2947,6 +3270,17 @@ class AI_VC(Abstract):
         except Exception:
             return
 
+        # PTT 新一轮开始:清理“提示音播完退出”等标志,避免 Close_flag 残留影响当前回合
+        try:
+            self.Close_flag = 0
+        except Exception:
+            pass
+        # 打断上一段 TTS 后可能仍有残留音频帧下发:短时间丢弃,避免“断断续续继续播”
+        try:
+            self._drop_tts_audio = 1
+        except Exception:
+            pass
+
         t0 = 0
         try:
             t0 = utime.ticks_ms()
@@ -2959,6 +3293,13 @@ class AI_VC(Abstract):
         except Exception:
             pass
 
+        # 再强制停播一次(兼容:VC_init 未完全覆盖播放对象的场景)
+        try:
+            if getattr(self, "VC_Play_flag", 0) == 1 or getattr(self, "play_pcm", None) != None:
+                self.VC_Play_End()
+        except Exception:
+            pass
+
         # 若上一轮录音尚未结束,先强制停掉,避免 record_thread 复用出错
         try:
             if getattr(self, "VC_record_state_flag", 0) != 0:
@@ -3270,14 +3611,10 @@ class AI_VC(Abstract):
         self._tts_pending_ms = 0
         # 各类兜底的节流时间戳(避免“兜底过激/连续触发”)
         self._fb_last_thinking_restart_ms = 0
-        self._fb_last_force_tts_ms = 0
         self._fb_last_tts_pending_timeout_ms = 0
         # thinking 兜底:部分情况下服务端只返回 llm.completed 而不触发 tts.started/completed,
         # 会导致一直停留在 thinking。此时超时自动回到聆听。
         self._llm_completed_ms = 0
-        # llm→tts 兜底:若服务端只回 llm.completed 没有自动触发 tts,则由端侧主动发 synthesis 触发 TTS
-        self._llm_text_pending_tts = ""
-        self._llm_force_tts_ms = 0
         # 语音上行统计(真实发送到 VC 发送队列的开始/结束)
         self._uplink_active = 0
         self._uplink_bytes = 0
@@ -3368,49 +3705,27 @@ class AI_VC(Abstract):
             else:
                 #self.server_ip="sevenpin.qipai.com.cn"
                 self.server_ip="118.145.158.207:22082"
-            if dev_type == 'jswm' or dev_type == 'jswm_BOX':# 
-                #self.server_ip="115.190.94.208:22080"
-                self.server_ip="118.145.158.207:22086"   
-            elif dev_type == "7PIN" or dev_type == "7PIN_1_5":
-                self.server_ip=constants.AMP_SERVER
-            elif dev_type == "G10":
-                self.server_ip="115.190.94.208:22080"
-            elif dev_type == "sjgq":
-                self.server_ip="118.145.158.207:22084"
-            elif dev_type == "7PIN_BK" or dev_type == 'csh'or dev_type == "7PIN_BK_coze"or dev_type == 'momo':
-                #self.server_ip="amp.raisound.com"
-                self.server_ip="dmp.qipai.com.cn:30746"#118.145.158.207:22086"
-                #self.server_ip="115.190.94.208:22080"
-            elif dev_type == "7PIN_coze":
-                self.server_ip="118.145.158.207:22086"
-            elif  dev_type == "7PIN_BK_EU":
-                #self.server_ip="amp-global.raisound.com"
-                self.server_ip="amp-cdn-test.raisound.com"
+            # 默认走 constants.AMP_SERVER(由 default_srv.py 统一管理,可在 usr 覆盖)
+            try:
+                if constants.AMP_SERVER:
+                    self.server_ip = constants.AMP_SERVER
+            except Exception:
+                pass
 
         #开机提示音
         self.power_on_tone = EventMesh.publish("get_storage_config","power_on_tone")#
-        if dev_type != "7PIN"  and  dev_type != "7PIN_1_5" and dev_type != "7PIN_coze"and dev_type != "jswm" and  dev_type != 'jswm_BOX' and dev_type != "7PIN_BK":
-            self.power_on_tone = None
+        try:
+            if "vc_config" in globals() and vc_config:
+                if not vc_config.get_bool("POWER_ON_TONE_ENABLED", True):
+                    self.power_on_tone = None
+        except Exception:
+            pass
         if self.power_on_tone == None:
-            if dev_type == "G10":
-                self.power_on_tone = "已开机,您好!我是北科瑞讯智能 AI bot_name"
-            elif dev_type == "7PIN_BK"or dev_type == "7PIN_BK_coze":
-                self.power_on_tone = "-bot_name来了!我们一起来愉快地聊天吧!" 
-            elif  dev_type == "7PIN_BK_EU":
-                self.power_on_tone = "Hi. May I help you ?" 
-            elif dev_type == 'momo':
-                self.power_on_tone = "DuloDulo,我是上古神兽食梦貘,主人可以叫我momo,我来自《山海经》,是一只以梦为食的神秘灵兽,每当颜色朦胧、人们入睡时,我就会悄悄飞到人们的床头,用我长长的鼻子把噩梦统统吞噬掉,只留下甜甜的美梦。从今往后,就由我守护在主人身边,一起度过每一个星河璀璨的夜晚。"
-            elif dev_type == "sjgq":
-                self.power_on_tone = "您好!我是巴马四季甘泉的智能助手。我可以为你解答各种各样的问题,像是有关巴马四季甘泉知识库、中基长寿科学产品、卫斯曼院士国际先进医疗中心的问题,还有日常生活与工作、旅游信息、健康咨询、教育与学习、情感交流、全球资讯、世界文化等方面的问题哦。你有没有这方面的问题想要问我呀?"
-            elif dev_type == "szbst":
-                self.power_on_tone = "深圳百事通来了!请问您有什么需要我帮忙的吗?" 
-            elif dev_type == 'jswm'or dev_type == 'jswm_BOX':
-                self.power_on_tone = "我来陪你聊天了"
-            elif dev_type == 'csh':
-                self.power_on_tone = "欢迎使用助手小福"  
-            else:
-                self.power_on_tone = "您好!我是世界首创柒牌男装AI生活好帮手-bot_name, 很高兴为您服务,我可以帮您解答柒牌公司知识库、日常生活与工作、旅游信息、健康与运动咨询、教育与学习、情感交流、全球资讯、世界文化等问题!请问您有什么需要我帮忙的吗?" 
-                self.power_on_tone = "你好,我来了"
+            try:
+                if "vc_config" in globals() and vc_config:
+                    self.power_on_tone = vc_config.get_attr("POWER_ON_TONE_DEFAULT", None)
+            except Exception:
+                pass
 
         self.VC_record_TYPE = VC_record_TYPE_PCM #0:PCM 1:AMR
         self.VC_play_TYPE = VC_play_TYPE_PCM #0:PCM 1:mp3 
@@ -3434,153 +3749,30 @@ class AI_VC(Abstract):
         
         self.vad_silence = EventMesh.publish("get_storage_config","vad_silence")#语速配置
         if self.vad_silence == None:
-            if dev_type == "7PIN" or dev_type == "7PIN_1_5" or dev_type == "7PIN_coze":
-                self.vad_silence = 1000
-            else:
+            try:
+                if "vc_config" in globals() and vc_config:
+                    self.vad_silence = vc_config.get_int("VAD_SILENCE_DEFAULT", 300)
+                else:
+                    self.vad_silence = 300
+            except Exception:
                 self.vad_silence = 300
 
         self.VC_TTS_voice_type = EventMesh.publish("get_storage_config","VC_TTS_voice_type")#音色配置
         if self.VC_TTS_voice_type == None :
-            if dev_type == "G10" or dev_type == "szbst" :#or  dev_type == "7PIN_BK":
-                self.VC_TTS_voice_type = {   
-                                            "女":{
-                                            "bot_name":"小瑞",
-                                            "voice":"zh_female_wanwanxiaohe_moon_bigtts" ,
-                                            "lang":"zh-cn"
-                                            },
-                                            "男":{
-                                            "bot_name":"小瑞",
-                                            "voice":"zh_male_wennuanahu_moon_bigtts"  ,
-                                            "lang":"zh-cn"
-                                            },
-                                            "童":{
-                                            "bot_name":"小瑞",
-                                            "voice":"ICL_zh_female_huoponvhai_tob"  ,
-                                            "lang":"zh-cn"
-                                            },
-                                            "粤":{
-                                            "bot_name":"小瑞",
-                                            "voice":"zh_female_wanqudashu_moon_bigtts" ,
-                                            "lang":"zh-hk" 
-                                            },
-                                            "四川":{
-                                            "bot_name":"小瑞",
-                                            "voice":"zh_female_daimengchuanmei_moon_bigtts",
-                                            "lang":"&lang=zh-cn-sc"  
-                                            },
-                                            "瑞小蜜":{
-                                            "bot_name":"瑞小蜜",
-                                            "voice":"zh_male_tiancaitongsheng_mars_bigtts",
-                                            "lang":"&lang=zh-cn-sc" , 
-                                            "bot_id":"7491251662036811816",#瑞小蜜
-                                            },
-                                            "瑞小粉":{
-                                            "bot_name":"瑞小粉",
-                                            "voice":"ICL_zh_female_tiaopigongzhu_tob",
-                                            "bot_id":"7501268622456045603",#瑞小粉
-                                            "lang":"&lang=zh-cn-sc"  
-                                            },
-                                            "个性":{
-                                            "bot_name":"小瑞",
-                                            "voice":"zh_male_sunwukong_mars_bigtts" ,
-                                            "lang":"zh-cn" 
-                                            }
-                                           
-                                        }
-            else:
-                #女,男,童,粤,川,个性声
-                self.VC_TTS_voice_type = {
-                                            "女":{
-                                            "bot_name":"柒妹妹",
-                                            "voice":"zh_female_wanwanxiaohe_moon_bigtts" ,
-                                            "lang":"zh-cn"
-                                            },
-                                            "男":{
-                                            "bot_name":"柒先生",
-                                            "voice":"zh_male_wennuanahu_moon_bigtts"  ,
-                                            "lang":"zh-cn"
-                                            },
-                                            "童":{
-                                            "bot_name":"柒乐乐",
-                                            "voice":"ICL_zh_female_huoponvhai_tob"  ,
-                                            "lang":"zh-cn"
-                                            },
-                                            "闽南": {
-                                                "bot_name": "柒妹妹",
-                                                "voice": "x3_linlin",
-                                                "lang": "zh-cn"
-                                                },
-                                            "上海": {
-                                                "bot_name": "柒妹妹",
-                                                "voice": "x3_ziling",
-                                                "lang": "zh-cn"
-                                                },
-                                            "安徽合肥": {
-                                                "bot_name": "柒先生",
-                                                "voice": "x2_xiaofei",
-                                                "lang": "zh-cn"
-                                                },
-                                            "香港粤语": {
-                                                "bot_name": "柒妹妹",
-                                                "voice": "x3_xiaoyue",
-                                                "lang": "zh-cn"
-                                                },
-                                            "山东话": {
-                                                "bot_name": "柒妹妹",
-                                                "voice": "x2_xiaodong",
-                                                "lang": "zh-cn"
-                                                },
-                                            "陕西": {
-                                                "bot_name": "柒妹妹",
-                                                "voice": "x2_xiaoying",
-                                                "lang": "zh-cn"
-                                                },
-                                            "广东": {
-                                                "bot_name": "柒妹妹",
-                                                "voice": "x_xiaomei",
-                                                "lang": "zh-cn"
-                                                },
-                                            "成都": {
-                                                "bot_name": "柒妹妹",
-                                                "voice": "x3_xiaodu",
-                                                "lang": "zh-cn"
-                                                },
-                                            "湖南": {
-                                                "bot_name": "柒先生",
-                                                "voice": "x2_xiaoqiang",
-                                                "lang": "zh-cn"
-                                                },
-                                            "苏州": {
-                                                "bot_name": "柒妹妹",
-                                                "voice": "x2_SuhCn_XiXi",
-                                                "lang": "zh-cn"
-                                                },
-                                            "东北": {
-                                                "bot_name": "柒妹妹",
-                                                "voice": "x2_xiaoqian",
-                                                "lang": "zh-cn"
-                                                },
-                                            "四川": {
-                                                "bot_name": "柒妹妹",
-                                                "voice": "x3_yezi_sc",
-                                                "lang": "zh-cn"
-                                                },
-                                            "河南": {
-                                                "bot_name": "柒先生",
-                                                "voice": "x2_xiaokun",
-                                                "lang": "zh-cn"
-                                                },
-                                            "湖北": {
-                                                "bot_name": "柒先生",
-                                                "voice": "x2_xiaowang",
-                                                "lang": "zh-cn"
-                                                },
-                                            "内蒙古话": {
-                                                "bot_name": "柒先生",
-                                                "voice": "x2_xiaobao",
-                                                "lang": "zh-cn"
-                                                }
-                                        }
+            try:
+                if "vc_config" in globals() and vc_config:
+                    cfg = vc_config.get_attr("VC_TTS_VOICE_TYPE_DEFAULT", None)
+                    if isinstance(cfg, dict):
+                        self.VC_TTS_voice_type = cfg
+            except Exception:
+                pass
+        # 若配置未提供,沿用原逻辑内置兜底(保持兼容)
+        if self.VC_TTS_voice_type == None:
+            self.VC_TTS_voice_type = {
+                "女":{"bot_name":"柒妹妹","voice":"zh_female_wanwanxiaohe_moon_bigtts","lang":"zh-cn"},
+                "男":{"bot_name":"柒先生","voice":"zh_male_wennuanahu_moon_bigtts","lang":"zh-cn"},
+                "童":{"bot_name":"柒乐乐","voice":"ICL_zh_female_huoponvhai_tob","lang":"zh-cn"},
+            }
             
             # self.VC_TTS_voice_type = {0:"zh_female_xinlingjitang_moon_bigtts",1:"zh_male_wennuanahu_moon_bigtts",2:"ICL_zh_female_huoponvhai_tob",
             #                           3:"aliyun::longjiaxin",4:"zh_female_daimengchuanmei_moon_bigtts"}
@@ -3591,14 +3783,12 @@ class AI_VC(Abstract):
         try:
             self.VC_TTS_voice_key = EventMesh.publish("get_storage_config","VC_TTS_voice_key")#音色配置
             if self.VC_TTS_voice_key == None :
-                if dev_type == "7PIN_BK"or dev_type == "7PIN_BK_EU"or dev_type == "7PIN_BK_coze":
-                    self.VC_TTS_voice_key = "童"
-                    #self.VC_TTS_voice_key = "男"
-                elif dev_type == 'momo':
-                    self.VC_TTS_voice_key = "女"
-                elif dev_type == "jswm"or dev_type == 'jswm_BOX':
-                    self.VC_TTS_voice_key = "林悦"    
-                else:
+                try:
+                    if "vc_config" in globals() and vc_config:
+                        self.VC_TTS_voice_key = vc_config.get_attr("VC_TTS_VOICE_KEY_DEFAULT", None)
+                except Exception:
+                    pass
+                if not self.VC_TTS_voice_key:
                     self.VC_TTS_voice_key = "男"
             if self.VC_TTS_voice_key in self.VC_TTS_voice_type:
                 pass
@@ -3610,8 +3800,6 @@ class AI_VC(Abstract):
             usys.print_exception(e)
         #配置词
         self.commands_mode = 2 #=1用大模型判断命令,=0用服务器本地插件判断命令 =2用设备本地判断方式
-        if dev_type == "7PIN_BK"or dev_type == "7PIN_BK_EU"or dev_type == "7PIN_BK_coze":
-            self.commands_mode = 2
         self.commands = []
         if self.VC_TTS_volume == None:
             self.VC_TTS_volume = 100
@@ -3764,7 +3952,7 @@ class AI_VC(Abstract):
         EventMesh.subscribe("chenggong_tone",self.chenggong_tone)
         
         pass
-        EventMesh.publish("close_led")
+        EventMesh.publish("set_led_state", {"ai_state": "idle"})
         self.dialog_attributes_provider =  EventMesh.publish("get_storage_config","dialog_attributes_provider")#智能体类型配置
         if self.dialog_attributes_provider == None:
             self.dialog_attributes_provider = "coze"
@@ -3773,11 +3961,7 @@ class AI_VC(Abstract):
             self.outbound_attributess_provider = "volcengine"
         self.inbound_attributess_provider = EventMesh.publish("get_storage_config","inbound_attributess_provider")#tts服务选择
         if self.inbound_attributess_provider == None:
-            if  dev_type == "7PIN" or dev_type == "7PIN_1_5" or  dev_type == "7PIN_coze" :
-                self.inbound_attributess_provider = "xun-fei"
-                self.inbound_attributess_provider = "volcengine"
-            else:
-                self.inbound_attributess_provider = "volcengine"
+            self.inbound_attributess_provider = "volcengine"
         
         self.bot_name = "柒先生"
         try:
@@ -3789,8 +3973,11 @@ class AI_VC(Abstract):
             usys.print_exception(e)
         try:
             bt_ota_flag=0
-            if dev_type == "7PIN_1_5":
-                bt_ota_flag = self.ai_OTA.bt_ota()#先检查蓝牙是否要升级
+            try:
+                if "vc_config" in globals() and vc_config and vc_config.get_bool("BT_OTA_ENABLED", False):
+                    bt_ota_flag = self.ai_OTA.bt_ota()#先检查蓝牙是否要升级
+            except Exception:
+                pass
 
             cat1_ota_flag = self.ai_OTA.min_sys_ota()
             if bt_ota_flag==1 or cat1_ota_flag == 1:
@@ -3939,14 +4126,7 @@ class AI_VC(Abstract):
         response = None
         #http://180.184.206.142/bz-api/dev/config?deviceId=xxx
         try:
-            url=None
-            if dev_type == "7PIN_BK_EU":#英文小瑞
-                url = "http://dmp-global.raisound.com/bz-api/dev/config/{}".format(modem.getDevImei())
-            elif dev_type == "7PIN" or dev_type == "7PIN_1_5" or dev_type == "7PIN_coze":#柒牌
-                url = "http://ota.qipai.com/bz-cmp-api/api/config/{}".format(modem.getDevImei())
-            else:
-                url = "https://qipai-dev.dobell.top/qp-dmp-api/dev/config/{}".format(modem.getDevImei())
-                url = "http://dmp-dev.raisound.com/dmp-api/dev/config/{}".format(modem.getDevImei())
+            url = (constants.DMP_BASE + "/dev/config/{}").format(modem.getDevImei())
                 
                 
             print(url)
@@ -4021,10 +4201,20 @@ class AI_VC(Abstract):
             self.audio_play_state =1
             #EventMesh.publish("set_audio_state", 1)
             print('audio-play start.')
+            # 本地播放真正开始:统一进入 playing(绿灯态由 AI_led 表决定)
+            try:
+                EventMesh.publish("set_led_state", {"ai_state": "playing"})
+            except Exception:
+                pass
         elif event == 7:
             self.audio_play_state = 0
             #EventMesh.publish("set_audio_state", 0)   
             print('audio-play finish.!!!!!!')
+            # 本地播放真正结束:统一退出 playing
+            try:
+                EventMesh.publish("set_led_state", {"ai_state": "idle"})
+            except Exception:
+                pass
     def set_tts_volume(self,event,msg):
         EventMesh.publish("set_storage_config",["VC_TTS_volume",msg])#音量配置
         self.VC_TTS_volume = msg
@@ -4107,28 +4297,88 @@ class AI_VC(Abstract):
         # self.chenggong_tone() #播放按键音
 
     def AI_key_press(self, event=None, msg = None):#按键按下
-        if dev_type == "7PIN": #2代产品要延时播放按键音 为了连接蓝牙后不播放按键音的问题
-            # print("1111111111播放按键音!!!!!!!!!!")
-            # self.aud.aud_tone_play(10,400)#播放按键音
-            # 抢占规则:本地提示音不可打断流播放
-            try:
+        # 按键时打印 LED 聚合状态/最终模式(用于定位“绿灯不灭/闪一下”)
+        try:
+            if "vc_config" in globals() and vc_config and vc_config.get_bool("KEY_LED_DEBUG", False):
+                try:
+                    led = EventMesh.publish("get_led_debug_state")
+                except Exception:
+                    led = None
+                try:
+                    t = getattr(self.fsm, "turn", None)
+                except Exception:
+                    t = None
+                print("[KEY] AI_key_press VC_mode={} VC_state={} turn={} led={}".format(
+                    getattr(self, "VC_mode", -1), getattr(self, "VC_state", -1), t, led))
+        except Exception:
+            pass
+        # 按键提示音(设备差异由 default_config.py 控制)
+        try:
+            tone_file = None
+            if "vc_config" in globals() and vc_config:
+                tone_file = vc_config.get_attr("KEY_PRESS_TONE_FILE", None)
+            if tone_file:
                 if EventMesh.publish("get_vc_stream_active") != 1:
-                    self.aud.play(1, 1, 'U:/static/start.mp3')  #播放按键音
-            except Exception:
-                pass
-        # 播放状态判定
+                    self.aud.play(1, 1, tone_file)
+        except Exception:
+            pass
+        # 单对话(PTT,VC_mode==1):
+        # - 短按用于“停止当前播报/打断当前回合”,不自动开麦(必须长按才录音)
+        # - 防止和长对话的 cancel→canceled→自动开麦逻辑混用
+        try:
+            if self.VC_mode == 1:
+                # 若正在播放/接收 TTS:本地立刻停播 + 通知服务端 cancel,回到 idle
+                try:
+                    playing = False
+                    try:
+                        t = getattr(self.fsm, "turn", VCTurnState.Idle)
+                        playing = (t in (VCTurnState.TtsReceiving, VCTurnState.Playing))
+                    except Exception:
+                        playing = False
+                    if playing or (self.VC_state >= VC_State_TTSStart and self.VC_state <= VC_State_TTSEnd) or getattr(self, "VC_Play_flag", 0) == 1:
+                        self._ptt_short_press_stop = 1
+                        try:
+                            cancel = {"event": "cancel", "payload": {}}
+                            self.AI_client_VC_send(ujson.dumps(cancel))
+                        except Exception:
+                            pass
+                        try:
+                            self.VC_Play_End()
+                        except Exception:
+                            pass
+                        try:
+                            self.fsm.await_played = False
+                        except Exception:
+                            pass
+                        try:
+                            EventMesh.publish("set_led_state", {"ai_state": "idle"})
+                        except Exception:
+                            pass
+                        return
+                except Exception:
+                    pass
+                # 非播放态:短按不做任何事
+                return
+        except Exception:
+            pass
+
+        # 长对话播放态:短按打断并续聊(复用 dialog_id)
         if  self.VC_state >= VC_State_TTSStart and self.VC_state <= VC_State_TTSEnd:
             print("【打断播放】设备正在说话,仅中断播放,不发起新对话")    
             self.is_ruppt_tts = 1
             EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_RequestToSpeak})#打断
             return
 
-        # 长对话:单按键语义为“打断当前对话,然后继续开麦上行”
-        # - 若服务端返回 canceled,则会在 canceled 分支自动触发开麦(见 recv 里的 request_uplink_start("canceled"))
+        # 长对话(VC_mode==0):
+        # - 对话进行中:短按 AI 键只打断/续聊,复用本次会话的 dialog_id(不重连、不新建会话)
+        # - 已停止/未 started:短按 AI 键发起新会话(会产生新的 dialog_id)
         try:
             if self.VC_mode == 0:
-                EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_client_VC_RequestToSpeak})
-                return
+                if getattr(self, "AI_client_VC_isconnect", 0) == 1 and getattr(self, "_vc_session_started", 0) == 1:
+                    # 若服务端返回 canceled,则会在 canceled 分支自动触发开麦(见 recv 里的 FSM uplink_start:canceled)
+                    EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_client_VC_RequestToSpeak})
+                    return
+                # 否则走下方“新会话”流程
         except Exception:
             pass
 
@@ -4141,12 +4391,10 @@ class AI_VC(Abstract):
             self.Close()
             self.revoice_cnt = 0
             self.revoice_timer.stop()#回复定时器关闭,计数器清零
-            EventMesh.publish("open_led_green")
             EventMesh.publish("start_voice_record",2)#开始语音录音
             return
         elif self.meet_flag == 1:#会议纪要模式
             self.Close()
-            EventMesh.publish("open_led_green")
             EventMesh.publish("start_voice_record",3)#开始会议录音
             return
         elif self.trans_flag == 1:#AI翻译模式
@@ -4158,32 +4406,17 @@ class AI_VC(Abstract):
         self.key_state = 1
             # EventMesh.publish("audio_montage_play",["chenggong.mp3"])  
             # self.chenggong_tone() #播放按键音
-        if dev_type == "7PIN_1_5": #2代产品要延时播放按键音 为了连接蓝牙后不播放按键音的问题
-            self.ai_key_press_audio.stop()
-            self.ai_key_press_audio.start(300, 0, self.ai_key_press_audio_cb1)
-        if PRESS_AUDIO_MODE == 1:
-            if dev_type == "7PIN" or dev_type == "7PIN_1_5":
-                if dev_type == "7PIN_1_5":
-                    pass
-                    # self.ai_key_press_audio.stop()
-                    # self.ai_key_press_audio.start(300, 0, self.ai_key_press_audio_cb1)
-                    # self.aud.aud_tone_play(10,200)#播放按键音
-                else:
-                    pass
-                    # self.aud.aud_tone_play(10,200)#播放按键音
+        try:
+            delay_ms = 0
+            if "vc_config" in globals() and vc_config:
+                delay_ms = vc_config.get_int("KEY_PRESS_TONE_DELAY_MS", 0)
+            if delay_ms and delay_ms > 0:
+                self.ai_key_press_audio.stop()
+                self.ai_key_press_audio.start(delay_ms, 0, self.ai_key_press_audio_cb1)
+        except Exception:
+            pass
         utime.sleep_ms(500)
         self.Close()
-        if PRESS_AUDIO_MODE == 0:
-            if dev_type == "7PIN" or dev_type == "7PIN_1_5":
-                if dev_type == "7PIN_1_5":
-                    pass
-                    # self.ai_key_press_audio.stop()
-                    # self.ai_key_press_audio.start(200, 0, self.ai_key_press_audio_cb2)
-                    # self.chenggong_tone()
-                    # self.aud.aud_tone_play(10,200)#播放按键音
-                else:
-                    pass
-                    # self.aud.aud_tone_play(10,200)#播放按键音
 
         # if dev_type == "7PIN":
         #     self.chenggong_tone()
@@ -4219,23 +4452,18 @@ class AI_VC(Abstract):
         self.aud.aud_tone_play(10,400)#播放按键音
         # EventMesh.publish("audio_montage_play",["chenggong.mp3"])  
         # self.chenggong_tone() #播放按键音
-        if PRESS_AUDIO_MODE == 1:
-            if dev_type == "7PIN" or dev_type == "7PIN_1_5":
-                pass
-                # self.aud.aud_tone_play(10,400)#播放按键音
-        # 长对话:蓝牙按键同单按——打断并继续开麦上行
+        # 长对话:蓝牙按键同单按
+        # - 对话进行中:打断/续聊(复用 dialog_id)
+        # - 已停止/未 started:走新会话流程
         try:
             if self.VC_mode == 0:
-                EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_client_VC_RequestToSpeak})
-                return
+                if getattr(self, "AI_client_VC_isconnect", 0) == 1 and getattr(self, "_vc_session_started", 0) == 1:
+                    EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_client_VC_RequestToSpeak})
+                    return
         except Exception:
             pass
 
         self.Close()
-        if PRESS_AUDIO_MODE == 0:
-            if dev_type == "7PIN" or dev_type == "7PIN_1_5":
-                pass
-                # self.chenggong_tone()
         
         if self.VC_mode == 1: #长按对话模式 接收到蓝牙耳机按键事件
             
@@ -4281,6 +4509,20 @@ class AI_VC(Abstract):
         EventMesh.publish("exit_voice_message_mode")
 
     def AI_key_release(self, event=None, msg=None):#按键弹起
+        try:
+            if "vc_config" in globals() and vc_config and vc_config.get_bool("KEY_LED_DEBUG", False):
+                try:
+                    led = EventMesh.publish("get_led_debug_state")
+                except Exception:
+                    led = None
+                try:
+                    t = getattr(self.fsm, "turn", None)
+                except Exception:
+                    t = None
+                print("[KEY] AI_key_release VC_mode={} VC_state={} turn={} led={}".format(
+                    getattr(self, "VC_mode", -1), getattr(self, "VC_state", -1), t, led))
+        except Exception:
+            pass
         print("AI_key_release123")
         self.key_state = 0
         if self.trans_flag == 1:#AI翻译模式
@@ -4290,7 +4532,7 @@ class AI_VC(Abstract):
             self.stop_voice_timer.stop()
             self.voice_flag=0
             if EventMesh.publish("GET_USB_STATE") == 0:
-                EventMesh.publish("close_led")
+                EventMesh.publish("set_led_state", {"ai_state": "idle"})
             EventMesh.publish("stop_voice_record")#停止静默录音
             tts_play_str = "留言已发送"
             self.voice_flag=0
@@ -4310,14 +4552,24 @@ class AI_VC(Abstract):
             
         else :
             if self.VC_mode == 1 :#长按单次问答模式
+                # 若刚刚短按用于“停止播报”,则不再触发提示音 TTS,直接回到 idle
+                try:
+                    if getattr(self, "_ptt_short_press_stop", 0) == 1:
+                        self._ptt_short_press_stop = 0
+                        return
+                except Exception:
+                    pass
                 # try:
                 #     EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) 
                 # except Exception as e:
                 #     usys.print_exception(e)
                 #EventMesh.publish("publish_AI_btnInfo",{"func":self.key_prompt})  #提示请您按住中间的按钮开始讲话,讲完松开即可   
-                if dev_type == "7PIN_BK_EU":
-                    self.AI_TTS_str = "Please press and hold the button to speak. "
-                else:
+                try:
+                    if "vc_config" in globals() and vc_config:
+                        self.AI_TTS_str = vc_config.get_attr("PTT_HINT", None)
+                except Exception:
+                    pass
+                if not self.AI_TTS_str:
                     self.AI_TTS_str = "请您按住圆形的按钮开始讲话,讲完松开即可 "
                 EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start})
                 pass
@@ -4325,6 +4577,11 @@ class AI_VC(Abstract):
                 #self.VC_Speech_End()
     def pwk_key_double_press(self,event,msg):#pwk双击
         print("come 双击")
+        # 切换模式:必须打断当前对话/录音/播放,回到 idle,等待按键触发新一轮
+        try:
+            EventMesh.publish("publish_AI_btnInfo", {"func": self.Close})
+        except Exception:
+            pass
         if self.VC_mode == 0:
             self.VC_mode = 1
             tts_str = "已切换到单对话模式" 
@@ -4343,15 +4600,29 @@ class AI_VC(Abstract):
                 self._last_tts_kind = "mode_switch_long"
             except Exception:
                 pass
+        # 提示音播完即退出(Close_flag=1),保持 idle,等待按键
         EventMesh.publish("play_tts",[tts_str,1])
         EventMesh.publish("set_storage_config",["VC_mode",self.VC_mode])
 
     def AI_key_long_press(self, event, msg):#按键长按
+        try:
+            if "vc_config" in globals() and vc_config and vc_config.get_bool("KEY_LED_DEBUG", False):
+                try:
+                    led = EventMesh.publish("get_led_debug_state")
+                except Exception:
+                    led = None
+                try:
+                    t = getattr(self.fsm, "turn", None)
+                except Exception:
+                    t = None
+                print("[KEY] AI_key_long_press VC_mode={} VC_state={} turn={} led={}".format(
+                    getattr(self, "VC_mode", -1), getattr(self, "VC_state", -1), t, led))
+        except Exception:
+            pass
         print("AI_key_long_press")
         # 单对话(PTT):任何中间态都允许打断并开启新一轮录音上行
         if self.trans_flag == 1:#AI翻译模式
             self.Close()
-            EventMesh.publish("open_led_green")
             EventMesh.publish("start_voice_record",4)#开始翻译录音
         self.AI_key_long_press_flag = 1
         if self.VC_mode == 1:
@@ -4440,6 +4711,11 @@ class AI_VC(Abstract):
                     usys.print_exception(e) 
                 
                 self.VC_record_state_flag = 1
+                # 录音开始:聆听灯(蓝慢闪)
+                try:
+                    EventMesh.publish("set_led_state", {"ai_state": "listening"})
+                except Exception:
+                    pass
                 
         except Exception as e:
             self.websocket_error()
@@ -4492,6 +4768,11 @@ class AI_VC(Abstract):
             self.AI_record_tmp_queue.clear()
         
         self.VC_record_state_flag = 0
+        # 录音停止:关闭聆听灯(恢复 base)
+        try:
+            EventMesh.publish("set_led_state", {"ai_state": "idle"})
+        except Exception:
+            pass
         print("[VC] Speech_End record_state={}".format(self.VC_record_state_flag))
     #关闭录音线程   
     def VC_record_thread_close(self): 
@@ -4749,12 +5030,12 @@ class AI_VC(Abstract):
             print("token:{}".format(token))
             
             req_str = "vc/chat?is_auth={}".format(self.is_auth)
-            if dev_type == '7PIN_BK_coze' or dev_type == '7PIN_coze':
-                req_str = "vc/coze?is_auth={}".format(self.is_auth)
-            elif dev_type == 'jswm' or dev_type == 'jswm_BOX' :
-                req_str = "vc/agent?is_auth={}".format(self.is_auth)
-            elif dev_type == "7PIN":#内部测试,不用coze
-                req_str = "vc/agent?is_auth={}".format(self.is_auth)
+            try:
+                if "vc_config" in globals() and vc_config:
+                    base = vc_config.get_attr("VC_WS_PATH", "vc/chat") or "vc/chat"
+                    req_str = "{}?is_auth={}".format(base, self.is_auth)
+            except Exception:
+                pass
             if(token):
                 url = 'ws://{}/{}&dt={}'.format(self.server_ip,req_str,token)
             else:
@@ -4820,7 +5101,7 @@ class AI_VC(Abstract):
         self.AI_ASR_flag  = 0
         # 可能由收包线程/其它线程触发:统一切回主线程执行 stop,避免“异常→重试→再异常”的循环
         EventMesh.publish("publish_AI_btnInfo",{"func":self._uplink_request_stop, "data":"websocket_error"})
-        EventMesh.publish("close_led")
+        EventMesh.publish("set_led_state", {"ai_state": "idle"})
         if TTS_str == None:
             self.websocket_error_count+=1
             # if self.websocket_error_count <=3:
@@ -5153,20 +5434,20 @@ class AI_VC(Abstract):
                             #payload = jsload_data["payload"]
                             # self.VC_dialog_id = payload["dialog_id"] 
                             # self.VC_task_id = jsload_data["task_id"] 
-                            EventMesh.publish("open_led_blue")
+                            # started 仅表示链路就绪:不在这里提前切灯态;
+                            # 聆听灯只在“录音真正开始/停止”处更新(VC_Speech_Start/End)。
                             # 会话开始:允许上行;连续对话模式下直接进入“可发送音频”状态
                             self._vc_session_started = 1
-                            # 新会话开始必须允许连续对话自动开麦(防止上一轮 Close_flag 残留导致 Deny START)
-                            self.Close_flag = 0
+                            # started 时不要强制清 Close_flag:
+                            # - Close_flag==1:提示音/模式切换播完退出
+                            # - Close_flag==0:正常对话流程
                             self._ptt_audio_created = 0
                             self._server_vad_silence = 0
                             self._turn_has_asr_completed = 0
                             self._turn_has_vad_silence = 0
                             self._turn_has_tts_started = 0
                             self._llm_completed_ms = 0
-                            self._llm_text_pending_tts = ""
-                            self._llm_force_tts_ms = 0
-                            if self.VC_mode == 0:
+                            if self.VC_mode == 0 and getattr(self, "Close_flag", 0) == 0:
                                 # 会话已 started:若此时上行未启动,则在这里补一次开麦,避免“Start 前开麦被 Close 停掉”后
                                 # 出现首轮无音频上行导致“第一次对话没有”的情况。
                                 if self.record_data_save_flag == 0 and self.VC_record_state_flag == 0:
@@ -5227,8 +5508,11 @@ class AI_VC(Abstract):
                                 self.voice_choose_flag = 1
                             else:
                                 #开始上传语音
-                                if dev_type != "7PIN_coze" and dev_type != "7PIN" and  dev_type != "7PIN_1_5":
-                                    self.chenggong_tone()
+                                try:
+                                    if "vc_config" in globals() and vc_config and vc_config.get_bool("UPLOAD_START_TONE_ENABLED", False):
+                                        self.chenggong_tone()
+                                except Exception:
+                                    pass
                                 if self.VC_mode == 0    :
                                     self.VC_record_state_flag  =2
                                 else:
@@ -5258,17 +5542,17 @@ class AI_VC(Abstract):
                             self._turn_has_vad_silence = 0
                             self._turn_has_tts_started = 0
                             self._llm_completed_ms = 0
-                            self._llm_text_pending_tts = ""
-                            self._llm_force_tts_ms = 0
+                            try:
+                                self._drop_tts_audio = 0
+                            except Exception:
+                                pass
                             if self.VC_mode == 1    :
                                 self.VC_record_state_flag = 2
                             self.LocalRespondingEnded_timerout = 0
-                            EventMesh.publish("open_led_blue")
                         elif jsload_data["event"] == "asr.result" :#asr结果
                             self.AI_ASR_str = jsload_data["payload"]["content"]
                             if self.AI_ASR_str == "":#没识别到
                                 self.AI_TTS_str = "我没听清,请再说一遍"
-                            EventMesh.publish("open_led_blue")
                         elif jsload_data["event"] == "asr.completed" :#asr 终止的标识 
                             self._turn_has_asr_completed = 1
                             # 抢占规则:本地提示音不可打断流播放
@@ -5287,7 +5571,7 @@ class AI_VC(Abstract):
                                     if self.AI_ASR_send_data_queue.empty()!=True:
                                         self.AI_ASR_send_data_queue.clear()
                                     self.AI_ASR_send_buf_len = 0
-                                    EventMesh.publish("open_led_all")
+                                    EventMesh.publish("set_led_state", {"ai_state": "thinking"})
                                     try:
                                         
                                         self.request_uplink_stop("asr.completed/config_cmd")
@@ -5309,9 +5593,11 @@ class AI_VC(Abstract):
                             # if dev_type != "7PIN" :
                             #EventMesh.publish("publish_AI_btnInfo",{"func":self.send_tone}) 
                         elif jsload_data["event"] == "vad.active" :#VAD 检测到说话→聆听
-                            if dev_type in ("7PIN_1_5", "7PIN", "7PIN_coze"):
-                                self._server_vad_silence = 0
-                                EventMesh.publish("open_led_blue")
+                            try:
+                                if "vc_config" in globals() and vc_config and vc_config.get_bool("VAD_ACTIVE_BLUE_LED", True):
+                                    self._server_vad_silence = 0
+                            except Exception:
+                                pass
                         elif jsload_data["event"] == "vad.silence" :#VAD 终止的标识 
                             # 说明服务端已判定“本轮说话结束”;此时继续上行只会干扰后续(例如推迟 TTS)。
                             # 仅在“正在录音上行”的语音阶段才停止,避免误触发。
@@ -5322,14 +5608,12 @@ class AI_VC(Abstract):
                                 if self.VC_record_state_flag != 0 and self.VC_state >= VC_State_SpeechStart:
                                     self.request_uplink_stop("vad.silence")
                         elif jsload_data["event"] == "llm.created" :#思考(LLM)
-                            if dev_type in ("7PIN_1_5", "7PIN", "7PIN_coze"):
-                                EventMesh.publish("flicker_led_blue_green")
-                            else:
-                                EventMesh.publish("open_led_red_green")
+                            try:
+                                EventMesh.publish("set_led_state", {"ai_state": "thinking"})
+                            except Exception:
+                                pass
                             self.VC_state = VC_State_Thinking
                             self._llm_completed_ms = 0
-                            self._llm_text_pending_tts = ""
-                            self._llm_force_tts_ms = 0
                             # EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Play_Start})
                             pass
                         elif jsload_data["event"] == "llm.completed" :#llm完成(可能无 tts)
@@ -5338,14 +5622,6 @@ class AI_VC(Abstract):
                             except Exception:
                                 # 勿用 1:ticks_diff(now,1)≈开机至今,会瞬间满足 thinking 超时误以为该重启
                                 self._llm_completed_ms = 0
-                            # 若服务端没有自动触发 tts.started,则准备由端侧主动发 synthesis
-                            try:
-                                txt = jsload_data.get("payload", {}).get("content", "")
-                            except Exception:
-                                txt = ""
-                            if isinstance(txt, str) and txt.strip() and VC_PROTO_GUARDS:
-                                self._llm_text_pending_tts = txt.strip()
-                                self._llm_force_tts_ms = self._llm_completed_ms
                             try:
                                 self._cur_dialog_id = jsload_data.get("payload", {}).get("dialog_id", "") or ""
                             except Exception:
@@ -5365,8 +5641,6 @@ class AI_VC(Abstract):
                             self._turn_has_tts_started = 1
                             self._tts_pending = 0
                             self._tts_pending_ms = 0
-                            self._llm_text_pending_tts = ""
-                            self._llm_force_tts_ms = 0
                             self._uplink_mark_end("tts.started")
                             # stop uplink + play_start 由 FSM action list 统一触发,避免多处重复调用
                             # 标记本轮 TTS 来源:
@@ -5398,9 +5672,9 @@ class AI_VC(Abstract):
                                 self._pending_tts_kind = ""
                             except Exception:
                                 pass
-                            EventMesh.publish("open_led_green")#绿色
+                            # 播放灯由阶段事件控制
                         elif jsload_data["event"] == "tts.completed" :#tts结束
-                            EventMesh.publish("open_led_green")#绿色
+                            # tts.completed 仅表示下发结束,本地可能仍在播放;绿灯关闭在本地播放结束时处理
                             self.VC_state = VC_State_TTSEnd
                             try:
                                 # server event 已在统一入口 on_server_event 触发 FSM,这里避免重复驱动
@@ -5555,7 +5829,12 @@ class AI_VC(Abstract):
                         #self.AI_ASR_str = ""#下发音频后清掉asr结果
                         
                         
-                        EventMesh.publish("open_led_green")#绿色
+                        # PTT 打断后丢弃残留 TTS 音频帧,避免“断断续续继续播”
+                        try:
+                            if getattr(self, "_drop_tts_audio", 0) == 1:
+                                continue
+                        except Exception:
+                            pass
                         if self.VC_stop_play_audio_flag == 0:
                             print("新的AI对话不允许以前的播放数据:")
                             break
@@ -5762,7 +6041,7 @@ class AI_VC(Abstract):
                 self.AI_VC_send_data_queue.clear()
             if self.AI_ASR_send_data_queue.empty()!=True:
                 self.AI_ASR_send_data_queue.clear()
-            EventMesh.publish("open_led_all")
+            EventMesh.publish("set_led_state", {"ai_state": "thinking"})
             self.AI_ASR_send_buf_len = 0
             self._uplink_request_stop("play_tts_cb")
             self.websocket_deconnect_VC()
@@ -6122,20 +6401,18 @@ class AI_VC(Abstract):
                     #     self.AI_TTS_str = "更改失败,没找到对应声音" 
                     #     return 0
                 if text.find("切换对话模式") != -1:
-                    if dev_type == "7PIN_BK_EU":
-                        if self.VC_mode == 0:
-                            self.VC_mode = 1
-                            self.AI_TTS_str = "change dialogue mode" 
-                        else:
-                            self.VC_mode = 0 
-                            self.AI_TTS_str = "pushtalk mode" 
+                    if self.VC_mode == 0:
+                        self.VC_mode = 1
+                        try:
+                            self.AI_TTS_str = vc_config.get_attr("CMD_TOGGLE_MODE_TO_PTT_TTS", "已切换到单对话模式")
+                        except Exception:
+                            self.AI_TTS_str = "已切换到单对话模式"
                     else:
-                        if self.VC_mode == 0:
-                            self.VC_mode = 1
-                            self.AI_TTS_str = "已切换到单对话模式" 
-                        else:
-                            self.VC_mode = 0 
-                            self.AI_TTS_str = "已切换到长对话模式" 
+                        self.VC_mode = 0
+                        try:
+                            self.AI_TTS_str = vc_config.get_attr("CMD_TOGGLE_MODE_TO_LONG_TTS", "已切换到长对话模式")
+                        except Exception:
+                            self.AI_TTS_str = "已切换到长对话模式"
                     EventMesh.publish("set_storage_config",["VC_mode",self.VC_mode])
                     # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])
                     #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功
@@ -6284,53 +6561,48 @@ class AI_VC(Abstract):
                     else:
                         self.AI_TTS_str = "当前已是最新版本"
                     return 0
-                if dev_type == "7PIN_1_5":#二代才有蓝牙和语音留言功能
+                try:
+                    bt_voice_en = ("vc_config" in globals() and vc_config and vc_config.get_bool("BT_VOICE_FEATURES_ENABLED", False))
+                except Exception:
+                    bt_voice_en = False
+                if bt_voice_en:
                     if text.find("语音留言") != -1:
                         self.voice_flag = 1
-                        self.AI_TTS_str = "已进入语音留言模式,长按按钮开始录音,松开按钮结束" 
+                        self.AI_TTS_str = "已进入语音留言模式,长按按钮开始录音,松开按钮结束"
                         self.Close_flag = 1
-                        self.stop_voice_timer.stop() #关闭语音留言模式定时器
+                        self.stop_voice_timer.stop()
                         self.stop_voice_timer.start(30*1000,0,self.exit_voice_message_timer)
                         print("语音留言!!!!!!!!!!")
                         return 0
                     if text.find("开广播") != -1 or text.find("开蓝牙广播") != -1:
-                        
-                        self.AI_TTS_str = "正在开蓝牙广播" 
+                        self.AI_TTS_str = "正在开蓝牙广播"
                         EventMesh.publish("AI_send_bt_ble_switch_toble",1)
-
                         print("正在开蓝牙广播")
                         return 0
                     if text.find("关广播") != -1 or text.find("关蓝牙广播") != -1:
-                        
-                        self.AI_TTS_str = "正在关蓝牙广播" 
+                        self.AI_TTS_str = "正在关蓝牙广播"
                         EventMesh.publish("AI_send_bt_ble_switch_toble",2)
-
                         print("正在关蓝牙广播")
                         return 0
                     if text.find("开经典蓝牙") != -1:
-                        
-                        self.AI_TTS_str = "正在开经典蓝牙" 
+                        self.AI_TTS_str = "正在开经典蓝牙"
                         EventMesh.publish("AI_send_bt_ble_switch_toble",3)
                         print("正在开经典蓝牙")
                         return 0
                     if text.find("关闭经典蓝牙") != -1 or text.find("关经典蓝牙") != -1:
-                        
-                        self.AI_TTS_str = "正在关经典蓝牙" 
+                        self.AI_TTS_str = "正在关经典蓝牙"
                         EventMesh.publish("AI_send_bt_ble_switch_toble",4)
                         print("正在关经典蓝牙")
                         return 0
-                        
                     if text.find("确认解绑设备") != -1 or text.find("确认设备解绑") != -1:
-                        self.AI_TTS_str = "设备解绑中...." 
+                        self.AI_TTS_str = "设备解绑中...."
                         self.Close_flag = 1
                         EventMesh.publish("send_unbind_dev_to_iot")
                         print("解绑设备!!!!!!!!!!!!!!")
                         return 0
                     if text.find("删除耳机记录") != -1 or text.find("清楚耳机记录") != -1:
-                        
-                        self.AI_TTS_str = "正在删除" 
+                        self.AI_TTS_str = "正在删除"
                         EventMesh.publish("clear_earphone_record")
-
                         print("正在删除")
                         return 0
                 # if len(text)<16 and (text.find("再见") != -1 or text.find("拜拜") != -1 or text.find("关闭对话") != -1):
@@ -6344,9 +6616,12 @@ class AI_VC(Abstract):
                 #         #EventMesh.publish("sleep_BT")#休眠蓝牙
                 #         return 1
                 if len(text)<12 and (text.find("关机") != -1 ):
-                    if dev_type == "7PIN" or dev_type == "7PIN_coze" or dev_type == "7PIN_1_5":#柒牌
-                        EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) 
-                        #EventMesh.publish("sleep_BT")#休眠蓝牙
+                    try:
+                        close_only = ("vc_config" in globals() and vc_config and vc_config.get_bool("POWEROFF_CMD_CLOSE_ONLY", True))
+                    except Exception:
+                        close_only = True
+                    if close_only:
+                        EventMesh.publish("publish_AI_btnInfo",{"func":self.Close})
                         return 1
                     EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) 
                     EventMesh.publish("Power_off")
@@ -6434,6 +6709,10 @@ class AI_VC(Abstract):
                 elif self.VC_play_TYPE == VC_play_TYPE_MP3:
                     pass
                 self.VC_Play_flag = 1
+                try:
+                    EventMesh.publish("set_led_state", {"ai_state": "playing"})
+                except Exception:
+                    pass
             except Exception as e:
                 self.VC_Play_End()
                 usys.print_exception(e)
@@ -6471,9 +6750,21 @@ class AI_VC(Abstract):
         if self.AI_audio_queue.empty()!=True:
             self.AI_audio_queue.clear()
 
-        # 播放结束后:退出“播报中”绿灯态。默认回到蓝灯(可说/待机态)。
+        # 播放结束后:退出“播报中”绿灯态(恢复 base)。
         try:
-            EventMesh.publish("open_led_blue")
+            EventMesh.publish("set_led_state", {"ai_state": "idle"})
+        except Exception:
+            pass
+        # 关键日志:定位“tts 结束绿灯仍不灭”究竟是 base 态(如 charging/full)还是 playing 未退出
+        try:
+            if "vc_config" in globals() and vc_config and (
+                vc_config.get_bool("LED_DEBUG", False) or vc_config.get_bool("KEY_LED_DEBUG", False) or vc_config.get_bool("HW_STATUS_DEBUG", False)
+            ):
+                try:
+                    led = EventMesh.publish("get_led_debug_state")
+                except Exception:
+                    led = None
+                print("[VC] VC_Play_End led={}".format(led))
         except Exception:
             pass
         
@@ -6508,7 +6799,6 @@ class AI_VC(Abstract):
                     self._tts_pending_ms = 0
                     if self.VC_mode == 0 and self.Close_flag == 0:
                         self.VC_state = VC_State_None
-                        EventMesh.publish("open_led_blue")
                         EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_VC_start})
         except Exception:
             pass
@@ -6521,11 +6811,7 @@ class AI_VC(Abstract):
                 # 只有在 llm.completed 之后才允许超时重启
                 if turn == VCTurnState.Thinking and llm_completed_ms and self._turn_has_tts_started == 0:
                     age_ms = utime.ticks_diff(now_ms, llm_completed_ms)
-                    # 有 force_tts pending 时不可用 6s 短超时:会与下方 force_tts(约 5s)抢跑 AI_VC_start,
-                    # 打断 synthesis/会话;改为长超时兜底,仍以 throttle 为保护。
-                    pending_for_force_tts = VC_PROTO_GUARDS and (
-                        self._llm_text_pending_tts or self._llm_force_tts_ms)
-                    restart_threshold_ms = 40000 if pending_for_force_tts else 20000
+                    restart_threshold_ms = 20000
                     # _fb_last_thinking_restart_ms==0 时 ticks_diff(now,0) 非预期(间隔被误判极大),
                     # 会在 llm.completed 后首批 tick 就触发 AI_VC_start → notts(无 tts.started);首次仅信任 age 门限
                     try:
@@ -6546,44 +6832,11 @@ class AI_VC(Abstract):
                                 age_ms, restart_threshold_ms))
                         except Exception:
                             pass
-                        EventMesh.publish("open_led_blue")
                         # thinking_timeout 策略:重启会话(而不是抢开麦),避免干扰服务端 LLM/TTS 流程
                         EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_VC_start})
         except Exception:
             pass
 
-        # 3) llm→tts 兜底:仅 Thinking 期且足够等待/节流时触发;若仍在录音则先 stop,下一次 tick 再判断(受 VC_PROTO_GUARDS)
-        try:
-            if VC_PROTO_GUARDS and self._llm_text_pending_tts and self._llm_force_tts_ms and self._turn_has_tts_started == 0:
-                # 注意:服务端可能出现 llm.completed 后直接 completed(无 tts 事件)的情况,
-                # 此时 FSM turn 可能已回到 Listening;兜底不能硬绑 Thinking,否则会“只见 llm 不见 tts”。
-                if (turn not in (VCTurnState.TtsReceiving, VCTurnState.Playing, VCTurnState.AwaitPlayedAck) and
-                    utime.ticks_diff(now_ms, self._llm_force_tts_ms) > 5000 and
-                    utime.ticks_diff(now_ms, self._fb_last_force_tts_ms) > 15000 and
-                    self._tts_pending == 0 and self._need_audio_played_ack == 0 and self.VC_Play_flag == 0):
-                    self._fb_last_force_tts_ms = now_ms
-                    if self.record_data_save_flag == 0 and self.VC_record_state_flag != 0:
-                        self.request_uplink_stop("force_tts_pre_stop")
-                        return
-                    self._llm_force_tts_ms = 0
-                    self.AI_TTS_str = self._llm_text_pending_tts
-                    self._llm_text_pending_tts = ""
-                    self._server_vad_silence = 1
-                    if self.record_data_save_flag == 0:
-                        self.request_uplink_stop("force_tts")
-                    try:
-                        sid = getattr(self, "_cur_sid", "")
-                        did = getattr(self, "_cur_dialog_id", "")
-                    except Exception:
-                        sid, did = "", ""
-                    try:
-                        print("[VC][force_tts] send synthesis sid={} did={} turn={}".format(sid, did, turn))
-                    except Exception:
-                        pass
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_synthesis})
-        except Exception:
-            pass
-
     def _1S_timer_cb_(self):    
     
         EventMesh.publish("system_sleep_rest")#防止黑屏
@@ -6632,7 +6885,6 @@ class AI_VC(Abstract):
                     except Exception:
                         pass
                     if (is_pcm_empty and drained) or too_long:
-                        EventMesh.publish("open_led_blue")
                         EventMesh.publish("publish_AI_btnInfo", {"func": self.VC_Play_End})
                         self._fsm_apply_actions(self.fsm.on_local_play_end())
                         self.VC_state = VC_State_None
@@ -6667,10 +6919,6 @@ class AI_VC(Abstract):
     #VC开始
     def AI_VC_start(self):
         print("AI_VC_start1")
-        try:
-            print("[VC] build:{}".format(VC_BUILD_TAG))
-        except Exception:
-            pass
         
         EventMesh.publish(constants.EVENT.SYSTEM_UP)#唤醒休眠
         self.VC_satrt_flag = 1
@@ -6678,7 +6926,7 @@ class AI_VC(Abstract):
         self.VC_satrt_kws_flag = 1
         if self.VC_Thinking_timerout < 100:
             self.VC_Thinking_timerout = 0
-        EventMesh.publish("open_led_blue")
+        # 不在这里提前切灯态:播放/聆听灯只在“播放/录音真正开始/停止”处更新
         EventMesh.publish("wakeup_BT")
         #self.VC_Play_End()#关闭音频播放
         print("AI_VC_start2")
@@ -6844,89 +7092,51 @@ class AI_VC(Abstract):
                 json_data["payload"]["outbound_attributes"]["provider"]=self.VC_TTS_voice_type[self.VC_TTS_voice_key]["outbound_attributess_provider"]
                 print("outbound_attributess_provider是VC_TTS_voice_type里的:{}".format(self.VC_TTS_voice_type[self.VC_TTS_voice_key]["outbound_attributess_provider"]))
 
-        if dev_type == "7PIN_BK"or dev_type == "7PIN_BK_coze"or dev_type == "G10":#小瑞
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7411071327182438412"#语言助手
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7468577560454496295"
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"]=True
-            # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7486697248416989193"#极简
-            # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7486698347416649778"
-            #json_data["payload"]["dialog_attributes"]["provider"]="doubao"#豆包
-            #json_data["payload"]["inbound_attributes"]["vad_silence"] = 200
-            #if self.VC_TTS_voice_type[self.VC_TTS_voice_key]["bot_id"] !="":
-            if "bot_id" in self.VC_TTS_voice_type[self.VC_TTS_voice_key]:
-                json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]=self.VC_TTS_voice_type[self.VC_TTS_voice_key]["bot_id"]
-                if "workflow_id" in self.VC_TTS_voice_type[self.VC_TTS_voice_key]:
-                    json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]= self.VC_TTS_voice_type[self.VC_TTS_voice_key]["workflow_id"]
-                else:
-                    json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]=""
-                if json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"] == "":
-                    json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"]=False
-            
+        # 根据配置设置默认 bot/workflow,并允许 VC_TTS_voice_type 覆盖
+        try:
+            if "vc_config" in globals() and vc_config:
+                opt = vc_config.get_attr("DIALOG_BOT_OPTION", None)
+                if isinstance(opt, dict):
+                    if "bot_id" in opt and opt["bot_id"]:
+                        json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"] = opt["bot_id"]
+                    if "workflow_id" in opt:
+                        json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"] = opt.get("workflow_id") or ""
+                    if "use_workflow" in opt:
+                        json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"] = bool(opt.get("use_workflow"))
+        except Exception:
+            pass
 
-            keywords = []#热词
-            for key in self.VC_TTS_voice_type:
-                keywords.append(key) 
-            json_data["payload"]["inbound_attributes"]["cfg"]["keywords"] = keywords
-        elif dev_type == "7PIN_BK_EU":
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7493368740600446995"#英文
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7493369551587213323"
-        elif dev_type == "csh":
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7490852493640384538"#慈善会
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"]=False
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]=""
-        elif dev_type == "7PIN" or dev_type == "7PIN_1_5" :#柒牌
+        try:
+            # voice 配置可覆盖 bot_id/workflow_id/openai_option
+            cur = self.VC_TTS_voice_type[self.VC_TTS_voice_key]
+            if isinstance(cur, dict):
+                if cur.get("bot_id"):
+                    json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"] = cur.get("bot_id")
+                if "workflow_id" in cur:
+                    json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"] = cur.get("workflow_id") or ""
+                if json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"].get("workflow_id", "") == "":
+                    json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"] = False
+                if cur.get("openai_option"):
+                    json_data["payload"]["dialog_attributes"]["cfg"]["openai_option"] = cur.get("openai_option")
+        except Exception:
             pass
-            #end金三
-            # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7550138354483298347"#
-            # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7549142130376671267"
-            # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7411071327182438412"
-            # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7601036330500669467"
-            #json_data["payload"]["inbound_attributes"]["vad_silence"] = 1000
-        elif dev_type == "7PIN_coze":
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7550138354483298347"#
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7549142130376671267"
-            json_data["payload"]["dialog_attributes"]["provider"]="qipai"
-        #
-        elif dev_type == 'momo':#食梦貘
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7491256313561825332"
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]=""
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"]=False
-            if "bot_id" in self.VC_TTS_voice_type[self.VC_TTS_voice_key]:
-                json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]=self.VC_TTS_voice_type[self.VC_TTS_voice_key]["bot_id"]
-                if "workflow_id" in self.VC_TTS_voice_type[self.VC_TTS_voice_key]:
-                    json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]= self.VC_TTS_voice_type[self.VC_TTS_voice_key]["workflow_id"]
-                else:
-                    json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]=""
-                if json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"] == "":
-                    json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"]=False
-            
 
-            keywords = []#热词
-            for key in self.VC_TTS_voice_type:
-                keywords.append(key) 
-            json_data["payload"]["inbound_attributes"]["cfg"]["keywords"] = keywords
-        elif dev_type == 'sjgq':#四季甘泉
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7472201279826690111"
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="472203898494500914"
+        try:
+            if "vc_config" in globals() and vc_config:
+                p = vc_config.get_attr("DIALOG_PROVIDER_DEFAULT", None)
+                if p:
+                    json_data["payload"]["dialog_attributes"]["provider"] = p
+        except Exception:
+            pass
+
+        try:
+            if "vc_config" in globals() and vc_config and vc_config.get_bool("KEYWORDS_FROM_VOICE_TYPE", False):
+                keywords = []
+                for key in self.VC_TTS_voice_type:
+                    keywords.append(key)
+                json_data["payload"]["inbound_attributes"]["cfg"]["keywords"] = keywords
+        except Exception:
             pass
-        elif dev_type == 'szbst':#深圳百事通
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7469964258592931852"
-            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7469968083063603241"
-        elif dev_type == 'jswm' or dev_type == 'jswm_BOX':#金三完美
-            #json_data["payload"]["device_id"]= "WangQunTestID"
-            if self.VC_TTS_voice_type[self.VC_TTS_voice_key]["bot_id"] !="":
-                json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]=self.VC_TTS_voice_type[self.VC_TTS_voice_key]["bot_id"]
-            if self.VC_TTS_voice_type[self.VC_TTS_voice_key]["workflow_id"] == "":
-                json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"]=False
-                json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]= ""             
-            else:
-                json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]= self.VC_TTS_voice_type[self.VC_TTS_voice_key]["workflow_id"]
-            if self.VC_TTS_voice_type[self.VC_TTS_voice_key]["openai_option"] :
-                json_data["payload"]["dialog_attributes"]["cfg"]["openai_option"] =self.VC_TTS_voice_type[self.VC_TTS_voice_key]["openai_option"]
-            keywords = []#热词
-            for key in self.VC_TTS_voice_type:
-                keywords.append(key) 
-            json_data["payload"]["inbound_attributes"]["cfg"]["keywords"] = keywords
         if self.dialog_attributes_provider != None:
             json_data["payload"]["dialog_attributes"]["provider"] = self.dialog_attributes_provider
         if self.commands_mode !=0 :
@@ -7043,7 +7253,10 @@ class AI_VC(Abstract):
             return
         print("kws_even_cb")
         if self.VC_mode == 1: 
-            tts_str = "请您按住圆形的按钮开始讲话,讲完松开即可 "
+            try:
+                tts_str = vc_config.get_attr("KWS_PTT_HINT", "请您按住圆形的按钮开始讲话,讲完松开即可 ")
+            except Exception:
+                tts_str = "请您按住圆形的按钮开始讲话,讲完松开即可 "
             EventMesh.publish("play_tts",[tts_str,1]) 
             return
         if self.VC_mode == 0:
@@ -7054,15 +7267,7 @@ class AI_VC(Abstract):
                     EventMesh.publish("stop_voice_record")#停止静默录音
             self.aud.aud_tone_play(10,400)
             # EventMesh.publish("audio_montage_play",["chenggong.mp3"])  
-            if PRESS_AUDIO_MODE == 1:
-                if dev_type == "7PIN" or dev_type == "7PIN_1_5" :
-                    # self.aud.aud_tone_play(10,200)
-                    pass
             self.Close()
-            if PRESS_AUDIO_MODE == 0:
-                if dev_type == "7PIN" or dev_type == "7PIN_1_5":
-                    pass
-                    # self.chenggong_tone()
             # if dev_type == "7PIN" :
             #     self.aud.aud_tone_play(10,400)#播放按键音
             #self.aud.aud_tone_play(10,200)#播放按键音
@@ -7248,7 +7453,7 @@ class AI_VC(Abstract):
                 self.AI_VC_send_data_queue.clear()
             if self.AI_ASR_send_data_queue.empty()!=True:
                 self.AI_ASR_send_data_queue.clear()
-            EventMesh.publish("open_led_all")
+            EventMesh.publish("set_led_state", {"ai_state": "thinking"})
             self.AI_ASR_send_buf_len = 0
             self._uplink_request_stop("play_single_voice_cb")
             self.websocket_deconnect_VC()
@@ -7294,7 +7499,7 @@ class AI_VC(Abstract):
                 self.AI_VC_send_data_queue.clear()
             if self.AI_ASR_send_data_queue.empty()!=True:
                 self.AI_ASR_send_data_queue.clear()
-            EventMesh.publish("open_led_all")
+            EventMesh.publish("set_led_state", {"ai_state": "thinking"})
             self.AI_ASR_send_buf_len = 0
             self._uplink_request_stop("play_new_voice_cb")
             self.websocket_deconnect_VC()
@@ -7329,7 +7534,7 @@ class AI_VC(Abstract):
                 self.AI_VC_send_data_queue.clear()
             if self.AI_ASR_send_data_queue.empty()!=True:
                 self.AI_ASR_send_data_queue.clear()
-            EventMesh.publish("open_led_all")
+            EventMesh.publish("set_led_state", {"ai_state": "thinking"})
             self.AI_ASR_send_buf_len = 0
             self._uplink_request_stop("play_his_voice_cb")
             self.websocket_deconnect_VC()
@@ -7367,7 +7572,7 @@ class AI_VC(Abstract):
                 self.AI_VC_send_data_queue.clear()
             if self.AI_ASR_send_data_queue.empty()!=True:
                 self.AI_ASR_send_data_queue.clear()
-            EventMesh.publish("open_led_all")
+            EventMesh.publish("set_led_state", {"ai_state": "thinking"})
             self.AI_ASR_send_buf_len = 0
             self._uplink_request_stop("play_wait_voice_cb")
             self.websocket_deconnect_VC()
@@ -7409,7 +7614,7 @@ class AI_VC(Abstract):
                 self.AI_VC_send_data_queue.clear()
             if self.AI_ASR_send_data_queue.empty()!=True:
                 self.AI_ASR_send_data_queue.clear()
-            EventMesh.publish("open_led_all")
+            EventMesh.publish("set_led_state", {"ai_state": "thinking"})
             self.AI_ASR_send_buf_len = 0
             self._uplink_request_stop("play_music_cb")
             self.websocket_deconnect_VC()
@@ -7433,7 +7638,7 @@ class AI_VC(Abstract):
                 self.AI_VC_send_data_queue.clear()
             if self.AI_ASR_send_data_queue.empty()!=True:
                 self.AI_ASR_send_data_queue.clear()
-            EventMesh.publish("open_led_all")
+            EventMesh.publish("set_led_state", {"ai_state": "thinking"})
             self.AI_ASR_send_buf_len = 0
             self._uplink_request_stop("play_trans_tts_cb")
             self.websocket_deconnect_VC()
@@ -7625,9 +7830,18 @@ class AI_VC(Abstract):
         self._tts_pending_ms = 0
         self._vc_session_started = 0
         self._ptt_audio_created = 0
+        # Power 短按停止对话后,再次按 AI 需要新建 dialog_id:清理本轮 dialog/session 标识
+        try:
+            self._cur_dialog_id = ""
+        except Exception:
+            pass
+        try:
+            self._cur_sid = ""
+        except Exception:
+            pass
         self.is_ruppt_tts = 0#打断标志位清零
         print("ai_VC Close1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
-        EventMesh.publish("close_led")
+        EventMesh.publish("set_led_state", {"ai_state": "idle"})
         self.tts_in_data_len = 0
         self.tts_out_data_len = 0
         #必须先销毁线程,不然线程会容易报错
@@ -7683,7 +7897,7 @@ class AI_VC(Abstract):
         print("关闭但是没有重置语音标志位")
         self.AI_ASR_send_buf_len = 0
         #self.AI_WS_connect_Queue.put(self.AI_client_VC)
-        EventMesh.publish("close_led")
+        EventMesh.publish("set_led_state", {"ai_state": "idle"})
         self.VC_init()
         self.VC_satrt_flag = 0
         # try:
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN/default_config.py
new file mode 100644 (file)
index 0000000..456c568
--- /dev/null
@@ -0,0 +1,54 @@
+# 设备分支配置:7PIN\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "7PIN"\r
+\r
+LED_GPIO = ("GPIO36", "GPIO44", "GPIO43")  # (R, G, B)\r
+UART_SUPPORTED = False\r
+LANG = "zh"\r
+\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None\r
+PIN_MOT_GPIO = None\r
+AUDIO_QDAI_CFG = None\r
+\r
+EXTINT_AI_GPIO = "GPIO22"\r
+PWK_KEY_GPIO = "GPIO26"\r
+\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None\r
+PIN_WAKEUP_BT_GPIO = None\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 5\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "你好,我来了"\r
+VAD_SILENCE_DEFAULT = 300\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = None\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/agent"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = False\r
+UPLOAD_START_TONE_ENABLED = False\r
+THINKING_LED_MODE = "flicker_blue_green"\r
+VAD_ACTIVE_BLUE_LED = True\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+BT_VOICE_FEATURES_ENABLED = False\r
+POWEROFF_CMD_CLOSE_ONLY = True\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+DIALOG_BOT_OPTION = None\r
+DIALOG_PROVIDER_DEFAULT = None\r
+KEYWORDS_FROM_VOICE_TYPE = False\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = "U:/static/start.mp3"\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_1_5/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_1_5/default_config.py
new file mode 100644 (file)
index 0000000..5a8b234
--- /dev/null
@@ -0,0 +1,54 @@
+# 设备分支配置:7PIN_1_5\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "7PIN_1_5"\r
+\r
+LED_GPIO = ("GPIO28", "GPIO44", "GPIO30")  # (R, G, B)\r
+UART_SUPPORTED = True\r
+LANG = "zh"\r
+\r
+BT_POWER_MOTOR_ENABLED = True\r
+PIN_BT_ON_GPIO = "GPIO31"\r
+PIN_MOT_GPIO = "GPIO36"\r
+AUDIO_QDAI_CFG = (1, 0, 0, 2, 0, 1, 1, 1)\r
+\r
+EXTINT_AI_GPIO = "GPIO43"\r
+PWK_KEY_GPIO = "GPIO41"\r
+\r
+BT_WAKEUP_4G_ENABLED = True\r
+EXTINT_WAKEUP_CTA1_GPIO = "GPIO22"\r
+PIN_WAKEUP_BT_GPIO = "GPIO21"\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 5\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "你好,我来了"\r
+VAD_SILENCE_DEFAULT = 1000\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = None\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/agent"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = True\r
+UPLOAD_START_TONE_ENABLED = False\r
+THINKING_LED_MODE = "flicker_blue_green"\r
+VAD_ACTIVE_BLUE_LED = True\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+BT_VOICE_FEATURES_ENABLED = True\r
+POWEROFF_CMD_CLOSE_ONLY = True\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+DIALOG_BOT_OPTION = None\r
+DIALOG_PROVIDER_DEFAULT = None\r
+KEYWORDS_FROM_VOICE_TYPE = False\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = None\r
+KEY_PRESS_TONE_DELAY_MS = 300\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK/default_config.py
new file mode 100644 (file)
index 0000000..01cd4ca
--- /dev/null
@@ -0,0 +1,53 @@
+# 设备分支配置:7PIN_BK\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "7PIN_BK"\r
+\r
+LED_GPIO = ("GPIO36", "GPIO21", "GPIO19")  # (R, G, B)\r
+UART_SUPPORTED = False\r
+LANG = "zh"\r
+\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None\r
+PIN_MOT_GPIO = None\r
+AUDIO_QDAI_CFG = None\r
+\r
+EXTINT_AI_GPIO = "GPIO22"\r
+PWK_KEY_GPIO = "GPIO26"\r
+\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None\r
+PIN_WAKEUP_BT_GPIO = None\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 3\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "-bot_name来了!我们一起来愉快地聊天吧!"\r
+VAD_SILENCE_DEFAULT = 300\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = "童"\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/chat"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = False\r
+UPLOAD_START_TONE_ENABLED = True\r
+THINKING_LED_MODE = "open_red_green"\r
+VAD_ACTIVE_BLUE_LED = False\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+BT_VOICE_FEATURES_ENABLED = False\r
+POWEROFF_CMD_CLOSE_ONLY = False\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+DIALOG_BOT_OPTION = {"bot_id":"7411071327182438412","workflow_id":"7468577560454496295","use_workflow":True}\r
+DIALOG_PROVIDER_DEFAULT = None\r
+KEYWORDS_FROM_VOICE_TYPE = True\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = None\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK_EU/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK_EU/default_config.py
new file mode 100644 (file)
index 0000000..265ec69
--- /dev/null
@@ -0,0 +1,54 @@
+# 设备分支配置:7PIN_BK_EU\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "7PIN_BK_EU"\r
+\r
+LED_GPIO = ("GPIO36", "GPIO8", "GPIO19")  # (R, G, B)\r
+UART_SUPPORTED = False\r
+LANG = "en"\r
+\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None\r
+PIN_MOT_GPIO = None\r
+AUDIO_QDAI_CFG = None\r
+\r
+EXTINT_AI_GPIO = "GPIO5"\r
+PWK_KEY_GPIO = "GPIO41"\r
+\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None\r
+PIN_WAKEUP_BT_GPIO = None\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 3\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "Hi. May I help you ?"\r
+VAD_SILENCE_DEFAULT = 300\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = "童"\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/chat"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = False\r
+UPLOAD_START_TONE_ENABLED = True\r
+THINKING_LED_MODE = "open_red_green"\r
+VAD_ACTIVE_BLUE_LED = False\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "change dialogue mode"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "pushtalk mode"\r
+BT_VOICE_FEATURES_ENABLED = False\r
+POWEROFF_CMD_CLOSE_ONLY = False\r
+KWS_PTT_HINT = "Please press and hold the button to speak. "\r
+DIALOG_BOT_OPTION = {"bot_id":"7493368740600446995","workflow_id":"7493369551587213323","use_workflow":True}\r
+DIALOG_PROVIDER_DEFAULT = None\r
+KEYWORDS_FROM_VOICE_TYPE = False\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = None\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+PTT_HINT = "Please press and hold the button to speak. "\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK_coze/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK_coze/default_config.py
new file mode 100644 (file)
index 0000000..b667161
--- /dev/null
@@ -0,0 +1,53 @@
+# 设备分支配置:7PIN_BK_coze\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "7PIN_BK_coze"\r
+\r
+LED_GPIO = ("GPIO36", "GPIO21", "GPIO19")  # (R, G, B)\r
+UART_SUPPORTED = False\r
+LANG = "zh"\r
+\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None\r
+PIN_MOT_GPIO = None\r
+AUDIO_QDAI_CFG = None\r
+\r
+EXTINT_AI_GPIO = "GPIO22"\r
+PWK_KEY_GPIO = "GPIO26"\r
+\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None\r
+PIN_WAKEUP_BT_GPIO = None\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 3\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "-bot_name来了!我们一起来愉快地聊天吧!"\r
+VAD_SILENCE_DEFAULT = 300\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = "童"\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/coze"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = False\r
+UPLOAD_START_TONE_ENABLED = True\r
+THINKING_LED_MODE = "open_red_green"\r
+VAD_ACTIVE_BLUE_LED = False\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+BT_VOICE_FEATURES_ENABLED = False\r
+POWEROFF_CMD_CLOSE_ONLY = False\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+DIALOG_BOT_OPTION = {"bot_id":"7411071327182438412","workflow_id":"7468577560454496295","use_workflow":True}\r
+DIALOG_PROVIDER_DEFAULT = None\r
+KEYWORDS_FROM_VOICE_TYPE = True\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = None\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_coze/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_coze/default_config.py
new file mode 100644 (file)
index 0000000..0163961
--- /dev/null
@@ -0,0 +1,54 @@
+# 设备分支配置:7PIN_coze\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "7PIN_coze"\r
+\r
+LED_GPIO = ("GPIO36", "GPIO44", "GPIO43")  # (R, G, B)\r
+UART_SUPPORTED = False\r
+LANG = "zh"\r
+\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None\r
+PIN_MOT_GPIO = None\r
+AUDIO_QDAI_CFG = None\r
+\r
+EXTINT_AI_GPIO = "GPIO22"\r
+PWK_KEY_GPIO = "GPIO26"\r
+\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None\r
+PIN_WAKEUP_BT_GPIO = None\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 5\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "你好,我来了"\r
+VAD_SILENCE_DEFAULT = 1000\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = None\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/coze"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = False\r
+UPLOAD_START_TONE_ENABLED = False\r
+THINKING_LED_MODE = "flicker_blue_green"\r
+VAD_ACTIVE_BLUE_LED = True\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+BT_VOICE_FEATURES_ENABLED = False\r
+POWEROFF_CMD_CLOSE_ONLY = True\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+DIALOG_BOT_OPTION = {"bot_id":"7550138354483298347","workflow_id":"7549142130376671267","use_workflow":True}\r
+DIALOG_PROVIDER_DEFAULT = "qipai"\r
+KEYWORDS_FROM_VOICE_TYPE = False\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = None\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/G10/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/G10/default_config.py
new file mode 100644 (file)
index 0000000..81c9670
--- /dev/null
@@ -0,0 +1,53 @@
+# 设备分支配置:G10\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "G10"\r
+\r
+LED_GPIO = ("GPIO36", "GPIO44", "GPIO21")  # (R, G, B)\r
+UART_SUPPORTED = False\r
+LANG = "zh"\r
+\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None\r
+PIN_MOT_GPIO = None\r
+AUDIO_QDAI_CFG = None\r
+\r
+EXTINT_AI_GPIO = "GPIO19"\r
+PWK_KEY_GPIO = "GPIO26"\r
+\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None\r
+PIN_WAKEUP_BT_GPIO = None\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 5\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "已开机,您好!我是北科瑞讯智能 AI bot_name"\r
+VAD_SILENCE_DEFAULT = 300\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = None\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/chat"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = False\r
+UPLOAD_START_TONE_ENABLED = True\r
+THINKING_LED_MODE = "open_red_green"\r
+VAD_ACTIVE_BLUE_LED = False\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+BT_VOICE_FEATURES_ENABLED = False\r
+POWEROFF_CMD_CLOSE_ONLY = False\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+DIALOG_BOT_OPTION = {"bot_id":"7411071327182438412","workflow_id":"7468577560454496295","use_workflow":True}\r
+DIALOG_PROVIDER_DEFAULT = None\r
+KEYWORDS_FROM_VOICE_TYPE = True\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = None\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/README.md b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/README.md
new file mode 100644 (file)
index 0000000..5a00599
--- /dev/null
@@ -0,0 +1,9 @@
+本目录用于**保留所有设备分支的配置文件**,供编译/打包阶段按参数选择。\r
+\r
+运行时加载优先级仍然是:\r
+- `usr/default_config.py`(或兼容误拼 `usr/defualt_config.py`)\r
+- `core/default_config.py`(freeze 内置)\r
+\r
+这里的文件**默认不会被运行时 import**,也**不要求 freeze**;你可以在编译阶段把某个\r
+`configs/<DEV_TYPE>/default_config.py` 复制为 `core/default_config.py` 来生效。\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/csh/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/csh/default_config.py
new file mode 100644 (file)
index 0000000..716c77c
--- /dev/null
@@ -0,0 +1,54 @@
+# 设备分支配置:csh\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "csh"\r
+\r
+LED_GPIO = ("GPIO36", "GPIO21", "GPIO19")  # (R, G, B)\r
+UART_SUPPORTED = False\r
+LANG = "zh"\r
+\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None\r
+PIN_MOT_GPIO = None\r
+AUDIO_QDAI_CFG = None\r
+\r
+EXTINT_AI_GPIO = "GPIO22"\r
+PWK_KEY_GPIO = "GPIO26"\r
+\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None\r
+PIN_WAKEUP_BT_GPIO = None\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 5\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "欢迎使用助手小福"\r
+VAD_SILENCE_DEFAULT = 300\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = None\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/chat"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = False\r
+UPLOAD_START_TONE_ENABLED = True\r
+THINKING_LED_MODE = "open_red_green"\r
+VAD_ACTIVE_BLUE_LED = False\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+BT_VOICE_FEATURES_ENABLED = False\r
+POWEROFF_CMD_CLOSE_ONLY = False\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+DIALOG_BOT_OPTION = {"bot_id":"7490852493640384538","workflow_id":"","use_workflow":False}\r
+DIALOG_PROVIDER_DEFAULT = None\r
+KEYWORDS_FROM_VOICE_TYPE = False\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = None\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/jswm/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/jswm/default_config.py
new file mode 100644 (file)
index 0000000..6ff926c
--- /dev/null
@@ -0,0 +1,53 @@
+# 设备分支配置:jswm\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "jswm"\r
+\r
+LED_GPIO = ("GPIO36", "GPIO44", "GPIO21")  # (R, G, B)\r
+UART_SUPPORTED = False\r
+LANG = "zh"\r
+\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None\r
+PIN_MOT_GPIO = None\r
+AUDIO_QDAI_CFG = None\r
+\r
+EXTINT_AI_GPIO = "GPIO26"\r
+PWK_KEY_GPIO = "GPIO19"\r
+\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None\r
+PIN_WAKEUP_BT_GPIO = None\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 5\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = True\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "我来陪你聊天了"\r
+VAD_SILENCE_DEFAULT = 300\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = None\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/agent"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = False\r
+UPLOAD_START_TONE_ENABLED = True\r
+THINKING_LED_MODE = "open_red_green"\r
+VAD_ACTIVE_BLUE_LED = False\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+BT_VOICE_FEATURES_ENABLED = False\r
+POWEROFF_CMD_CLOSE_ONLY = False\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+DIALOG_BOT_OPTION = None\r
+DIALOG_PROVIDER_DEFAULT = None\r
+KEYWORDS_FROM_VOICE_TYPE = True\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = None\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/jswm_BOX/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/jswm_BOX/default_config.py
new file mode 100644 (file)
index 0000000..acd1956
--- /dev/null
@@ -0,0 +1,53 @@
+# 设备分支配置:jswm_BOX\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "jswm_BOX"\r
+\r
+LED_GPIO = ("GPIO36", "GPIO44", "GPIO21")  # (R, G, B)\r
+UART_SUPPORTED = False\r
+LANG = "zh"\r
+\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None\r
+PIN_MOT_GPIO = None\r
+AUDIO_QDAI_CFG = None\r
+\r
+EXTINT_AI_GPIO = "GPIO22"\r
+PWK_KEY_GPIO = "GPIO26"\r
+\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None\r
+PIN_WAKEUP_BT_GPIO = None\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 5\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = True\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "我来陪你聊天了"\r
+VAD_SILENCE_DEFAULT = 300\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = None\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/agent"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = False\r
+UPLOAD_START_TONE_ENABLED = True\r
+THINKING_LED_MODE = "open_red_green"\r
+VAD_ACTIVE_BLUE_LED = False\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+BT_VOICE_FEATURES_ENABLED = False\r
+POWEROFF_CMD_CLOSE_ONLY = False\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+DIALOG_BOT_OPTION = None\r
+DIALOG_PROVIDER_DEFAULT = None\r
+KEYWORDS_FROM_VOICE_TYPE = True\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = None\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/momo/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/momo/default_config.py
new file mode 100644 (file)
index 0000000..4ef846b
--- /dev/null
@@ -0,0 +1,54 @@
+# 设备分支配置:momo\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "momo"\r
+\r
+LED_GPIO = ("GPIO36", "GPIO21", "GPIO19")  # (R, G, B)\r
+UART_SUPPORTED = False\r
+LANG = "zh"\r
+\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None\r
+PIN_MOT_GPIO = None\r
+AUDIO_QDAI_CFG = None\r
+\r
+EXTINT_AI_GPIO = "GPIO22"\r
+PWK_KEY_GPIO = "GPIO26"\r
+\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None\r
+PIN_WAKEUP_BT_GPIO = None\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 5\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "DuloDulo,我是上古神兽食梦貘,主人可以叫我momo,我来自《山海经》,是一只以梦为食的神秘灵兽,每当颜色朦胧、人们入睡时,我就会悄悄飞到人们的床头,用我长长的鼻子把噩梦统统吞噬掉,只留下甜甜的美梦。从今往后,就由我守护在主人身边,一起度过每一个星河璀璨的夜晚。"\r
+VAD_SILENCE_DEFAULT = 300\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = "女"\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/chat"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = False\r
+UPLOAD_START_TONE_ENABLED = True\r
+THINKING_LED_MODE = "open_red_green"\r
+VAD_ACTIVE_BLUE_LED = False\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+BT_VOICE_FEATURES_ENABLED = False\r
+POWEROFF_CMD_CLOSE_ONLY = False\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+DIALOG_BOT_OPTION = {"bot_id":"7491256313561825332","workflow_id":"","use_workflow":False}\r
+DIALOG_PROVIDER_DEFAULT = None\r
+KEYWORDS_FROM_VOICE_TYPE = True\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = None\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/sjgq/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/sjgq/default_config.py
new file mode 100644 (file)
index 0000000..05dd4da
--- /dev/null
@@ -0,0 +1,54 @@
+# 设备分支配置:sjgq\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "sjgq"\r
+\r
+LED_GPIO = ("GPIO36", "GPIO21", "GPIO19")  # (R, G, B)\r
+UART_SUPPORTED = False\r
+LANG = "zh"\r
+\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None\r
+PIN_MOT_GPIO = None\r
+AUDIO_QDAI_CFG = None\r
+\r
+EXTINT_AI_GPIO = "GPIO22"\r
+PWK_KEY_GPIO = "GPIO26"\r
+\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None\r
+PIN_WAKEUP_BT_GPIO = None\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 5\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "您好!我是巴马四季甘泉的智能助手。我可以为你解答各种各样的问题,像是有关巴马四季甘泉知识库、中基长寿科学产品、卫斯曼院士国际先进医疗中心的问题,还有日常生活与工作、旅游信息、健康咨询、教育与学习、情感交流、全球资讯、世界文化等方面的问题哦。你有没有这方面的问题想要问我呀?"\r
+VAD_SILENCE_DEFAULT = 300\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = None\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/chat"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = False\r
+UPLOAD_START_TONE_ENABLED = True\r
+THINKING_LED_MODE = "open_red_green"\r
+VAD_ACTIVE_BLUE_LED = False\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+BT_VOICE_FEATURES_ENABLED = False\r
+POWEROFF_CMD_CLOSE_ONLY = False\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+DIALOG_BOT_OPTION = {"bot_id":"7472201279826690111","workflow_id":"472203898494500914","use_workflow":True}\r
+DIALOG_PROVIDER_DEFAULT = None\r
+KEYWORDS_FROM_VOICE_TYPE = False\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = None\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/szbst/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/szbst/default_config.py
new file mode 100644 (file)
index 0000000..83e79e6
--- /dev/null
@@ -0,0 +1,54 @@
+# 设备分支配置:szbst\r
+# 仅用于编译/打包阶段选择,不作为运行时加载入口。\r
+\r
+DEV_TYPE = "szbst"\r
+\r
+LED_GPIO = ("GPIO36", "GPIO21", "GPIO19")  # (R, G, B)\r
+UART_SUPPORTED = False\r
+LANG = "zh"\r
+\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None\r
+PIN_MOT_GPIO = None\r
+AUDIO_QDAI_CFG = None\r
+\r
+EXTINT_AI_GPIO = "GPIO22"\r
+PWK_KEY_GPIO = "GPIO26"\r
+\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None\r
+PIN_WAKEUP_BT_GPIO = None\r
+\r
+# ---- 按键/防抖差异 ----\r
+KEY_RELEASE_DEBOUNCE_COUNT = 5\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
+\r
+# ---- 开机提示/语音参数默认值 ----\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "深圳百事通来了!请问您有什么需要我帮忙的吗?"\r
+VAD_SILENCE_DEFAULT = 300\r
+VC_TTS_VOICE_TYPE_DEFAULT = None\r
+VC_TTS_VOICE_KEY_DEFAULT = None\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/chat"\r
+\r
+# 是否支持蓝牙 OTA\r
+BT_OTA_ENABLED = False\r
+UPLOAD_START_TONE_ENABLED = True\r
+THINKING_LED_MODE = "open_red_green"\r
+VAD_ACTIVE_BLUE_LED = False\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+BT_VOICE_FEATURES_ENABLED = False\r
+POWEROFF_CMD_CLOSE_ONLY = False\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+DIALOG_BOT_OPTION = {"bot_id":"7469964258592931852","workflow_id":"7469968083063603241","use_workflow":True}\r
+DIALOG_PROVIDER_DEFAULT = None\r
+KEYWORDS_FROM_VOICE_TYPE = False\r
+\r
+# ---- 按键音/提示音策略 ----\r
+KEY_PRESS_TONE_FILE = None\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+\r
index a3844a6..b905e29 100644 (file)
-class PROTOCOL:\r
-    LK_SEND = "LK_SEND"\r
-    LK_RECV = "LK_RECV"\r
-\r
-    PING_SEND = "PING_SEND"\r
-    PING_RECV = "PING_RECV"\r
-\r
-    KA_SEND = "KA_SEND"\r
-    KA_RECV = "KA_RECV"\r
-\r
-    UD_SEND = "UD_SEND"\r
-    UD_RECV = "UD_RECV"\r
-\r
-    CR_SEND = "CR_SEND"\r
-    CR_RECV = "CR_RECV"\r
-\r
-    AL_SEND = "AL_SEND"\r
-    AL_RECV = "AL_RECV"\r
-\r
-    FIND_SEND = "FIND_SEND"\r
-    FIND_RECV = "FIND_RECV"\r
-\r
-    POWEROFF_SEND = "POWEROFF_SEND"\r
-    POWEROFF_RECV = "POWEROFF_RECV"\r
-\r
-    PHL_SEND = "PHL_SEND"\r
-    PHL_RECV = "PHL_RECV"\r
-\r
-    TK_SEND = "TK_SEND"\r
-    TK_RECV = "TK_RECV"\r
-\r
-    TKS_SEND = "TKS_SEND"\r
-    TKS_RECV = "TKS_RECV"\r
-\r
-    MESSAGE_SEND = "MESSAGE_SEND"\r
-    MESSAGE_RECV = "MESSAGE_RECV"\r
-\r
-    WT_SEND = "WT_SEND"\r
-    WT_RECV = "WT_RECV"\r
-\r
-    REMIND_SEND = "REMIND_SEND"\r
-    REMIND_RECV = "REMIND_RECV"\r
-\r
-    HRTSTART_SEND = "hrtstart_SEND"\r
-    HRTSTART_RECV = "hrtstart_RECV"\r
-\r
-    HEART_SEND = "heart_SEND"\r
-    HEART_RECV = "heart_RECV"\r
-    \r
-    OXYGEN_SEND = "oxygen_SEND"\r
-    OXYGEN_RECV = "oxygen_RECV"\r
-\r
-    OXSTART_SEND = "oxstart_SEND"\r
-    OXSTART_RECV = "oxstart_RECV"\r
-\r
-    TEMP_SEND = "temp_SEND"\r
-    TEMP_RECV = "temp_RECV"\r
-\r
-    DLT_SEND = "DLT_SEND"\r
-    DLT_RECV = "DLT_RECV"\r
-\r
-    UPLOAD_SEND = "UPLOAD_SEND"\r
-    UPLOAD_RECV = "UPLOAD_RECV"\r
-\r
-    CENTER_SEND = "CENTER_SEND"\r
-    CENTER_RECV = "CENTER_RECV"\r
-\r
-    MONITOR_SEND = "MONITOR_SEND"\r
-    MONITOR_RECV = "MONITOR_RECV"\r
-\r
-    SOS_SEND = "SOS_SEND"\r
-    SOS_RECV = "SOS_RECV"\r
-\r
-    BOOTOFF_SEND = "BOOTOFF_SEND"\r
-    BOOTOFF_RECV = "BOOTOFF_RECV"\r
-\r
-    WDSTART_SEND ="wdstart_SEND"\r
-    WDSTART_RECV ="wdstart_RECV"\r
-\r
-\r
-    LOWBAT_SEND = "LOWBAT_SEND"\r
-    LOWBAT_RECV = "LOWBAT_RECV"\r
-\r
-    TIME_SEND = "Time_SEND"\r
-    TIME_RECV = "Time_RECV"\r
-\r
-    WLKEY_SEND = "WLKEY_SEND"\r
-    WLKEY_RECV = "WLKEY_RECV"\r
-\r
-    SILENCETIME2_SEND = "SILENCETIME2_SEND"\r
-    SILENCETIME2_RECV = "SILENCETIME2_RECV"\r
-\r
-    KEYBRD_SEND = "KEYBRD_SEND"\r
-    KEYBRD_RECV = "KEYBRD_RECV"\r
-\r
-    FALLDOWN_SEND = "FALLDOWN_SEND"\r
-    FALLDOWN_RECV = "FALLDOWN_RECV"\r
-    \r
-    HELP_SEND = "HELP_SEND"\r
-    HELP_RECV = "HELP_RECV"\r
-    \r
-    REMOVE_SEND = "REMOVE_SEND"\r
-    REMOVE_RECV = "REMOVE_RECV"\r
-\r
-    BLOOD_SEND = "blood_SEND"\r
-    BLOOD_RECV = "blood_RECV"\r
-\r
-    BLDSTART_SEND ="bldstart_SEND"\r
-    BLDSTART_RECV = "bldstart_RECV"\r
-\r
-    BGSTART_SEND = "bgstart_SEND"\r
-    BGSTART_RECV = "bgstart_RECV"\r
-\r
-    BLOODGLUSOCE_SEND = "bloodglucose_SEND"\r
-    BLOODGLUSOCE_RECV = "bloodglucose_RECV"\r
-\r
-    REMIND_CH_DRINK_SEND = "REMIND_CH_DRINK_SEND"\r
-    REMIND_CH_DRINK_RECV = "REMIND_CH_DRINK_RECV"\r
-\r
-    REMIND_CH_MEDICINE2_SEND = "REMIND_CH_MEDICINE2_SEND"\r
-    REMIND_CH_MEDICINE2_RECV = "REMIND_CH_MEDICINE2_RECV"\r
-\r
-    REMIND_CH_HOME_SEND = "REMIND_CH_HOME_SEND"\r
-    REMIND_CH_HOME_RECV = "REMIND_CH_HOME_RECV"\r
-\r
-    REMIND_CH_WAKEUP_SEND = "REMIND_CH_WAKEUP_SEND"\r
-    REMIND_CH_WAKEUP_RECV = "REMIND_CH_WAKEUP_RECV"\r
-\r
-    REMIND_CH_SLEEP_SEND = "REMIND_CH_SLEEP_SEND"\r
-    REMIND_CH_SLEEP_RECV = "REMIND_CH_SLEEP_RECV"\r
-\r
-    REMIND_CH_REST_SEND = "REMIND_CH_REST_SEND"\r
-    REMIND_CH_REST_RECV = "REMIND_CH_REST_RECV"\r
-\r
-    SLEEP_DATA_SEND = "SleepReport_SEND"\r
-    SLEEP_DATA_RECV = "SleepReport_RECV"\r
-\r
-    SLEEPTIME_SEND = "SLEEPTIME_SEND"\r
-    SLEEPTIME_RECV = "SLEEPTIME_RECV"\r
-\r
-    FACTORY_SEND = "FACTORY_SEND"\r
-    FACTORY_RECV = "FACTORY_RECV"\r
-\r
-    RESET_SEND = "RESET_SEND"\r
-    RESET_RECV = "RESET_RECV"\r
-\r
-    REMIND_CH_SIT_SEND = "REMIND_CH_SIT_SEND"\r
-    REMIND_CH_SIT_RECV = "REMIND_CH_SIT_RECV"\r
-\r
-    SCREEN_SHOW_SEND = "SCREEN_SHOW_SEND"\r
-    SCREEN_SHOW_RECV = "SCREEN_SHOW_RECV"\r
-\r
-    JPREG_SEND = "JPREG_SEND"\r
-    JPREG_RECV = "JPREG_RECV"\r
-\r
-    MEMBERS_SEND = "MEMBERS_SEND"\r
-    MEMBERS_RECV = "MEMBERS_RECV"\r
-\r
-    CALLING_SEND = "CALLING_SEND"\r
-    CALLING_RECV = "CALLING_RECV"\r
-    \r
-\r
-    RCALLING_SEND  = "RCALLING_SEND"\r
-    RCALLING_RECV  = "RCALLING_RECV"\r
-\r
-    AGTALK_SEND = "AGTALK_SEND"\r
-    AGTALK_RECV = "AGTALK_RECV"\r
-\r
-    RTALK_SEND = "RTALK_SEND"\r
-    RTALK_RECV = "RTALK_RECV"\r
-\r
-    JMEMBERS_SEND = "JMEMBERS_SEND"\r
-    JMEMBERS_RECV = "JMEMBERS_RECV"\r
-\r
-    RINGING_SEND = "RINGING_SEND"\r
-    RINGING_RECV = "RINGING_RECV"\r
-\r
-    HANGUP_SEND = "HANGUP_SEND"\r
-    HANGUP_RECV = "HANGUP_RECV"\r
-\r
-    CALLCANCEL_SEND ="CALLCANCEL_SEND"\r
-    CALLCANCEL_RECV = "CALLCANCEL_RECV"\r
-    \r
-\r
-# 服务器环境配置,切换只需修改 SERVER_ENV\r
-# "beike" = 北科测试, "kxc" = 科学城demo\r
-SERVER_ENV = "beike_dev"\r
-\r
-_SERVER_CFG = {\r
-    "beike": {\r
-        "dmp_base": "http://dmp.raisound.com/bz-api",\r
-        "amp_server": "115.190.94.208:22080",\r
-        "iot_ws_url": "ws://wsiot-nocdn.raisound.com/ws-hub/dev/v1",\r
-    },\r
-    "kxc": {\r
-        "dmp_base": "http://kxc.raisound.com/bz-api",\r
-        "amp_server": "kxc.raisound.com/amp-api",\r
-        "iot_ws_url": "ws://kxc.raisound.com/iot-api/ws-hub/dev/v1",\r
-    },\r
-    "beike_dev": {\r
-        "dmp_base": "http://dmp-dev.raisound.com/dmp-api",\r
-        "iot_ws_url": "ws://dmp-dev.raisound.com/iot-api/ws-hub/dev/v1",\r
-        "amp_server": "118.145.158.207:22080",        \r
-    },\r
-}\r
-\r
-DMP_BASE = _SERVER_CFG[SERVER_ENV]["dmp_base"]\r
-AMP_SERVER = _SERVER_CFG[SERVER_ENV]["amp_server"]\r
-IOT_WS_URL = _SERVER_CFG[SERVER_ENV]["iot_ws_url"]\r
-\r
-\r
-class EVENT:\r
-    CHANNEL_SOCKET_SEND = "CHANNEL_SOCKET_SEND"\r
-    START_LOCATION = "START_LOCATION" \r
-    START_LOCATION_TEST = "START_LOCATION_TEST" \r
-    READ_LOCATION = "READ_LOCATION"  \r
-    CLOSE_LOCATION = "CLOSE_LOCATION"\r
-    GPSOPEN = "GPSOPEN"\r
-    GPSCLOSE = "GPSCLOSE"\r
-    GPSINFO = "GPSINFO"\r
-    WIFISCANOPEN = "WIFISCANOPEN"\r
-    WIFIINFO = "WIFIINFO"\r
-\r
-    GET_KEY = "GET_KEY"\r
-    SET_KEY = "SET_KEY"\r
-    GET_IMEI = "GET_IMEI"\r
-    GET_CID = "GET_CID"\r
-    SET_CID = "SET_CID"\r
-    GET_IMSI = "GET_IMSI"\r
-    GET_PASSWORD = "GET_PASSWORD"\r
-    SET_PASSWORD = "SET_PASSWORD"\r
-    GET_BATTERY = "GET_BATTERY"\r
-    PERSISTENT_CONFIG_GET = "PERSISTENT_CONFIG_GET"\r
-    PERSISTENT_CONFIG_STORE = "PERSISTENT_CONFIG_STORE"\r
-    SET_PING = "SET_PING"\r
-    GET_PING = "GET_PING"\r
-    SET_CONNECT = "SET_CONNECT"\r
-    GET_CONNECT = "GET_CONNECT"\r
-    GET_STEP = "GET_STEP"\r
-    PUSH_STEP = "PUSH_STEP"\r
-    SYSTEM_SLEEP = "SYSTEM_SLEEP"\r
-    SYSTEM_UP = "SYSTEM_UP"\r
-    START_HEART = "START_HEART" \r
-    GET_HEART = "GET_HEART"\r
-    STOP_HEART = "STOP_HEART"\r
-    GET_WEAR = "GET_WEAR"\r
-    START_TEMP = "START_TEMP"\r
-    STOP_TEMP = "STOP_TEMP"\r
-    GET_TEMP = "GET_TEMP"\r
-    START_BLOOD_OXYGEN = "STARTT_BLOOD_OXYGEN" \r
-    GET_BLOOD_OXYGEN = "GET_BLOOD_OXYGEN"\r
-    STOP_BLOOD_OXYGEN = "STOP_BLOOD_OXYGEN"\r
-    CHANNEL_IOT_WEB_SEND = "CHANNEL_IOT_WEB_SEND"\r
-    \r
+class PROTOCOL:
+    LK_SEND = "LK_SEND"
+    LK_RECV = "LK_RECV"
+
+    PING_SEND = "PING_SEND"
+    PING_RECV = "PING_RECV"
+
+    KA_SEND = "KA_SEND"
+    KA_RECV = "KA_RECV"
+
+    UD_SEND = "UD_SEND"
+    UD_RECV = "UD_RECV"
+
+    CR_SEND = "CR_SEND"
+    CR_RECV = "CR_RECV"
+
+    AL_SEND = "AL_SEND"
+    AL_RECV = "AL_RECV"
+
+    FIND_SEND = "FIND_SEND"
+    FIND_RECV = "FIND_RECV"
+
+    POWEROFF_SEND = "POWEROFF_SEND"
+    POWEROFF_RECV = "POWEROFF_RECV"
+
+    PHL_SEND = "PHL_SEND"
+    PHL_RECV = "PHL_RECV"
+
+    TK_SEND = "TK_SEND"
+    TK_RECV = "TK_RECV"
+
+    TKS_SEND = "TKS_SEND"
+    TKS_RECV = "TKS_RECV"
+
+    MESSAGE_SEND = "MESSAGE_SEND"
+    MESSAGE_RECV = "MESSAGE_RECV"
+
+    WT_SEND = "WT_SEND"
+    WT_RECV = "WT_RECV"
+
+    REMIND_SEND = "REMIND_SEND"
+    REMIND_RECV = "REMIND_RECV"
+
+    HRTSTART_SEND = "hrtstart_SEND"
+    HRTSTART_RECV = "hrtstart_RECV"
+
+    HEART_SEND = "heart_SEND"
+    HEART_RECV = "heart_RECV"
+    
+    OXYGEN_SEND = "oxygen_SEND"
+    OXYGEN_RECV = "oxygen_RECV"
+
+    OXSTART_SEND = "oxstart_SEND"
+    OXSTART_RECV = "oxstart_RECV"
+
+    TEMP_SEND = "temp_SEND"
+    TEMP_RECV = "temp_RECV"
+
+    DLT_SEND = "DLT_SEND"
+    DLT_RECV = "DLT_RECV"
+
+    UPLOAD_SEND = "UPLOAD_SEND"
+    UPLOAD_RECV = "UPLOAD_RECV"
+
+    CENTER_SEND = "CENTER_SEND"
+    CENTER_RECV = "CENTER_RECV"
+
+    MONITOR_SEND = "MONITOR_SEND"
+    MONITOR_RECV = "MONITOR_RECV"
+
+    SOS_SEND = "SOS_SEND"
+    SOS_RECV = "SOS_RECV"
+
+    BOOTOFF_SEND = "BOOTOFF_SEND"
+    BOOTOFF_RECV = "BOOTOFF_RECV"
+
+    WDSTART_SEND ="wdstart_SEND"
+    WDSTART_RECV ="wdstart_RECV"
+
+
+    LOWBAT_SEND = "LOWBAT_SEND"
+    LOWBAT_RECV = "LOWBAT_RECV"
+
+    TIME_SEND = "Time_SEND"
+    TIME_RECV = "Time_RECV"
+
+    WLKEY_SEND = "WLKEY_SEND"
+    WLKEY_RECV = "WLKEY_RECV"
+
+    SILENCETIME2_SEND = "SILENCETIME2_SEND"
+    SILENCETIME2_RECV = "SILENCETIME2_RECV"
+
+    KEYBRD_SEND = "KEYBRD_SEND"
+    KEYBRD_RECV = "KEYBRD_RECV"
+
+    FALLDOWN_SEND = "FALLDOWN_SEND"
+    FALLDOWN_RECV = "FALLDOWN_RECV"
+    
+    HELP_SEND = "HELP_SEND"
+    HELP_RECV = "HELP_RECV"
+    
+    REMOVE_SEND = "REMOVE_SEND"
+    REMOVE_RECV = "REMOVE_RECV"
+
+    BLOOD_SEND = "blood_SEND"
+    BLOOD_RECV = "blood_RECV"
+
+    BLDSTART_SEND ="bldstart_SEND"
+    BLDSTART_RECV = "bldstart_RECV"
+
+    BGSTART_SEND = "bgstart_SEND"
+    BGSTART_RECV = "bgstart_RECV"
+
+    BLOODGLUSOCE_SEND = "bloodglucose_SEND"
+    BLOODGLUSOCE_RECV = "bloodglucose_RECV"
+
+    REMIND_CH_DRINK_SEND = "REMIND_CH_DRINK_SEND"
+    REMIND_CH_DRINK_RECV = "REMIND_CH_DRINK_RECV"
+
+    REMIND_CH_MEDICINE2_SEND = "REMIND_CH_MEDICINE2_SEND"
+    REMIND_CH_MEDICINE2_RECV = "REMIND_CH_MEDICINE2_RECV"
+
+    REMIND_CH_HOME_SEND = "REMIND_CH_HOME_SEND"
+    REMIND_CH_HOME_RECV = "REMIND_CH_HOME_RECV"
+
+    REMIND_CH_WAKEUP_SEND = "REMIND_CH_WAKEUP_SEND"
+    REMIND_CH_WAKEUP_RECV = "REMIND_CH_WAKEUP_RECV"
+
+    REMIND_CH_SLEEP_SEND = "REMIND_CH_SLEEP_SEND"
+    REMIND_CH_SLEEP_RECV = "REMIND_CH_SLEEP_RECV"
+
+    REMIND_CH_REST_SEND = "REMIND_CH_REST_SEND"
+    REMIND_CH_REST_RECV = "REMIND_CH_REST_RECV"
+
+    SLEEP_DATA_SEND = "SleepReport_SEND"
+    SLEEP_DATA_RECV = "SleepReport_RECV"
+
+    SLEEPTIME_SEND = "SLEEPTIME_SEND"
+    SLEEPTIME_RECV = "SLEEPTIME_RECV"
+
+    FACTORY_SEND = "FACTORY_SEND"
+    FACTORY_RECV = "FACTORY_RECV"
+
+    RESET_SEND = "RESET_SEND"
+    RESET_RECV = "RESET_RECV"
+
+    REMIND_CH_SIT_SEND = "REMIND_CH_SIT_SEND"
+    REMIND_CH_SIT_RECV = "REMIND_CH_SIT_RECV"
+
+    SCREEN_SHOW_SEND = "SCREEN_SHOW_SEND"
+    SCREEN_SHOW_RECV = "SCREEN_SHOW_RECV"
+
+    JPREG_SEND = "JPREG_SEND"
+    JPREG_RECV = "JPREG_RECV"
+
+    MEMBERS_SEND = "MEMBERS_SEND"
+    MEMBERS_RECV = "MEMBERS_RECV"
+
+    CALLING_SEND = "CALLING_SEND"
+    CALLING_RECV = "CALLING_RECV"
+    
+
+    RCALLING_SEND  = "RCALLING_SEND"
+    RCALLING_RECV  = "RCALLING_RECV"
+
+    AGTALK_SEND = "AGTALK_SEND"
+    AGTALK_RECV = "AGTALK_RECV"
+
+    RTALK_SEND = "RTALK_SEND"
+    RTALK_RECV = "RTALK_RECV"
+
+    JMEMBERS_SEND = "JMEMBERS_SEND"
+    JMEMBERS_RECV = "JMEMBERS_RECV"
+
+    RINGING_SEND = "RINGING_SEND"
+    RINGING_RECV = "RINGING_RECV"
+
+    HANGUP_SEND = "HANGUP_SEND"
+    HANGUP_RECV = "HANGUP_RECV"
+
+    CALLCANCEL_SEND ="CALLCANCEL_SEND"
+    CALLCANCEL_RECV = "CALLCANCEL_RECV"
+    
+
+# ---- Server/协议相关配置(统一从 default_srv.py 读取,usr 优先覆盖)----
+try:
+    import srv_config as _srv
+except Exception:
+    _srv = None
+
+try:
+    import default_srv as _srv_default
+except Exception:
+    _srv_default = None
+
+# 保留 _SERVER_CFG 变量名(兼容历史引用),来源为 default_srv.py(usr 优先覆盖)
+try:
+    SERVER_ENV = "beike_dev"
+    if _srv:
+        SERVER_ENV = _srv.get_attr("SERVER_ENV", SERVER_ENV) or SERVER_ENV
+    elif _srv_default:
+        SERVER_ENV = getattr(_srv_default, "SERVER_ENV", SERVER_ENV) or SERVER_ENV
+except Exception:
+    SERVER_ENV = "beike_dev"
+
+try:
+    if _srv:
+        DMP_BASE = _srv.get_addr("DMP_BASE", "")
+        AMP_SERVER = _srv.get_addr("AMP_SERVER", "")
+        IOT_WS_URL = _srv.get_addr("IOT_WS_URL", "")
+    else:
+        DMP_BASE = ""
+        AMP_SERVER = ""
+        IOT_WS_URL = ""
+
+    # 兼容历史:提供与旧 _SERVER_CFG 相似的结构
+    _SERVER_CFG = {
+        SERVER_ENV: {
+            "dmp_base": DMP_BASE,
+            "amp_server": AMP_SERVER,
+            "iot_ws_url": IOT_WS_URL,
+        }
+    }
+except Exception:
+    # 保守兜底(若配置缺失,避免 import 阶段直接崩溃)
+    DMP_BASE = ""
+    AMP_SERVER = ""
+    IOT_WS_URL = ""
+    _SERVER_CFG = {SERVER_ENV: {"dmp_base": "", "amp_server": "", "iot_ws_url": ""}}
+
+
+class EVENT:
+    CHANNEL_SOCKET_SEND = "CHANNEL_SOCKET_SEND"
+    START_LOCATION = "START_LOCATION" 
+    START_LOCATION_TEST = "START_LOCATION_TEST" 
+    READ_LOCATION = "READ_LOCATION"  
+    CLOSE_LOCATION = "CLOSE_LOCATION"
+    GPSOPEN = "GPSOPEN"
+    GPSCLOSE = "GPSCLOSE"
+    GPSINFO = "GPSINFO"
+    WIFISCANOPEN = "WIFISCANOPEN"
+    WIFIINFO = "WIFIINFO"
+
+    GET_KEY = "GET_KEY"
+    SET_KEY = "SET_KEY"
+    GET_IMEI = "GET_IMEI"
+    GET_CID = "GET_CID"
+    SET_CID = "SET_CID"
+    GET_IMSI = "GET_IMSI"
+    GET_PASSWORD = "GET_PASSWORD"
+    SET_PASSWORD = "SET_PASSWORD"
+    GET_BATTERY = "GET_BATTERY"
+    PERSISTENT_CONFIG_GET = "PERSISTENT_CONFIG_GET"
+    PERSISTENT_CONFIG_STORE = "PERSISTENT_CONFIG_STORE"
+    SET_PING = "SET_PING"
+    GET_PING = "GET_PING"
+    SET_CONNECT = "SET_CONNECT"
+    GET_CONNECT = "GET_CONNECT"
+    GET_STEP = "GET_STEP"
+    PUSH_STEP = "PUSH_STEP"
+    SYSTEM_SLEEP = "SYSTEM_SLEEP"
+    SYSTEM_UP = "SYSTEM_UP"
+    START_HEART = "START_HEART" 
+    GET_HEART = "GET_HEART"
+    STOP_HEART = "STOP_HEART"
+    GET_WEAR = "GET_WEAR"
+    START_TEMP = "START_TEMP"
+    STOP_TEMP = "STOP_TEMP"
+    GET_TEMP = "GET_TEMP"
+    START_BLOOD_OXYGEN = "STARTT_BLOOD_OXYGEN" 
+    GET_BLOOD_OXYGEN = "GET_BLOOD_OXYGEN"
+    STOP_BLOOD_OXYGEN = "STOP_BLOOD_OXYGEN"
+    CHANNEL_IOT_WEB_SEND = "CHANNEL_IOT_WEB_SEND"
+    
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/default_config.py
new file mode 100644 (file)
index 0000000..424c7b7
--- /dev/null
@@ -0,0 +1,128 @@
+# 设备侧默认配置(freeze 内置)。\r
+#\r
+# 加载优先级(由 vc_config.py 执行):\r
+# 1) usr/default_config.py(或 usr/defualt_config.py)\r
+# 2) 本文件 default_config.py\r
+\r
+# 当前设备类型(编译期间确定;现场仅可用 usr/default_config.py 覆盖)\r
+DEV_TYPE = "7PIN"\r
+\r
+# 当前设备配置(仅保留“设备差异项”,不要放运行态变量)\r
+# led_gpio 使用 Pin 属性名(字符串),由 vc_config.py 转成 Pin.GPIOxx 常量。\r
+LED_GPIO = ("GPIO36", "GPIO44", "GPIO43")  # (R, G, B)\r
+\r
+# LED 电平极性(是否“反向”点亮)。\r
+# - 默认 LED_ACTIVE_LOW=False:高电平点亮(write(1)=亮)\r
+# - 若你的硬件是低电平点亮(write(0)=亮),将 LED_ACTIVE_LOW=True\r
+# - 若仅某一路反相,用 LED_ACTIVE_LOW_RGB 单独配置(按 LED_GPIO 顺序 R/G/B)\r
+LED_ACTIVE_LOW = False\r
+LED_ACTIVE_LOW_RGB = None  # 例如 (True, False, False) 表示仅红灯反相\r
+# LED_ACTIVE_LOW_RGB = (True, False, False)\r
+\r
+# 是否支持 UART 相关能力(例如 7PIN_1_5 才允许走串口)\r
+UART_SUPPORTED = False\r
+\r
+# 语言/地区(如 zh/en),用于少量文案/逻辑差异\r
+LANG = "zh"\r
+\r
+# --------------------\r
+# 硬件差异项(由每个设备的 default_config 固定)\r
+# --------------------\r
+LED_DEBUG = True\r
+KEY_LED_DEBUG = True\r
+HW_STATUS_DEBUG = True\r
+\r
+# 是否需要初始化蓝牙电源/马达/音频IIS配置等(原先仅 7PIN_1_5)\r
+BT_POWER_MOTOR_ENABLED = False\r
+PIN_BT_ON_GPIO = None      # 例如 "GPIO31"\r
+PIN_MOT_GPIO = None        # 例如 "GPIO36"\r
+\r
+# audio.set_qdai_cfg(...) 参数;若为 None 则不调用\r
+AUDIO_QDAI_CFG = None      # 例如 (1,0,0,2,0,1,1,1)\r
+\r
+# AI 按键中断与电源键中断引脚(ExtInt.GPIOxx)\r
+EXTINT_AI_GPIO = "GPIO22"\r
+PWK_KEY_GPIO = "GPIO26"\r
+\r
+# 蓝牙唤醒 4G/4G 唤醒蓝牙相关(原先仅 7PIN_1_5)\r
+BT_WAKEUP_4G_ENABLED = False\r
+EXTINT_WAKEUP_CTA1_GPIO = None  # 例如 "GPIO22"\r
+PIN_WAKEUP_BT_GPIO = None       # 例如 "GPIO21"\r
+\r
+# --------------------\r
+# 按键/防抖差异\r
+# --------------------\r
+\r
+# 释放防抖阈值(KeyAI/pwk):原代码部分设备用 3,其他用 5\r
+KEY_RELEASE_DEBOUNCE_COUNT = 5\r
+\r
+# 是否允许 AI 键长按 8 秒触发关机逻辑(原 jswm/jswm_BOX)\r
+AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
+\r
+# --------------------\r
+# 开机提示/语音参数默认值(与具体产品绑定,编译期决定)\r
+# --------------------\r
+\r
+# 若为 None 或 POWER_ON_TONE_ENABLED=False,则不开机播报提示词\r
+POWER_ON_TONE_ENABLED = True\r
+POWER_ON_TONE_DEFAULT = "你好,我来了"\r
+\r
+# VAD 静音阈值默认值(ms)\r
+VAD_SILENCE_DEFAULT = 300\r
+\r
+# 默认音色配置(与 ai_VC.py 中格式保持一致)\r
+VC_TTS_VOICE_TYPE_DEFAULT = None  # dict 或 None(None 表示沿用 ai_VC.py 内置兜底/存储值)\r
+VC_TTS_VOICE_KEY_DEFAULT = None   # 例如 "男"/"童"\r
+\r
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
+VC_WS_PATH = "vc/agent"\r
+\r
+# 是否支持蓝牙 OTA(原先仅 7PIN_1_5 会检查 bt_ota)\r
+BT_OTA_ENABLED = False\r
+\r
+# 是否在“开始上传语音”时播放成功提示音(原逻辑:非 7PIN/7PIN_1_5/7PIN_coze 才播)\r
+UPLOAD_START_TONE_ENABLED = False\r
+\r
+# LLM thinking 阶段 LED 策略:flicker_blue_green / open_red_green\r
+THINKING_LED_MODE = "flicker_blue_green"\r
+\r
+# 收到 vad.active 时是否强制切回蓝灯\r
+VAD_ACTIVE_BLUE_LED = True\r
+\r
+# 本地指令:切换对话模式时的提示语(是什么语言就写什么)\r
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
+\r
+# 蓝牙/语音留言类本地指令是否启用(原先仅 7PIN_1_5)\r
+BT_VOICE_FEATURES_ENABLED = False\r
+\r
+# “关机”语音指令是否仅关闭对话(不触发 Power_off)。原逻辑:7PIN/7PIN_coze/7PIN_1_5 只 Close\r
+POWEROFF_CMD_CLOSE_ONLY = True\r
+\r
+# 关键词唤醒时在 PTT 模式下播报的提示语\r
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+\r
+# 对话智能体/工作流默认配置(编译期确定;可在 usr/default_config.py 覆盖)\r
+# 结构示例:\r
+# DIALOG_BOT_OPTION = {"bot_id":"...", "workflow_id":"...", "use_workflow":True}\r
+DIALOG_BOT_OPTION = None\r
+\r
+# dialog_attributes.provider 覆盖(None 表示沿用存储配置 dialog_attributes_provider)\r
+DIALOG_PROVIDER_DEFAULT = None\r
+\r
+# 是否从 VC_TTS_voice_type 的 key 列表生成 ASR 热词\r
+KEYWORDS_FROM_VOICE_TYPE = False\r
+\r
+# --------------------\r
+# 按键音/提示音策略(设备差异项)\r
+# --------------------\r
+\r
+# AI 键按下时:若设置了该文件路径,则在“无 VC 流播放中”时播放该提示音(例如 7PIN 用 start.mp3)\r
+KEY_PRESS_TONE_FILE = None  # 例如 "U:/static/start.mp3"\r
+\r
+# AI 键按下时:延迟播放按键音(ms),用于规避蓝牙连接瞬间不出声等问题(例如 7PIN_1_5 取 300)\r
+KEY_PRESS_TONE_DELAY_MS = 0\r
+\r
+# PTT 提示语(单对话模式,未长按时的提示;是什么语言就写什么)\r
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/default_srv.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/default_srv.py
new file mode 100644 (file)
index 0000000..5ae3122
--- /dev/null
@@ -0,0 +1,34 @@
+# 设备侧 Server 配置(freeze 内置)。\r
+#\r
+# 注意:\r
+# - `constants.py` 中固定不变的常量(事件名/枚举)继续保留在 constants.py。\r
+# - 本文件统一承载“协议/服务器相关的可配置项”,并支持 usr 覆盖。\r
+\r
+# ---- 环境选择(服务器地址由 srv_configs/<SERVER_ENV>.py 承载)----\r
+# 服务器环境配置,切换只需修改 SERVER_ENV\r
+# "beike" = 北科测试, "kxc" = 科学城demo\r
+SERVER_ENV = "beike_dev"\r
+\r
+# ---- 默认环境地址(即使没有 srv_configs/<env>.py 也能工作)----\r
+# 这里默认给出 beike_dev 的地址;若要切换环境,建议:\r
+# - 修改 SERVER_ENV\r
+# - 同时提供对应的 srv_configs/<SERVER_ENV>.py(或 usr 覆盖)\r
+DMP_BASE = "http://dmp-dev.raisound.com/dmp-api"\r
+AMP_SERVER = "118.145.158.207:22080"\r
+IOT_WS_URL = "ws://dmp-dev.raisound.com/iot-api/ws-hub/dev/v1"\r
+\r
+# ---- DMP/认证/时间同步等(默认使用 constants.DMP_BASE 拼接)----\r
+DMP_TIME_PATH = "/dev/time"\r
+DMP_ACTIVE_PATH = "/dev/auth/active"\r
+DMP_SIGN_IN_PATH = "/dev/auth/sign_in"\r
+DMP_TOKEN_PATH = "/dev/auth/token"\r
+DMP_ICCID_PATH = "/dev/iccid"\r
+DMP_DEV_CONFIG_PATH_FMT = "/dev/config/{}"  # deviceId\r
+\r
+# ---- OTA(现网有的走 DMP_BASE,有的走 qipai 域名;先集中成可配项)----\r
+OTA_TASK_URL_FMT = "https://dmp-api.qipai.com/qp-dmp-api/ota/task?deviceId={}&sourceVersion={}"\r
+OTA_RESULT_PATH_FMT = "/ota/result?deviceId={}&currentVersion={}"\r
+\r
+# ---- AMP/健康检查等 ----\r
+AMP_HEALTH_URL_FMT = "http://{}/health?task_id={}"\r
+\r
index df2d847..962d7e9 100644 (file)
@@ -176,6 +176,11 @@ def main_init():
             app.append_manager(_ai.AI_led())
         except Exception as e:
             usys.print_exception(e)
+        # 精简硬件状态采集(替代 mgr):输出 charging/battery/signal → set_led_state
+        try:
+            app.append_manager(_ai.AI_hw_status())
+        except Exception as e:
+            usys.print_exception(e)
         try:
             app.append_manager(_ai.AI_dev())
         except Exception as e:
index 8a2aa1f..4b89844 100644 (file)
@@ -4280,43 +4280,6 @@ class IOTWeb_disconnect_btProtoCol(ProtoCol):
             EventMesh.publish("send_disconnect_bt_mac",mac)
         print("recv disconnect_bt{}".format(msg))
         EventMesh.publish(WEB_CMD_ENUM.DISCONNECT_BT_S)
-class IOTWeb_get_chat_configProtoCol(ProtoCol):
-    """get_chat_config"""
-    TYPE = "get_chat_config"
-
-    def send(self, event, msg):
-        # print("send get_chat_config{}".format(msg))
-        # 通过websocket发送到服务器端
-        date_tmp = utime.localtime()
-        time_tmp = utime.mktime(date_tmp)
-        get_chat_config = {
-            "cmd":"get_chat_config",
-            "ts":time_tmp,
-            "msg":"获取AI对话配置",
-            "data":None
-        }
-        send_data = b''
-        send_data = protocol_send_total_data(get_chat_config)
-        print("send_data get_chat_config{}".format(send_data))
-        EventMesh.publish("CHANNEL_IOT_WEB_SEND", send_data)
-
-    def recv(self, event, msg):
-        """
-
-        @param event:上行下发get_chat_config
-        @param msg: 接收到的下行数据
-        """
-        # {
-        #     "cmd":"post_rest",
-        #     "ts":1738283829,
-        #     "msg":"消息收到响应",
-        #     "data":{
-        #         "cmd":"get_chat_config",
-        #         "rest":"success|error",
-        #         "msg":"收到获取AI对话配置请求"
-        #     }
-        # }
-        print("RECV get_chat_config{}".format(msg))
 #IOT金三
 #接收小程序控制查找设备
 class IOTWeb_find_deviceProtoCol(ProtoCol):
@@ -4420,36 +4383,6 @@ class IOTWeb_switch_volumeProtoCol(ProtoCol):
         print("音量修改为:{}".format(volume-100))
         EventMesh.publish("change_volume",volume)
 
-#接收小程序控制设置音量
-class IOTWeb_switch_volumeProtoCol(ProtoCol):
-    """switch_volume"""
-    TYPE = "switch_volume"
-
-    def send(self, event, msg):
-        # print("c{}".format(msg))
-        # 通过websocket发送到服务器端
-        date_tmp = utime.localtime()
-        time_tmp = utime.mktime(date_tmp)
-        come_trans = {
-            "msg": "设置音量",
-            "data": None,
-            "cmd": "switch_volume",
-            "ts": time_tmp
-        }
-        send_data = b''
-        send_data = protocol_send_total_data(come_trans)
-        print("send_data switch_volume{}".format(send_data))
-        EventMesh.publish("CHANNEL_IOT_WEB_SEND", send_data)
-
-    def recv(self, event, msg):
-        """
-        @param event:switch_volume
-        @param msg: 接收到的下行数据
-        """
-        volume = int(msg["data"]["target"]) + 100
-        print("音量修改为:{}".format(volume-100))
-        EventMesh.publish("change_volume",volume)
-
 class LK_ProtoCol(ProtoCol):
     """链路保持"""
     TYPE = "LK"
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_config.py
new file mode 100644 (file)
index 0000000..953ff02
--- /dev/null
@@ -0,0 +1,44 @@
+# Server 配置加载器:\r
+# - 优先 usr/default_srv.py(或兼容误拼 usr/defualt_srv.py)\r
+# - 否则使用 freeze 内置 default_srv.py\r
+\r
+def _try_import(name):\r
+    try:\r
+        return __import__(name)\r
+    except Exception:\r
+        return None\r
+\r
+\r
+# 只做“优先 import usr 下文件;失败再 import 默认文件”,不做变量覆盖/合并\r
+_DEFAULT_SRV_MODULE = None\r
+_DEFAULT_SRV_LOADED = 0\r
+\r
+\r
+def load_default_srv_module():\r
+    global _DEFAULT_SRV_MODULE, _DEFAULT_SRV_LOADED\r
+    if _DEFAULT_SRV_LOADED:\r
+        return _DEFAULT_SRV_MODULE\r
+    _DEFAULT_SRV_LOADED = 1\r
+    _DEFAULT_SRV_MODULE = (\r
+        _try_import("usr.default_srv")\r
+        or _try_import("usr.defualt_srv")\r
+        or _try_import("default_srv")\r
+    )\r
+    return _DEFAULT_SRV_MODULE\r
+\r
+\r
+def get_attr(name, default=None):\r
+    m = load_default_srv_module()\r
+    try:\r
+        if m and hasattr(m, name):\r
+            return getattr(m, name)\r
+    except Exception:\r
+        return default\r
+    return default\r
+\r
+\r
+def get_addr(name, default=None):\r
+    # 运行时只从 default_srv.py 读取地址(usr 优先覆盖)。\r
+    # srv_configs/<SERVER_ENV>.py 仅保留给编译期选择/拷贝使用,不参与运行时 import。\r
+    return get_attr(name, default)\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/README.md b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/README.md
new file mode 100644 (file)
index 0000000..335adb7
--- /dev/null
@@ -0,0 +1,18 @@
+本目录用于**服务器环境地址配置**,按 `SERVER_ENV` 分类管理。\r
+\r
+示例:\r
+- `beike.py`:北科测试\r
+- `kxc.py`:科学城 demo\r
+- `beike_dev.py`:北科开发环境\r
+\r
+每个环境文件需要导出以下常量:\r
+- `DMP_BASE`\r
+- `AMP_SERVER`\r
+- `IOT_WS_URL`\r
+\r
+本目录文件**不参与运行时加载**,仅用于编译期选择/拷贝。\r
+\r
+运行时的优先级固定为:\r
+1) `usr/default_srv.py`(或兼容误拼 `usr/defualt_srv.py`)\r
+2) freeze 内置 `core/default_srv.py`\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/beike.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/beike.py
new file mode 100644 (file)
index 0000000..1852494
--- /dev/null
@@ -0,0 +1,6 @@
+# SERVER_ENV = beike(北科测试)\r
+\r
+DMP_BASE = "http://dmp.raisound.com/bz-api"\r
+AMP_SERVER = "115.190.94.208:22080"\r
+IOT_WS_URL = "ws://wsiot-nocdn.raisound.com/ws-hub/dev/v1"\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/beike_dev.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/beike_dev.py
new file mode 100644 (file)
index 0000000..a6a8d2f
--- /dev/null
@@ -0,0 +1,6 @@
+# SERVER_ENV = beike_dev(北科开发环境)\r
+\r
+DMP_BASE = "http://dmp-dev.raisound.com/dmp-api"\r
+AMP_SERVER = "118.145.158.207:22080"\r
+IOT_WS_URL = "ws://dmp-dev.raisound.com/iot-api/ws-hub/dev/v1"\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/dev_type_url_backup.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/dev_type_url_backup.py
new file mode 100644 (file)
index 0000000..f16a565
--- /dev/null
@@ -0,0 +1,15 @@
+# dev_type 维度的“网络地址/接口域名”历史备份。\r
+#\r
+# 说明:\r
+# - 这些内容来源于 ai_VC.py 里注释掉的 dev_type 分支(仅做备份/编译期参考)。\r
+# - 运行时不加载本文件;实际运行时由 default_srv.py(可被 usr/default_srv.py 覆盖)决定 DMP_BASE 等。\r
+\r
+# OTA task 接口(旧逻辑里按 dev_type 走不同域名)\r
+OTA_TASK_URL_BY_DEV_TYPE = {\r
+    # 英文小瑞\r
+    "7PIN_BK_EU": "http://dmp-global.raisound.com/bz-api/ota/task?deviceId={deviceId}&sourceVersion={sourceVersion}",\r
+    # 柒牌(coze 与非 coze 共用)\r
+    "7PIN": "http://ota.qipai.com/bz-cmp-api/api/task?deviceId={deviceId}&sourceVersion={sourceVersion}",\r
+    "7PIN_coze": "http://ota.qipai.com/bz-cmp-api/api/task?deviceId={deviceId}&sourceVersion={sourceVersion}",\r
+}\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/kxc.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/kxc.py
new file mode 100644 (file)
index 0000000..5c21635
--- /dev/null
@@ -0,0 +1,6 @@
+# SERVER_ENV = kxc(科学城 demo)\r
+\r
+DMP_BASE = "http://kxc.raisound.com/bz-api"\r
+AMP_SERVER = "kxc.raisound.com/amp-api"\r
+IOT_WS_URL = "ws://kxc.raisound.com/iot-api/ws-hub/dev/v1"\r
+\r
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/usr/ai_VC.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/usr/ai_VC.py
deleted file mode 100644 (file)
index d0f3bb7..0000000
+++ /dev/null
@@ -1,2175 +0,0 @@
-from common import Abstract, LogAdapter\r
-import EventMesh\r
-import uwebsocket\r
-import usys\r
-import gc\r
-import urandom\r
-import uhashlib\r
-import ubinascii\r
-import ujson\r
-import osTimer\r
-import _thread\r
-from queue import Queue\r
-import utime\r
-import audio\r
-import uos\r
-from machine import Pin\r
-from machine import ExtInt\r
-from machine import WDT\r
-import modem\r
-import sim\r
-import net\r
-import base64\r
-import ucryptolib\r
-import urandom as random\r
-import request\r
-import ql_fs\r
-from misc import Power,USB,PowerKey\r
-import ntptime\r
-import machine\r
-class AI_led(Abstract):\r
-    def __init__(self):\r
-        self.led_red = Pin(Pin.GPIO36, Pin.OUT, Pin.PULL_PD, 0)\r
-        self.led_green = Pin(Pin.GPIO21, Pin.OUT, Pin.PULL_PD, 1)\r
-        self.led_white = Pin(Pin.GPIO19, Pin.OUT, Pin.PULL_PD, 1)\r
-        EventMesh.subscribe("open_led_red",self.open_led_red)\r
-        EventMesh.subscribe("open_led_white",self.open_led_white)\r
-        EventMesh.subscribe("open_led_green",self.open_led_green)\r
-        EventMesh.subscribe("open_led_all",self.open_led_all)\r
-        EventMesh.subscribe("close_led",self.close_led)\r
-        EventMesh.publish("open_led_red")\r
-    def open_led_red(self,event,msg):\r
-        print("open_led_red")\r
-        #self.led_red.write(0)\r
-        self.led_white.write(0)\r
-        self.led_green.write(0)\r
-        self.led_red.write(1)\r
-\r
-    def open_led_white(self,event,msg):\r
-        print("open_led_white")\r
-        self.led_red.write(0)\r
-        #self.led_white.write(0)\r
-        self.led_green.write(0)\r
-        self.led_white.write(1)\r
-\r
-    def open_led_green(self,event,msg):\r
-        print("open_led_green")\r
-        self.led_red.write(0)\r
-        self.led_white.write(0)\r
-        #self.led_green.write(0)\r
-        self.led_green.write(1)\r
-\r
-    def open_led_all(self,event,msg):\r
-        print("open_led_all")\r
-        #self.led_red.write(0)\r
-        self.led_white.write(1)\r
-        self.led_green.write(1)\r
-        self.led_red.write(1)\r
-\r
-    def close_led(self,event,msg):\r
-        print("close_led")\r
-        self.led_red.write(0)\r
-        self.led_white.write(0)\r
-        self.led_green.write(0)\r
-audio_buf = ['dianliangshengyu10', 'dianliangshengyu100', 'dianliangshengyu20', 'dianliangshengyu40', 'dianliangshengyu60', 'dianliangshengyu80', 'dianliangshengyu90', 'IMEIhao', 'jianquancuowu', 'key_prompt', 'liuliangtishi', 'Low_power_warning', 'peizhichenggong', 'qiehuanchenggong', 'R_CHARGE_FULL', 'R_CHARGE_IN', 'R_CHARGE_OUT', 'R_POWER_OFF_1', 'R_READ_TIME_0', 'R_READ_TIME_1', 'R_READ_TIME_2', 'R_READ_TIME_3', 'R_READ_TIME_4', 'R_READ_TIME_5', 'R_READ_TIME_6', 'R_READ_TIME_7', 'R_READ_TIME_8', 'R_READ_TIME_9', 'R_SIM_FAILE', 'xianyikaiji', 'xinhaoruo1', 'xinhaoruo2', 'yinliangyizuida', 'yinliangyizuixiao', 'zhengzaiguanji']\r
-\r
-class AI_dev(Abstract):\r
-    # AI\r
-    def __init__(self):\r
-        self.VBATT_tab = {"charge_full":4300,100 :4250 ,  90:3994 , 80:3883, 60: 3707, 40:3604, 20:3537,  10:3486,}\r
-        self.KeyAI_status = 0\r
-        self.KeyAI_timer_count = 0\r
-        self.KeyAI_long_press = 0\r
-        self.KeyAI_press = 0\r
-        self.KeyAI_timer = osTimer()\r
-        #self.extint_AI = ExtInt(ExtInt.GPIO19,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb)\r
-        self.extint_AI = ExtInt(ExtInt.GPIO22,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb)\r
-        self.extint_AI.enable()\r
-        self.pwk_key_status = 0\r
-        self.pwk_key_timer_count = 0\r
-        self.pwk_key_long_press = 0\r
-        self.pwk_key_press = 0\r
-        self.pwk_key_timer = osTimer()\r
-        #self.pwk_key = ExtInt(ExtInt.GPIO26, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_DISABLE, self.pwk_extint_cb)\r
-        self.pwk_key = ExtInt(ExtInt.GPIO41, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb)\r
-        self.pwk_key.enable() \r
-        self.btnInfo_queue = Queue()\r
-        _thread.stack_size(10*1024)\r
-        _thread.start_new_thread(self.btnInfo_queue_thread, ())\r
-        _thread.stack_size(8*1024)\r
-        EventMesh.subscribe("publish_AI_btnInfo",self.publish_AI_btnInfo)\r
-        EventMesh.subscribe("get_battery",self.get_battery)\r
-        EventMesh.subscribe("audio_montage_play",self.audio_montage_play)\r
-        EventMesh.subscribe("paly_iccid_imei",self.paly_iccid_imei)\r
-        EventMesh.subscribe("paly_device_res_error",self.paly_device_res_error)\r
-        \r
-        self.wdt = WDT(30) #开启看门狗\r
-        # self.wdt_timer = osTimer()\r
-        # self.wdt_timer.start(10000, 1, self.wdt_timer_cb)\r
-        self.pk = PowerKey()\r
-        self.pk.powerKeyEventRegister(self.powerKey_callback)\r
-        self.usb = USB()\r
-        self.usb.setCallback(self.usb_event_cb)\r
-        self.usb_status = self.usb.getStatus()\r
-        self.usb_charge_flag = 0 \r
-        self.AI_dev_timer = osTimer()\r
-        self.AI_dev_timer.start(10000, 1, self.AI_dev_timer_cb)\r
-        self.aud = audio.Audio(0)\r
-        self.VC_TTS_volume =  EventMesh.publish("get_storage_config","VC_TTS_volume")#音量配置\r
-        if self.VC_TTS_volume == None:\r
-            self.VC_TTS_volume = 100\r
-        self.aud.setVolume(self.VC_TTS_volume //10)\r
-        #self.aud.play(1,0,'U:/static/xianyikaiji.mp3')#开机音频\r
-        #EventMesh.publish("audio_montage_play",["xianyikaiji.mp3"])\r
-        #EventMesh.publish("publish_AI_btnInfo",{"func":self.ntptime_cb})\r
-    def ntptime_cb(self):\r
-        #ntptime.settime(8)\r
-        print("timer:{}!!!!!!!!\r\n".format(utime.localtime()))\r
-    def usb_event_cb(self, state):\r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.usb_event,"data":state})\r
-    def usb_event(self, state):    \r
-        status = state\r
-        self.usb_charge_flag = 0\r
-        if status == 1:#插入USB\r
-            print("charge R_CHARGE_in")\r
-            self.usb_status = 1\r
-            self.aud.stop()\r
-            #self.aud.play(1,1,'U:/static/R_CHARGE_IN.mp3')\r
-            EventMesh.publish("audio_montage_play",["R_CHARGE_IN.mp3"])\r
-            pass\r
-        elif status == 0:#拨出usbs\r
-            self.usb_status = 0\r
-            self.aud.stop()\r
-            EventMesh.publish("audio_montage_play",["R_CHARGE_OUT.mp3"])\r
-            #self.aud.play(1,1,'U:/static/R_CHARGE_OUT.mp3')\r
-    def btnInfo_queue_thread(self):\r
-        while True:\r
-            data = self.btnInfo_queue.get()\r
-            #EventMesh.debug_log("Info_queue:data = {}".format(data))\r
-            if data != None:\r
-                try:\r
-                    if "data" in data :\r
-                        data["func"](data["data"])\r
-                    else :\r
-                        data["func"]()\r
-                except Exception as e:\r
-                    #EventMesh.debug_log("btnInfo_queue:ERROR:{}".format(e))\r
-                    usys.print_exception(e)\r
-    def publish_AI_btnInfo(self,event,msg):\r
-        self.btnInfo_queue.put(msg)\r
-    def powerKey_callback(self, status):\r
-        print("powerKey_callback:{}".format(status))\r
-\r
-    def pwk_extint_cb(self,args):#pwk\r
-        try:\r
-            self.pwk_key_status = int(args[1])\r
-            if self.pwk_key_status == 0:\r
-                self.pwk_key_status = 1\r
-            else:\r
-                self.pwk_key_status = 0\r
-                pass\r
-            if self.pwk_key_status == 0:#按下\r
-                if self.pwk_key_press == 0 :\r
-                    self.pwk_key.disable()\r
-                    self.pwk_key_press = 1\r
-                    self.pwk_key_long_press = 0\r
-                    self.pwk_key_timer.start(100, 1, self.pwk_key_timer_cb)\r
-                    self.pwk_key_timer_count = 0\r
-                    #EventMesh.publish("AI_key_press")\r
-                    \r
-        except Exception as e: \r
-            usys.print_exception(e)\r
-    def pwk_key_timer_cb(self, *args, **kwargs):\r
-        try:\r
-            self.pwk_key_status = self.pwk_key.read_level()\r
-            self.pwk_key_timer_count +=1\r
-            if self.pwk_key_timer_count >= 10*3: #长按3s \r
-                #print("pwk_key_long_press {}".format(self.pwk_key_long_press))\r
-                if self.pwk_key_long_press == 0:\r
-                        self.pwk_key_long_press = 1\r
-                        #EventMesh.publish("AI_key_long_press")\r
-                        EventMesh.publish("publish_AI_btnInfo",{"func":self.pwk_key_Long_Press})  \r
-            if self.pwk_key_status == 1:#松开\r
-                #print("pwk_key_timer_cb:{}".format(self.pwk_key_timer_count))\r
-                if self.pwk_key_timer_count >= 5: #防抖200ms\r
-                    #EventMesh.publish("AI_key_release")\r
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.pwk_key_release})\r
-                    self.pwk_key.enable()\r
-                    self.pwk_key_timer.stop()\r
-                    self.pwk_key_timer_count = 0\r
-                    self.pwk_key_press = 0\r
-            \r
-        except Exception as e: \r
-            usys.print_exception(e) \r
-            \r
-    def keyAI_extint_cb(self,args):#call 2\r
-        try:\r
-            #print("AI_btn:keyAI_extint_cb{}".format(args[1]))\r
-            self.KeyAI_status = int(args[1])\r
-            if self.KeyAI_status == 0:\r
-                self.KeyAI_status = 1\r
-            else:\r
-                self.KeyAI_status = 0\r
-            \r
-            if self.KeyAI_status == 0:#按下\r
-                if self.KeyAI_press == 0 :\r
-                    self.extint_AI.disable()\r
-                    self.KeyAI_press = 1\r
-                    self.KeyAI_long_press = 0\r
-                    self.KeyAI_timer.start(100, 1, self.KeyAI_timer_cb)\r
-                    self.KeyAI_timer_count = 0\r
-                    #EventMesh.publish("AI_key_press")\r
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_key_press})  \r
-        except Exception as e: \r
-            usys.print_exception(e)\r
-    def KeyAI_timer_cb(self, *args, **kwargs):\r
-        try:\r
-            self.KeyAI_status = self.extint_AI.read_level()\r
-            self.KeyAI_timer_count +=1\r
-            if self.KeyAI_timer_count >= 10*1: #长按3s \r
-                if self.KeyAI_long_press == 0:\r
-                        self.KeyAI_long_press = 1\r
-                        #EventMesh.publish("AI_key_long_press")\r
-                        EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_key_long_press})  \r
-            if self.KeyAI_status == 1:#松开\r
-                #print("KeyAI_timer_cb:{}".format(self.KeyAI_timer_count))\r
-                if self.KeyAI_timer_count >= 5: #防抖200ms\r
-                    #EventMesh.publish("AI_key_release")\r
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_key_release})  \r
-                    self.extint_AI.enable()\r
-                    self.KeyAI_timer.stop()\r
-                    self.KeyAI_timer_count = 0\r
-                    self.KeyAI_press = 0\r
-            \r
-        except Exception as e: \r
-            usys.print_exception(e) \r
-       \r
-    def AI_key_press(self):\r
-        #print("AI_key_press")\r
-        EventMesh.publish("AI_key_press")\r
-    def AI_key_long_press(self):\r
-        #print("AI_key_long_press")\r
-        EventMesh.publish("AI_key_long_press")\r
-        \r
-    def AI_key_release(self):\r
-        #print("AI_key_release")\r
-        EventMesh.publish("AI_key_release")\r
-    def pwk_key_Long_Press(self):\r
-        print("pwk_key_long_press!!!!!!!")\r
-        print("pwk_key_long_press!!!!!!!")\r
-        \r
-        # EventMesh.publish("paly_iccid_imei")\r
-        # return\r
-        EventMesh.publish("audio_montage_play",["zhengzaiguanji.mp3"])\r
-        #self.aud.play(1,0,'U:/static/zhengzaiguanji.mp3')#关机音频\r
-        EventMesh.publish("open_led_red")\r
-        utime.sleep_ms(3000)\r
-        Power.powerDown()\r
-        #print("AI_key_release")\r
-        EventMesh.publish("pwk_key_long_press")\r
-        \r
-    def pwk_key_release(self):\r
-        #print("pwk_key_release")\r
-        EventMesh.publish("pwk_key_release")\r
-\r
-    def AI_dev_timer_cb(self, *args, **kwargs):\r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_dev_timer_event})  \r
-    def AI_dev_timer_event(self):\r
-        self.wdt.feed()\r
-        Vbatt = Power.getVbatt()\r
-        if self.usb_charge_flag == 0 and self.usb_status == 1 and Vbatt>=self.VBATT_tab["charge_full"]:#充电充满\r
-            EventMesh.publish("audio_montage_play",["R_CHARGE_FULL.mp3"])\r
-            #self.aud.play(1,0,'U:/static/R_CHARGE_FULL.mp3')#充电已满\r
-            self.usb_charge_flag = 1\r
-        if self.usb_charge_flag == 0 and self.usb_status == 0 and Vbatt<self.VBATT_tab[10]:#低电报警\r
-            #self.aud.play(1,0,'Low_power_warning.mp3')\r
-            EventMesh.publish("audio_montage_play",["Low_power_warning.mp3"])\r
-            self.usb_charge_flag = 1\r
-        pass\r
-    def get_battery(self, event=None, msg=None):\r
-        Vbatt = Power.getVbatt()\r
-        if Vbatt>self.VBATT_tab[90]:\r
-            return 100\r
-        if Vbatt>self.VBATT_tab[80]:\r
-            return 90\r
-        if Vbatt>self.VBATT_tab[60]:\r
-            return 80\r
-        if Vbatt>self.VBATT_tab[40]:\r
-            return 60\r
-        if Vbatt>self.VBATT_tab[20]:\r
-            return 40\r
-        if Vbatt>self.VBATT_tab[10]:\r
-            return 20\r
-        if Vbatt<=self.VBATT_tab[10]:\r
-            return 10\r
-    def audio_montage_play(self,event,msg):\r
-        self.aud.stopPlayStream()\r
-        str_data='mp3files='\r
-        for i in msg:\r
-            try:\r
-                str_tmp = i.replace(".mp3","")\r
-                str_data+="{}.mp3+".format(audio_buf.index(str_tmp))\r
-            except Exception as e:\r
-                    usys.print_exception(e)    \r
-        str_data = str_data[:-1]\r
-        print("audio_montage_play:{}".format(str_data))\r
-        self.aud.montage_play('U:/static/audio.bin',1,1,str_data)\r
-    def paly_iccid_imei(self,event,msg):\r
-        str_data = 'mp3files={}.mp3+'.format(audio_buf.index("liuliangtishi"))#流量提示\r
-        imei  = modem.getDevImei()\r
-        iccid = sim.getIccid()\r
-        if iccid != -1 and len(iccid) > 5:\r
-            str_data += '{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+'.format(audio_buf.index("R_READ_TIME_{}".format(iccid[0]))\\r
-                ,audio_buf.index("R_READ_TIME_{}".format(iccid[1])),audio_buf.index("R_READ_TIME_{}".format(iccid[2])),audio_buf.index("R_READ_TIME_{}".format(iccid[3])),\\r
-                audio_buf.index("R_READ_TIME_{}".format(iccid[4])),audio_buf.index("R_READ_TIME_{}".format(iccid[5])),audio_buf.index("R_READ_TIME_{}".format(iccid[6])),audio_buf.index("R_READ_TIME_{}".format(iccid[7])),\\r
-                audio_buf.index("R_READ_TIME_{}".format(iccid[8])),audio_buf.index("R_READ_TIME_{}".format(iccid[9])),audio_buf.index("R_READ_TIME_{}".format(iccid[10])),audio_buf.index("R_READ_TIME_{}".format(iccid[11])),\\r
-                audio_buf.index("R_READ_TIME_{}".format(iccid[12])),audio_buf.index("R_READ_TIME_{}".format(iccid[13])),audio_buf.index("R_READ_TIME_{}".format(iccid[14])))\r
-        str_data += '{}.mp3+'.format(audio_buf.index("IMEIhao"))#IMEI号为:\r
-        str_data += '{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3'.format(audio_buf.index("R_READ_TIME_{}".format(imei[0]))\\r
-                ,audio_buf.index("R_READ_TIME_{}".format(imei[1])),audio_buf.index("R_READ_TIME_{}".format(imei[2])),audio_buf.index("R_READ_TIME_{}".format(imei[3])),\\r
-                audio_buf.index("R_READ_TIME_{}".format(imei[4])),audio_buf.index("R_READ_TIME_{}".format(imei[5])),audio_buf.index("R_READ_TIME_{}".format(imei[6])),audio_buf.index("R_READ_TIME_{}".format(imei[7])),\\r
-                audio_buf.index("R_READ_TIME_{}".format(imei[8])),audio_buf.index("R_READ_TIME_{}".format(imei[9])),audio_buf.index("R_READ_TIME_{}".format(imei[10])),audio_buf.index("R_READ_TIME_{}".format(imei[11])),\\r
-                audio_buf.index("R_READ_TIME_{}".format(imei[12])),audio_buf.index("R_READ_TIME_{}".format(imei[13])),audio_buf.index("R_READ_TIME_{}".format(imei[14])))\r
-        #print("str_data:{}".format(str_data))\r
-        self.aud.montage_play('U:/static/audio.bin',1,1,str_data)\r
-    #鉴权出错,播放imei号\r
-    def paly_device_res_error(self,event,msg):\r
-        str_data = 'mp3files={}.mp3+'.format(audio_buf.index("jianquancuowu"))#AI功能异常,请联系客户查询,设备号为:\r
-        imei  = modem.getDevImei()\r
-        str_data += '{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3+{}.mp3'.format(audio_buf.index("R_READ_TIME_{}".format(imei[0]))\\r
-                ,audio_buf.index("R_READ_TIME_{}".format(imei[1])),audio_buf.index("R_READ_TIME_{}".format(imei[2])),audio_buf.index("R_READ_TIME_{}".format(imei[3])),\\r
-                audio_buf.index("R_READ_TIME_{}".format(imei[4])),audio_buf.index("R_READ_TIME_{}".format(imei[5])),audio_buf.index("R_READ_TIME_{}".format(imei[6])),audio_buf.index("R_READ_TIME_{}".format(imei[7])),\\r
-                audio_buf.index("R_READ_TIME_{}".format(imei[8])),audio_buf.index("R_READ_TIME_{}".format(imei[9])),audio_buf.index("R_READ_TIME_{}".format(imei[10])),audio_buf.index("R_READ_TIME_{}".format(imei[11])),\\r
-                audio_buf.index("R_READ_TIME_{}".format(imei[12])),audio_buf.index("R_READ_TIME_{}".format(imei[13])),audio_buf.index("R_READ_TIME_{}".format(imei[14])))\r
-        #print("str_data:{}".format(str_data))\r
-        self.aud.montage_play('U:/static/audio.bin',1,1,str_data)\r
-#存储信息\r
-class getStorageDataManager(Abstract):#获取内存数据\r
-        def __init__(self):\r
-            self.config_data = {}\r
-            check = ql_fs.path_exists("/usr/static/storage_file/config.json")\r
-            if check == True:\r
-                with open("/usr/static/storage_file/config.json","r") as fd:\r
-                    self.config_data = ujson.load(fd)\r
-            else :\r
-                self.config_data = {'old_time': 0, 'flip_sw': 0}\r
-                pass\r
-\r
-        def post_processor_after_instantiation(self):\r
-            EventMesh.subscribe("set_storage_data", self.set_storage_data)\r
-            EventMesh.subscribe("set_storage_config", self.set_storage_config)\r
-            EventMesh.subscribe("get_storage_data", self.get_storage_data)\r
-            EventMesh.subscribe("get_storage_config", self.get_storage_config)\r
-\r
-        def set_storage_data(self, event, msg): \r
-            # EventMesh.debug_log("set_storage_data:{}".format(msg))\r
-            if msg != None:\r
-                self.config_data = msg\r
-                with open("/usr/static/storage_file/config.json",'w+',encoding="utf-8") as fd:\r
-                    ujson.dump(self.config_data,fd)\r
-        \r
-\r
-        def set_storage_config(self,event,msg): \r
-            # EventMesh.debug_log("set_storage_key_data1:{}".format(msg))\r
-            if len(msg) >= 2:\r
-                self.config_data[msg[0]]=msg[1]\r
-                # EventMesh.debug_log("set_storage_key_data2:{}".format(self.config_data[msg[0]]))\r
-                EventMesh.publish("publish_message_event_ui",{"func":self.set_storage_save,"data":0})\r
-        def set_storage_save(self, data): \r
-            with open("/usr/static/storage_file/config.json",'w+',encoding="utf-8") as fd:\r
-                ujson.dump(self.config_data,fd)\r
-        def get_storage_data(self, event, msg): \r
-            # EventMesh.debug_log("get_storage_data:{}".format(self.config_data))\r
-            return self.config_data \r
-        def get_storage_config(self,event,msg):\r
-            # EventMesh.debug_log("get_storage_key_data1:{}".format(msg))\r
-            b = msg in self.config_data.keys()\r
-            if b == True:\r
-                # EventMesh.debug_log("get_storage_key_data2:{}".format(self.config_data[msg]))\r
-                return self.config_data[msg]\r
-            else :\r
-                return None\r
-            # try:\r
-            #     return self.config_data[msg]\r
-            # except:\r
-            #     EventMesh.debug_log("get_storage_key_data:none key:{}",msg)\r
-            #     return None\r
-#设备资源授权平台\r
-class device_res_author(Abstract):\r
-   \r
-    def __init__(self) :\r
-        self.deviceId = modem.getDevImei()#"876226002022574"\r
-        self.SHA1_BLOCK_SIZE = 64\r
-        self.PAD_BLOCK_SIZE = 16\r
-        self.SHA256 = uhashlib.sha256\r
-        self.pad = lambda s: s + chr(self.PAD_BLOCK_SIZE - len(s) % self.PAD_BLOCK_SIZE) * (self.PAD_BLOCK_SIZE - len(s) % self.PAD_BLOCK_SIZE)\r
-        # 除去补16字节的多余字符\r
-        self.unpad = lambda s: s[:-s[-1]]\r
-        #K01\r
-        # self.key = b"MWrMZjdtcPhj41jWuoqFAhTmqyFluqj1" \r
-        # self.pid = "qAtdDOGXgXYjT2HGFr3a"\r
-        #G15\r
-        # self.key = b"3LWfBicxfRZ3ZAqmZCFuvMdGUXdAFWkb" \r
-        # self.pid = "qLx4Pu4mSUQxyfVKGLXG"\r
-        #7pin\r
-        self.key = b"uKLrChwrxA1LklgBc3VwawYjUkbT3BgX" \r
-        self.pid = "cqxJZi5CNgzjS3mX21Zw"\r
-        \r
-        self.dev_res_timer = osTimer()\r
-        self.dev_res_timer.start(10000, 1, self.dev_timer_cb)\r
-        self.dev_res_timerCount = 0\r
-        self.ud_token_timer = osTimer()\r
-        self.ud_token_timer.start(30000, 1, self.ud_token_timer_cb)\r
-        self.ud_token_timer_Count = 0\r
-        self.dev_token = None\r
-        self.res_error_count = 0\r
-        EventMesh.subscribe("get_dev_token", self.get_dev_token)\r
-        EventMesh.subscribe("update_dev_token", self.update_dev_token)\r
-        self.dev_active() #设备激活\r
-        self.dev_sign_in() #设备登入\r
-        self.ntptime_flag = 0\r
-\r
-    def get_dev_token(self, event, msg): \r
-        return self.dev_token\r
-    #网络校时\r
-    def dev_NTP(self):\r
-        url = "http://dmp.raisound.com/bz-api/dev/time"\r
-        response = request.get(url)\r
-        data = response.json()\r
-        print("dev_NTP:{}".format(data))\r
-        if data:\r
-            try:\r
-                timeSecond = data["data"]["timestamp"]//1000\r
-                \r
-                next_alarm_time = utime.localtime(timeSecond)\r
-                print("timeSecond {} next_alarm_time {}".format(timeSecond,next_alarm_time))\r
-                machine.RTC().datetime((next_alarm_time[0],next_alarm_time[1],next_alarm_time[2],next_alarm_time[6],next_alarm_time[3],next_alarm_time[4],next_alarm_time[5],0))\r
-            except Exception as e:\r
-                    usys.print_exception(e)\r
-    def dev_timer_cb(self, *args): #设备资源管理鉴权平台定时器\r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.dev_timer_cb_}) \r
-\r
-    def dev_timer_cb_(self):    \r
-        #if EventMesh.DEV_RES_MANAGE_AUTHEN_PLATFORM == 1:\r
-        if self.dev_token == None:\r
-            if self.ntptime_flag == 0:\r
-                self.ntptime_flag  = 1\r
-                EventMesh.publish("publish_AI_btnInfo",{"func":self.dev_NTP})\r
-            print("timer:{}!!!!!!!!\r\n".format(utime.localtime()))\r
-            self.dev_active() #设备激活\r
-            self.dev_sign_in() #设备登入\r
-            self.dev_res_timerCount+=1\r
-            if self.dev_res_timerCount > 6: #开机一分钟内没有获取到密码和token 等下一次更新令牌在走登入 激活流程\r
-                self.dev_res_timerCount=0\r
-                self.dev_res_timer.stop()\r
-    def ud_token_timer_cb(self, *args): \r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.ud_token_timer_cb_}) \r
-\r
-    def ud_token_timer_cb_(self):   \r
-        #print("ud_token_timer_!!!!")\r
-        self.ud_token_timer_Count+=1\r
-        if self.ud_token_timer_Count >= 20: #定时30*200s时更新token\r
-            self.ud_token_timer_Count = 0\r
-            EventMesh.publish("update_dev_token")\r
-            \r
-    def get_sim_Status(self):\r
-        return sim.getStatus() \r
-    def HMAC(self,k, m):\r
-    \r
-        KEY_BLOCK = k + (b'\0' * (self.SHA1_BLOCK_SIZE - len(k)))\r
-        KEY_INNER = bytes((x ^ 0x36) for x in KEY_BLOCK)\r
-        KEY_OUTER = bytes((x ^ 0x5C) for x in KEY_BLOCK)\r
-        inner_message = KEY_INNER + m\r
-        outer_message = KEY_OUTER + self.SHA256(inner_message).digest()\r
-        return self.SHA256(outer_message)\r
-    def get_hmac_sha256(self,k, m):\r
-        data = self.HMAC(k, m).digest()\r
-        # print("HMAC(k, m).digest():", data)\r
-        # print("HMAC(k, m).digest():", ubinascii.hexlify(data))\r
-        hex_data = ubinascii.hexlify(data)\r
-        hex_data = hex_data.decode('ascii')\r
-        return hex_data\r
-    # 加密函数\r
-    def aes_CBC_Encrypt(self,data, key, iv):  # CBC模式的加密函数,data为明文,key为16字节密钥,iv为16字节的偏移量\r
-        key = key.encode('utf-8')\r
-        iv = iv.encode('utf-8')  # CBC 模式下的偏移量\r
-        data = self.pad(data)  # 补位\r
-        data = data.encode('utf-8')\r
-        aes = ucryptolib.aes(key,ucryptolib.MODE_CBC,iv)\r
-        result = base64.b64encode(aes.encrypt(data))\r
-        return str(result, 'utf-8')  # 以字符串的形式返回\r
-\r
-    # 解密函数\r
-    def aes_CBC_Decrypt(self,data, key, iv):  # CBC模式的解密函数,data为密文,key为16字节密钥\r
-        key = key.encode('utf-8')\r
-        iv = iv.encode('utf-8')\r
-        \r
-        aes = ucryptolib.aes(key,ucryptolib.MODE_CBC,iv) #CBC模式\r
-\r
-        # decrypt AES解密  B64decode为base64 转码\r
-        result = aes.decrypt(base64.b64decode(data))\r
-        result = self.unpad(result)  # 除去补16字节的多余字符\r
-        return str(result, 'utf-8')  # 以字符串的形式返回\r
-    #激活接口 没有密码走激活\r
-    def dev_active(self):\r
-        signal = net.csqQueryPoll()\r
-        if signal == -1 or self.get_sim_Status() != 1:#网络不正常\r
-            print("dev_active 无 SIM卡!!!!!!!!\r\n")\r
-            return\r
-        # 签名内容: = deviceId+pid+timeStamp\r
-        dev_pass = ""\r
-        dev_pass = EventMesh.publish("get_storage_config","dev_pass")\r
-        print("dev_pass:{}\r\n".format(dev_pass))\r
-        if dev_pass == None:\r
-            dev_pass = ""\r
-        if dev_pass == "" or dev_pass == None:\r
-            date_tmp = utime.localtime() #获取当前时间\r
-            print("date_tmp:{}\r\n".format(date_tmp)) #转换时间戳s\r
-            timeStamp = (utime.mktime(date_tmp))*1000#获取时间戳ms\r
-            deviceId = self.deviceId #"876226002022574" #以imei号\r
-            pid = self.pid\r
-            key = self.key\r
-            sign_data = "{}{}{}".format(deviceId,pid,timeStamp)  #签名内容\r
-            print("sign_data:{}\r\n".format(sign_data))\r
-            sha256_hex = self.get_hmac_sha256(key,sign_data)\r
-            print("sha256_hex:{}\r\n".format(sha256_hex))\r
-\r
-            data = {\r
-                "deviceId":"{}".format(deviceId), #设备名\r
-                "pid":pid, #产品PID\r
-                "sign":"{}".format(sha256_hex), #HMACSHA256签名后的数据\r
-                "timeStamp":timeStamp, #要以ms的形式\r
-                "signMethod":"HMACSHA256" #签名方式 HMACSHA256\r
-            }\r
-            print(ujson.dumps(data))\r
-            headers_T ={"Content-Type":"application/json"}\r
-            url = "http://dmp.raisound.com/bz-api/dev/auth/active"\r
-            data =ujson.dumps(data)\r
-            response = 0\r
-            response_result = 0\r
-            try:\r
-                response = request.put(url,data=data,headers = headers_T)\r
-                response_result = 1\r
-            except Exception as e:\r
-                print("put error!!!!!\r\n")\r
-                response_result = 0\r
-            \r
-            IV = "" #偏移量\r
-            PASSWORD= "" #服务器返回后的加密内容 密码\r
-            if response_result == 1: #访问成功ip\r
-                if response.status_code == 200:\r
-                    print("headers:{}".format(response.headers))\r
-                    content = response.content\r
-                    c = next(content)\r
-                    # "api.xcloudtech.com"\r
-                    # d_server_port = 9000\r
-                    data =  ujson.loads(c)\r
-                    # data = response.json()\r
-                    print("data-{}".format(data))\r
-                    if data != None:\r
-                        if "success" in data:\r
-                            if data['success'] == True:\r
-                                if "data" in data:\r
-                                    data_tmp = data["data"]\r
-                                    if "nonce" in data_tmp: #偏移量\r
-                                        IV = data_tmp["nonce"]\r
-                                    if "password" in data_tmp:\r
-                                        PASSWORD = data_tmp["password"]\r
-                                        # EventMesh.publish("set_storage_config",["dev_pass",PASS])\r
-                            if data["code"] == 20001:#鉴权成功\r
-                                pass\r
-                            elif data["code"] > 50000:#时间错误\r
-                                self.res_error_count+=1\r
-                                if self.res_error_count>=3:\r
-                                    self.res_error_count = 0\r
-                                    EventMesh.publish("paly_device_res_error")\r
-                                if data["code"] == 50003:#时间错误\r
-                                    self.ntptime_flag  = 0\r
-                    if PASSWORD != None and IV != None:\r
-                        if len(PASSWORD) != 0 and len(IV) != 0:\r
-                            password = PASSWORD\r
-                            iv = IV\r
-                            #解密 之后保存本地下一次登入做使用\r
-                            decrypt_data = self.aes_CBC_Decrypt(password, self.key, iv) #对服务器下发的密码进行解密\r
-                            print("decrypt_data {}".format(decrypt_data))\r
-                            EventMesh.publish("set_storage_config",["dev_pass",decrypt_data])\r
-                    \r
-                        \r
-                print("IV:{}\r\n PASS:{}".format(IV,PASSWORD)) \r
-            return [response_result,PASSWORD,IV]\r
-    #随机生成16个字节的字符串作为加密的IV 偏移量\r
-    def generate_random_string(self,length=16): \r
-        random_str = ""\r
-        chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'\r
-        for i in range(length):\r
-            random_str+=chars[random.randint(0,length)]\r
-        return random_str\r
-\r
-    #设备登入 没有Token 走登入获取token\r
-    def dev_sign_in(self):\r
-        signal = net.csqQueryPoll()\r
-        if signal == -1 or self.get_sim_Status() != 1:#网络不正常\r
-            print("dev_sign_in 无 SIM卡!!!!!!!!\r\n")\r
-            return\r
-        token = ""\r
-        token = self.dev_token\r
-        dev_pass = EventMesh.publish("get_storage_config","dev_pass") \r
-        #print("token:{}\r\n".format(token))\r
-        if token == None:\r
-            token = ""\r
-        if dev_pass == None:\r
-            dev_pass = ""\r
-        if len(dev_pass) == 0:#没有密码\r
-            return\r
-        if token == None or token == "":\r
-            if 1: #返回结果成功\r
-                #获取本地保存的密码\r
-                decrypt_data=EventMesh.publish("get_storage_config","dev_pass")\r
-                # decrypt_data = self.aes_CBC_Decrypt(password, self.key, iv) #对服务器下发的密码进行解密\r
-                print("decrypt_data {}".format(decrypt_data))\r
-                #随机生成16个字符串 设备生成做加密使用\r
-                random_string = self.generate_random_string(16) #随机的16个字符串\r
-                enc_iv = random_string #加密的IV偏移量\r
-                #设备端进行密码加密\r
-                encrypt_data = self.aes_CBC_Encrypt(decrypt_data, self.key, enc_iv)\r
-                print("encrypt_data {}".format(encrypt_data))\r
-\r
-                #登入数据\r
-                deviceId = self.deviceId\r
-                sign_in_data = {\r
-                    "deviceId":"{}".format(deviceId), #设备ID\r
-                    "password":"{}".format(encrypt_data), #加密的数据\r
-                    "nonce":"{}".format(random_string) #随机的16个字符串\r
-                }\r
-                print(ujson.dumps(sign_in_data))\r
-                sign_url = "http://dmp.raisound.com/bz-api/dev/auth/sign_in" #登入地址\r
-                headers_T ={"Content-Type":"application/json"}\r
-                response_result = 0\r
-                response = 0\r
-                try:\r
-                    response = request.post(sign_url,data=ujson.dumps(sign_in_data),headers = headers_T)\r
-                    response_result = 1\r
-                except Exception as e:\r
-                    print("post error!!!!!\r\n")\r
-                    response_result = 0\r
-                # {'msg': '', 'code': 20001, 'success': True, \r
-                # 'data': {'deviceId': '876226002022574', \r
-                # 'token': '95436a9e09fd0ff89feb8825257dca982f'}\r
-                # }\r
-                token = ""\r
-                if response_result == 1:\r
-                    if response.status_code == 200:\r
-                        content = response.content\r
-                        c = next(content)\r
-                        data =  ujson.loads(c)\r
-                        print("data-{}".format(data))\r
-                        if data != None:\r
-                            if "success" in data:\r
-                                if data['success'] == True: #登入成功\r
-                                    if "data" in data:\r
-                                        data_tmp = data["data"]\r
-                                        if "token" in data_tmp: #token\r
-                                            self.dev_token = data_tmp["token"]\r
-                                if data["code"] == 50003:#时间错误\r
-                                    self.ntptime_flag  = 0\r
-                print("token:{}\r\n".format(token))\r
-                pass\r
-    #获取新的令牌 更新token\r
-    def update_dev_token(self, event, msg):\r
-        print("update_dev_token")\r
-        dev_pass = ""\r
-        dev_pass = EventMesh.publish("get_storage_config","dev_pass")\r
-        \r
-        if dev_pass == None:\r
-            dev_pass = ""\r
-        if len(dev_pass) == 0: #没有密码走激活\r
-            print("no dev_pass:{}\r\n".format(dev_pass))\r
-            self.dev_active()\r
-        token = self.dev_token\r
-        if token == None:\r
-            token = ""\r
-        if len(token) == 0: #没有token走登入\r
-            print("no dev_token:{}\r\n".format(token))\r
-            self.dev_sign_in()\r
-\r
-        dev_tokenip = "http://dmp.raisound.com/bz-api/dev/auth/token" #设备新令牌更新地址\r
-        token = self.dev_token\r
-        if token == None:\r
-            token = ""\r
-        if len(token) != 0:\r
-            response_result=0\r
-            response = 0\r
-            headers_T = {"bz-dt":"{}".format(token)}\r
-            try:\r
-                response = request.get(dev_tokenip,headers = headers_T)\r
-                response_result = 1\r
-            except Exception as e:\r
-                print("get error!!!!!\r\n")\r
-                response_result = 0\r
-            if response_result == 1:\r
-                if response.status_code == 200:\r
-                    try:\r
-                        headers_data = response.headers\r
-                        # print("headers_data!!!!! headers_data:{}\r\n".format(headers_data))\r
-                        if "bz-dt" in headers_data: #bz-dt字段是否在头部数据里面 如果有就需要更新\r
-                            bz_dt = headers_data["bz-dt"] \r
-                            self.dev_token = bz_dt.replace(" ", "") #去掉所有的空格符\r
-                            print("update_dev_token:{}".format(self.dev_token))\r
-                    except Exception as e:\r
-                        print("headers_data!!!!! error\r\n")\r
-        \r
-        pass\r
-\r
-\r
-\r
-\r
-#阿里voice_chat状态枚举\r
-VC_State_None=0\r
-VC_State_Listening=1#听\r
-VC_State_SpeechStart=2#说开始\r
-VC_State_SpeechEnd=3#说结束\r
-VC_State_Thinking=4#想(chat)\r
-VC_State_Responding=5#音频播放\r
-VC_State_TTSStart=6\r
-VC_State_TTSData=7\r
-VC_State_TTSFinish=8\r
-VC_State_TTSEnd=9\r
-VC_State_TTSError=10\r
-VC_State_DialogError=11\r
-VC_State_End=12\r
-\r
-VC_record_TYPE_PCM = 0\r
-VC_record_TYPE_AMR = 1\r
-VC_play_TYPE_PCM = 0\r
-VC_play_TYPE_MP3 = 1\r
-\r
-#websocket发送数据编号\r
-# AI_client_asr_num = 0\r
-# AI_client_chat_num = 1\r
-# AI_client_tts_num = 2\r
-AI_client_voice_chat_num = 3\r
-AI_client_asr_num = 4\r
-class AI_VC(Abstract):\r
-    # AI\r
-    \r
-    def __init__(self):\r
-        self.record_data_save_flag = 0 #是否保存录音文件\r
-        self.record_fd = None\r
-        #self.VC_mode = 0 #0:短按连续问答模式 1:长按录音模式\r
-        self.VC_mode = EventMesh.publish("get_storage_config","VC_mode")#音色配置\r
-        if self.VC_mode == None :\r
-            self.VC_mode = 0\r
-\r
-        self.VC_server = 2 #0正式服务器,1:测试服务器1,2:测试服务器2\r
-        self.VC_record_TYPE = VC_record_TYPE_PCM #0:PCM 1:AMR\r
-        self.VC_play_TYPE = VC_play_TYPE_PCM #0:PCM 1:mp3 \r
-        self.VC_record_samplerate = 16000\r
-        self.VC_play_samplerate = 16000\r
-        #女,男,童,粤,川\r
-        self.VC_TTS_voice_type = {0:"huoshan::zh_female_xinlingjitang_moon_bigtts",1:"huoshan::zh_male_wennuanahu_moon_bigtts",2:"huoshan::ICL_zh_female_huoponvhai_tob",\r
-                                  3:"aliyun::longjiaxin",4:"huoshan::zh_female_daimengchuanmei_moon_bigtts"}\r
-        #self.VC_TTS_voice_type = ["aliyun::longxiaoxia","aliyun::longnan","aliyun::longling"]\r
-        self.VC_TTS_voice_num = EventMesh.publish("get_storage_config","VC_TTS_voice_num")#音色配置\r
-        if self.VC_TTS_voice_num == None or self.VC_TTS_voice_num>=len(self.VC_TTS_voice_type):\r
-            self.VC_TTS_voice_num = 0\r
-         \r
-        self.VC_TTS_volume =  EventMesh.publish("get_storage_config","VC_TTS_volume")#音量配置\r
-        if self.VC_TTS_volume == None:\r
-            self.VC_TTS_volume = 100\r
-        self.AI_audio_queue_thread_id = 0\r
-        self.AI_send_data_queue_thread_id = 0\r
-\r
-        self.AI_record_tmp_queue = Queue(100)\r
-        self.AI_send_data_queue = Queue(100)\r
-        self.AI_audio_queue = Queue(100)\r
-        self.AI_TTS_str = ""\r
-        self.AI_ASR_str = ""\r
-        self.AI_ASR_flag = 0\r
-        self.AI_ASR_str_tmp = ""\r
-        # #开始线程\r
-        # if self.AI_audio_queue_thread_id ==0:\r
-        #     self.AI_audio_queue_thread_id = _thread.start_new_thread(self.AI_audio_queue_thread, ())\r
-        # else:\r
-        #     print("AI_VC_start :AI_audio_queue_thread_id != 0 ")\r
-        # if self.AI_send_data_queue_thread_id == 0:    \r
-        #     self.AI_send_data_queue_thread_id = _thread.start_new_thread(self.AI_send_data_queue_thread, ())\r
-            \r
-        self.voice_chat_state = VC_State_None #阿里ai voice_chat状态\r
-        self.VC_dialog_id = ""\r
-        self.VC_message_id=None\r
-        self.VC_task_id =None\r
-        self.AI_client_voice_chat = None\r
-        self.AI_client_voice_chat_recv_id = 0\r
-        self.AI_client_voice_chat_isconnect =0\r
-\r
-        self.asr_state = VC_State_None #阿里VC_ASR voice_chat状态\r
-        self.VC_asr_dialog_id = ""\r
-        self.VC_asr_message_id=None\r
-        self.VC_asr_task_id =None\r
-        self.AI_client_asr = None\r
-        self.AI_client_asr_recv_id = 0\r
-        self.AI_client_asr_isconnect =0\r
-\r
-        self.asr_satrt_flag = 0\r
-\r
-        self.record_pcm = None\r
-        self.play_pcm = None\r
-        self.VC_record_thread_id = 0\r
-        self.pingping_timerout = 0\r
-        \r
-        self.factory_timer = osTimer()\r
-        self._1S_timer = osTimer()\r
-        self.Audio_buf_size = 16*1024\r
-        self.record = audio.Record()\r
-        #self.record.end_callback(self.record_callback)\r
-        self.record.gain_set(4,10)\r
-        self.aud = audio.Audio(0)\r
-        self.aud.setCallback(self.audio_cb)\r
-        #self.aud.setVolume(self.VC_TTS_volume //10)\r
-        self.audio_play_state = 1 #音频播放完状态\r
-        self.close_timerout = 0\r
-        self.LocalRespondingEnded_timerout = 0\r
-        \r
-        self.play_flag = 0\r
-        self.VC_record_state_flag = 0\r
-        self.AI_key_long_press_flag = 0\r
-        self.websocket_error_count = 0\r
-\r
-        self.tts_in_data_len = 0\r
-        self.tts_out_data_len = 0\r
-        EventMesh.subscribe("AI_key_press", self.AI_key_press)\r
-        EventMesh.subscribe("AI_key_release", self.AI_key_release)\r
-        EventMesh.subscribe("AI_key_long_press", self.AI_key_long_press)\r
-        EventMesh.subscribe("pwk_key_release", self.pwk_key_release)\r
-        EventMesh.subscribe("get_AI_audio_queue", self.get_AI_audio_queue)\r
-        \r
-        EventMesh.publish("close_led")\r
-        #开机提示语,如果联网失败,直接提示信号弱\r
-        #女,男,童,粤,川\r
-        self.bot_name = "柒先生"\r
-        if self.VC_TTS_voice_num == 0 or self.VC_TTS_voice_num == 3 or self.VC_TTS_voice_num == 4:\r
-            self.bot_name = "柒妹妹"\r
-        elif self.VC_TTS_voice_num == 1:\r
-            self.bot_name = "柒先生"\r
-        elif self.VC_TTS_voice_num == 2:\r
-            self.bot_name = "柒思思"\r
-        self.AI_TTS_str = "您好!我是柒牌 AI 智能男装生活好帮手-{}, 很高兴为您服务,我可以帮您解答日常生活、工作,旅游信息、健康咨询、教育与学习、情感交流、全球资讯等问题!请问您有什么需要我帮忙的吗?".format(self.bot_name )\r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) \r
-\r
-    def post_processor_after_instantiation(self):\r
-        pass\r
-    def get_AI_audio_queue(self, event, msg):\r
-        return self.AI_audio_queue\r
-    def audio_cb(self,event):\r
-        if event == 0:\r
-            self.audio_play_state =1\r
-            #EventMesh.publish("set_audio_state", 1)\r
-            print('audio-play start.')\r
-        elif event == 7:\r
-            self.audio_play_state = 0\r
-            #EventMesh.publish("set_audio_state", 0)   \r
-            print('audio-play finish.!!!!!!')\r
-\r
-    def AI_key_press(self, event, msg):#按键按下\r
-        print("AI_key_press")\r
-        self.aud.aud_tone_play(16,200)#播放按键音\r
-        self.asr_satrt_flag = 1#\r
-        self.AI_TTS_str = ""#"你好,有什么吩咐"\r
-        self.AI_ASR_str = ""\r
-        self.AI_ASR_str_tmp = ""\r
-        # if self.voice_chat_state != VC_State_None:\r
-        #     EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) \r
-        #     EventMesh.publish("publish_AI_btnInfo",{"func":utime.sleep_ms,'data':(10)})\r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) \r
-        # self.Close()\r
-        # self.AI_VC_start()\r
-        self.AI_key_long_press_flag = 0\r
-\r
-    def AI_key_release(self, event, msg):#按键弹起\r
-        print("AI_key_release123")\r
-        if self.AI_key_long_press_flag == 1 :#有长按\r
-            self.AI_client_voice_chat_end_speech()\r
-        else :\r
-            if self.VC_mode == 1 :#长按单次问答模式\r
-                EventMesh.publish("audio_montage_play",["key_prompt.mp3"])\r
-                #self.aud.play(1,1,'U:/static/key_prompt.mp3')#提示请您按住中间的按钮开始讲话,讲完松开即可\r
-                self.AI_send_data_queue.clear()\r
-                try:\r
-                    self.websocket_deconnect_voice_chat()\r
-                except Exception as e:\r
-                    usys.print_exception(e)\r
-                self.VC_Speech_End()\r
-    def AI_key_long_press(self, event, msg):#按键长按\r
-        print("AI_key_long_press")\r
-        self.AI_key_long_press_flag = 1\r
-\r
-    def pwk_key_release(self, event, msg):#电源键短按,关闭\r
-        print("pwk_key_release")\r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) \r
-\r
-    \r
-#****************************************ASR连接**********************************************************************\r
-    def websocket_connect_asr(self):\r
-        print("websocket_connect_asr:{} {}!!!!!!!!!!!!!!!!!!!!!".format(self.AI_client_asr_isconnect,_thread.threadIsRunning(self.AI_client_asr_recv_id)))\r
-        if self.AI_client_asr_isconnect == 1:\r
-            return\r
-        # 创建VC客户端\r
-        try:\r
-            signal = net.csqQueryPoll()\r
-            if signal == -1 or sim.getStatus() != 1:#网络正常\r
-                self.websocket_error()\r
-                return\r
-            # Headers = {'X-NLS-Token':'0c8b8f05a46f423096be64a9c4c46310'}\r
-            # self.AI_client_asr = uwebsocket.Client.connect('wss://nls-gateway-cn-beijing.aliyuncs.com/ws/v1',headers=Headers, debug=False)\r
-            if self.VC_server == 1:# \r
-                self.AI_client_asr = uwebsocket.Client.connect('ws://118.145.158.207:22080/asr/ws', debug=False)#测试环境\r
-            elif self.VC_server == 2:# \r
-                if self.VC_TTS_voice_num <= 2:\r
-                    self.AI_client_asr = uwebsocket.Client.connect('ws://118.145.158.207:22080/asr/ws?platform=aliyun&lang=zh-cn', debug=False)#普通话测试环境\r
-                elif self.VC_TTS_voice_num == 3:\r
-                    self.AI_client_asr = uwebsocket.Client.connect('ws://118.145.158.207:22080/asr/ws?platform=aliyun&lang=zh-hk', debug=False)#粤语测试环境\r
-                elif self.VC_TTS_voice_num == 4:\r
-                    self.AI_client_asr = uwebsocket.Client.connect('ws://118.145.158.207:22080/asr/ws?platform=aliyun&lang=zh-cn-sc', debug=False)#四川话测试环境\r
-                else :\r
-                    self.AI_client_asr = uwebsocket.Client.connect('ws://118.145.158.207:22080/asr/ws?platform=aliyun&lang=zh-cn', debug=False)#普通话测试环境\r
-            else:\r
-                token = EventMesh.publish("get_dev_token")\r
-                print("token:{}".format(token))\r
-                if token != None:\r
-                    self.AI_client_asr = uwebsocket.Client.connect('ws://amp.raisound.com/asr/ws?dt={}'.format(token), debug=False)\r
-                else:\r
-                    pass\r
-                    return\r
-        except Exception as e: #网络连接异常\r
-            usys.print_exception(e)\r
-            print("websocket_connect_voice_chat error!!!\r\n")\r
-            #self.connect_timerout_popup(2)  \r
-            self.websocket_error()\r
-            return\r
-        if self.AI_client_asr == None:\r
-            EventMesh.publish("update_dev_token")#获取token\r
-            return \r
-        # 线程接收数据\r
-        if self.AI_client_asr_recv_id != 0:\r
-            try:\r
-                _thread.stop_thread(self.AI_client_asr_recv_id)\r
-            except Exception as e:\r
-                    usys.print_exception(e)\r
-            self.AI_client_asr_recv_id = 0\r
-        _thread.stack_size(self.Audio_buf_size+8*1024)\r
-        self.AI_client_asr_recv_id = _thread.start_new_thread(self.AI_client_asr_recv, (self.AI_client_asr,))\r
-        _thread.stack_size(8*1024)\r
-        self.AI_client_asr_isconnect = 1\r
-        # \r
-\r
-    def websocket_deconnect_asr(self):\r
-        print("websocket_deconnect_asr {}!!!!!!!".format(self.AI_client_asr_isconnect))\r
-        print("websocket_deconnect_asr!!!!!!!")\r
-        if self.AI_client_asr_recv_id != 0:#关闭线程\r
-            try:\r
-                _thread.stop_thread(self.AI_client_asr_recv_id)\r
-            except Exception as e:\r
-                usys.print_exception(e)\r
-        self.AI_client_asr_recv_id = 0\r
-        if self.AI_client_asr_isconnect == 1:\r
-            self.AI_client_asr_isconnect = 0\r
-            self.AI_client_asr.close()\r
-        print("websocket_deconnect_asr {}!!!!!!!".format(self.AI_client_asr_isconnect))\r
-\r
-    #websocket发送数据    \r
-    def AI_client_asr_send(self,data_str):\r
-        if isinstance(data_str, str):#是字符串\r
-            print("ASR ASR AI_client_asr_send:{}".format(data_str))\r
-            pass\r
-        else:\r
-            pass\r
-            #print("ASR ASR AI_client_asr_send:len:{}".format(len(data_str)))\r
-        self.AI_send_data_queue.put([AI_client_asr_num,data_str]) \r
-    #Ai VC websocket返回数据       \r
-    def AI_client_asr_recv(self,cli):\r
-        while True:\r
-            try:\r
-                # 死循环接收数据\r
-                utime.sleep_ms(1)\r
-                recv_data = cli.recv()\r
-                self.close_timerout = 0#服务器有返回清零退出时间\r
-                if not recv_data:\r
-                    # 服务器关闭连接或客户端关闭连接\r
-                    print("AI_client_asr_recv close!!!!!!!!!!!!!!!!!!!!!!!!!!!")\r
-                    #self.AI_client_voice_chat_isconnect = 0\r
-                    #self.websocket_deconnect_voice_chat()\r
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_deconnect_asr}) \r
-                    #EventMesh.publish("publish_AI_btnInfo",{"func":utime.sleep_ms,'data':(1500)})\r
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_connect_asr}) \r
-                    break\r
-                try:\r
-                    if isinstance(recv_data, str):\r
-                        jsload_data =  ujson.loads(recv_data)\r
-                        print("ASR ASR recv_data: {}".format(jsload_data))\r
-                        if jsload_data["event"] != None:\r
-                            if jsload_data["event"] == "TranscriptionStarted": #开始录音\r
-                                pass\r
-                        if recv_data.find('\"result\"') == -1:\r
-                        #if jsload_data["result"] == None:\r
-                            #print("continue recv_data:{}".format(recv_data))\r
-                            continue \r
-                        if jsload_data["result"] == None:\r
-                            #print("continue recv_data:{}".format(recv_data))\r
-                            continue \r
-                        if jsload_data["result"]["result"]:\r
-                            #self.AI_listen_text = str(jsload_data["result"]["result"])\r
-                            text= str(jsload_data["result"]["result"])\r
-                            \r
-\r
-                            print("ASR recv self.voice_chat_state :{}".format(self.voice_chat_state))\r
-                            if self.voice_chat_state >= VC_State_TTSStart:#开始播音后不响应asr结果\r
-                                print("asr continue")\r
-                                continue\r
-                            EventMesh.publish("open_led_red")\r
-                            if jsload_data["result"]["is_end"] == True:  #asr结束\r
-                                # if text.find('你好') != -1:\r
-                                #     self.asr_satrt_flag = 0\r
-                                #     self.AI_TTS_str = ""#"你好,有什么吩咐"\r
-                                #     self.AI_ASR_str = ""\r
-                                #     self.asr_satrt_flag = 1\r
-                                #     self.aud.aud_tone_play(16,200)#播放按键音\r
-                                #     # self.AI_client_asr_StopTranscription_requset()#终止前面合成\r
-                                #     # self.AI_client_asr_start_requset()#开始新的合成\r
-                                #     EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_deconnect_voice_chat}) \r
-                                #     EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) \r
-                                #     EventMesh.publish("open_led_red")\r
-                                #     continue\r
-                                #     #self.VC_Play_End()#关闭音频播放\r
-                                ret= self.check_text(text)\r
-                                if ret == 0:#配置指令\r
-                                    #print("check_text ok:{} self.VC_TTS_voice_num:{},{}".format(text,self.VC_TTS_voice_num,self.VC_TTS_voice_type[self.VC_TTS_voice_num]))\r
-                                    self.AI_send_data_queue.clear()\r
-                                    EventMesh.publish("open_led_all")\r
-                                    try:\r
-                                        EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_deconnect_voice_chat}) \r
-                                        #EventMesh.publish("publish_AI_btnInfo",{"func":utime.sleep_ms,'data':(1500)})\r
-                                        EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) \r
-                                    except Exception as e:\r
-                                        usys.print_exception(e)\r
-                                    continue\r
-                                elif ret == 1:#不处理\r
-                                    pass\r
-                                else:#正常asr\r
-                                    if self.AI_ASR_flag == 0:#d第一次识别,没有打断\r
-                                        self.AI_ASR_str = text#\r
-                                        self.AI_ASR_str_tmp = self.AI_ASR_str\r
-                                        self.AI_ASR_flag  = 1\r
-                                    else:#第二次识别,打断了\r
-                                        self.AI_ASR_str = self.AI_ASR_str_tmp+text\r
-                                        print("ASR ASR 打断 续集 AI_ASR_str {}".format(self.AI_ASR_str))\r
-                                        self.AI_ASR_str_tmp = self.AI_ASR_str\r
-                                        EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init2})#关闭vc连接\r
-                                    EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) \r
-\r
-\r
-                                    # if self.AI_ASR_str != "":#识别过一次asr,打断当前思考或者tts播放\r
-                                    #     self.AI_ASR_str_tmp = self.AI_ASR_str\r
-                                    #     print("ASR ASR 打断1 AI_ASR_str_tmp {}".format(self.AI_ASR_str_tmp))\r
-                                    #     self.AI_ASR_str = ""\r
-                                    # if self.AI_ASR_str_tmp != "":\r
-                                    #     self.AI_ASR_str = self.AI_ASR_str_tmp +text#加上之前的数据\r
-                                    #     print("ASR ASR 打断 续集 AI_ASR_str {}".format(self.AI_ASR_str))\r
-                                    # else:\r
-                                    #     self.AI_ASR_str = text#\r
-                                    # EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) \r
-                                    # self.AI_ASR_str_tmp = ""\r
-                                        \r
-                                    \r
-                            elif jsload_data["result"]["is_end"] == False:\r
-                                if self.AI_ASR_flag ==1 :#如果已经识别过一次asr\r
-                                    self.AI_ASR_flag = 2\r
-                                    print("asr 打断,关闭VC连接")\r
-                                    EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init2})#关闭vc连接\r
-                                    EventMesh.publish("publish_AI_btnInfo",{"func":EventMesh.publish,"data":"open_led_red"})#关闭vc连接\r
-                                pass\r
-                except Exception as e:\r
-                    usys.print_exception(e)\r
-                \r
-            except Exception as e:\r
-                    usys.print_exception(e)\r
-                    #self.websocket_error()\r
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) \r
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_error})#\r
-                    break\r
-        self.AI_client_asr_isconnect = 0\r
-        self.AI_client_asr_recv_id = 0 \r
-        print("AI_client_asr_recv END!!!!!!!!!!!!!!!!!!!!!!!!!!!")\r
-    #ASR开始会话\r
-    def AI_client_asr_start_requset(self):\r
-        \r
-        json_data = \\r
-        { \r
-            "header":{\r
-                "event":"StartTranscription",\r
-                "trace_id":self.get_trace_id()\r
-                },\r
-            "payload":{\r
-                "format":"pcm",\r
-                "sample_rate":self.VC_record_samplerate,\r
-                }\r
-            \r
-        }\r
-        if self.VC_record_TYPE == VC_record_TYPE_AMR :\r
-            json_data["payload"]["format"]='amr'\r
-            pass\r
-        # if self.VC_mode == 1:\r
-        #     json_data["payload"]["voice_detection"]='disable'\r
-\r
-        self.AI_client_asr_send(ujson.dumps(json_data))\r
-    #ASR终止\r
-    def AI_client_asr_StopTranscription_requset(self):   \r
-        json_data = \\r
-        {\r
-            "header":{\r
-                "event":"StopTranscription",\r
-                "trace_id":self.get_trace_id()\r
-                }\r
-        }\r
-\r
-        self.AI_client_asr_send(ujson.dumps(json_data))\r
-    \r
-     #开始录音\r
-    def VC_Speech_Start(self):\r
-        #self.voice_chat_state =  VC_State_SpeechStart\r
-        print("VC_Speech_Start VC_record_state_flag:{} self.AI_ASR_flag:{}!!!!!!!!".format(self.VC_record_state_flag,self.AI_ASR_flag))  \r
-        if self.AI_ASR_flag  != 0:\r
-            return\r
-        if self.VC_record_state_flag  == 0:\r
-            self.AI_client_asr_start_requset()#开始请求\r
-            if self.VC_record_thread_id != 0:\r
-                try:\r
-                    _thread.stop_thread(self.VC_record_thread_id)\r
-                except Exception as e:\r
-                        usys.print_exception(e)\r
-                self.VC_record_thread_id = 0\r
-            _thread.stack_size(self.Audio_buf_size+8*1024)\r
-            self.VC_record_thread_id = _thread.start_new_thread(self.VC_record_thread,())\r
-            _thread.stack_size(8*1024)\r
-            print("self.VC_record_thread_id:{}".format(self.VC_record_thread_id))\r
-            if self.VC_record_TYPE == VC_record_TYPE_AMR :\r
-                try :\r
-                    self.record.stream_start(audio.Record.AMRNB, self.VC_record_samplerate, 0)\r
-                except Exception as e:\r
-                        usys.print_exception(e)\r
-            elif self.VC_record_TYPE == VC_record_TYPE_PCM:\r
-                print("record_pcm.stream_read_start()!!!!!!!!!!!!")\r
-                self.record.stream_start(audio.Record.WAV, self.VC_record_samplerate, 0)\r
-                # if self.record_pcm != None:\r
-                #     try:\r
-                #         self.record_pcm.stream_stop()\r
-                #         self.record_pcm.close()\r
-                #         self.record_pcm = None\r
-                #     except Exception as e:\r
-                #         usys.print_exception(e)\r
-                # if self.record_pcm == None:        \r
-                #     ret = self.record_pcm = audio.Audio.PCM(0,1,16000,0,1,2)\r
-                #     print("audio.Audio.PCM:ret:{}".format(ret))\r
-                #     ret = self.record_pcm.stream_read_start()\r
-                #     print("self.record_pcm.stream_read_start:ret:{}".format(ret))\r
-            self.VC_record_state_flag = 1\r
-    #停止录音\r
-    def VC_Speech_End(self):\r
-        try:\r
-            self.AI_ASR_flag = 0\r
-            self.AI_client_asr_StopTranscription_requset()#请求停止\r
-            if self.VC_record_TYPE == VC_record_TYPE_AMR:\r
-                self.record.stream_stop()\r
-                self.record.stop()#关闭录音\r
-                Record_read_buf = bytearray(self.Audio_buf_size)\r
-                for i in range(10):\r
-                    Record_len = self.record.stream_read(Record_read_buf, self.Audio_buf_size)\r
-                    print("Record_len:!!!!!!{}".format(Record_len))\r
-                    if Record_len <= 0:\r
-                        break\r
-            elif self.VC_record_TYPE == VC_record_TYPE_PCM:\r
-                self.record.stream_stop()\r
-                self.record.stop()#关闭录音\r
-                Record_read_buf = bytearray(self.Audio_buf_size)\r
-                for i in range(10):\r
-                    Record_len = self.record.stream_read(Record_read_buf, self.Audio_buf_size)\r
-                    print("Record_len:!!!!!!{}".format(Record_len))\r
-                    if Record_len <= 0:\r
-                        break\r
-                # if self.record_pcm != None:\r
-                #     try:\r
-                #         self.record_pcm.stream_stop()\r
-                #         self.record_pcm.close()\r
-                #         self.record_pcm = None\r
-                #     except Exception as e:\r
-                #         usys.print_exception(e)\r
-        except Exception as e:\r
-            usys.print_exception(e)\r
-        if self.VC_record_thread_id != 0:\r
-            try:\r
-                _thread.stop_thread(self.VC_record_thread_id)\r
-            except Exception as e:\r
-                    usys.print_exception(e)\r
-            self.VC_record_thread_id = 0\r
-        \r
-        self.VC_record_state_flag = 0\r
-        print("VC_Speech_End VC_record_state_flag:{}!!!!!!!!".format(self.VC_record_state_flag))   \r
-    #获取录音数据\r
-    def VC_record_thread(self):\r
-        ##return\r
-        print("VC_record_thread start!!!!!!!!!!!!!!!!!!!!\r\n")\r
-        count = 0\r
-        # try:\r
-        #     uos.remove('/usr/test.pcm')\r
-        # except Exception as e:\r
-        #     usys.print_exception(e)\r
-        #record_data_queue = Queue(100)\r
-        #fd = open('/usr/test.pcm','w')\r
-        # if self.VC_record_TYPE == 1:\r
-        #     h_data= [0x23,0x21 ,0x41 ,0x4D ,0x52 ,0x0A ]\r
-        #     h_data_b = bytes(h_data)\r
-        #     self.AI_client_voice_chat_send(h_data_b)\r
-        \r
-        count = 0\r
-        while True:\r
-            try:\r
-                \r
-                # 死循环接收数据\r
-                #if self.voice_chat_state ==  VC_State_SpeechStart:\r
-                Record_read_buf = bytearray(self.Audio_buf_size)\r
-                \r
-                Record_len = 0\r
-                if self.VC_record_TYPE == VC_record_TYPE_PCM:#pcm\r
-                    Record_len = self.record.stream_read(Record_read_buf, self.Audio_buf_size)\r
-                    utime.sleep_ms(20)\r
-                    \r
-                else :\r
-                    \r
-                    Record_len = self.record.stream_read(Record_read_buf, self.Audio_buf_size)\r
-                    utime.sleep_ms(600)\r
-\r
-                #Record_len = 1024*2\r
-                #print("VC_record_thread:{}".format(Record_len))\r
-                if Record_len > 0:\r
-                    read_buf = bytes(Record_read_buf[:Record_len])\r
-                    if self.record_fd != None:\r
-                        self.record_fd.write(read_buf)\r
-                    self.AI_client_asr_send(read_buf)\r
-                    \r
-                    # if self.voice_chat_state !=  VC_State_SpeechStart:#没发送前先存起来\r
-                    #     self.AI_record_tmp_queue.put(read_buf)\r
-                    # else:\r
-                    #     while True:\r
-                    #         if self.AI_record_tmp_queue.empty() == True:\r
-                    #             break\r
-                    #         else:\r
-                    #             self.AI_client_voice_chat_send(self.AI_record_tmp_queue.get())  #发送之前存的数据\r
-                    #     self.AI_client_voice_chat_send(read_buf)   \r
-                    #print("VC_record_thread:{}".format(len(read_buf)))\r
-                    count+=len(read_buf)\r
-                # if count>=500*1024:#结束\r
-                #     self.AI_client_voice_chat_end_speech()\r
-                #     break\r
-                utime.sleep_ms(40)\r
-                # if self.voice_chat_state >=  VC_State_SpeechEnd:\r
-                #     break\r
-                count+=1\r
-                if count %10 == 0:\r
-                    print("VC_record_thread on line {} asr recv :{} send:{}".format(Record_len,_thread.threadIsRunning(self.AI_client_asr_recv_id),_thread.threadIsRunning(self.AI_send_data_queue_thread_id)))\r
-            except Exception as e:\r
-                    usys.print_exception(e)\r
-                    #break\r
-\r
-        #fd.close()\r
-        print("VC_record_thread:exit")\r
-        self.VC_record_thread_id = 0#线程退出\r
-###################################################### VC ###################################################################################\r
-    def websocket_connect_voice_chat(self):\r
-        print("websocket_connect_voice_chat:{}!!!!!!!!!!!!!!!!!!!!!".format(self.AI_client_voice_chat_isconnect))\r
-        if self.AI_client_voice_chat_isconnect == 1:\r
-            return\r
-        # 创建VC客户端\r
-        try:\r
-            signal = net.csqQueryPoll()\r
-            if signal == -1 or sim.getStatus() != 1:#网络正常\r
-                self.websocket_error()\r
-                return\r
-            # Headers = {'X-NLS-Token':'0c8b8f05a46f423096be64a9c4c46310'}\r
-            # self.AI_client_voice_chat = uwebsocket.Client.connect('wss://nls-gateway-cn-beijing.aliyuncs.com/ws/v1',headers=Headers, debug=False)\r
-            if self.VC_server == 1:# \r
-                self.AI_client_voice_chat = uwebsocket.Client.connect('ws://118.145.158.207:22080/voice-chat/ws', debug=False)#测试环境\r
-            elif self.VC_server == 2:# \r
-                if self.VC_TTS_voice_num <= 2:\r
-                    self.AI_client_voice_chat = uwebsocket.Client.connect('ws://118.145.158.207:22080/voice-chat/ws?is_auth=0&platform=raisound&lang=zh-cn', debug=False)#普通话测试环境\r
-                elif self.VC_TTS_voice_num == 3:\r
-                    self.AI_client_voice_chat = uwebsocket.Client.connect('ws://118.145.158.207:22080/voice-chat/ws?is_auth=0&platform=raisound&lang=zh-hk', debug=False)#粤语测试环境\r
-                elif self.VC_TTS_voice_num == 4:\r
-                    self.AI_client_voice_chat = uwebsocket.Client.connect('ws://118.145.158.207:22080/voice-chat/ws?is_auth=0&platform=raisound&lang=zh-cn-sc', debug=False)#四川话测试环境\r
-                else :\r
-                    self.AI_client_voice_chat = uwebsocket.Client.connect('ws://118.145.158.207:22080/voice-chat/ws?is_auth=0&platform=raisound&lang=zh-cn', debug=False)#普通话测试环境\r
-            else:\r
-                token = EventMesh.publish("get_dev_token")\r
-                print("token:{}".format(token))\r
-                if token != None:\r
-                    self.AI_client_voice_chat = uwebsocket.Client.connect('ws://amp.raisound.com/voice-chat/ws?dt={}'.format(token), debug=False)\r
-                else:\r
-                    self.websocket_error()\r
-                    return\r
-        except Exception as e: #网络连接异常\r
-            usys.print_exception(e)\r
-            print("websocket_connect_voice_chat error!!!\r\n")\r
-            #self.connect_timerout_popup(2)\r
-            self.websocket_error()\r
-            return\r
-        print("AI_client_voice_chat:{}".format(self.AI_client_voice_chat))\r
-        if self.AI_client_voice_chat == None:\r
-            EventMesh.publish("update_dev_token")#获取token\r
-            self.websocket_error()\r
-            return\r
-        utime.sleep_ms(20)\r
-        # 线程接收数据\r
-        if self.AI_client_voice_chat_recv_id != 0:\r
-            try:\r
-                _thread.stop_thread(self.AI_client_voice_chat_recv_id)\r
-            except Exception as e:\r
-                    usys.print_exception(e)\r
-            self.AI_client_voice_chat_recv_id = 0\r
-        _thread.stack_size(self.Audio_buf_size+8*1024)\r
-        self.AI_client_voice_chat_recv_id = _thread.start_new_thread(self.AI_client_voice_chat_recv, (self.AI_client_voice_chat,))\r
-        _thread.stack_size(8*1024)\r
-        self.AI_client_voice_chat_isconnect = 1\r
-    def websocket_error(self):\r
-        print("websocket_error!!!!")\r
-        print("websocket_error!!!!")\r
-        print("websocket_error!!!!")\r
-        print("websocket_error!!!!")\r
-        self.websocket_error_count+=1\r
-        if self.websocket_error_count <=3:\r
-            EventMesh.publish("audio_montage_play",["xinhaoruo1.mp3"])\r
-        elif self.websocket_error_count <10 :\r
-            EventMesh.publish("audio_montage_play",["xinhaoruo2.mp3"])\r
-        elif self.websocket_error_count >=10:\r
-            EventMesh.publish("paly_iccid_imei")    \r
-        else:\r
-            EventMesh.publish("audio_montage_play",["R_SIM_FAILE.mp3"])\r
-        #self.aud.play(1,1,'U:/static/R_SIM_FAILE.mp3')\r
-        self.AI_send_data_queue.clear()\r
-        self.AI_audio_queue.clear()\r
-        #self.VC_Speech_End()\r
-        EventMesh.publish("close_led")\r
-        try:\r
-            self.websocket_deconnect_voice_chat()\r
-        except Exception as e:\r
-                usys.print_exception(e)\r
-        try:\r
-            self.websocket_deconnect_asr()\r
-        except Exception as e:\r
-                usys.print_exception(e)\r
-\r
-    def websocket_deconnect_voice_chat(self):\r
-        print("websocket_deconnect_voice_chat {}!!!!!!!".format(self.AI_client_voice_chat_isconnect))\r
-        print("websocket_deconnect_voice_chat!!!!!!!")\r
-        if self.AI_client_voice_chat_recv_id != 0:#关闭线程\r
-            try:\r
-                _thread.stop_thread(self.AI_client_voice_chat_recv_id)\r
-            except Exception as e:\r
-                usys.print_exception(e)\r
-        self.AI_client_voice_chat_recv_id = 0\r
-        if self.AI_client_voice_chat_isconnect == 1:\r
-            self.AI_client_voice_chat_isconnect = 0\r
-            self.AI_client_voice_chat.close()\r
-        print("websocket_deconnect_voice_chat {}!!!!!!!".format(self.AI_client_voice_chat_isconnect))\r
-    #websocket发送ping\r
-    def AI_client_voice_chat_ping(self):\r
-        pass\r
-        if self.AI_client_voice_chat_isconnect == 1:\r
-            #self.AI_client_voice_chat.write_frame(0x09,b'ping ping')\r
-            self.AI_client_voice_chat_send("ping")\r
-            #print("websocket ping ping")\r
-\r
-    #websocket发送数据    \r
-    def AI_client_voice_chat_send(self,data_str):\r
-        if isinstance(data_str, str):#是字符串\r
-            print("AI_client_voice_chat_send:{}".format(data_str))\r
-            pass\r
-        # else:\r
-        #     print("AI_client_voice_chat_send:len{}".format(len(data_str)))\r
-        self.AI_send_data_queue.put([AI_client_voice_chat_num,data_str]) \r
-    \r
-    #Ai VC websocket返回数据       \r
-    def AI_client_voice_chat_recv(self,cli):\r
-        count = 0\r
-        while True:\r
-            try:\r
-                # 死循环接收数据\r
-                count+=1\r
-                if self.tts_in_data_len - self.tts_out_data_len > 64*1024 or count>4:\r
-                    count = 0\r
-                    utime.sleep_ms(1)\r
-                recv_data = cli.recv()\r
-                self.close_timerout = 0#服务器有返回清零退出时间\r
-                if not recv_data:\r
-                    # 服务器关闭连接或客户端关闭连接\r
-                    print("服务器主动关闭连接!!!!!!!!!!!!!!!!!!!!!!!!!!!")\r
-                    #self.AI_client_voice_chat_isconnect = 0\r
-                    #self.websocket_error()\r
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) \r
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_error}) \r
-                    #EventMesh.publish("publish_AI_btnInfo",{"func":utime.sleep_ms,'data':(1500)})\r
-                    \r
-                    break\r
-                try:\r
-                    self.websocket_error_count = 0\r
-                    if isinstance(recv_data, str):#返回的是字符串\r
-                        print("VC VC:recv_data:{}".format(recv_data))\r
-                        jsload_data =  ujson.loads(recv_data)\r
-                        #print("AI_client_voice_chat_recv jsload_data = {}".format(jsload_data))\r
-                        if jsload_data["status"] != 20000000:#返回错误\r
-                            self.websocket_error()\r
-                            break\r
-                        if jsload_data["event"] == "Started" :#会话开始\r
-                            payload = jsload_data["payload"]\r
-                            self.VC_dialog_id = payload["dialog_id"] \r
-                            self.VC_task_id = jsload_data["task_id"] \r
-                            print("VC:Started!!!!!!!!\r\n")\r
-                        elif jsload_data["event"]  == "SpeechContent" :#asr转译\r
-                            print("VC:SpeechContent!!!!!!!!\r\n")\r
-                            payload = jsload_data["payload"]\r
-                            \r
-                            \r
-                            if(payload['finished'] == True):#asr结束\r
-                                self.voice_chat_state =  VC_State_SpeechEnd\r
-                                #self.VC_Speech_End()#停止录音\r
-                                text = payload["text"]\r
-                                if self.check_text(text) == 0:\r
-                                    #print("check_text ok:{} self.VC_TTS_voice_num:{},{}".format(text,self.VC_TTS_voice_num,self.VC_TTS_voice_type[self.VC_TTS_voice_num]))\r
-                                    self.AI_send_data_queue.clear()\r
-                                    EventMesh.publish("open_led_all")\r
-                                    try:\r
-                                        EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_deconnect_voice_chat}) \r
-                                        #EventMesh.publish("publish_AI_btnInfo",{"func":utime.sleep_ms,'data':(1500)})\r
-                                        EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) \r
-                                    except Exception as e:\r
-                                        usys.print_exception(e)\r
-                                \r
-                                pass\r
-                            else:\r
-                                self.AI_listen_end = 0\r
-\r
-                        elif jsload_data["event"]  == "SpeechEnded" :#服务器下发ASR说话结束\r
-                            self.voice_chat_state =  VC_State_SpeechEnd\r
-                        elif jsload_data["event"]  == "RespondingContent" :#chat回答      \r
-                            pass\r
-                            # payload = jsload_data["payload"]\r
-\r
-                            # if(payload['finished'] == True):#chat回答 结束,开始tts\r
-                            #     self.AI_client_chat_end_flag = 1\r
-                            #     pass\r
-                            # else:\r
-                                \r
-                            #     self.AI_client_chat_end_flag = 0\r
-                            #     self.AI_client_tts_data_len = 0\r
-                            #utime.sleep_ms(5)\r
-                            \r
-                        elif jsload_data["event"]  == "RespondingStarted" :#音频开始下发\r
-                            self.play_flag = 0\r
-                            self.voice_chat_state = VC_State_TTSStart\r
-                            self.VC_Speech_End()#停止录音\r
-                            self.VC_Play_Start()\r
-                            #self.tts_fd = open('/usr/tts_tesr.pcm','w')\r
-                            pass\r
-                        elif jsload_data["event"]  == "RespondingEnded" :#音频下发结束\r
-                            #if self.voice_chat_state == VC_State_TTSStart:\r
-                                print("RespondingEnded!!!!!!" )\r
-                                self.voice_chat_state = VC_State_TTSEnd\r
-                                if self.asr_satrt_flag == 0 :\r
-                                    self.asr_satrt_flag =1\r
-                            #self.tts_fd.close()\r
-                            #pass\r
-                        elif jsload_data["event"]  == "DialogStateChanged" :#状态切换事件\r
-                            payload = jsload_data["payload"]\r
-                            if payload["state"] == "Listening":\r
-                                self.voice_chat_state = VC_State_Listening\r
-                                if self.AI_TTS_str != "" or self.AI_ASR_str != "":#有tts数据,则请求TTS数据,没有就请求开始上传语音\r
-                                    self.AI_client_voice_chat_RequestToRespond()\r
-                                else:\r
-                                    self.VC_Speech_Start()#开启线程获取录音数据\r
-                                    #self.AI_client_voice_chat_send_speech()#开始上传语音\r
-                                #self.AI_client_voice_chat_RequestToRespond()#chat请求或者tts请求\r
-                                EventMesh.publish("open_led_red")\r
-                            if payload["state"] == "Thinking":#准备开始TTS\r
-                                self.voice_chat_state = VC_State_Thinking\r
-                                \r
-                                self.AI_client_tts_data_total_len = 0\r
-                                EventMesh.publish("open_led_all")\r
-                            if payload["state"] == "Responding":\r
-                                self.voice_chat_state = VC_State_Responding\r
-                                EventMesh.publish("open_led_green")\r
-                        elif jsload_data["event"]  == "RequestAccepted" :#请求上传语音被允许\r
-                            #self.voice_chat_state =  VC_State_Responding\r
-                            #self.AI_client_voice_chat_send_speech()#开始上传语音\r
-                            pass\r
-                    else:#下发音频数据\r
-                        #填充头\r
-                        #self.tts_fd.write(recv_data)\r
-                        #recv_data_len = len(recv_data)\r
-                        # data_len_b = recv_data_len.to_bytes(4,'little')#数据长度转16进制数组\r
-                        # h_data = [ 0x52 ,0x49 ,0x46 ,0x46 #,0x24 ,0x00 ,0x00 ,0x00 #文件标识、文件大小\r
-                        #         ,0x57 ,0x41 ,0x56 ,0x45 ,0x66 ,0x6D ,0x74 ,0x20  #文件格式、格式块标识符\r
-                        #         ,0x10 ,0x00 ,0x00 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x80 ,0x3E ,0x00 ,0x00  #格式块大小4、音频格式2、声道数2、采样率4\r
-                        #         ,0x80 ,0x3E ,0x00 ,0x00 ,0x02 ,0x00 ,0x10 ,0x00 ,0x64 ,0x61 ,0x74 ,0x61]#每秒字节数4、数据块对齐2、位深度2、data4\r
-                        # h_data_b = bytes(h_data)\r
-                        # file_len = recv_data_len+len(h_data_b)+4+4\r
-                        # file_len_b = file_len.to_bytes(4,'little')#文件长度转16进制数组\r
-                        # h_data_b = h_data_b[:4]+file_len_b+h_data_b[4:]+data_len_b\r
-\r
-                        #print("下发音频数据1:{}".format(len(recv_data)))\r
-                        # # self.AI_client_tts_data_total_len += len(recv_data)\r
-                        # # self.AI_client_tts_data_len += len(recv_data)\r
-                        # #if self.AI_client_tts_data_total_len >10*1024:\r
-                        # ret=self.AI_audio_queue.put([recv_data,""])\r
-                        # print("下发音频数据2:{}".format(len(recv_data)))\r
-                        if self.voice_chat_state >= VC_State_TTSStart:\r
-                            self.put_record_data([recv_data,""])\r
-                        #EventMesh.publish("publish_AI_btnInfo",{"func":self.put_record_data,"data":[recv_data,""]}) \r
-                except Exception as e:\r
-                    usys.print_exception(e)\r
-                \r
-            except Exception as e:\r
-                    usys.print_exception(e)\r
-                    #self.websocket_error()\r
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) \r
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_error})#\r
-                    break\r
-        self.AI_client_voice_chat_isconnect = 0\r
-        self.AI_client_voice_chat_recv_id = 0 \r
-        print("AI_client_voice_chat_recv END!!!!!!!!!!!!!!!!!!!!!!!!!!!")\r
-    def put_record_data(self,data):\r
-        #print("下发音频数据1:{}".format(len(data[0])))\r
-        # self.AI_client_tts_data_total_len += len(recv_data)\r
-        # self.AI_client_tts_data_len += len(recv_data)\r
-        #if self.AI_client_tts_data_total_len >10*1024:\r
-        ret=self.AI_audio_queue.put(data)\r
-        self.tts_in_data_len += len(data[0])\r
-        print("下发音频数据2:{},{}".format(len(data[0]),self.tts_in_data_len))\r
-    def check_text(self,text):\r
-        if len(text)>60:\r
-            return -1\r
-        try:\r
-            if isinstance(text, str): \r
-                if text.find("更改声音") != -1:\r
-                    self.VC_TTS_voice_num += 1\r
-                    if self.VC_TTS_voice_num >= len(self.VC_TTS_voice_type):\r
-                        self.VC_TTS_voice_num = 0\r
-                    EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_TTS_voice_num])\r
-                    # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])\r
-                    #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功\r
-                    self.AI_TTS_str = "更改成功"    \r
-                    return 0\r
-                if text.find("声音改为") != -1 and (text.find("男声") != -1 or text.find("男生") != -1 ):\r
-                    self.VC_TTS_voice_num = 1\r
-                    \r
-                    EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_TTS_voice_num])\r
-                    # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])\r
-                    #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功\r
-                    self.AI_TTS_str = "更改成功" \r
-                    return 0\r
-                if text.find("声音改为") != -1 and  (text.find("女声") != -1 or text.find("女生") != -1 ):\r
-                    self.VC_TTS_voice_num = 0\r
-                    \r
-                    EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_TTS_voice_num])\r
-                    # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])\r
-                    #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功\r
-                    self.AI_TTS_str = "更改成功" \r
-                    return 0\r
-                if text.find("声音改为") != -1 and  (text.find("同声") != -1 or text.find("童声") != -1 ):\r
-                    self.VC_TTS_voice_num = 2\r
-                    \r
-                    EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_TTS_voice_num])\r
-                    # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])\r
-                    #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功\r
-                    self.AI_TTS_str = "更改成功" \r
-                    return 0\r
-                if text.find("声音改为") != -1 and  (text.find("粤语") != -1 or text.find("越野") != -1 ):\r
-                    self.VC_TTS_voice_num = 3\r
-                    \r
-                    EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_TTS_voice_num])\r
-                    # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])\r
-                    #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功\r
-                    self.AI_TTS_str = "更改成功" \r
-                    return 0\r
-                if text.find("声音改为") != -1 and text.find("四川话") != -1 :\r
-                    self.VC_TTS_voice_num = 4\r
-                    \r
-                    EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_TTS_voice_num])\r
-                    # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])\r
-                    #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功\r
-                    self.AI_TTS_str = "更改成功" \r
-                    return 0\r
-                if text.find("切换对话模式") != -1:\r
-                    if self.VC_mode == 0:\r
-                       self.VC_mode = 1\r
-                       self.AI_TTS_str = "已切换到单对话模式" \r
-                    else:\r
-                        self.VC_mode = 0 \r
-                        self.AI_TTS_str = "已切换到长对话模式" \r
-                    EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_mode])\r
-                    # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])\r
-                    #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功\r
-\r
-                    return 0\r
-                if text.find("音量") != -1 and text.find("加") != -1 :\r
-                    self.VC_TTS_volume += 10\r
-                    if self.VC_TTS_volume > 100:\r
-                        #EventMesh.publish("audio_montage_play",["yinliangyizuida.mp3"])\r
-                        #self.aud.play(1,0,'U:/static/yinliangyizuida.mp3')#音量已最大\r
-                        self.AI_TTS_str = "音量已最大" \r
-                        self.VC_TTS_volume = 100\r
-                    else:\r
-                        self.aud.setVolume(self.VC_TTS_volume //10)\r
-                        EventMesh.publish("set_storage_config",["VC_TTS_volume",self.VC_TTS_volume])\r
-                        #EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])\r
-                        #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#配置成功\r
-                        self.AI_TTS_str = "配置成功,当前音量 {}".format(self.VC_TTS_volume)\r
-                        \r
-                    return 0\r
-                if text.find("音量") != -1 and text.find("减") != -1:\r
-                    self.VC_TTS_volume -= 10\r
-                    if self.VC_TTS_volume < 0:\r
-                        self.VC_TTS_volume = 0\r
-                        #EventMesh.publish("audio_montage_play",["yinliangyizuixiao.mp3"])\r
-                        #self.aud.play(1,0,'U:/static/yinliangyizuixiao.mp3')#音量已最小\r
-                        self.AI_TTS_str = "音量已最小"\r
-                    else:\r
-                        self.aud.setVolume(self.VC_TTS_volume //10)\r
-                        EventMesh.publish("set_storage_config",["VC_TTS_volume",self.VC_TTS_volume])\r
-                        #EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])\r
-                        #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#配置成功\r
-                        self.AI_TTS_str = "配置成功,当前音量 {}".format(self.VC_TTS_volume)\r
-                    return 0\r
-                if text.find("电量") != -1 and text.find("查询") != -1:\r
-                    battery = EventMesh.publish("get_battery")\r
-                    #EventMesh.publish("audio_montage_play",["dianliangshengyu{}.mp3".format(battery)])\r
-                    #self.aud.play(1,0,'U:/static/dianliangshengyu{}.mp3'.format(battery))#电量剩余\r
-                    self.AI_TTS_str = "电量剩余百分之{}".format(battery)\r
-                    return 0\r
-                if text.find("电压") != -1 and text.find("查询") != -1:\r
-                    Vbatt = Power.getVbatt()\r
-                    #EventMesh.publish("audio_montage_play",["dianliangshengyu{}.mp3".format(battery)])\r
-                    #self.aud.play(1,0,'U:/static/dianliangshengyu{}.mp3'.format(battery))#电量剩余\r
-                    self.AI_TTS_str = "当前电池电压{}".format(Vbatt)\r
-                    return 0\r
-                if text.find("进入工厂模式") != -1 :\r
-                    self.factory_mode()\r
-                    return 1\r
-                if text.find("信号") != -1 and text.find("查询") != -1:\r
-                    signal = net.csqQueryPoll()\r
-                    \r
-                    self.AI_TTS_str = "当前信号{}".format(signal)\r
-                    return 0\r
-                \r
-                if text.find("再见") != -1 or text.find("拜拜") != -1:\r
-                    EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) \r
-                    return 1\r
-        except Exception as e:\r
-                usys.print_exception(e)\r
-        return -1\r
-    #获取trace_id\r
-    def get_trace_id(self):\r
-        t = utime.mktime(utime.localtime())\r
-        t = t*1000+urandom.randint(0, 1000)\r
-        md5_data = "{}".format(t)#md5签名\r
-        sign_data = ""\r
-        hash_obj = uhashlib.md5(md5_data)\r
-        res = hash_obj.digest()\r
-\r
-        # 转成十六进制表示\r
-        sign_data = ubinascii.hexlify(res)\r
-        sign_data = sign_data.decode('ascii')\r
-        return sign_data\r
-    def get_new_message_id(self):\r
-        message_id = self.get_trace_id()+"aaa"+self.get_trace_id()\r
-        self.VC_message_id=message_id[:32]\r
-        return self.VC_message_id \r
-    def get_new_task_id(self):\r
-        task_id = self.get_trace_id()+"aaa"+self.get_trace_id()\r
-        self.VC_task_id=task_id[:32]\r
-        return self.VC_task_id\r
-    #开始播放声音\r
-    def VC_Play_Start(self):\r
-        self.tts_in_data_len = 0\r
-        self.tts_out_data_len = 0\r
-        if self.VC_play_TYPE == VC_play_TYPE_PCM:\r
-            if self.VC_play_samplerate == 8000:\r
-                pass\r
-            elif self.VC_play_samplerate == 16000:\r
-                if self.play_pcm == None:        \r
-                    self.play_pcm = audio.Audio.PCM(0,1,16000,1,1,2)\r
-                    #self.play_pcm.setVolume(11)\r
-                    ret = self.play_pcm.stream_write_start()\r
-                    print("self.record_pcm.stream_write_start:ret:{}".format(ret))\r
-        elif self.VC_play_TYPE == VC_play_TYPE_MP3:\r
-            pass\r
-    #停止播放声音\r
-    def VC_Play_End(self):\r
-        if self.VC_play_TYPE == VC_play_TYPE_PCM:\r
-            if self.VC_play_samplerate == 8000:\r
-                self.aud.stopPlayStream()\r
-                self.aud.stopAll()\r
-            elif self.VC_play_samplerate == 16000:\r
-                if self.play_pcm != None:\r
-                    print("Close:play_pcm.close()!!!!!!!!!!!!!!!!!!")\r
-                    try:\r
-                        self.play_pcm.stream_stop()\r
-                        self.play_pcm.close()\r
-                    except Exception as e:\r
-                        usys.print_exception(e)\r
-                    self.play_pcm=None\r
-                self.aud.stopPlayStream()\r
-                self.aud.stopAll()\r
-        elif self.VC_play_TYPE == VC_play_TYPE_MP3:\r
-            self.aud.stopPlayStream()\r
-            self.aud.stopAll()\r
-   \r
-    def _1S_timer_cb(self,*argc):\r
-        EventMesh.publish("system_sleep_rest")#防止黑屏\r
-        self.close_timerout += 1\r
-        if self.close_timerout > 30:#20秒没数据就close\r
-            EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) \r
-        # print("get_audio_state !!!!!{} {} {}\r\n".format(self.play_end,EventMesh.publish("get_audio_state"),self.play_flag))\r
-        #self.LocalRespondingEnded_timerout+=1\r
-        if self.voice_chat_state == VC_State_TTSEnd and self.AI_audio_queue.empty()  :#self.AI_audio_queue为空且tts下发结束\r
-            self.LocalRespondingEnded_timerout += 1\r
-        if self.LocalRespondingEnded_timerout >= 3:\r
-            self.LocalRespondingEnded_timerout = 0\r
-            if self.VC_mode == 1 :#长按单次问答模式\r
-                EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) \r
-            else:\r
-                #通知服务器播放结束\r
-                self.AI_client_voice_chat_LocalRespondingEnded()\r
-        self.pingping_timerout+=1\r
-        if self.pingping_timerout>5:\r
-            self.pingping_timerout=0\r
-            self.AI_client_voice_chat_ping()\r
-        \r
-    #VC开始\r
-    def AI_VC_start(self):\r
-        \r
-        self.VC_Play_End()#关闭音频播放\r
-        \r
-        #self.aud.aud_tone_play(16,200)#播放按键音\r
-        self.LocalRespondingEnded_timerout = 0\r
-        self.close_timerout = 0\r
-        self.websocket_connect_asr()\r
-        if self.AI_client_asr_isconnect == 0:\r
-            return\r
-        if self.record_data_save_flag == 1:\r
-            try:\r
-                uos.remove('/usr/record_data.pcm')\r
-            except Exception as e:\r
-                usys.print_exception(e)\r
-            self.record_fd = open('/usr/record_data.pcm','w')\r
-        #utime.sleep_ms(50)\r
-        if self.AI_client_voice_chat_isconnect == 0:#没连接的时候请求开始\r
-            self.websocket_connect_voice_chat()#连接服务器\r
-            self.AI_client_voice_chat_start_requset()\r
-        else:\r
-            print("self.voice_chat_state :{}".format(self.voice_chat_state ))\r
-            if self.voice_chat_state > VC_State_SpeechStart:\r
-                #客户端打断对话\r
-                print("打断对话")\r
-                self.AI_client_voice_chat_RequestToSpeak()\r
-            elif self.voice_chat_state == VC_State_Listening:\r
-                #直接chat\r
-                print("直接chat")\r
-                self.AI_client_voice_chat_RequestToRespond()\r
-        if self.AI_client_voice_chat_isconnect == 0:\r
-            return\r
-        self.voice_chat_state = VC_State_None\r
-        if self.AI_TTS_str == "":#没有tts要播放的时候才开始录音\r
-            #开始asr录音\r
-            self.VC_Speech_Start()\r
-            pass\r
-        #开始线程\r
-        if self.AI_audio_queue_thread_id ==0:\r
-            _thread.stack_size(24*1024)\r
-            self.AI_audio_queue_thread_id = _thread.start_new_thread(self.AI_audio_queue_thread, ())\r
-            _thread.stack_size(8*1024)\r
-            print("AI_VC_start :AI_audio_queue_thread_id :{} ".format(self.AI_audio_queue_thread_id))\r
-        else:\r
-            print("AI_VC_start :AI_audio_queue_thread_id != 0 ")\r
-        if self.AI_send_data_queue_thread_id == 0:    \r
-            _thread.stack_size(self.Audio_buf_size+8*1024)\r
-            self.AI_send_data_queue_thread_id = _thread.start_new_thread(self.AI_send_data_queue_thread, ())\r
-            _thread.stack_size(8*1024)\r
-            print("AI_VC_start :AI_send_data_queue_thread_id :{} ".format(self.AI_send_data_queue_thread_id))\r
-        self._1S_timer.start(1000,1,self._1S_timer_cb)\r
-        self.pingping_timerout = 0\r
-        \r
-        \r
-    #开始会话\r
-    def AI_client_voice_chat_start_requset(self):\r
-        \r
-        json_data = \\r
-        {\r
-            "header":{\r
-                "trace_id":self.get_trace_id(),\r
-                "event":"Start"\r
-                },\r
-            "payload":{\r
-                "dialog_id":self.VC_dialog_id,\r
-                "device_id":modem.getDevImei(),\r
-                "user_agent":"python",\r
-                "in_format":"pcm",\r
-                "out_format":"mp3",\r
-                "in_sample_rate":self.VC_record_samplerate,\r
-                "sample_rate":self.VC_play_samplerate,\r
-                "space_time": 150,\r
-                "volume": str(self.VC_TTS_volume),\r
-                "voice":self.VC_TTS_voice_type[self.VC_TTS_voice_num],\r
-                "voice_detection":"enabled",\r
-                "simple_response":True,\r
-                "custom_variables":{\r
-                    "bot_name":"{}".format(self.bot_name)\r
-                }\r
-                },\r
-            \r
-        }\r
-        if self.VC_play_TYPE == VC_play_TYPE_PCM:\r
-            json_data["payload"]["out_format"]='pcm'\r
-        if self.VC_record_TYPE == VC_record_TYPE_AMR :\r
-            json_data["payload"]["in_format"]='amr'\r
-            pass\r
-        if self.VC_mode == 1:\r
-            json_data["payload"]["voice_detection"]='disable'\r
-        self.voice_chat_state = VC_State_None\r
-        self.AI_client_voice_chat_send(ujson.dumps(json_data))\r
- \r
-    #开始上传语音\r
-    def AI_client_voice_chat_send_speech(self):\r
-        json_data = \\r
-        {\r
-            "header":{\r
-                "trace_id":self.get_trace_id(),\r
-                "event":"SendSpeech"\r
-                },\r
-            "payload":\r
-            {\r
-                "dialog_id":self.VC_dialog_id\r
-            }\r
-        }\r
-        self.AI_client_voice_chat_send(ujson.dumps(json_data))\r
-        self.VC_Speech_Start()#开启线程获取录音数据\r
-        self.voice_chat_state =  VC_State_SpeechStart\r
-    #结束上传语音\r
-    def AI_client_voice_chat_end_speech(self):\r
-        json_data = \\r
-        {\r
-            "header":{\r
-                "trace_id":self.get_trace_id(),\r
-                "event":"StopSpeech"\r
-                },\r
-            "payload":{\r
-                "dialog_id":self.VC_dialog_id\r
-                }\r
-        }\r
-        self.AI_client_voice_chat_send(ujson.dumps(json_data))\r
-        self.VC_Speech_End()#停止线程录音\r
-\r
-    #通知服务器开始播放\r
-    def AI_client_voice_chat_LocalRespondingStarted(self):\r
-        json_data = \\r
-        {\r
-            "header":{\r
-                "trace_id":self.get_trace_id(),\r
-                "event":"LocalRespondingStarted"\r
-                },\r
-            "payload":{\r
-                "dialog_id":self.VC_dialog_id\r
-                }\r
-        }\r
-        self.AI_client_voice_chat_send(ujson.dumps(json_data))\r
-    #通知服务器播放结束\r
-    def AI_client_voice_chat_LocalRespondingEnded(self):\r
-        json_data = \\r
-        {\r
-            "header":{\r
-                "trace_id":self.get_trace_id(),\r
-                "event":"LocalRespondingEnded"\r
-                },\r
-            "payload":{\r
-                "dialog_id":self.VC_dialog_id\r
-                }\r
-        }\r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init}) \r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_voice_chat_send,"data":ujson.dumps(json_data)}) \r
-        # utime.sleep_ms(1)\r
-        # self.AI_client_voice_chat_send(ujson.dumps(json_data))\r
-        self.voice_chat_state = VC_State_End\r
-    #客户端打断对话\r
-    def AI_client_voice_chat_RequestToSpeak(self):\r
-        json_data = \\r
-        {\r
-            "header":{\r
-                "trace_id":self.get_trace_id(),\r
-                "event":"RequestToSpeak"\r
-                },\r
-            "payload":{\r
-                "dialog_id":self.VC_dialog_id\r
-                }\r
-        }\r
-        print("AI_client_voice_chat_RequestToSpeak!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")\r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init}) \r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_voice_chat_send,"data":ujson.dumps(json_data)}) \r
-        # utime.sleep_ms(1)\r
-    #请求TTS或者chat事件\r
-    def AI_client_voice_chat_RequestToRespond(self):\r
-        json_data = \\r
-        {\r
-            "header":{\r
-                "trace_id":self.get_trace_id(),\r
-                "event":"RequestToRespond"\r
-                },\r
-            "payload":{\r
-                "dialog_id":self.VC_dialog_id,\r
-                "type":"transcript",#prompt是跳过asr,transcript是跳过asr和大模型\r
-                "text":""\r
-                }\r
-        }\r
-\r
-        print("AI_client_voice_chat_RequestToRespond!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")\r
-        if self.AI_TTS_str != "":\r
-            json_data["payload"]["text"] = self.AI_TTS_str\r
-            json_data["payload"]["type"] = "transcript"\r
-            EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init}) \r
-            EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_voice_chat_send,"data":ujson.dumps(json_data)}) \r
-            self.AI_TTS_str = ""\r
-        elif self.AI_ASR_str != "":\r
-            json_data["payload"]["text"] = self.AI_ASR_str\r
-            json_data["payload"]["type"] = "prompt"\r
-            EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init}) \r
-            EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_voice_chat_send,"data":ujson.dumps(json_data)})\r
-            self.AI_ASR_str = ""\r
-        # utime.sleep_ms(1)\r
-    #发送数据队列\r
-    def AI_send_data_queue_thread(self):\r
-        print("AI_send_data_queue_thread:start")\r
-        count_t = 0\r
-        while True:\r
-            if self.AI_send_data_queue.empty() :#不能去掉,去掉会卡死\r
-                count_t+=1\r
-                # if count_t%200 == 0:\r
-                #     print("self.AI_send_data_queue.empty")\r
-                utime.sleep_ms(1)\r
-            else:\r
-                #data[0]是websocket连接对象编号,data[1]是数据\r
-                #print("AI_send_data_queue_thread:get")\r
-                data = self.AI_send_data_queue.get()\r
-                #print("AI_send_data_queue_thread:num{} len{}".format(data[0],len(data[1])))\r
-                if data != None:\r
-                    try:\r
-                        #data["func"](data["data"])\r
-                        # 发送数据\r
-                        #bytes_data = bytes(data[1])\r
-                        #data[0].send(data[1])\r
-                        #print("AI_send_data_queue_thread:len:{}".format(len(data[1])))\r
-                        #print("AI_send_data_queue_thread on line asr recv :{} vc recv:{}".format(_thread.threadIsRunning(self.AI_client_asr_recv_id),_thread.threadIsRunning(self.AI_client_voice_chat_recv_id)))\r
-                        if data[0] == AI_client_voice_chat_num:\r
-                            # if self.AI_client_voice_chat_isconnect == 0:\r
-                            #     try:\r
-                            #         self.websocket_connect_voice_chat() \r
-                            #     except Exception as e: #网络连接异常\r
-                            #         usys.print_exception(e)\r
-                            self.pingping_timerout = 0\r
-                            #print("VC: send_data len:{}".format(len(data[1])))\r
-                            if self.AI_client_voice_chat != None and self.AI_client_voice_chat_isconnect == 1:\r
-                                self.AI_client_voice_chat.send(data[1])\r
-                            #print("VC: send_data end")\r
-\r
-                        if data[0] == AI_client_asr_num:\r
-                            #self.pingping_timerout = 0\r
-                            #print("VC: send_data len:{}".format(len(data[1])))\r
-                            if self.AI_client_asr != None and self.AI_client_asr_isconnect == 1:\r
-                                self.AI_client_asr.send(data[1])\r
-                        #print("VC: send_data end")\r
-                    except Exception as e:\r
-                        print("DeviceInfo_queue_thread:ERROR:{}".format(e))\r
-                        usys.print_exception(e)\r
-                        if data[0] == AI_client_voice_chat_num:\r
-                            #self.websocket_error()\r
-                            pass\r
-                            #self.websocket_deconnect_voice_chat()\r
-                            self.AI_client_voice_chat_isconnect = 0\r
-                            try:\r
-                                self.websocket_error()\r
-                                #self.websocket_deconnect_voice_chat()\r
-                            except Exception as e: #网络连接异常\r
-                                usys.print_exception(e)\r
-                        if data[0] == AI_client_asr_num: \r
-                            EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_connect_asr}) #重连\r
-                         \r
-    ############################################\r
-    # 音频队列        \r
-    def AI_audio_queue_thread(self):\r
-        print("AI_audio_queue_thread start")\r
-        count = 0\r
-        while True:\r
-            try:\r
-                # if self.AI_send_data_queue_thread_id == 0:\r
-                #     break\r
-                # print("AI_audio_queue_thread")\r
-                if self.AI_audio_queue.empty() :\r
-                    utime.sleep_ms(1)\r
-                    count+=1\r
-                    if count%5000 == 1:\r
-                        print("AI_audio_queue_thread on")\r
-                else:\r
-                    data = self.AI_audio_queue.get()\r
-                    self.close_timerout = 0\r
-                    if self.play_flag == 0:\r
-                        self.play_flag =1\r
-                        print("AI_client_voice_chat_LocalRespondingStarted!!!")\r
-                        self.AI_client_voice_chat_LocalRespondingStarted()#通知服务器开始播放\r
-                    #self.AI_client_tts_data_len=len(data)\r
-                    print("\r\naudio_queue:len:{},data{}".format(len(data[0]),len(data[1])))\r
-                    if len(data[0]) > 10:\r
-                        try:\r
-                            if self.VC_play_TYPE == VC_play_TYPE_PCM:\r
-                                if self.VC_play_samplerate == 8000:\r
-                                    tmp= self.aud.playStream(1,data[0] )\r
-                                elif self.VC_play_samplerate == 16000:\r
-                                \r
-                                \r
-                                    \r
-                                    write_buf = bytearray(data[0])\r
-                                    #print("play_pcm.stream_write1!!")\r
-                                    if self.play_pcm != None:\r
-                                        ret = self.play_pcm.stream_write(write_buf,len(write_buf))\r
-                                        #ret= self.aud.playStream(1, data[0])#播放音频流\r
-                                        self.tts_out_data_len += ret\r
-                                        print("play_pcm.stream_write:{}".format(self.tts_out_data_len))\r
-                            elif self.VC_play_TYPE == VC_play_TYPE_MP3:\r
-                                tmp= self.aud.playStream(3, data[0])#播放音频流\r
-                                \r
-                                if tmp != 0:\r
-                                    print("2playStream:error tmp:{} data len:{}!!!!!!!!!!!!".format(tmp,len(data[0])))\r
-                                    # # #播放失败的时候填充WAV头\r
-                                    # data_len = len(data[0])\r
-                                    # data_len_b = data_len.to_bytes(4,'little')#数据长度转16进制数组\r
-                                    # h_data = [ 0x52 ,0x49 ,0x46 ,0x46 #,0x24 ,0x00 ,0x00 ,0x00 #文件标识、文件大小\r
-                                    #         ,0x57 ,0x41 ,0x56 ,0x45 ,0x66 ,0x6D ,0x74 ,0x20  #文件格式、格式块标识符\r
-                                    #         ,0x10 ,0x00 ,0x00 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x80 ,0x3E ,0x00 ,0x00  #格式块大小4、音频格式2、声道数2、采样率4\r
-                                    #         ,0x80 ,0x3E ,0x00 ,0x00 ,0x02 ,0x00 ,0x10 ,0x00 ,0x64 ,0x61 ,0x74 ,0x61]#每秒字节数4、数据块对齐2、位深度2、data4\r
-                                    # h_data_b = bytes(h_data)\r
-                                    # file_len = data_len+len(h_data_b)+4+4\r
-                                    # file_len_b = file_len.to_bytes(4,'little')#文件长度转16进制数组\r
-                                    # h_data_b = h_data_b[:4]+file_len_b+h_data_b[4:]+data_len_b\r
-                                    # #self.aud.playStream(2, h_data_b)#播放音频流\r
-                                    # tmp= self.aud.playStream(2, h_data_b+data[0])#播放音频流\r
-                                    # print("3playStream:tmp:{} !!!!!!!!!!!!".format(tmp))\r
-                            \r
-                            #print("出:{},{}!!!".format(len(data[0]),self.AI_client_tts_data_len))\r
-                            mem = gc.mem_free()\r
-                            #print('1剩余内存RAM:{} KB'.format(mem / 1024))\r
-                        except Exception as e:\r
-                            print("AI_audio_queue_thread:ERROR:")\r
-                            usys.print_exception(e)\r
-                    \r
-                    # if self.voice_chat_state == VC_State_TTSEnd and self.AI_audio_queue.empty() :#self.AI_audio_queue为空且tts下发结束\r
-                    #     #通知服务器播放结束\r
-                    #     self.AI_client_voice_chat_LocalRespondingEnded()\r
-            except Exception as e:\r
-                print("AI_audio_queue_thread:ERROR:")\r
-                usys.print_exception(e)\r
-        #print("AI_audio_queue_thread:exit")\r
-    def factory_mode(self):\r
-        print("factory_mode")\r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) \r
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.factory_start}) \r
-    def factory_start(self):\r
-        self.factory_timer.start(1000, 1, self.factory_timer_cb)\r
-    def factory_timer_cb(self, *args, **kwargs):\r
-        print("factory_timer_cb play......")\r
-        self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功\r
-\r
-    def Close(self):\r
-        print("ai_VC Close1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")\r
-        self.tts_in_data_len = 0\r
-        self.tts_out_data_len = 0\r
-        \r
-        print("ai_VC Close1.1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")\r
-        self.VC_init()\r
-        self.VC_Speech_End()\r
-        print("ai_VC Close1.2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")\r
-        if self.AI_send_data_queue.empty()!=True:\r
-            self.AI_send_data_queue.clear()\r
-        self.AI_TTS_str = ""\r
-        self.AI_ASR_str = ""\r
-        self.AI_ASR_str_tmp = ""\r
-        self.AI_ASR_flag  = 0\r
-        print("ai_VC Close1.3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")\r
-        try:\r
-        #销毁线程\r
-            if self.AI_audio_queue_thread_id != 0:\r
-                try:\r
-                    _thread.stop_thread(self.AI_audio_queue_thread_id)\r
-                except Exception as e:\r
-                    usys.print_exception(e)\r
-                self.AI_audio_queue_thread_id = 0\r
-            if self.AI_send_data_queue_thread_id != 0:\r
-                try:\r
-                    _thread.stop_thread(self.AI_send_data_queue_thread_id)\r
-                except Exception as e:\r
-                    usys.print_exception(e)\r
-            self.AI_send_data_queue_thread_id = 0\r
-            \r
-\r
-        except Exception as e:\r
-            usys.print_exception(e)\r
-        print("ai_VC Close2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")\r
-        try:\r
-            self.websocket_deconnect_voice_chat()\r
-        except Exception as e:\r
-            usys.print_exception(e)\r
-        print("ai_VC Close3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n")\r
-        try:\r
-            self.websocket_deconnect_asr()\r
-        except Exception as e:\r
-            usys.print_exception(e)\r
-        self._1S_timer.stop()\r
-        self.factory_timer.stop()\r
-        \r
-        if self.record_data_save_flag == 1:\r
-            if self.record_fd :\r
-                self.record_fd.close()\r
-            self.record_fd = None\r
-    def VC_init2(self):\r
-        self.VC_init()\r
-        if self.AI_send_data_queue.empty()!=True:\r
-            self.AI_send_data_queue.clear()\r
-        print("ai_VC VC_init2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")\r
-        try:\r
-            self.websocket_deconnect_voice_chat()\r
-        except Exception as e:\r
-            usys.print_exception(e)\r
-        print("ai_VC Close3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n")\r
-        self._1S_timer.stop()\r
-\r
-\r
-    def VC_init(self):\r
-        \r
-        print("VC_init:AI_send_data_queue:size:{}".format(self.AI_send_data_queue.size()))\r
-        if self.AI_audio_queue.empty()!=True:\r
-            self.AI_audio_queue.clear()\r
-        \r
-        print("VC_init2")\r
-        #self.VC_Speech_End()\r
-        print("VC_init3")\r
-        self.VC_Play_End()\r
-        print("VC_init4")\r
-        \r
-        EventMesh.publish("close_led")\r
-        # num = EventMesh.publish("get_volum_size")\r
-        # if num == None:\r
-        #     num = 8\r
-        # self.aud.setVolume(num)#恢复原始音量\r
-        
\ No newline at end of file
diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/vc_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/vc_config.py
new file mode 100644 (file)
index 0000000..68479bc
--- /dev/null
@@ -0,0 +1,114 @@
+# 配置加载器:将 dev_type 分支逐步从 ai_VC.py 抽离出来。\r
+#\r
+# 目标:\r
+# - usr 下可覆盖(现场可改,无需重新 freeze)\r
+# - freeze 内置默认值兜底(出厂可用)\r
+\r
+def _try_import(name):\r
+    try:\r
+        return __import__(name)\r
+    except Exception:\r
+        return None\r
+\r
+\r
+# 只做“优先 import usr 下文件;失败再 import 默认文件”,不做变量覆盖/合并\r
+_DEFAULT_CFG_MODULE = None\r
+_DEFAULT_CFG_LOADED = 0\r
+\r
+\r
+def load_default_config_module():\r
+    global _DEFAULT_CFG_MODULE, _DEFAULT_CFG_LOADED\r
+    if _DEFAULT_CFG_LOADED:\r
+        return _DEFAULT_CFG_MODULE\r
+    _DEFAULT_CFG_LOADED = 1\r
+    # 兼容用户描述里的拼写 defualt_config.py\r
+    _DEFAULT_CFG_MODULE = (\r
+        _try_import("usr.default_config")\r
+        or _try_import("usr.defualt_config")\r
+        or _try_import("default_config")\r
+    )\r
+    return _DEFAULT_CFG_MODULE\r
+\r
+def get_dev_type(default_dev_type="7PIN"):\r
+    m = load_default_config_module()\r
+    try:\r
+        if m and hasattr(m, "DEV_TYPE"):\r
+            return getattr(m, "DEV_TYPE") or default_dev_type\r
+    except Exception:\r
+        return default_dev_type\r
+    return default_dev_type\r
+\r
+\r
+def led_gpio_tuple(Pin=None):\r
+    # 从 default_config(或 usr/default_config) 取 LED_GPIO。\r
+    # 返回 (r_gpio, g_gpio, b_gpio) 的 Pin.GPIOxx 常量。\r
+    if Pin is None:\r
+        try:\r
+            from machine import Pin as _Pin\r
+            Pin = _Pin\r
+        except Exception:\r
+            # 无法获取 Pin 类型时,无法做 GPIO 名称到常量的映射,直接返回常用默认值\r
+            return (36, 21, 19)\r
+    m = load_default_config_module()\r
+    names = None\r
+    try:\r
+        if m and hasattr(m, "LED_GPIO"):\r
+            names = getattr(m, "LED_GPIO")\r
+    except Exception:\r
+        names = None\r
+\r
+    if isinstance(names, (tuple, list)) and len(names) == 3:\r
+        try:\r
+            return (getattr(Pin, names[0]), getattr(Pin, names[1]), getattr(Pin, names[2]))\r
+        except Exception:\r
+            pass\r
+    try:\r
+        return (Pin.GPIO36, Pin.GPIO21, Pin.GPIO19)\r
+    except Exception:\r
+        return (36, 21, 19)\r
+\r
+\r
+def uart_supported():\r
+    m = load_default_config_module()\r
+    try:\r
+        if m and hasattr(m, "UART_SUPPORTED"):\r
+            return bool(getattr(m, "UART_SUPPORTED"))\r
+    except Exception:\r
+        pass\r
+    return False\r
+\r
+\r
+def lang(default_lang="zh"):\r
+    m = load_default_config_module()\r
+    try:\r
+        if m and hasattr(m, "LANG"):\r
+            return getattr(m, "LANG") or default_lang\r
+    except Exception:\r
+        return default_lang\r
+    return default_lang\r
+\r
+\r
+def get_attr(name, default=None):\r
+    m = load_default_config_module()\r
+    try:\r
+        if m and hasattr(m, name):\r
+            return getattr(m, name)\r
+    except Exception:\r
+        pass\r
+    return default\r
+\r
+\r
+def get_int(name, default=0):\r
+    try:\r
+        v = get_attr(name, default)\r
+        return int(v)\r
+    except Exception:\r
+        return int(default)\r
+\r
+\r
+def get_bool(name, default=False):\r
+    try:\r
+        return bool(get_attr(name, default))\r
+    except Exception:\r
+        return bool(default)\r
+\r
index 55f3cd6..f75fe00 100644 (file)
Binary files a/2.sdk/project/7PIN_1_5/sdk/system/platform/ASR_1606/boards/EG810MCN_GA_VOLTE/images/firmware_base_release_pack.zip and b/2.sdk/project/7PIN_1_5/sdk/system/platform/ASR_1606/boards/EG810MCN_GA_VOLTE/images/firmware_base_release_pack.zip differ