--- /dev/null
+# 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
--- /dev/null
+# 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
-# 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.
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:
#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'#四季甘泉
#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)
# 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
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)
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, ())
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 中不需要上传")
# 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
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
#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()
#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):
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
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):
#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()
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()
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!!!!!")
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)#唤醒休眠
#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()
#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})
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")
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
# 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()
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"])
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()
}
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
}
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")
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:
#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:
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)
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)
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={}¤tVersion={}".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={}¤tVersion={}".format(modem.getDevImei(),currentVersion)
- # else:
url = (constants.DMP_BASE + "/ota/result?deviceId={}¤tVersion={}").format(modem.getDevImei(),currentVersion)
print(url)
response = request.post(url,timeout=5)
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:
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
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
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
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()
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:
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
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
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"}
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
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
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"
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:
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:
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)
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
# 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
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翻译模式
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()
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: #长按对话模式 接收到蓝牙耳机按键事件
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翻译模式
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
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
#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 = "已切换到单对话模式"
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:
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()
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):
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:
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:
#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:
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:
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
# 抢占规则:本地提示音不可打断流播放
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")
# 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)。
# 仅在“正在录音上行”的语音阶段才停止,避免误触发。
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)
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:
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 来源:
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,这里避免重复驱动
#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
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()
# 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')#切换成功
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):
# #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")
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)
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
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
# 只有在 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:
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")#防止黑屏
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
#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
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")
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 :
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:
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)#播放按键音
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()
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()
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()
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()
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()
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()
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
#必须先销毁线程,不然线程会容易报错
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:
--- /dev/null
+# 设备分支配置: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
--- /dev/null
+# 设备分支配置: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
--- /dev/null
+# 设备分支配置: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
--- /dev/null
+# 设备分支配置: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
--- /dev/null
+# 设备分支配置: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
--- /dev/null
+# 设备分支配置: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
--- /dev/null
+# 设备分支配置: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
--- /dev/null
+本目录用于**保留所有设备分支的配置文件**,供编译/打包阶段按参数选择。\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
--- /dev/null
+# 设备分支配置: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
--- /dev/null
+# 设备分支配置: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
--- /dev/null
+# 设备分支配置: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
--- /dev/null
+# 设备分支配置: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
--- /dev/null
+# 设备分支配置: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
--- /dev/null
+# 设备分支配置: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
-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"
+
--- /dev/null
+# 设备侧默认配置(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
--- /dev/null
+# 设备侧 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={}¤tVersion={}"\r
+\r
+# ---- AMP/健康检查等 ----\r
+AMP_HEALTH_URL_FMT = "http://{}/health?task_id={}"\r
+\r
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:
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):
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"
--- /dev/null
+# 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
--- /dev/null
+本目录用于**服务器环境地址配置**,按 `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
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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
+++ /dev/null
-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
--- /dev/null
+# 配置加载器:将 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
Version="V1.0" \r
-Build_Time="2026-05-07 14:29:21" \r
+Build_Time="2026-05-08 5:36:51" \r