From: SnickerSun Date: Thu, 7 May 2026 22:22:54 +0000 (+0800) Subject: 重构代码 led已经连接硬件,充电,状态都可显示,但是对话逻辑还需微调 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=592d3e64e8d15318399629ab0ea0a8ed4f946586;p=mirrors%2FASR1603_G5.git 重构代码 led已经连接硬件,充电,状态都可显示,但是对话逻辑还需微调 --- diff --git "a/1.doc/AI\345\220\212\345\235\240LED\347\212\266\346\200\201\344\274\230\345\205\210\347\272\247\347\212\266\346\200\201\346\234\272.md" "b/1.doc/AI\345\220\212\345\235\240LED\347\212\266\346\200\201\344\274\230\345\205\210\347\272\247\347\212\266\346\200\201\346\234\272.md" new file mode 100644 index 00000000..151feb79 --- /dev/null +++ "b/1.doc/AI\345\220\212\345\235\240LED\347\212\266\346\200\201\344\274\230\345\205\210\347\272\247\347\212\266\346\200\201\346\234\272.md" @@ -0,0 +1,53 @@ +# AI吊坠 LED 状态优先级状态机(实现用) +# +# 目标:只要输入四类状态(充电/电量/信号/AI对话),LED 自动按优先级显示,且同一时间只显示一种灯效。 +# 说明:AI 对话阶段优先级最高;其结束后才显示充电/电量/信号等基础状态。 +# +# 输入状态域 +# - ai_state: idle / listening / thinking / playing +# - charging: none / charging / full +# - battery: normal(>=30%) / low(10~30%) / empty(<10%) +# - signal: normal / weak +# +# +## 1) 优先级总表(从高到低) +# +| 优先级 | 状态域 | 状态值 | LED显示 | 说明 | +| ---: | --- | --- | --- | --- | +| P1 | AI对话 | playing | 绿灯常亮 | 播放态最高优先级 | +| P2 | AI对话 | thinking | 蓝绿交替慢闪(1秒切换一次) | 交互规范:思考模式 | +| P3 | AI对话 | listening | 蓝色慢闪(1次/秒) | 交互规范:聆听模式 | +| P4 | 充电 | full | 绿灯常亮 | 非对话阶段:满电提示 | +| P5 | 充电 | charging | 红灯常亮 | 非对话阶段:充电中 | +| P6 | 电量 | empty | 红色快闪3次(2次/秒)→熄灭 | 事件型提示;之后通常进入关机/熄灭 | +| P7 | 电量 | low | 红色慢闪3次(1次/秒)→熄灭 | 事件型提示;建议 5 分钟节流一次 | +| P8 | 信号 | weak | 蓝绿交替慢闪(1次/2秒) | 网络/信号弱提示(持续态) | +| P9 | AI对话 | idle | 熄灭 | 交互规范:待机灯灭 | +| P10 | 其它 | 默认 | 熄灭 | 兜底 | +# +# +## 2) 决策表(输入 → 输出) +# +按顺序匹配,命中即返回: +# +| 顺序 | 条件(输入状态) | 输出 LED | +| ---: | --- | --- | +| 1 | ai_state == playing | 绿常亮 | +| 2 | ai_state == thinking | 蓝绿交替慢闪(1秒切换) | +| 3 | ai_state == listening | 蓝慢闪(1次/秒) | +| 4 | charging == full | 绿常亮 | +| 5 | charging == charging | 红常亮 | +| 6 | battery == empty | 红快闪3次→熄灭(事件型) | +| 7 | battery == low | 红慢闪3次→熄灭(事件型、建议节流) | +| 8 | signal == weak | 蓝绿交替慢闪(1次/2秒) | +| 9 | ai_state == idle | 熄灭 | +| 10 | else | 熄灭 | +# +# +## 3) 事件型 vs 状态型(工程建议) +# +| 类型 | 涵盖状态 | 特性 | 冲突处理建议 | +| --- | --- | --- | --- | +| 状态型(持续显示) | AI三阶段、充电中/满、信号弱 | 状态为真就一直显示 | 被 P1~P3 覆盖;结束后恢复 | +| 事件型(播一次) | 低电提醒、耗尽提醒 | 播完即回到当前最高状态 | 若 AI 阶段中,延后或丢弃本次提示,避免抢占交互 | +# diff --git "a/1.doc/AI\345\220\212\345\235\240\357\274\210\345\217\214\346\214\211\351\224\256+\344\270\211\350\211\262\346\214\207\347\244\272\347\201\257\357\274\211\344\272\244\344\272\222\350\247\204\350\214\203.md" "b/1.doc/AI\345\220\212\345\235\240\357\274\210\345\217\214\346\214\211\351\224\256+\344\270\211\350\211\262\346\214\207\347\244\272\347\201\257\357\274\211\344\272\244\344\272\222\350\247\204\350\214\203.md" new file mode 100644 index 00000000..883afa79 --- /dev/null +++ "b/1.doc/AI\345\220\212\345\235\240\357\274\210\345\217\214\346\214\211\351\224\256+\344\270\211\350\211\262\346\214\207\347\244\272\347\201\257\357\274\211\344\272\244\344\272\222\350\247\204\350\214\203.md" @@ -0,0 +1,112 @@ +# AI吊坠(双按键+三色指示灯)交互规范 + +核心原则:**操作有反馈、状态有提示、逻辑不冲突**,适配吊坠随身佩戴、无屏操作场景,按键+灯光+提示音三者联动,让用户无需记忆,凭直观反馈即可判断设备状态。 + +基础约定: + +* 按键:Power键(开关键)、AI键(语音交互键) + +* 指示灯:红(R)、蓝(B)、绿(G)三色(遵循定义:绿=正常/电量/充满电;蓝=AI交互;红=低电/异常) + +* 提示音:采用短促、清晰的单音/双音,区分不同操作,音量适中(避免刺耳,适配贴身佩戴),支持后续可调节(可选) + +* 操作逻辑:长按=特殊功能(开关机、强制重启、连续对话);短按/双击=常用功能(唤醒、打断、复读),杜绝误触 + + +## 备注 + +聆听模式:蓝色慢闪 + +思考模式:蓝绿交替慢闪 + +播放模式:绿灯长亮 + +进入聆听模式:单声“滴”(短促) + +[请至钉钉文档查看附件《start.mp3》。](https://alidocs.dingtalk.com/i/nodes/KGZLxjv9VGj15aBlU1wKrXGzW6EDybno?iframeQuery=anchorId%3DX02moo4wrj78r6ita1utoy&utm_scene=person_space) + +接入拾音/进入思考:单声“层”(短促,有尾音) + +[请至钉钉文档查看附件《5c893cf044bde33914.mp3》。](https://alidocs.dingtalk.com/i/nodes/KGZLxjv9VGj15aBlU1wKrXGzW6EDybno?iframeQuery=anchorId%3DX02moo4y0r5romh54qr1l&utm_scene=person_space) + +开机提示音 + +[请至钉钉文档查看附件《开机.mp3》。](https://alidocs.dingtalk.com/i/nodes/KGZLxjv9VGj15aBlU1wKrXGzW6EDybno?iframeQuery=anchorId%3DX02moo4z0qlkd1hwu42as&utm_scene=person_space) + +## 第一部分:基础操作(Power键)+ 灯光+提示音联动 + +| 操作动作 | 设备当前状态 | 指示灯状态 | 提示音 | 执行结果 | +| --- | --- | --- | --- | --- | +| Power键 长按3秒 | 关机状态 | 绿色灯常亮(持续3秒,同步长按时间),然后熄灭 | 现有设备开机提示音(后续视需求可修改) | 设备开机,进入正常待机状态 | +| Power键 长按8秒 | 任何状态(死机/卡死/异常) | 红色快闪3次(1次/秒),然后熄灭 | “滴、滴、滴”(3声短促,与灯光同步) | 设备关机,切断所有电源 | +| Power键 短按(单击) | 待机状态 | 无变化 | 无提示音 | 无操作 | +| Power键 短按(单击) | AI交互中(聆听/处理/TTS) | 无变化(保持当前交互灯光) | 无提示音 | 停止对话,进入待机模式 | +| Power键 短按(双击) | 待机状态 | 无变化 | 播报:单对话模式/长对话模式 | 切换对话模式 | + +## 第二部分:AI交互操作(AI键)+ 灯光+提示音联动 + +| 操作动作 | 对话模式 | 设备当前状态 | 指示灯状态 | 提示音 | 执行结果 | +| --- | --- | --- | --- | --- | --- | +| AI键 短按1次 | 长对话模式 | 待机状态 | 立即切换为蓝色慢闪(1次/秒) | 单声“滴”(短促,清脆) | 唤醒AI,进入语音聆听状态,开始收音(用户可说话) | +| AI键 短按1次 | 长对话模式 | 语音聆听中(蓝色慢闪) | 切换为蓝色慢闪 | 单声“滴”(短促) | 重新进入语音聆听状态,开始收音(用户可说话) | +| AI键 短按1次 | 长对话模式 | TTS播报中(绿色常亮灯) | 切换为蓝色慢闪 | 单声“滴”(短促) | 进入语音聆听状态,开始收音(用户可说话) | +| AI键 短按1次 | 长对话模式 | 思考中(蓝绿交替闪) | 切换为蓝色慢闪 | 单声“滴”(短促) | 进入语音聆听状态,开始收音(用户可说话) | +| AI键 双击(两次短按,间隔≤1秒)-> 可选(根据可实现性而定) | | 待机状态 & TTS播报结束后1分钟内 | 蓝色灯常亮(与正常TTS播报灯光一致) | “滴、滴”(2声短促,间隔0.5秒) | 复读上一次AI的TTS回复内容,复读结束后回到待机状态(蓝色灯灭) | +| AI键 双击>>暂时无功能 | | | | | | +| AI键 长按(按下) | 单对话模式 | 待机状态/思考状态/播报状态 | 蓝色快闪(频率加快,2次/秒) | 单声“滴”(短促,清脆) | 进入收音状态 | +| AI键 长按(松开) | 单对话模式 | 聆听中 | 蓝绿交替闪 | “曾——”(长音,持续1秒) | 进入思考模式 | + +## 第三部分:电量/充电状态 + 灯光+提示音联动 + +| 设备状态 | 触发条件 | 指示灯状态 | 提示音 | 补充说明 | +| --- | --- | --- | --- | --- | +| 正常待机(电量≥30%) | 开机后无操作、交互结束后 | 指示灯灭(AI交互过程遵循如上第二部分的定义) | 无提示音 | | +| 低电量提醒(10%≤电量<30%) | 电量降至阈值、每5分钟触发1次 | 红色慢闪(1次/1秒),每次闪3次 | “滴、滴”(2声短促,与灯光同步) | 提醒用户尽快充电,不频繁打扰 | +| 电量耗尽(电量<10%) | 电量降至关机阈值 | 红色快闪3次(2次/秒)→ 熄灭 | “滴、滴、滴”(3声短促,与灯光同步) | 快闪结束后设备自动关机 | +| 充电中(电量<100%) | 连接充电器,接触正常 | 红色常亮 | 单声“滴”(短促) | 充电期间,按键操作仍有效(开关机、AI交互) | +| 充电满(电量=100%) | 充电至满电阈值 | 红色常亮→切换为绿色常亮(延迟1秒) | “滴——”(长音,持续1秒) | 绿色常亮保持,提醒用户可拔下充电器(晚上不打扰) | + +## 第四部分:AI交互异常状态 + 灯光+提示音联动  + +| 异常场景 | 指示灯状态 | 提示音 | 处理方式 | +| --- | --- | --- | --- | +| 语音识别失败(未听清/无法识别) | 红蓝快闪2次(2次/秒)→ 回到待机状态(灯灭) | “滴、滴”(2声短促,与灯光同步) | 用户可再次短按AI键,重新唤醒聆听 | +| 网络异常(无法请求AI) | 蓝绿交替慢闪(1次/2秒),持续闪烁 | “网络异常信号弱”(每5秒1次,循环) | 检查网络连接,恢复网络后自动回到待机状态 | +| AI处理超时 | 蓝色常亮→红蓝快闪2次→回到待机状态(灯灭) | “滴、滴”(2声短促) | 处理失败,用户可重新发起语音请求 | + +## 第五部分:补充规范(工程&用户体验) + +### 1. 提示音规范 + +* 音量:默认中等(约50dB),避免贴身佩戴时刺耳,支持后续通过APP调节(可选) + +* 音色:统一采用清脆的电子音,避免复杂音效,确保不同场景的提示音可区分(短滴=操作确认,长滴=状态切换,多滴=提醒/异常) + +* 优先级:异常提示音(网络异常)>操作提示音(唤醒、打断)>状态提示音(充电满、低电) + + +### 2. 灯光规范 + +* 亮度:柔和不刺眼(≤100cd/m²),适配夜间、贴身佩戴场景,避免强光照射皮肤 + +* 响应速度:按键操作后,灯光和提示音同步触发(延迟≤100ms),无卡顿 + +* 冲突规避:同一时间仅显示一种状态灯光(如充电中触发AI交互,优先显示AI交互灯光,充电状态暂停显示,交互结束后恢复) + + +### 3. 工程可实现性说明 + +* 按键逻辑:长按时间(3秒/8秒/2秒)可通过MCU精准控制,避免误判(如长按2秒切换进入连续对话模式,需持续检测按键按压时间,不足3秒不执行) + +* 灯光控制:三色灯采用单灯三色设计,无需额外硬件,逻辑简单易实现 + +* 提示音:喇叭播放,无需额外蜂鸣器 + + +### 4. 用户易用性补充 + +* 所有操作均有“灯光+提示音”双重反馈,无屏状态下也能清晰判断设备状态 + +* 避免复杂操作,核心功能(唤醒、开关机)仅需1种按键动作,老人、儿童可快速上手 + +* 误触防护:短按Power键无操作、双击AI键仅在待机/播报后有效,减少误操作带来的困扰 \ No newline at end of file diff --git a/1.doc/v2_5.pdf b/1.doc/v2_5.pdf new file mode 100644 index 00000000..29dbc448 Binary files /dev/null and b/1.doc/v2_5.pdf differ diff --git a/2.sdk/project/7PIN_1_5/images/customer_fs.bin b/2.sdk/project/7PIN_1_5/images/customer_fs.bin index c347d98d..fc080431 100644 Binary files a/2.sdk/project/7PIN_1_5/images/customer_fs.bin and b/2.sdk/project/7PIN_1_5/images/customer_fs.bin differ diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/Makefile b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/Makefile index 51994be6..013850e6 100644 --- a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/Makefile +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/Makefile @@ -1,1170 +1,1173 @@ -# 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)/EventMesh.mpy \ - $(BUILD)/mgr.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. +# 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. diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/ai_VC.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/ai_VC.py index 476d06a8..7ba05ab7 100644 --- a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/ai_VC.py +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/ai_VC.py @@ -31,6 +31,10 @@ import dataCall import constants import versions from machine import UART +try: + import vc_config +except Exception as e: + usys.print_exception(e) try: import VAD except Exception as e: @@ -46,7 +50,7 @@ PRESS_AUDIO_MODE = 0 #是按键音 0 是使用音频文件 #dev_type = "7PIN_BK_coze"#k扣子小瑞 #dev_type = "7PIN_BK_EU"#英文小瑞 #dev_type = "7PIN_coze"#柒牌扣子 -dev_type = "7PIN"#柒牌 +dev_type = "7PIN"#柒牌(默认值,实际优先从 usr/default_config.py 覆盖) # dev_type = "7PIN_1_5"#柒牌1.5 #dev_type = 'momo'#食梦貘 #dev_type = 'sjgq'#四季甘泉 @@ -55,6 +59,13 @@ dev_type = "7PIN"#柒牌 #dev_type = 'jswm_BOX'#金三完美柒牌盒子 #dev_type = 'csh'#慈善会 +# 统一从配置加载 DEV_TYPE(usr 覆盖优先) +try: + if "vc_config" in globals() and vc_config: + dev_type = vc_config.get_dev_type(dev_type) +except Exception: + pass + # 1=打印 VC 周期性保活专用行「VC: ping ping」;默认 0(WS send 明细里已跳过 ping,无需再开此项) VC_HEARTBEAT_LOG = 0 # 1=打印音频帧级日志:Record_len / send_data len / 下发音频长度;默认 0(只看 uplink START/END) @@ -62,28 +73,22 @@ VC_HEARTBEAT_LOG = 0 # 1=启用我们新增的协议层“严格门控/缓冲/兜底”行为;0=临时排除这些改动(用于定位协议影响) # 受控项(与对端 V2.5+ 能力对齐;关=回退旧端行为): # - 上行:收到 started 前缓冲/丢弃 PCM;PTT 模式下 audio.create 前禁发 PCM -# - 兜底:llm.completed 后若久无 tts.started,端侧 force_tts 主动发 synthesis +# - 兜底:llm.completed 后若久无 tts.started,端侧可重启会话(不做 force_tts) # 注意:audio.played 不受此开关控制——金三 V2.5 服务端依赖端侧播完后上报才能进入下一轮 ASR; # 若误关会导致问候结束后首轮用户说话无 vad/asr。 VC_PROTO_GUARDS = 0 # 1=打印 VC WebSocket 每条收发的完整文本(流量大、易刷屏);0 仅一行 event 摘要(llm.delta 省略) -VC_WS_IO_LOG = 1 - -# 用于现场确认设备实际运行的 ai_VC 版本(只打印一次,不影响业务) -VC_BUILD_TAG = "fsm_tts_actions_2026-05-06" +VC_WS_IO_LOG = 0 class AI_led(Abstract): def __init__(self): - if dev_type == "G10" or dev_type == 'jswm': - r_gpio, g_gpio, b_gpio = Pin.GPIO36, Pin.GPIO44, Pin.GPIO21 - elif dev_type == "7PIN_BK_EU": - r_gpio, g_gpio, b_gpio = Pin.GPIO36, Pin.GPIO8, Pin.GPIO19 - elif dev_type == "7PIN_1_5": - r_gpio, g_gpio, b_gpio = Pin.GPIO28, Pin.GPIO44, Pin.GPIO30 - elif dev_type == "7PIN": - r_gpio, g_gpio, b_gpio = Pin.GPIO36, Pin.GPIO44, Pin.GPIO43 - else: + try: + if "vc_config" in globals() and vc_config: + r_gpio, g_gpio, b_gpio = vc_config.led_gpio_tuple() + else: + r_gpio, g_gpio, b_gpio = Pin.GPIO36, Pin.GPIO21, Pin.GPIO19 + except Exception: r_gpio, g_gpio, b_gpio = Pin.GPIO36, Pin.GPIO21, Pin.GPIO19 self._led_gpio_r = r_gpio self._led_gpio_g = g_gpio @@ -94,211 +99,459 @@ class AI_led(Abstract): print("AI_led GPIO dev_type={} red={} green={} blue={}".format( dev_type, r_gpio, g_gpio, b_gpio)) - #=1 红灯闪,=2蓝灯闪,=3绿灯闪,=4全部灯闪,=5 思考:蓝绿交替 - self.led_flicker_flag = 0 - self.led_flicker_on_off_flag = 0 - self.led_think_phase = 0 - self.led_flicker_timer = osTimer() - - EventMesh.subscribe("open_led_red",self.open_led_red) - EventMesh.subscribe("open_led_blue",self.open_led_blue) - EventMesh.subscribe("open_led_green",self.open_led_green) - EventMesh.subscribe("open_led_all",self.open_led_all) - EventMesh.subscribe("open_led_red_blue",self.open_led_red_blue) - EventMesh.subscribe("open_led_red_green",self.open_led_red_green) - EventMesh.subscribe("flicker_led_red",self.flicker_led_red) - EventMesh.subscribe("flicker_led_blue",self.flicker_led_blue) - EventMesh.subscribe("flicker_led_green",self.flicker_led_green) - EventMesh.subscribe("flicker_led_all",self.flicker_led_all) - EventMesh.subscribe("flicker_led_blue_green",self.flicker_led_blue_green) - EventMesh.subscribe("close_led",self.close_led) - EventMesh.publish("open_led_red") - - # 开机演示:每秒切换一次 LED,红->绿->蓝 为一轮,共 2 轮后停止 - self._boot_led_demo_timer = osTimer() - self._boot_led_demo_step = 0 - self._boot_led_demo_left = 3 * 2 # 3 色 * 2 è½® - self._boot_led_demo_timer.start(1000, 1, self._boot_led_demo_timer_cb) - - def _boot_led_demo_timer_cb(self, *args, **kwargs): - EventMesh.publish("publish_AI_btnInfo", {"func": self._boot_led_demo_timer_cb_}) - - def _boot_led_demo_timer_cb_(self): - try: - if self._boot_led_demo_left <= 0: - self._boot_led_demo_timer.stop() - return - # 不与闪烁抢占:演示期强制关掉闪烁 - self.led_flicker_flag = 0 - self._led_stop_flicker_timer() - - if (self._boot_led_demo_step % 3) == 0: - print("boot_led_demo: RED (gpio={})".format( - self._led_gpio_r)) - self.open_led_red(None, None) - elif (self._boot_led_demo_step % 3) == 1: - print("boot_led_demo: GREEN (gpio={})".format( - self._led_gpio_g)) - self.open_led_green(None, None) + # 统一输入状态(充电/电量/信号/AI对话),按优先级表输出 + self._st_ai = "idle" # idle/listening/thinking/playing + self._st_charging = "none" # none/charging/full + self._st_battery = "normal" # normal/low/empty + self._st_signal = "normal" # normal/weak + + self._timer = osTimer() + self._mode = "off" # off/red_on/green_on/blue_blink/red_blink/bg_alt + self._blink_on = 0 + self._bg_phase = 0 + self._period_ms = 1000 + + EventMesh.subscribe("set_led_state", self.set_led_state) + EventMesh.subscribe("get_led_debug_state", self.get_led_debug_state) + try: + self._set_off() + except Exception: + pass + # 1=打印每次 set_led_state 后的最终生效模式(默认关闭,避免刷屏) + try: + if "vc_config" in globals() and vc_config: + self._dbg = 1 if vc_config.get_bool("LED_DEBUG", False) else 0 else: - print("boot_led_demo: BLUE (gpio={})".format( - self._led_gpio_b)) - self.open_led_blue(None, None) - - self._boot_led_demo_step += 1 - self._boot_led_demo_left -= 1 - if self._boot_led_demo_left <= 0: - self._boot_led_demo_timer.stop() - except Exception as e: - try: - self._boot_led_demo_timer.stop() - except Exception: - pass - print("_boot_led_demo_timer_cb_ fail: {}".format(e)) + self._dbg = 0 + except Exception: + self._dbg = 0 + try: + if "vc_config" in globals() and vc_config: + self._key_dbg = 1 if vc_config.get_bool("KEY_LED_DEBUG", False) else 0 + else: + self._key_dbg = 0 + except Exception: + self._key_dbg = 0 + # LED 电平极性:有些板子是低电平点亮(active-low),也可能仅某一路反相 + self._inv_r = 0 + self._inv_g = 0 + self._inv_b = 0 + try: + if "vc_config" in globals() and vc_config: + inv = vc_config.get_attr("LED_ACTIVE_LOW_RGB", None) + if isinstance(inv, (tuple, list)) and len(inv) == 3: + self._inv_r = 1 if inv[0] else 0 + self._inv_g = 1 if inv[1] else 0 + self._inv_b = 1 if inv[2] else 0 + else: + all_inv = 1 if vc_config.get_bool("LED_ACTIVE_LOW", False) else 0 + self._inv_r = all_inv + self._inv_g = all_inv + self._inv_b = all_inv + except Exception: + pass + + def _timer_stop(self): + try: + self._timer.stop() + except Exception: + pass - def _led_stop_flicker_timer(self): + def _set_rgb(self, r, g, b): try: - self.led_flicker_timer.stop() + rr = 1 if r else 0 + gg = 1 if g else 0 + bb = 1 if b else 0 + if self._inv_r: + rr = 0 if rr else 1 + if self._inv_g: + gg = 0 if gg else 1 + if self._inv_b: + bb = 0 if bb else 1 + self.led_red.write(rr) + self.led_green.write(gg) + self.led_blue.write(bb) except Exception: pass - def flicker_led_red(self,event,msg): - self._led_stop_flicker_timer() - self.led_flicker_flag = 1 - self.led_flicker_timer.start(1500, 1, self.led_flicker_timer_cb) - - def flicker_led_blue(self,event,msg): - self._led_stop_flicker_timer() - self.led_flicker_flag = 2 - self.led_flicker_timer.start(1500, 1, self.led_flicker_timer_cb) - - def flicker_led_green(self,event,msg): - self._led_stop_flicker_timer() - self.led_flicker_flag = 3 - self.led_flicker_timer.start(1500, 1, self.led_flicker_timer_cb) - - def flicker_led_all(self,event,msg): - self._led_stop_flicker_timer() - self.led_flicker_flag = 4 - self.led_flicker_timer.start(1500, 1, self.led_flicker_timer_cb) - - def flicker_led_blue_green(self,event,msg): - # 思考态:蓝/绿交替亮(各占半个周期),红灯关闭 - self._led_stop_flicker_timer() - self.led_flicker_flag = 5 - self.led_think_phase = 0 - self.led_red.write(0) - self.led_blue.write(1) - self.led_green.write(0) - self.led_think_phase = 1 - self.led_flicker_timer.start(400, 1, self.led_flicker_timer_cb) - - def led_flicker_timer_cb(self, *args, **kwargs): - EventMesh.publish("publish_AI_btnInfo",{"func":self.led_flicker_timer_cb_}) - def led_flicker_timer_cb_(self): - if self.led_flicker_flag == 0: - self._led_stop_flicker_timer() + def _set_off(self): + self._mode = "off" + self._timer_stop() + self._set_rgb(0, 0, 0) + + def _set_red_on(self): + self._mode = "red_on" + self._timer_stop() + self._set_rgb(1, 0, 0) + + def _set_green_on(self): + self._mode = "green_on" + self._timer_stop() + self._set_rgb(0, 1, 0) + + def _set_blue_blink(self, period_ms=1000): + self._mode = "blue_blink" + self._period_ms = period_ms or 1000 + self._blink_on = 1 + self._timer_stop() + self._set_rgb(0, 0, 1) + self._timer.start(self._period_ms, 1, self._timer_cb) + + def _set_red_blink(self, period_ms=1000): + self._mode = "red_blink" + self._period_ms = period_ms or 1000 + self._blink_on = 1 + self._timer_stop() + self._set_rgb(1, 0, 0) + self._timer.start(self._period_ms, 1, self._timer_cb) + + def _set_bg_alt(self, period_ms=1000): + self._mode = "bg_alt" + self._period_ms = period_ms or 1000 + self._bg_phase = 0 + self._timer_stop() + self._set_rgb(0, 0, 1) + self._timer.start(self._period_ms, 1, self._timer_cb) + + def _timer_cb(self, *args, **kwargs): + EventMesh.publish("publish_AI_btnInfo", {"func": self._timer_cb_}) + + def _timer_cb_(self): + if self._mode == "blue_blink": + self._blink_on = 0 if self._blink_on else 1 + self._set_rgb(0, 0, 1 if self._blink_on else 0) + return + if self._mode == "red_blink": + self._blink_on = 0 if self._blink_on else 1 + self._set_rgb(1 if self._blink_on else 0, 0, 0) return - if self.led_flicker_flag == 5: - self.led_red.write(0) - if self.led_think_phase == 0: - self.led_blue.write(1) - self.led_green.write(0) - self.led_think_phase = 1 + if self._mode == "bg_alt": + if self._bg_phase == 0: + self._set_rgb(0, 1, 0) + self._bg_phase = 1 else: - self.led_blue.write(0) - self.led_green.write(1) - self.led_think_phase = 0 + self._set_rgb(0, 0, 1) + self._bg_phase = 0 return - if self.led_flicker_on_off_flag == 0: - self.led_red.write(0) - self.led_blue.write(0) - self.led_green.write(0) - self.led_flicker_on_off_flag = 1 - else: - self.led_flicker_on_off_flag = 0 - if self.led_flicker_flag == 1: - self.led_blue.write(0) - self.led_green.write(0) - self.led_red.write(1) - elif self.led_flicker_flag == 2: - self.led_red.write(0) - self.led_green.write(0) - self.led_blue.write(1) - elif self.led_flicker_flag == 3: - self.led_red.write(0) - self.led_blue.write(0) - self.led_green.write(1) - elif self.led_flicker_flag == 4: - self.led_blue.write(1) - self.led_green.write(1) - self.led_red.write(1) - - def open_led_red(self,event,msg): - #print("open_led_red") - self.led_flicker_flag = 0 - self._led_stop_flicker_timer() - #self.led_red.write(0) - self.led_blue.write(0) - self.led_green.write(0) - self.led_red.write(1) - - def open_led_blue(self,event,msg): - #print("open_led_blue") - self.led_flicker_flag = 0 - self._led_stop_flicker_timer() - self.led_red.write(0) - #self.led_blue.write(0) - self.led_green.write(0) - self.led_blue.write(1) - - def open_led_green(self,event,msg): - #print("open_led_green") - self.led_flicker_flag = 0 - self._led_stop_flicker_timer() - self.led_red.write(0) - self.led_blue.write(0) - #self.led_green.write(0) - self.led_green.write(1) - - def open_led_red_blue(self,event,msg): - #print("open_led_blue") - self.led_flicker_flag = 0 - self._led_stop_flicker_timer() - self.led_red.write(1) - #self.led_blue.write(0) - self.led_green.write(0) - self.led_blue.write(1) - - def open_led_red_green(self,event,msg): - #print("open_led_blue") - self.led_flicker_flag = 0 - self._led_stop_flicker_timer() - self.led_red.write(1) - #self.led_blue.write(0) - self.led_green.write(1) - self.led_blue.write(0) - - def open_led_all(self,event,msg): - #print("open_led_all") - self.led_flicker_flag = 0 - self._led_stop_flicker_timer() - #self.led_red.write(0) - self.led_blue.write(1) - self.led_green.write(1) - self.led_red.write(1) - - def close_led(self,event,msg): - #print("close_led") - self.led_flicker_flag = 0 - self._led_stop_flicker_timer() - try: - self._boot_led_demo_timer.stop() + + def set_led_state(self, event=None, msg=None): + # msg: dict {ai_state, charging, battery, signal} + try: + if isinstance(msg, dict): + if "ai_state" in msg: + self._st_ai = msg.get("ai_state") or "idle" + if "charging" in msg: + self._st_charging = msg.get("charging") or "none" + if "battery" in msg: + self._st_battery = msg.get("battery") or "normal" + if "signal" in msg: + self._st_signal = msg.get("signal") or "normal" + except Exception: + pass + self._apply_by_table(msg) + + def _apply_by_table(self, _msg=None): + prev_mode = self._mode + # P1~P3:AI 阶段(播放 > 思考 > 聆听) + try: + if self._st_ai == "playing": + self._set_green_on() + return self._dbg_print(prev_mode, _msg) + if self._st_ai == "thinking": + self._set_bg_alt(1000) + return self._dbg_print(prev_mode, _msg) + if self._st_ai == "listening": + self._set_blue_blink(1000) + return self._dbg_print(prev_mode, _msg) + except Exception: + pass + # 基础态:充电/电量/信号 + try: + if self._st_charging == "full": + self._set_green_on() + return self._dbg_print(prev_mode, _msg) + if self._st_charging == "charging": + self._set_red_on() + return self._dbg_print(prev_mode, _msg) + if self._st_battery in ("empty", "low"): + self._set_red_blink(1000) + return self._dbg_print(prev_mode, _msg) + if self._st_signal == "weak": + self._set_bg_alt(2000) + return self._dbg_print(prev_mode, _msg) + except Exception: + pass + self._set_off() + return self._dbg_print(prev_mode, _msg) + + def _dbg_print(self, prev_mode, _msg): + if getattr(self, "_dbg", 0) != 1: + return + try: + # 仅在模式变化或本次携带 ai_state 时打印,减少刷屏 + if prev_mode != self._mode: + print("[LED] msg={} st(ai={},chg={},bat={},sig={}) mode:{}->{}".format( + _msg, + self._st_ai, self._st_charging, self._st_battery, self._st_signal, + prev_mode, self._mode)) + else: + try: + if isinstance(_msg, dict) and ("ai_state" in _msg or "charging" in _msg): + print("[LED] msg={} st(ai={},chg={},bat={},sig={}) mode={}".format( + _msg, + self._st_ai, self._st_charging, self._st_battery, self._st_signal, + self._mode)) + except Exception: + pass + except Exception: + pass + + def get_led_debug_state(self, event=None, msg=None): + # 供按键/状态机打印当前 LED 聚合状态与最终模式 + try: + return { + "ai": self._st_ai, + "charging": self._st_charging, + "battery": self._st_battery, + "signal": self._st_signal, + "mode": self._mode, + "period_ms": self._period_ms, + } + except Exception: + return {"mode": getattr(self, "_mode", "?")} + + +class AI_hw_status(Abstract): + # 精简硬件状态采集:仅维护 LED 状态机所需的 charging/battery/signal + def __init__(self): + # 无条件首行:确认是否进入初始化(避免被异常/注册顺序误判) + try: + print("[HW] __init__ enter") + except Exception: + pass + # 参考 mgr.py 的 BATTERY_OCV_TABLE(nix_coy_mnzo2),按电压插值换算 SoC + # 仅保留 LED 状态机所需:>=20 正常;<20 低电;<5 极低/空电 + self._ocv_map = { + 4290: 100, 4237: 95, 4179: 90, 4123: 85, 4070: 80, 4020: 75, 3963: 70, 3919: 65, 3882: 60, 3847: 55, + 3818: 50, 3794: 45, 3772: 40, 3752: 35, 3733: 30, 3716: 25, 3699: 20, 3677: 15, 3652: 10, 3629: 5, 3400: 0, + } + self._ocv_volts = None + try: + self._ocv_volts = sorted(self._ocv_map.keys(), reverse=True) + except Exception: + self._ocv_volts = None + # cached state (avoid repeat publish) + self._chg = None + self._bat = None + self._sig = None + self._usb = None + self._timer = osTimer() + self._period_ms = 10000 + self._weak_csq = 10 + self._dbg = 0 + try: + if "vc_config" in globals() and vc_config: + self._period_ms = vc_config.get_int("HW_STATUS_PERIOD_MS", 10000) or 10000 + self._weak_csq = vc_config.get_int("SIGNAL_WEAK_CSQ", 10) or 10 + self._dbg = 1 if vc_config.get_bool("HW_STATUS_DEBUG", False) else 0 + # 允许覆盖 OCV 表(用电压门限的方式降级兼容) + try: + if vc_config.get_bool("USE_SIMPLE_VBATT_THRESH", False): + cf = vc_config.get_int("VBATT_CHARGE_FULL_MV", 4300) + v20 = vc_config.get_int("VBATT_LOW_MV", 3699) + v5 = vc_config.get_int("VBATT_EMPTY_MV", 3629) + self._vbatt_simple = (int(cf), int(v20), int(v5)) + else: + self._vbatt_simple = None + except Exception: + self._vbatt_simple = None + except Exception: + pass + # 若开启了 LED/按键调试,也一并打开硬件监控打印,便于关联分析 + try: + if "vc_config" in globals() and vc_config: + if vc_config.get_bool("LED_DEBUG", False) or vc_config.get_bool("KEY_LED_DEBUG", False): + self._dbg = 1 + except Exception: + pass + + # 注意:AI_dev 也会注册 USB callback;USB 模块通常只支持一个 callback,后注册会覆盖先注册。 + # 为避免“刚开始有效,后面失效”,这里不直接 setCallback,改为订阅 AI_dev 转发的 USB 状态事件, + # 并在 10 秒轮询中再读一次 GET_USB_STATE 作兜底。 + try: + EventMesh.subscribe("hw_usb_state", self._on_usb_state) + except Exception: + pass + + # 初始化:先立即刷新一次,再开启周期轮询(避免 one-shot/覆盖差异导致只跑一次) + try: + self._update() + except Exception: + pass + try: + self._timer.start(self._period_ms, 1, self._tick_cb) + except Exception: + pass + # 初始化打印(一次) + try: + print("[HW] init ok period_ms={} weak_csq={} usb_init={} algo={}".format( + self._period_ms, + self._weak_csq, + self._usb, + "simple" if getattr(self, "_vbatt_simple", None) else "ocv")) + if self._dbg == 1: + print("[HW] init detail vbatt_simple={}".format(getattr(self, "_vbatt_simple", None))) + except Exception: + pass + + def _on_usb_state(self, event=None, msg=None): + try: + state = msg + self._usb = 1 if state == 1 else 0 except Exception: pass - self.led_red.write(0) - self.led_blue.write(0) - self.led_green.write(0) + try: + if self._dbg == 1: + print("[HW] usb_evt state={} usb={}".format(state, self._usb)) + except Exception: + pass + try: + self._update() + except Exception: + pass + + def _tick_cb(self, *args, **kwargs): + # 定时器回调直接刷新(不依赖 AI_dev 的事件线程) + try: + self._tick() + except Exception: + pass + + def _tick(self, *args, **kwargs): + self._update() + + def _update(self): + # 每次刷新都“同步推送一次”当前硬件基础态到 LED(不依赖变化检测) + # 目的:保证 10 秒轮询和 USB callback 都能及时刷新充电/电量/信号的基础态显示 + # charging/battery + try: + v = Power.getVbatt() + except Exception: + v = None + soc = None + csq = None + rssi = None + chg = "none" + bat = "normal" + sig = "normal" + try: + usb_status = self._usb + if usb_status is None: + try: + usb_status = EventMesh.publish("GET_USB_STATE") + if usb_status is None: + usb_status = 0 + except Exception: + usb_status = 0 + # charging + if usb_status == 1: + # 充满:默认用 4290mV 对齐 mgr OCV 100%,也允许用 simple 门限覆盖 + full_mv = 4290 + try: + if getattr(self, "_vbatt_simple", None): + full_mv = int(self._vbatt_simple[0]) + except Exception: + full_mv = 4290 + if v is not None and v >= full_mv: + chg = "full" + else: + chg = "charging" + # battery level for LED table + if usb_status != 1 and v is not None: + soc = self._soc_from_vbatt(v) + if soc is not None: + if soc < 5: + bat = "empty" + elif soc < 20: + bat = "low" + self._chg = chg + self._bat = bat + except Exception: + pass + + # signal + try: + csq = net.csqQueryPoll() + # csqQueryPoll 返回 (rssi, ber) 或 int,按保守取 rssi + try: + if isinstance(csq, (tuple, list)) and len(csq) > 0: + rssi = csq[0] + else: + rssi = csq + except Exception: + rssi = csq + sig = "weak" if (rssi is not None and int(rssi) >= 0 and int(rssi) < int(self._weak_csq)) else "normal" + self._sig = sig + except Exception: + pass + + # 统一推送一次当前基础态(一次调用带齐字段,减少来回切换) + try: + EventMesh.publish("set_led_state", {"charging": chg, "battery": bat, "signal": sig}) + except Exception: + pass + + # 轮询调试打印(每次 10s tick 一次) + try: + if self._dbg == 1: + print("[HW] usb={} vbatt_mv={} soc={} chg={} bat={} csq={} rssi={} sig={} period_ms={}".format( + usb_status, v, soc, self._chg, self._bat, csq, rssi, self._sig, self._period_ms)) + except Exception: + pass + + def _soc_from_vbatt(self, volt_mv): + # 返回 0~100;异常返回 None + try: + v = int(volt_mv) + except Exception: + return None + # 若启用 simple 门限,直接按门限输出近似 soc(仅用于 LED 分级) + try: + if getattr(self, "_vbatt_simple", None): + _full, _v20, _v5 = self._vbatt_simple + if v >= _full: + return 100 + if v <= _v5: + return 0 + if v <= _v20: + return 10 + return 60 + except Exception: + pass + try: + volts = self._ocv_volts + if not volts: + return None + pre_volt = 0 + volt_not_under = 0 + soc1 = 0 + soc2 = 0 + for vv in volts: + if v > vv: + volt_not_under = 1 + soc1 = self._ocv_map.get(vv, 0) + soc2 = self._ocv_map.get(pre_volt, 0) + break + else: + pre_volt = vv + if pre_volt == 0: + return soc1 + if volt_not_under == 0: + return 0 + # 线性插值(对齐 mgr.__get_soc_from_dict) + return int(soc2 - (soc2 - soc1) * (pre_volt - v) // (pre_volt - vv)) + except Exception: + return None def set_ipv4_datacall(): # 获取第一路的APN,ipType 等信息 pdpCtx = dataCall.getPDPContext(1) @@ -357,7 +610,13 @@ class AI_UART(): self.ping_json_str_tmp ="" self.read_uart_data = "" self.bt_versions="" - if dev_type == "7PIN_1_5": + try: + uart_ok = False + if "vc_config" in globals() and vc_config: + uart_ok = vc_config.uart_supported() + except Exception: + uart_ok = False + if uart_ok: self.uart_send_queue = Queue(100) self.uart_send_queue_thread_id = _thread.start_new_thread(self.uart_send_queue_thread, ()) @@ -840,7 +1099,10 @@ class AI_UART(): print("bt_send_end") def send_data(self,str_data,need_resend = None,ACK_time =None): - if dev_type != "7PIN_1_5": #不是1.5代不能发串口数据 + try: + if not ("vc_config" in globals() and vc_config and vc_config.uart_supported()): + return + except Exception: return if self.bt_ota_flag == 1: print("ota 中不需要上传") @@ -1086,19 +1348,43 @@ class AI_dev(Abstract): # set_ipv4_datacall() self.is_wdt = 0 #是否开启看门狗 #AT+QDAI=1,0,0,1,0,0,1,1PCM音频输出设置为主模式、短同步、16 kHz采样率和256 kHz时钟频率,采样位深为16bit,使用的时间间隙数量为1,并且使用第一个时间间隙。 - if dev_type == "7PIN_1_5" : - #蓝牙电源 - self.PIN_BT_ON =Pin(Pin.GPIO31, Pin.OUT, Pin.PULL_DISABLE, 0) - #马达 - self.PIN_MOT=Pin(Pin.GPIO36, Pin.OUT, Pin.PULL_DISABLE, 1) - - # #马达 - # self.PIN_MOT.write(1) - - utime.sleep_ms(200) - self.PIN_MOT.write(0) - self.PIN_BT_ON.write(1) - audio.set_qdai_cfg(1,0,0,2,0,1,1,1)#用iis做音频输入输出 + try: + bt_pm_en = False + pin_bt_on = None + pin_mot = None + qdai_cfg = None + if "vc_config" in globals() and vc_config: + bt_pm_en = bool(vc_config.get_attr("BT_POWER_MOTOR_ENABLED", False)) + pin_bt_on = vc_config.get_attr("PIN_BT_ON_GPIO", None) + pin_mot = vc_config.get_attr("PIN_MOT_GPIO", None) + qdai_cfg = vc_config.get_attr("AUDIO_QDAI_CFG", None) + except Exception: + bt_pm_en = False + pin_bt_on = None + pin_mot = None + qdai_cfg = None + + if bt_pm_en: + try: + if pin_bt_on: + self.PIN_BT_ON = Pin(getattr(Pin, pin_bt_on), Pin.OUT, Pin.PULL_DISABLE, 0) + if pin_mot: + self.PIN_MOT = Pin(getattr(Pin, pin_mot), Pin.OUT, Pin.PULL_DISABLE, 1) + except Exception: + pass + try: + utime.sleep_ms(200) + if hasattr(self, "PIN_MOT"): + self.PIN_MOT.write(0) + if hasattr(self, "PIN_BT_ON"): + self.PIN_BT_ON.write(1) + except Exception: + pass + try: + if isinstance(qdai_cfg, (tuple, list)) and len(qdai_cfg) == 8: + audio.set_qdai_cfg(*qdai_cfg) # 用iis做音频输入输出 + except Exception: + pass self.VBATT_tab = {"charge_full":4300,"100" :4250 , "90":4179 , "80":4070, "60": 3883, "40":3770, "20":3699, "10":3652,"5":3600,} self.KeyAI_status = 0 self.KeyAI_timer_count = 0 @@ -1129,32 +1415,39 @@ class AI_dev(Abstract): self.play_imei_timer_count=0 self.KeySOS_timer_count = 0 self.KeySOS_timer_flag = 0 - if dev_type == "G10" : - self.extint_AI = ExtInt(ExtInt.GPIO19,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb) - self.pwk_key = ExtInt(ExtInt.GPIO26, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb) - elif dev_type == 'jswm': - self.extint_AI = ExtInt(ExtInt.GPIO26,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb) - self.pwk_key = ExtInt(ExtInt.GPIO19, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb) - elif dev_type == "7PIN_BK_EU": - self.pwk_key = ExtInt(ExtInt.GPIO41, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb) - self.extint_AI = ExtInt(ExtInt.GPIO5,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb) - #蓝牙唤醒4G中断 - elif dev_type == "7PIN_1_5": - self.pwk_key = ExtInt(ExtInt.GPIO41, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb) - self.extint_AI = ExtInt(ExtInt.GPIO43,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb) - - self.extint_wakeup_cta1 = ExtInt(ExtInt.GPIO22,ExtInt.IRQ_RISING, ExtInt.PULL_DISABLE, self.wakeup_extint_cb) - #4G唤醒蓝牙中断 - self.PIN_wakeup_bt =Pin(Pin.GPIO21, Pin.OUT, Pin.PULL_DISABLE, 0) - - - - self.extint_wakeup_cta1_timer = osTimer() - self.extint_wakeup_cta1.enable() - else: - # self.pwk_key = ExtInt(ExtInt.GPIO41, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb) - self.pwk_key = ExtInt(ExtInt.GPIO26, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb) - self.extint_AI = ExtInt(ExtInt.GPIO22,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb) + try: + ai_gpio = "GPIO22" + pwk_gpio = "GPIO26" + bt_wakeup_en = False + wakeup_cta1_gpio = None + wakeup_bt_gpio = None + if "vc_config" in globals() and vc_config: + ai_gpio = vc_config.get_attr("EXTINT_AI_GPIO", "GPIO22") or "GPIO22" + pwk_gpio = vc_config.get_attr("PWK_KEY_GPIO", "GPIO26") or "GPIO26" + bt_wakeup_en = bool(vc_config.get_attr("BT_WAKEUP_4G_ENABLED", False)) + wakeup_cta1_gpio = vc_config.get_attr("EXTINT_WAKEUP_CTA1_GPIO", None) + wakeup_bt_gpio = vc_config.get_attr("PIN_WAKEUP_BT_GPIO", None) + except Exception: + ai_gpio = "GPIO22" + pwk_gpio = "GPIO26" + bt_wakeup_en = False + wakeup_cta1_gpio = None + wakeup_bt_gpio = None + + self.extint_AI = ExtInt(getattr(ExtInt, ai_gpio), ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb) + self.pwk_key = ExtInt(getattr(ExtInt, pwk_gpio), ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb) + + if bt_wakeup_en: + try: + if wakeup_cta1_gpio: + self.extint_wakeup_cta1 = ExtInt(getattr(ExtInt, wakeup_cta1_gpio), ExtInt.IRQ_RISING, ExtInt.PULL_DISABLE, self.wakeup_extint_cb) + if wakeup_bt_gpio: + self.PIN_wakeup_bt = Pin(getattr(Pin, wakeup_bt_gpio), Pin.OUT, Pin.PULL_DISABLE, 0) + self.extint_wakeup_cta1_timer = osTimer() + if hasattr(self, "extint_wakeup_cta1"): + self.extint_wakeup_cta1.enable() + except Exception: + pass self.extint_AI.enable() self.pwk_key_status = 0 @@ -1213,8 +1506,11 @@ class AI_dev(Abstract): #EventMesh.publish("audio_montage_play",["xianyikaiji.mp3"]) #EventMesh.publish("publish_AI_btnInfo",{"func":self.ntptime_cb}) self.check_rest_timer_count = 0 - if dev_type == "7PIN_1_5": #不是1.5代不能发串口数据 - self.ai_uart = AI_UART() + try: + if "vc_config" in globals() and vc_config and vc_config.uart_supported(): + self.ai_uart = AI_UART() + except Exception: + pass self.Keycall1_press_count = 0 self.ble_switch_flag_time = osTimer() @@ -1242,6 +1538,11 @@ class AI_dev(Abstract): #ntptime.settime(8) print("timer:{}!!!!!!!!\r\n".format(utime.localtime())) def usb_event_cb(self, state): + # 转发给精简硬件监控(AI_hw_status),避免 USB callback 被覆盖导致“后面失效” + try: + EventMesh.publish("hw_usb_state", state) + except Exception: + pass EventMesh.publish("publish_AI_btnInfo",{"func":self.usb_event,"data":state}) def usb_event(self, state): @@ -1261,7 +1562,11 @@ class AI_dev(Abstract): self.aud.stop() #EventMesh.publish("flicker_led_red")#充电闪灯 #self.aud.play(1,1,'U:/static/R_CHARGE_IN.mp3') - EventMesh.publish("open_led_red")#充电红灯常亮 + try: + if not ("vc_config" in globals() and vc_config and vc_config.get_bool("USE_MIN_HW_STATUS", True)): + EventMesh.publish("set_led_state", {"charging": "charging"}) + except Exception: + pass EventMesh.publish("audio_montage_play",["R_CHARGE_IN.mp3"]) self.Low_power_warning_flag = 0 pass @@ -1275,7 +1580,11 @@ class AI_dev(Abstract): voice_record_satrt_flag = 0 if VC_satrt_flag == 0 and voice_record_satrt_flag == 0: self.aud.stop() - EventMesh.publish("close_led") + try: + if not ("vc_config" in globals() and vc_config and vc_config.get_bool("USE_MIN_HW_STATUS", True)): + EventMesh.publish("set_led_state", {"charging": "none"}) + except Exception: + pass EventMesh.publish("audio_montage_play",["R_CHARGE_OUT.mp3"]) #self.aud.play(1,1,'U:/static/R_CHARGE_OUT.mp3') def get_usb_state(self,event,msg): @@ -1335,13 +1644,19 @@ class AI_dev(Abstract): #print("publish_AI_btnInfo 2") def sys_sleep_cb(self,event=None,msg=None):#休眠前回调 - if dev_type != "7PIN_1_5": #不是1.5代不能发串口数据 + try: + if not ("vc_config" in globals() and vc_config and vc_config.get_bool("BT_WAKEUP_4G_ENABLED", False)): + return + except Exception: return print("sys_sleep_cb!!!!!!!!!!!!!!!") EventMesh.publish("sleep_BT")#休眠蓝牙 self.PIN_wakeup_bt.write(0) def sys_up_cb(self,event=None,msg=None):#唤醒前回调 - if dev_type != "7PIN_1_5": #不是1.5代不能发串口数据 + try: + if not ("vc_config" in globals() and vc_config and vc_config.get_bool("BT_WAKEUP_4G_ENABLED", False)): + return + except Exception: return print("sys_up_cb!!!!!!!!!!!!!!!") self.wakeup_BT() @@ -1352,7 +1667,10 @@ class AI_dev(Abstract): utime.sleep_ms(100) self.PIN_BT_ON.write(1) def wakeup_BT(self,event=None,msg=None):#4G唤醒蓝牙 - if dev_type != "7PIN_1_5": #不是1.5代不能发串口数据 + try: + if not ("vc_config" in globals() and vc_config and vc_config.get_bool("BT_WAKEUP_4G_ENABLED", False)): + return + except Exception: return print("wakeup_BT!!!!!!!!!!!!!!!") wakeup_cta1_io = self.extint_wakeup_cta1.read_level() @@ -1377,7 +1695,10 @@ class AI_dev(Abstract): def sleep_BT(self,event=None,msg=None):#使蓝牙休眠 - if dev_type != "7PIN_1_5": #不是1.5代不能发串口数据 + try: + if not ("vc_config" in globals() and vc_config and vc_config.get_bool("BT_WAKEUP_4G_ENABLED", False)): + return + except Exception: return print("sleep_BT!!!!!") print("sleep_BT!!!!!") @@ -1395,7 +1716,10 @@ class AI_dev(Abstract): def wakeup_extint_cb(self,args):#蓝牙唤醒4g - if dev_type != "7PIN_1_5": #不是1.5代不能发串口数据 + try: + if not ("vc_config" in globals() and vc_config and vc_config.get_bool("BT_WAKEUP_4G_ENABLED", False)): + return + except Exception: return print("wakeup_extint_cb:!!!!!!!!!") EventMesh.publish(constants.EVENT.SYSTEM_UP)#唤醒休眠 @@ -1517,7 +1841,7 @@ class AI_dev(Abstract): #EventMesh.publish("AI_key_long_press") # EventMesh.publish("audio_montage_play",["zhengzaiguanji.mp3"]) self.aud.play(1,0,'U:/static/zhengzaiguanji.mp3')#关机音频 - EventMesh.publish("open_led_red") + EventMesh.publish("set_led_state", {"battery": "empty"}) utime.sleep_ms(2000) self.aud.stopPlayStream() self.aud.stopAll() @@ -1527,9 +1851,10 @@ class AI_dev(Abstract): #EventMesh.publish("publish_AI_btnInfo",{"func":self.pwk_key_Long_Press}) if self.pwk_key_status == 1:#松开 #print("pwk_key_timer_cb:{}".format(self.pwk_key_timer_count)) - key_count = 5 - if dev_type == "7PIN_BK" or dev_type == "7PIN_BK_EU"or dev_type == "7PIN_BK_coze": - key_count = 3 + try: + key_count = vc_config.get_int("KEY_RELEASE_DEBOUNCE_COUNT", 5) + except Exception: + key_count = 5 if self.pwk_key_timer_count >= key_count: #防抖200ms #EventMesh.publish("AI_key_release") EventMesh.publish("publish_AI_btnInfo",{"func":self.pwk_key_release}) @@ -1614,10 +1939,14 @@ class AI_dev(Abstract): pass elif self.KeyAI_timer_count >= 10*8:#关机 - if dev_type == 'jswm' or dev_type == 'jswm_BOX': + try: + allow_power_off = vc_config.get_bool("AI_LONG_PRESS_POWER_OFF_ENABLED", False) + except Exception: + allow_power_off = False + if allow_power_off: EventMesh.publish("audio_montage_play",["zhengzaiguanji.mp3"]) #self.aud.play(1,0,'U:/static/zhengzaiguanji.mp3')#关机音频 - EventMesh.publish("open_led_red") + EventMesh.publish("set_led_state", {"battery": "empty"}) utime.sleep_ms(2000) self.aud.stopPlayStream() print("stopAll:8") @@ -1625,9 +1954,10 @@ class AI_dev(Abstract): Power.powerDown() if self.KeyAI_status == 1:#松开 #print("KeyAI_timer_cb:{}".format(self.KeyAI_timer_count)) - key_count = 5 - if dev_type == "7PIN_BK"or dev_type == "7PIN_BK_EU"or dev_type == "7PIN_BK_coze": - key_count = 3 + try: + key_count = vc_config.get_int("KEY_RELEASE_DEBOUNCE_COUNT", 5) + except Exception: + key_count = 5 if self.KeyAI_timer_count >= key_count: #防抖200ms if self.KeySOS_timer_flag == 1: self.KeySOS_timer_flag = 0 @@ -1713,7 +2043,7 @@ class AI_dev(Abstract): # return EventMesh.publish("audio_montage_play",["zhengzaiguanji.mp3"]) #self.aud.play(1,0,'U:/static/zhengzaiguanji.mp3')#关机音频 - EventMesh.publish("open_led_red") + EventMesh.publish("set_led_state", {"battery": "empty"}) utime.sleep_ms(3000) self.aud.stopPlayStream() self.aud.stopAll() @@ -1747,23 +2077,39 @@ class AI_dev(Abstract): voice_record_satrt_flag = 0 Vbatt = Power.getVbatt() if self.usb_status == 1 and VC_satrt_flag == 0 and voice_record_satrt_flag == 0: - EventMesh.publish("open_led_red")#充电红灯常亮 + try: + if not ("vc_config" in globals() and vc_config and vc_config.get_bool("USE_MIN_HW_STATUS", True)): + EventMesh.publish("set_led_state", {"charging": "charging"})#充电红灯常亮 + except Exception: + pass if self.usb_status == 1 and Vbatt>=self.VBATT_tab["charge_full"]and VC_satrt_flag == 0 and voice_record_satrt_flag == 0:#充电充满 - EventMesh.publish("open_led_green") + try: + if not ("vc_config" in globals() and vc_config and vc_config.get_bool("USE_MIN_HW_STATUS", True)): + EventMesh.publish("set_led_state", {"charging": "full"}) + except Exception: + pass if self.usb_charge_flag == 0 : EventMesh.publish("audio_montage_play",["R_CHARGE_FULL.mp3"]) #self.aud.play(1,0,'U:/static/R_CHARGE_FULL.mp3')#充电已满 self.usb_charge_flag = 1 if self.usb_status == 0 and Vbatt= 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= VC_State_TTSStart and self.VC_state <= VC_State_TTSEnd) or getattr(self, "VC_Play_flag", 0) == 1: + self._ptt_short_press_stop = 1 + try: + cancel = {"event": "cancel", "payload": {}} + self.AI_client_VC_send(ujson.dumps(cancel)) + except Exception: + pass + try: + self.VC_Play_End() + except Exception: + pass + try: + self.fsm.await_played = False + except Exception: + pass + try: + EventMesh.publish("set_led_state", {"ai_state": "idle"}) + except Exception: + pass + return + except Exception: + pass + # 非播放态:短按不做任何事 + return + except Exception: + pass + + # 长对话播放态:短按打断并续聊(复用 dialog_id) if self.VC_state >= VC_State_TTSStart and self.VC_state <= VC_State_TTSEnd: print("【打断播放】设备正在说话,仅中断播放,不发起新对话") self.is_ruppt_tts = 1 EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_RequestToSpeak})#打断 return - # 长对话:单按键语义为“打断当前对话,然后继续开麦上行” - # - 若服务端返回 canceled,则会在 canceled 分支自动触发开麦(见 recv 里的 request_uplink_start("canceled")) + # 长对话(VC_mode==0): + # - 对话进行中:短按 AI 键只打断/续聊,复用本次会话的 dialog_id(不重连、不新建会话) + # - 已停止/未 started:短按 AI 键发起新会话(会产生新的 dialog_id) try: if self.VC_mode == 0: - EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_client_VC_RequestToSpeak}) - return + if getattr(self, "AI_client_VC_isconnect", 0) == 1 and getattr(self, "_vc_session_started", 0) == 1: + # 若服务端返回 canceled,则会在 canceled 分支自动触发开麦(见 recv 里的 FSM uplink_start:canceled) + EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_client_VC_RequestToSpeak}) + return + # 否则走下方“新会话”流程 except Exception: pass @@ -4141,12 +4391,10 @@ class AI_VC(Abstract): self.Close() self.revoice_cnt = 0 self.revoice_timer.stop()#回复定时器关闭,计数器清零 - EventMesh.publish("open_led_green") EventMesh.publish("start_voice_record",2)#开始语音录音 return elif self.meet_flag == 1:#会议纪要模式 self.Close() - EventMesh.publish("open_led_green") EventMesh.publish("start_voice_record",3)#开始会议录音 return elif self.trans_flag == 1:#AI翻译模式 @@ -4158,32 +4406,17 @@ class AI_VC(Abstract): self.key_state = 1 # EventMesh.publish("audio_montage_play",["chenggong.mp3"]) # self.chenggong_tone() #播放按键音 - if dev_type == "7PIN_1_5": #2代产品要延时播放按键音 为了连接蓝牙后不播放按键音的问题 - self.ai_key_press_audio.stop() - self.ai_key_press_audio.start(300, 0, self.ai_key_press_audio_cb1) - if PRESS_AUDIO_MODE == 1: - if dev_type == "7PIN" or dev_type == "7PIN_1_5": - if dev_type == "7PIN_1_5": - pass - # self.ai_key_press_audio.stop() - # self.ai_key_press_audio.start(300, 0, self.ai_key_press_audio_cb1) - # self.aud.aud_tone_play(10,200)#播放按键音 - else: - pass - # self.aud.aud_tone_play(10,200)#播放按键音 + try: + delay_ms = 0 + if "vc_config" in globals() and vc_config: + delay_ms = vc_config.get_int("KEY_PRESS_TONE_DELAY_MS", 0) + if delay_ms and delay_ms > 0: + self.ai_key_press_audio.stop() + self.ai_key_press_audio.start(delay_ms, 0, self.ai_key_press_audio_cb1) + except Exception: + pass utime.sleep_ms(500) self.Close() - if PRESS_AUDIO_MODE == 0: - if dev_type == "7PIN" or dev_type == "7PIN_1_5": - if dev_type == "7PIN_1_5": - pass - # self.ai_key_press_audio.stop() - # self.ai_key_press_audio.start(200, 0, self.ai_key_press_audio_cb2) - # self.chenggong_tone() - # self.aud.aud_tone_play(10,200)#播放按键音 - else: - pass - # self.aud.aud_tone_play(10,200)#播放按键音 # if dev_type == "7PIN": # self.chenggong_tone() @@ -4219,23 +4452,18 @@ class AI_VC(Abstract): self.aud.aud_tone_play(10,400)#播放按键音 # EventMesh.publish("audio_montage_play",["chenggong.mp3"]) # self.chenggong_tone() #播放按键音 - if PRESS_AUDIO_MODE == 1: - if dev_type == "7PIN" or dev_type == "7PIN_1_5": - pass - # self.aud.aud_tone_play(10,400)#播放按键音 - # 长对话:蓝牙按键同单按——打断并继续开麦上行 + # 长对话:蓝牙按键同单按 + # - 对话进行中:打断/续聊(复用 dialog_id) + # - 已停止/未 started:走新会话流程 try: if self.VC_mode == 0: - EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_client_VC_RequestToSpeak}) - return + if getattr(self, "AI_client_VC_isconnect", 0) == 1 and getattr(self, "_vc_session_started", 0) == 1: + EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_client_VC_RequestToSpeak}) + return except Exception: pass self.Close() - if PRESS_AUDIO_MODE == 0: - if dev_type == "7PIN" or dev_type == "7PIN_1_5": - pass - # self.chenggong_tone() if self.VC_mode == 1: #长按对话模式 接收到蓝牙耳机按键事件 @@ -4281,6 +4509,20 @@ class AI_VC(Abstract): EventMesh.publish("exit_voice_message_mode") def AI_key_release(self, event=None, msg=None):#按键弹起 + try: + if "vc_config" in globals() and vc_config and vc_config.get_bool("KEY_LED_DEBUG", False): + try: + led = EventMesh.publish("get_led_debug_state") + except Exception: + led = None + try: + t = getattr(self.fsm, "turn", None) + except Exception: + t = None + print("[KEY] AI_key_release VC_mode={} VC_state={} turn={} led={}".format( + getattr(self, "VC_mode", -1), getattr(self, "VC_state", -1), t, led)) + except Exception: + pass print("AI_key_release123") self.key_state = 0 if self.trans_flag == 1:#AI翻译模式 @@ -4290,7 +4532,7 @@ class AI_VC(Abstract): self.stop_voice_timer.stop() self.voice_flag=0 if EventMesh.publish("GET_USB_STATE") == 0: - EventMesh.publish("close_led") + EventMesh.publish("set_led_state", {"ai_state": "idle"}) EventMesh.publish("stop_voice_record")#停止静默录音 tts_play_str = "留言已发送" self.voice_flag=0 @@ -4310,14 +4552,24 @@ class AI_VC(Abstract): else : if self.VC_mode == 1 :#长按单次问答模式 + # 若刚刚短按用于“停止播报”,则不再触发提示音 TTS,直接回到 idle + try: + if getattr(self, "_ptt_short_press_stop", 0) == 1: + self._ptt_short_press_stop = 0 + return + except Exception: + pass # try: # EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) # except Exception as e: # usys.print_exception(e) #EventMesh.publish("publish_AI_btnInfo",{"func":self.key_prompt}) #提示请您按住中间的按钮开始讲话,讲完松开即可 - if dev_type == "7PIN_BK_EU": - self.AI_TTS_str = "Please press and hold the button to speak. " - else: + try: + if "vc_config" in globals() and vc_config: + self.AI_TTS_str = vc_config.get_attr("PTT_HINT", None) + except Exception: + pass + if not self.AI_TTS_str: self.AI_TTS_str = "请您按住圆形的按钮开始讲话,讲完松开即可 " EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) pass @@ -4325,6 +4577,11 @@ class AI_VC(Abstract): #self.VC_Speech_End() def pwk_key_double_press(self,event,msg):#pwk双击 print("come 双击") + # 切换模式:必须打断当前对话/录音/播放,回到 idle,等待按键触发新一轮 + try: + EventMesh.publish("publish_AI_btnInfo", {"func": self.Close}) + except Exception: + pass if self.VC_mode == 0: self.VC_mode = 1 tts_str = "已切换到单对话模式" @@ -4343,15 +4600,29 @@ class AI_VC(Abstract): self._last_tts_kind = "mode_switch_long" except Exception: pass + # 提示音播完即退出(Close_flag=1),保持 idle,等待按键 EventMesh.publish("play_tts",[tts_str,1]) EventMesh.publish("set_storage_config",["VC_mode",self.VC_mode]) def AI_key_long_press(self, event, msg):#按键长按 + try: + if "vc_config" in globals() and vc_config and vc_config.get_bool("KEY_LED_DEBUG", False): + try: + led = EventMesh.publish("get_led_debug_state") + except Exception: + led = None + try: + t = getattr(self.fsm, "turn", None) + except Exception: + t = None + print("[KEY] AI_key_long_press VC_mode={} VC_state={} turn={} led={}".format( + getattr(self, "VC_mode", -1), getattr(self, "VC_state", -1), t, led)) + except Exception: + pass print("AI_key_long_press") # 单对话(PTT):任何中间态都允许打断并开启新一轮录音上行 if self.trans_flag == 1:#AI翻译模式 self.Close() - EventMesh.publish("open_led_green") EventMesh.publish("start_voice_record",4)#开始翻译录音 self.AI_key_long_press_flag = 1 if self.VC_mode == 1: @@ -4440,6 +4711,11 @@ class AI_VC(Abstract): usys.print_exception(e) self.VC_record_state_flag = 1 + # 录音开始:聆听灯(蓝慢闪) + try: + EventMesh.publish("set_led_state", {"ai_state": "listening"}) + except Exception: + pass except Exception as e: self.websocket_error() @@ -4492,6 +4768,11 @@ class AI_VC(Abstract): self.AI_record_tmp_queue.clear() self.VC_record_state_flag = 0 + # 录音停止:关闭聆听灯(恢复 base) + try: + EventMesh.publish("set_led_state", {"ai_state": "idle"}) + except Exception: + pass print("[VC] Speech_End record_state={}".format(self.VC_record_state_flag)) #关闭录音线程 def VC_record_thread_close(self): @@ -4749,12 +5030,12 @@ class AI_VC(Abstract): print("token:{}".format(token)) req_str = "vc/chat?is_auth={}".format(self.is_auth) - if dev_type == '7PIN_BK_coze' or dev_type == '7PIN_coze': - req_str = "vc/coze?is_auth={}".format(self.is_auth) - elif dev_type == 'jswm' or dev_type == 'jswm_BOX' : - req_str = "vc/agent?is_auth={}".format(self.is_auth) - elif dev_type == "7PIN":#内部测试,不用coze - req_str = "vc/agent?is_auth={}".format(self.is_auth) + try: + if "vc_config" in globals() and vc_config: + base = vc_config.get_attr("VC_WS_PATH", "vc/chat") or "vc/chat" + req_str = "{}?is_auth={}".format(base, self.is_auth) + except Exception: + pass if(token): url = 'ws://{}/{}&dt={}'.format(self.server_ip,req_str,token) else: @@ -4820,7 +5101,7 @@ class AI_VC(Abstract): self.AI_ASR_flag = 0 # 可能由收包线程/其它线程触发:统一切回主线程执行 stop,避免“异常→重试→再异常”的循环 EventMesh.publish("publish_AI_btnInfo",{"func":self._uplink_request_stop, "data":"websocket_error"}) - EventMesh.publish("close_led") + EventMesh.publish("set_led_state", {"ai_state": "idle"}) if TTS_str == None: self.websocket_error_count+=1 # if self.websocket_error_count <=3: @@ -5153,20 +5434,20 @@ class AI_VC(Abstract): #payload = jsload_data["payload"] # self.VC_dialog_id = payload["dialog_id"] # self.VC_task_id = jsload_data["task_id"] - EventMesh.publish("open_led_blue") + # started 仅表示链路就绪:不在这里提前切灯态; + # 聆听灯只在“录音真正开始/停止”处更新(VC_Speech_Start/End)。 # 会话开始:允许上行;连续对话模式下直接进入“可发送音频”状态 self._vc_session_started = 1 - # 新会话开始必须允许连续对话自动开麦(防止上一轮 Close_flag 残留导致 Deny START) - self.Close_flag = 0 + # started 时不要强制清 Close_flag: + # - Close_flag==1:提示音/模式切换播完退出 + # - Close_flag==0:正常对话流程 self._ptt_audio_created = 0 self._server_vad_silence = 0 self._turn_has_asr_completed = 0 self._turn_has_vad_silence = 0 self._turn_has_tts_started = 0 self._llm_completed_ms = 0 - self._llm_text_pending_tts = "" - self._llm_force_tts_ms = 0 - if self.VC_mode == 0: + if self.VC_mode == 0 and getattr(self, "Close_flag", 0) == 0: # 会话已 started:若此时上行未启动,则在这里补一次开麦,避免“Start 前开麦被 Close 停掉”后 # 出现首轮无音频上行导致“第一次对话没有”的情况。 if self.record_data_save_flag == 0 and self.VC_record_state_flag == 0: @@ -5227,8 +5508,11 @@ class AI_VC(Abstract): self.voice_choose_flag = 1 else: #开始上传语音 - if dev_type != "7PIN_coze" and dev_type != "7PIN" and dev_type != "7PIN_1_5": - self.chenggong_tone() + try: + if "vc_config" in globals() and vc_config and vc_config.get_bool("UPLOAD_START_TONE_ENABLED", False): + self.chenggong_tone() + except Exception: + pass if self.VC_mode == 0 : self.VC_record_state_flag =2 else: @@ -5258,17 +5542,17 @@ class AI_VC(Abstract): self._turn_has_vad_silence = 0 self._turn_has_tts_started = 0 self._llm_completed_ms = 0 - self._llm_text_pending_tts = "" - self._llm_force_tts_ms = 0 + try: + self._drop_tts_audio = 0 + except Exception: + pass if self.VC_mode == 1 : self.VC_record_state_flag = 2 self.LocalRespondingEnded_timerout = 0 - EventMesh.publish("open_led_blue") elif jsload_data["event"] == "asr.result" :#asr结果 self.AI_ASR_str = jsload_data["payload"]["content"] if self.AI_ASR_str == "":#没识别到 self.AI_TTS_str = "我没听清,请再说一遍" - EventMesh.publish("open_led_blue") elif jsload_data["event"] == "asr.completed" :#asr 终止的标识 self._turn_has_asr_completed = 1 # 抢占规则:本地提示音不可打断流播放 @@ -5287,7 +5571,7 @@ class AI_VC(Abstract): if self.AI_ASR_send_data_queue.empty()!=True: self.AI_ASR_send_data_queue.clear() self.AI_ASR_send_buf_len = 0 - EventMesh.publish("open_led_all") + EventMesh.publish("set_led_state", {"ai_state": "thinking"}) try: self.request_uplink_stop("asr.completed/config_cmd") @@ -5309,9 +5593,11 @@ class AI_VC(Abstract): # if dev_type != "7PIN" : #EventMesh.publish("publish_AI_btnInfo",{"func":self.send_tone}) elif jsload_data["event"] == "vad.active" :#VAD 检测到说话→聆听 - if dev_type in ("7PIN_1_5", "7PIN", "7PIN_coze"): - self._server_vad_silence = 0 - EventMesh.publish("open_led_blue") + try: + if "vc_config" in globals() and vc_config and vc_config.get_bool("VAD_ACTIVE_BLUE_LED", True): + self._server_vad_silence = 0 + except Exception: + pass elif jsload_data["event"] == "vad.silence" :#VAD 终止的标识 # 说明服务端已判定“本轮说话结束”;此时继续上行只会干扰后续(例如推迟 TTS)。 # 仅在“正在录音上行”的语音阶段才停止,避免误触发。 @@ -5322,14 +5608,12 @@ class AI_VC(Abstract): if self.VC_record_state_flag != 0 and self.VC_state >= VC_State_SpeechStart: self.request_uplink_stop("vad.silence") elif jsload_data["event"] == "llm.created" :#思考(LLM) - if dev_type in ("7PIN_1_5", "7PIN", "7PIN_coze"): - EventMesh.publish("flicker_led_blue_green") - else: - EventMesh.publish("open_led_red_green") + try: + EventMesh.publish("set_led_state", {"ai_state": "thinking"}) + except Exception: + pass self.VC_state = VC_State_Thinking self._llm_completed_ms = 0 - self._llm_text_pending_tts = "" - self._llm_force_tts_ms = 0 # EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Play_Start}) pass elif jsload_data["event"] == "llm.completed" :#llm完成(可能无 tts) @@ -5338,14 +5622,6 @@ class AI_VC(Abstract): except Exception: # 勿用 1:ticks_diff(now,1)≈开机至今,会瞬间满足 thinking 超时误以为该重启 self._llm_completed_ms = 0 - # 若服务端没有自动触发 tts.started,则准备由端侧主动发 synthesis - try: - txt = jsload_data.get("payload", {}).get("content", "") - except Exception: - txt = "" - if isinstance(txt, str) and txt.strip() and VC_PROTO_GUARDS: - self._llm_text_pending_tts = txt.strip() - self._llm_force_tts_ms = self._llm_completed_ms try: self._cur_dialog_id = jsload_data.get("payload", {}).get("dialog_id", "") or "" except Exception: @@ -5365,8 +5641,6 @@ class AI_VC(Abstract): self._turn_has_tts_started = 1 self._tts_pending = 0 self._tts_pending_ms = 0 - self._llm_text_pending_tts = "" - self._llm_force_tts_ms = 0 self._uplink_mark_end("tts.started") # stop uplink + play_start 由 FSM action list 统一触发,避免多处重复调用 # 标记本轮 TTS 来源: @@ -5398,9 +5672,9 @@ class AI_VC(Abstract): self._pending_tts_kind = "" except Exception: pass - EventMesh.publish("open_led_green")#绿色 + # 播放灯由阶段事件控制 elif jsload_data["event"] == "tts.completed" :#tts结束 - EventMesh.publish("open_led_green")#绿色 + # tts.completed 仅表示下发结束,本地可能仍在播放;绿灯关闭在本地播放结束时处理 self.VC_state = VC_State_TTSEnd try: # server event 已在统一入口 on_server_event 触发 FSM,这里避免重复驱动 @@ -5555,7 +5829,12 @@ class AI_VC(Abstract): #self.AI_ASR_str = ""#下发音频后清掉asr结果 - EventMesh.publish("open_led_green")#绿色 + # PTT 打断后丢弃残留 TTS 音频帧,避免“断断续续继续播” + try: + if getattr(self, "_drop_tts_audio", 0) == 1: + continue + except Exception: + pass if self.VC_stop_play_audio_flag == 0: print("新的AI对话不允许以前的播放数据:") break @@ -5762,7 +6041,7 @@ class AI_VC(Abstract): self.AI_VC_send_data_queue.clear() if self.AI_ASR_send_data_queue.empty()!=True: self.AI_ASR_send_data_queue.clear() - EventMesh.publish("open_led_all") + EventMesh.publish("set_led_state", {"ai_state": "thinking"}) self.AI_ASR_send_buf_len = 0 self._uplink_request_stop("play_tts_cb") self.websocket_deconnect_VC() @@ -6122,20 +6401,18 @@ class AI_VC(Abstract): # self.AI_TTS_str = "更改失败,没找到对应声音" # return 0 if text.find("切换对话模式") != -1: - if dev_type == "7PIN_BK_EU": - if self.VC_mode == 0: - self.VC_mode = 1 - self.AI_TTS_str = "change dialogue mode" - else: - self.VC_mode = 0 - self.AI_TTS_str = "pushtalk mode" + if self.VC_mode == 0: + self.VC_mode = 1 + try: + self.AI_TTS_str = vc_config.get_attr("CMD_TOGGLE_MODE_TO_PTT_TTS", "已切换到单对话模式") + except Exception: + self.AI_TTS_str = "已切换到单对话模式" else: - if self.VC_mode == 0: - self.VC_mode = 1 - self.AI_TTS_str = "已切换到单对话模式" - else: - self.VC_mode = 0 - self.AI_TTS_str = "已切换到长对话模式" + self.VC_mode = 0 + try: + self.AI_TTS_str = vc_config.get_attr("CMD_TOGGLE_MODE_TO_LONG_TTS", "已切换到长对话模式") + except Exception: + self.AI_TTS_str = "已切换到长对话模式" EventMesh.publish("set_storage_config",["VC_mode",self.VC_mode]) # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"]) #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功 @@ -6284,53 +6561,48 @@ class AI_VC(Abstract): else: self.AI_TTS_str = "当前已是最新版本" return 0 - if dev_type == "7PIN_1_5":#二代才有蓝牙和语音留言功能 + try: + bt_voice_en = ("vc_config" in globals() and vc_config and vc_config.get_bool("BT_VOICE_FEATURES_ENABLED", False)) + except Exception: + bt_voice_en = False + if bt_voice_en: if text.find("语音留言") != -1: self.voice_flag = 1 - self.AI_TTS_str = "已进入语音留言模式,长按按钮开始录音,松开按钮结束" + self.AI_TTS_str = "已进入语音留言模式,长按按钮开始录音,松开按钮结束" self.Close_flag = 1 - self.stop_voice_timer.stop() #关闭语音留言模式定时器 + self.stop_voice_timer.stop() self.stop_voice_timer.start(30*1000,0,self.exit_voice_message_timer) print("语音留言!!!!!!!!!!") return 0 if text.find("开广播") != -1 or text.find("开蓝牙广播") != -1: - - self.AI_TTS_str = "正在开蓝牙广播" + self.AI_TTS_str = "正在开蓝牙广播" EventMesh.publish("AI_send_bt_ble_switch_toble",1) - print("正在开蓝牙广播") return 0 if text.find("关广播") != -1 or text.find("关蓝牙广播") != -1: - - self.AI_TTS_str = "正在关蓝牙广播" + self.AI_TTS_str = "正在关蓝牙广播" EventMesh.publish("AI_send_bt_ble_switch_toble",2) - print("正在关蓝牙广播") return 0 if text.find("开经典蓝牙") != -1: - - self.AI_TTS_str = "正在开经典蓝牙" + self.AI_TTS_str = "正在开经典蓝牙" EventMesh.publish("AI_send_bt_ble_switch_toble",3) print("正在开经典蓝牙") return 0 if text.find("关闭经典蓝牙") != -1 or text.find("关经典蓝牙") != -1: - - self.AI_TTS_str = "正在关经典蓝牙" + self.AI_TTS_str = "正在关经典蓝牙" EventMesh.publish("AI_send_bt_ble_switch_toble",4) print("正在关经典蓝牙") return 0 - if text.find("确认解绑设备") != -1 or text.find("确认设备解绑") != -1: - self.AI_TTS_str = "设备解绑中...." + self.AI_TTS_str = "设备解绑中...." self.Close_flag = 1 EventMesh.publish("send_unbind_dev_to_iot") print("解绑设备!!!!!!!!!!!!!!") return 0 if text.find("删除耳机记录") != -1 or text.find("清楚耳机记录") != -1: - - self.AI_TTS_str = "正在删除" + self.AI_TTS_str = "正在删除" EventMesh.publish("clear_earphone_record") - print("正在删除") return 0 # if len(text)<16 and (text.find("再见") != -1 or text.find("拜拜") != -1 or text.find("关闭对话") != -1): @@ -6344,9 +6616,12 @@ class AI_VC(Abstract): # #EventMesh.publish("sleep_BT")#休眠蓝牙 # return 1 if len(text)<12 and (text.find("关机") != -1 ): - if dev_type == "7PIN" or dev_type == "7PIN_coze" or dev_type == "7PIN_1_5":#柒牌 - EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) - #EventMesh.publish("sleep_BT")#休眠蓝牙 + try: + close_only = ("vc_config" in globals() and vc_config and vc_config.get_bool("POWEROFF_CMD_CLOSE_ONLY", True)) + except Exception: + close_only = True + if close_only: + EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) return 1 EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) EventMesh.publish("Power_off") @@ -6434,6 +6709,10 @@ class AI_VC(Abstract): elif self.VC_play_TYPE == VC_play_TYPE_MP3: pass self.VC_Play_flag = 1 + try: + EventMesh.publish("set_led_state", {"ai_state": "playing"}) + except Exception: + pass except Exception as e: self.VC_Play_End() usys.print_exception(e) @@ -6471,9 +6750,21 @@ class AI_VC(Abstract): if self.AI_audio_queue.empty()!=True: self.AI_audio_queue.clear() - # 播放结束后:退出“播报中”绿灯态。默认回到蓝灯(可说/待机态)。 + # 播放结束后:退出“播报中”绿灯态(恢复 base)。 try: - EventMesh.publish("open_led_blue") + EventMesh.publish("set_led_state", {"ai_state": "idle"}) + except Exception: + pass + # 关键日志:定位“tts 结束绿灯仍不灭”究竟是 base 态(如 charging/full)还是 playing 未退出 + try: + if "vc_config" in globals() and vc_config and ( + vc_config.get_bool("LED_DEBUG", False) or vc_config.get_bool("KEY_LED_DEBUG", False) or vc_config.get_bool("HW_STATUS_DEBUG", False) + ): + try: + led = EventMesh.publish("get_led_debug_state") + except Exception: + led = None + print("[VC] VC_Play_End led={}".format(led)) except Exception: pass @@ -6508,7 +6799,6 @@ class AI_VC(Abstract): self._tts_pending_ms = 0 if self.VC_mode == 0 and self.Close_flag == 0: self.VC_state = VC_State_None - EventMesh.publish("open_led_blue") EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_VC_start}) except Exception: pass @@ -6521,11 +6811,7 @@ class AI_VC(Abstract): # 只有在 llm.completed 之后才允许超时重启 if turn == VCTurnState.Thinking and llm_completed_ms and self._turn_has_tts_started == 0: age_ms = utime.ticks_diff(now_ms, llm_completed_ms) - # 有 force_tts pending 时不可用 6s 短超时:会与下方 force_tts(约 5s)抢跑 AI_VC_start, - # 打断 synthesis/会话;改为长超时兜底,仍以 throttle 为保护。 - pending_for_force_tts = VC_PROTO_GUARDS and ( - self._llm_text_pending_tts or self._llm_force_tts_ms) - restart_threshold_ms = 40000 if pending_for_force_tts else 20000 + restart_threshold_ms = 20000 # _fb_last_thinking_restart_ms==0 时 ticks_diff(now,0) 非预期(间隔被误判极大), # 会在 llm.completed 后首批 tick 就触发 AI_VC_start → notts(无 tts.started);首次仅信任 age 门限 try: @@ -6546,44 +6832,11 @@ class AI_VC(Abstract): age_ms, restart_threshold_ms)) except Exception: pass - EventMesh.publish("open_led_blue") # thinking_timeout 策略:重启会话(而不是抢开麦),避免干扰服务端 LLM/TTS 流程 EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_VC_start}) except Exception: pass - # 3) llm→tts 兜底:仅 Thinking 期且足够等待/节流时触发;若仍在录音则先 stop,下一次 tick 再判断(受 VC_PROTO_GUARDS) - try: - if VC_PROTO_GUARDS and self._llm_text_pending_tts and self._llm_force_tts_ms and self._turn_has_tts_started == 0: - # 注意:服务端可能出现 llm.completed 后直接 completed(无 tts 事件)的情况, - # 此时 FSM turn 可能已回到 Listening;兜底不能硬绑 Thinking,否则会“只见 llm 不见 tts”。 - if (turn not in (VCTurnState.TtsReceiving, VCTurnState.Playing, VCTurnState.AwaitPlayedAck) and - utime.ticks_diff(now_ms, self._llm_force_tts_ms) > 5000 and - utime.ticks_diff(now_ms, self._fb_last_force_tts_ms) > 15000 and - self._tts_pending == 0 and self._need_audio_played_ack == 0 and self.VC_Play_flag == 0): - self._fb_last_force_tts_ms = now_ms - if self.record_data_save_flag == 0 and self.VC_record_state_flag != 0: - self.request_uplink_stop("force_tts_pre_stop") - return - self._llm_force_tts_ms = 0 - self.AI_TTS_str = self._llm_text_pending_tts - self._llm_text_pending_tts = "" - self._server_vad_silence = 1 - if self.record_data_save_flag == 0: - self.request_uplink_stop("force_tts") - try: - sid = getattr(self, "_cur_sid", "") - did = getattr(self, "_cur_dialog_id", "") - except Exception: - sid, did = "", "" - try: - print("[VC][force_tts] send synthesis sid={} did={} turn={}".format(sid, did, turn)) - except Exception: - pass - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_synthesis}) - except Exception: - pass - def _1S_timer_cb_(self): EventMesh.publish("system_sleep_rest")#防止黑屏 @@ -6632,7 +6885,6 @@ class AI_VC(Abstract): except Exception: pass if (is_pcm_empty and drained) or too_long: - EventMesh.publish("open_led_blue") EventMesh.publish("publish_AI_btnInfo", {"func": self.VC_Play_End}) self._fsm_apply_actions(self.fsm.on_local_play_end()) self.VC_state = VC_State_None @@ -6667,10 +6919,6 @@ class AI_VC(Abstract): #VC开始 def AI_VC_start(self): print("AI_VC_start1") - try: - print("[VC] build:{}".format(VC_BUILD_TAG)) - except Exception: - pass EventMesh.publish(constants.EVENT.SYSTEM_UP)#唤醒休眠 self.VC_satrt_flag = 1 @@ -6678,7 +6926,7 @@ class AI_VC(Abstract): self.VC_satrt_kws_flag = 1 if self.VC_Thinking_timerout < 100: self.VC_Thinking_timerout = 0 - EventMesh.publish("open_led_blue") + # 不在这里提前切灯态:播放/聆听灯只在“播放/录音真正开始/停止”处更新 EventMesh.publish("wakeup_BT") #self.VC_Play_End()#关闭音频播放 print("AI_VC_start2") @@ -6844,89 +7092,51 @@ class AI_VC(Abstract): json_data["payload"]["outbound_attributes"]["provider"]=self.VC_TTS_voice_type[self.VC_TTS_voice_key]["outbound_attributess_provider"] print("outbound_attributess_provider是VC_TTS_voice_type里的:{}".format(self.VC_TTS_voice_type[self.VC_TTS_voice_key]["outbound_attributess_provider"])) - if dev_type == "7PIN_BK"or dev_type == "7PIN_BK_coze"or dev_type == "G10":#小瑞 - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7411071327182438412"#语言助手 - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7468577560454496295" - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"]=True - # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7486697248416989193"#极简 - # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7486698347416649778" - #json_data["payload"]["dialog_attributes"]["provider"]="doubao"#豆包 - #json_data["payload"]["inbound_attributes"]["vad_silence"] = 200 - #if self.VC_TTS_voice_type[self.VC_TTS_voice_key]["bot_id"] !="": - if "bot_id" in self.VC_TTS_voice_type[self.VC_TTS_voice_key]: - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]=self.VC_TTS_voice_type[self.VC_TTS_voice_key]["bot_id"] - if "workflow_id" in self.VC_TTS_voice_type[self.VC_TTS_voice_key]: - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]= self.VC_TTS_voice_type[self.VC_TTS_voice_key]["workflow_id"] - else: - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="" - if json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"] == "": - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"]=False - + # 根据配置设置默认 bot/workflow,并允许 VC_TTS_voice_type 覆盖 + try: + if "vc_config" in globals() and vc_config: + opt = vc_config.get_attr("DIALOG_BOT_OPTION", None) + if isinstance(opt, dict): + if "bot_id" in opt and opt["bot_id"]: + json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"] = opt["bot_id"] + if "workflow_id" in opt: + json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"] = opt.get("workflow_id") or "" + if "use_workflow" in opt: + json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"] = bool(opt.get("use_workflow")) + except Exception: + pass - keywords = []#热词 - for key in self.VC_TTS_voice_type: - keywords.append(key) - json_data["payload"]["inbound_attributes"]["cfg"]["keywords"] = keywords - elif dev_type == "7PIN_BK_EU": - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7493368740600446995"#英文 - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7493369551587213323" - elif dev_type == "csh": - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7490852493640384538"#慈善会 - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"]=False - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="" - elif dev_type == "7PIN" or dev_type == "7PIN_1_5" :#柒牌 + try: + # voice 配置可覆盖 bot_id/workflow_id/openai_option + cur = self.VC_TTS_voice_type[self.VC_TTS_voice_key] + if isinstance(cur, dict): + if cur.get("bot_id"): + json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"] = cur.get("bot_id") + if "workflow_id" in cur: + json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"] = cur.get("workflow_id") or "" + if json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"].get("workflow_id", "") == "": + json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"] = False + if cur.get("openai_option"): + json_data["payload"]["dialog_attributes"]["cfg"]["openai_option"] = cur.get("openai_option") + except Exception: pass - #end金三 - # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7550138354483298347"# - # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7549142130376671267" - # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7411071327182438412" - # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7601036330500669467" - #json_data["payload"]["inbound_attributes"]["vad_silence"] = 1000 - elif dev_type == "7PIN_coze": - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7550138354483298347"# - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7549142130376671267" - json_data["payload"]["dialog_attributes"]["provider"]="qipai" - # - elif dev_type == 'momo':#食梦貘 - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7491256313561825332" - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="" - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"]=False - if "bot_id" in self.VC_TTS_voice_type[self.VC_TTS_voice_key]: - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]=self.VC_TTS_voice_type[self.VC_TTS_voice_key]["bot_id"] - if "workflow_id" in self.VC_TTS_voice_type[self.VC_TTS_voice_key]: - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]= self.VC_TTS_voice_type[self.VC_TTS_voice_key]["workflow_id"] - else: - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="" - if json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"] == "": - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"]=False - - keywords = []#热词 - for key in self.VC_TTS_voice_type: - keywords.append(key) - json_data["payload"]["inbound_attributes"]["cfg"]["keywords"] = keywords - elif dev_type == 'sjgq':#四季甘泉 - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7472201279826690111" - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="472203898494500914" + try: + if "vc_config" in globals() and vc_config: + p = vc_config.get_attr("DIALOG_PROVIDER_DEFAULT", None) + if p: + json_data["payload"]["dialog_attributes"]["provider"] = p + except Exception: + pass + + try: + if "vc_config" in globals() and vc_config and vc_config.get_bool("KEYWORDS_FROM_VOICE_TYPE", False): + keywords = [] + for key in self.VC_TTS_voice_type: + keywords.append(key) + json_data["payload"]["inbound_attributes"]["cfg"]["keywords"] = keywords + except Exception: pass - elif dev_type == 'szbst':#深圳百事通 - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7469964258592931852" - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7469968083063603241" - elif dev_type == 'jswm' or dev_type == 'jswm_BOX':#金三完美 - #json_data["payload"]["device_id"]= "WangQunTestID" - if self.VC_TTS_voice_type[self.VC_TTS_voice_key]["bot_id"] !="": - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]=self.VC_TTS_voice_type[self.VC_TTS_voice_key]["bot_id"] - if self.VC_TTS_voice_type[self.VC_TTS_voice_key]["workflow_id"] == "": - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["use_workflow"]=False - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]= "" - else: - json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]= self.VC_TTS_voice_type[self.VC_TTS_voice_key]["workflow_id"] - if self.VC_TTS_voice_type[self.VC_TTS_voice_key]["openai_option"] : - json_data["payload"]["dialog_attributes"]["cfg"]["openai_option"] =self.VC_TTS_voice_type[self.VC_TTS_voice_key]["openai_option"] - keywords = []#热词 - for key in self.VC_TTS_voice_type: - keywords.append(key) - json_data["payload"]["inbound_attributes"]["cfg"]["keywords"] = keywords if self.dialog_attributes_provider != None: json_data["payload"]["dialog_attributes"]["provider"] = self.dialog_attributes_provider if self.commands_mode !=0 : @@ -7043,7 +7253,10 @@ class AI_VC(Abstract): return print("kws_even_cb") if self.VC_mode == 1: - tts_str = "请您按住圆形的按钮开始讲话,讲完松开即可 " + try: + tts_str = vc_config.get_attr("KWS_PTT_HINT", "请您按住圆形的按钮开始讲话,讲完松开即可 ") + except Exception: + tts_str = "请您按住圆形的按钮开始讲话,讲完松开即可 " EventMesh.publish("play_tts",[tts_str,1]) return if self.VC_mode == 0: @@ -7054,15 +7267,7 @@ class AI_VC(Abstract): EventMesh.publish("stop_voice_record")#停止静默录音 self.aud.aud_tone_play(10,400) # EventMesh.publish("audio_montage_play",["chenggong.mp3"]) - if PRESS_AUDIO_MODE == 1: - if dev_type == "7PIN" or dev_type == "7PIN_1_5" : - # self.aud.aud_tone_play(10,200) - pass self.Close() - if PRESS_AUDIO_MODE == 0: - if dev_type == "7PIN" or dev_type == "7PIN_1_5": - pass - # self.chenggong_tone() # if dev_type == "7PIN" : # self.aud.aud_tone_play(10,400)#播放按键音 #self.aud.aud_tone_play(10,200)#播放按键音 @@ -7248,7 +7453,7 @@ class AI_VC(Abstract): self.AI_VC_send_data_queue.clear() if self.AI_ASR_send_data_queue.empty()!=True: self.AI_ASR_send_data_queue.clear() - EventMesh.publish("open_led_all") + EventMesh.publish("set_led_state", {"ai_state": "thinking"}) self.AI_ASR_send_buf_len = 0 self._uplink_request_stop("play_single_voice_cb") self.websocket_deconnect_VC() @@ -7294,7 +7499,7 @@ class AI_VC(Abstract): self.AI_VC_send_data_queue.clear() if self.AI_ASR_send_data_queue.empty()!=True: self.AI_ASR_send_data_queue.clear() - EventMesh.publish("open_led_all") + EventMesh.publish("set_led_state", {"ai_state": "thinking"}) self.AI_ASR_send_buf_len = 0 self._uplink_request_stop("play_new_voice_cb") self.websocket_deconnect_VC() @@ -7329,7 +7534,7 @@ class AI_VC(Abstract): self.AI_VC_send_data_queue.clear() if self.AI_ASR_send_data_queue.empty()!=True: self.AI_ASR_send_data_queue.clear() - EventMesh.publish("open_led_all") + EventMesh.publish("set_led_state", {"ai_state": "thinking"}) self.AI_ASR_send_buf_len = 0 self._uplink_request_stop("play_his_voice_cb") self.websocket_deconnect_VC() @@ -7367,7 +7572,7 @@ class AI_VC(Abstract): self.AI_VC_send_data_queue.clear() if self.AI_ASR_send_data_queue.empty()!=True: self.AI_ASR_send_data_queue.clear() - EventMesh.publish("open_led_all") + EventMesh.publish("set_led_state", {"ai_state": "thinking"}) self.AI_ASR_send_buf_len = 0 self._uplink_request_stop("play_wait_voice_cb") self.websocket_deconnect_VC() @@ -7409,7 +7614,7 @@ class AI_VC(Abstract): self.AI_VC_send_data_queue.clear() if self.AI_ASR_send_data_queue.empty()!=True: self.AI_ASR_send_data_queue.clear() - EventMesh.publish("open_led_all") + EventMesh.publish("set_led_state", {"ai_state": "thinking"}) self.AI_ASR_send_buf_len = 0 self._uplink_request_stop("play_music_cb") self.websocket_deconnect_VC() @@ -7433,7 +7638,7 @@ class AI_VC(Abstract): self.AI_VC_send_data_queue.clear() if self.AI_ASR_send_data_queue.empty()!=True: self.AI_ASR_send_data_queue.clear() - EventMesh.publish("open_led_all") + EventMesh.publish("set_led_state", {"ai_state": "thinking"}) self.AI_ASR_send_buf_len = 0 self._uplink_request_stop("play_trans_tts_cb") self.websocket_deconnect_VC() @@ -7625,9 +7830,18 @@ class AI_VC(Abstract): self._tts_pending_ms = 0 self._vc_session_started = 0 self._ptt_audio_created = 0 + # Power 短按停止对话后,再次按 AI 需要新建 dialog_id:清理本轮 dialog/session 标识 + try: + self._cur_dialog_id = "" + except Exception: + pass + try: + self._cur_sid = "" + except Exception: + pass self.is_ruppt_tts = 0#打断标志位清零 print("ai_VC Close1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - EventMesh.publish("close_led") + EventMesh.publish("set_led_state", {"ai_state": "idle"}) self.tts_in_data_len = 0 self.tts_out_data_len = 0 #必须先销毁线程,不然线程会容易报错 @@ -7683,7 +7897,7 @@ class AI_VC(Abstract): print("关闭但是没有重置语音标志位") self.AI_ASR_send_buf_len = 0 #self.AI_WS_connect_Queue.put(self.AI_client_VC) - EventMesh.publish("close_led") + EventMesh.publish("set_led_state", {"ai_state": "idle"}) self.VC_init() self.VC_satrt_flag = 0 # try: diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN/default_config.py new file mode 100644 index 00000000..456c5689 --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN/default_config.py @@ -0,0 +1,54 @@ +# 设备分支配置:7PIN +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "7PIN" + +LED_GPIO = ("GPIO36", "GPIO44", "GPIO43") # (R, G, B) +UART_SUPPORTED = False +LANG = "zh" + +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None +PIN_MOT_GPIO = None +AUDIO_QDAI_CFG = None + +EXTINT_AI_GPIO = "GPIO22" +PWK_KEY_GPIO = "GPIO26" + +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None +PIN_WAKEUP_BT_GPIO = None + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 5 +AI_LONG_PRESS_POWER_OFF_ENABLED = False + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "你好,我来了" +VAD_SILENCE_DEFAULT = 300 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = None + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/agent" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = False +UPLOAD_START_TONE_ENABLED = False +THINKING_LED_MODE = "flicker_blue_green" +VAD_ACTIVE_BLUE_LED = True +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" +BT_VOICE_FEATURES_ENABLED = False +POWEROFF_CMD_CLOSE_ONLY = True +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " +DIALOG_BOT_OPTION = None +DIALOG_PROVIDER_DEFAULT = None +KEYWORDS_FROM_VOICE_TYPE = False + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = "U:/static/start.mp3" +KEY_PRESS_TONE_DELAY_MS = 0 +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_1_5/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_1_5/default_config.py new file mode 100644 index 00000000..5a8b2341 --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_1_5/default_config.py @@ -0,0 +1,54 @@ +# 设备分支配置:7PIN_1_5 +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "7PIN_1_5" + +LED_GPIO = ("GPIO28", "GPIO44", "GPIO30") # (R, G, B) +UART_SUPPORTED = True +LANG = "zh" + +BT_POWER_MOTOR_ENABLED = True +PIN_BT_ON_GPIO = "GPIO31" +PIN_MOT_GPIO = "GPIO36" +AUDIO_QDAI_CFG = (1, 0, 0, 2, 0, 1, 1, 1) + +EXTINT_AI_GPIO = "GPIO43" +PWK_KEY_GPIO = "GPIO41" + +BT_WAKEUP_4G_ENABLED = True +EXTINT_WAKEUP_CTA1_GPIO = "GPIO22" +PIN_WAKEUP_BT_GPIO = "GPIO21" + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 5 +AI_LONG_PRESS_POWER_OFF_ENABLED = False + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "你好,我来了" +VAD_SILENCE_DEFAULT = 1000 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = None + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/agent" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = True +UPLOAD_START_TONE_ENABLED = False +THINKING_LED_MODE = "flicker_blue_green" +VAD_ACTIVE_BLUE_LED = True +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" +BT_VOICE_FEATURES_ENABLED = True +POWEROFF_CMD_CLOSE_ONLY = True +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " +DIALOG_BOT_OPTION = None +DIALOG_PROVIDER_DEFAULT = None +KEYWORDS_FROM_VOICE_TYPE = False + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = None +KEY_PRESS_TONE_DELAY_MS = 300 +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK/default_config.py new file mode 100644 index 00000000..01cd4cad --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK/default_config.py @@ -0,0 +1,53 @@ +# 设备分支配置:7PIN_BK +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "7PIN_BK" + +LED_GPIO = ("GPIO36", "GPIO21", "GPIO19") # (R, G, B) +UART_SUPPORTED = False +LANG = "zh" + +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None +PIN_MOT_GPIO = None +AUDIO_QDAI_CFG = None + +EXTINT_AI_GPIO = "GPIO22" +PWK_KEY_GPIO = "GPIO26" + +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None +PIN_WAKEUP_BT_GPIO = None + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 3 +AI_LONG_PRESS_POWER_OFF_ENABLED = False + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "-bot_name来了!我们一起来愉快地聊天吧!" +VAD_SILENCE_DEFAULT = 300 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = "ç«¥" + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/chat" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = False +UPLOAD_START_TONE_ENABLED = True +THINKING_LED_MODE = "open_red_green" +VAD_ACTIVE_BLUE_LED = False +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" +BT_VOICE_FEATURES_ENABLED = False +POWEROFF_CMD_CLOSE_ONLY = False +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " +DIALOG_BOT_OPTION = {"bot_id":"7411071327182438412","workflow_id":"7468577560454496295","use_workflow":True} +DIALOG_PROVIDER_DEFAULT = None +KEYWORDS_FROM_VOICE_TYPE = True + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = None +KEY_PRESS_TONE_DELAY_MS = 0 +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK_EU/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK_EU/default_config.py new file mode 100644 index 00000000..265ec69a --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK_EU/default_config.py @@ -0,0 +1,54 @@ +# 设备分支配置:7PIN_BK_EU +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "7PIN_BK_EU" + +LED_GPIO = ("GPIO36", "GPIO8", "GPIO19") # (R, G, B) +UART_SUPPORTED = False +LANG = "en" + +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None +PIN_MOT_GPIO = None +AUDIO_QDAI_CFG = None + +EXTINT_AI_GPIO = "GPIO5" +PWK_KEY_GPIO = "GPIO41" + +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None +PIN_WAKEUP_BT_GPIO = None + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 3 +AI_LONG_PRESS_POWER_OFF_ENABLED = False + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "Hi. May I help you ?" +VAD_SILENCE_DEFAULT = 300 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = "ç«¥" + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/chat" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = False +UPLOAD_START_TONE_ENABLED = True +THINKING_LED_MODE = "open_red_green" +VAD_ACTIVE_BLUE_LED = False +CMD_TOGGLE_MODE_TO_PTT_TTS = "change dialogue mode" +CMD_TOGGLE_MODE_TO_LONG_TTS = "pushtalk mode" +BT_VOICE_FEATURES_ENABLED = False +POWEROFF_CMD_CLOSE_ONLY = False +KWS_PTT_HINT = "Please press and hold the button to speak. " +DIALOG_BOT_OPTION = {"bot_id":"7493368740600446995","workflow_id":"7493369551587213323","use_workflow":True} +DIALOG_PROVIDER_DEFAULT = None +KEYWORDS_FROM_VOICE_TYPE = False + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = None +KEY_PRESS_TONE_DELAY_MS = 0 +PTT_HINT = "Please press and hold the button to speak. " + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK_coze/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK_coze/default_config.py new file mode 100644 index 00000000..b6671610 --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_BK_coze/default_config.py @@ -0,0 +1,53 @@ +# 设备分支配置:7PIN_BK_coze +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "7PIN_BK_coze" + +LED_GPIO = ("GPIO36", "GPIO21", "GPIO19") # (R, G, B) +UART_SUPPORTED = False +LANG = "zh" + +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None +PIN_MOT_GPIO = None +AUDIO_QDAI_CFG = None + +EXTINT_AI_GPIO = "GPIO22" +PWK_KEY_GPIO = "GPIO26" + +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None +PIN_WAKEUP_BT_GPIO = None + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 3 +AI_LONG_PRESS_POWER_OFF_ENABLED = False + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "-bot_name来了!我们一起来愉快地聊天吧!" +VAD_SILENCE_DEFAULT = 300 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = "ç«¥" + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/coze" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = False +UPLOAD_START_TONE_ENABLED = True +THINKING_LED_MODE = "open_red_green" +VAD_ACTIVE_BLUE_LED = False +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" +BT_VOICE_FEATURES_ENABLED = False +POWEROFF_CMD_CLOSE_ONLY = False +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " +DIALOG_BOT_OPTION = {"bot_id":"7411071327182438412","workflow_id":"7468577560454496295","use_workflow":True} +DIALOG_PROVIDER_DEFAULT = None +KEYWORDS_FROM_VOICE_TYPE = True + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = None +KEY_PRESS_TONE_DELAY_MS = 0 +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_coze/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_coze/default_config.py new file mode 100644 index 00000000..01639619 --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/7PIN_coze/default_config.py @@ -0,0 +1,54 @@ +# 设备分支配置:7PIN_coze +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "7PIN_coze" + +LED_GPIO = ("GPIO36", "GPIO44", "GPIO43") # (R, G, B) +UART_SUPPORTED = False +LANG = "zh" + +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None +PIN_MOT_GPIO = None +AUDIO_QDAI_CFG = None + +EXTINT_AI_GPIO = "GPIO22" +PWK_KEY_GPIO = "GPIO26" + +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None +PIN_WAKEUP_BT_GPIO = None + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 5 +AI_LONG_PRESS_POWER_OFF_ENABLED = False + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "你好,我来了" +VAD_SILENCE_DEFAULT = 1000 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = None + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/coze" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = False +UPLOAD_START_TONE_ENABLED = False +THINKING_LED_MODE = "flicker_blue_green" +VAD_ACTIVE_BLUE_LED = True +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" +BT_VOICE_FEATURES_ENABLED = False +POWEROFF_CMD_CLOSE_ONLY = True +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " +DIALOG_BOT_OPTION = {"bot_id":"7550138354483298347","workflow_id":"7549142130376671267","use_workflow":True} +DIALOG_PROVIDER_DEFAULT = "qipai" +KEYWORDS_FROM_VOICE_TYPE = False + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = None +KEY_PRESS_TONE_DELAY_MS = 0 +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/G10/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/G10/default_config.py new file mode 100644 index 00000000..81c9670c --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/G10/default_config.py @@ -0,0 +1,53 @@ +# 设备分支配置:G10 +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "G10" + +LED_GPIO = ("GPIO36", "GPIO44", "GPIO21") # (R, G, B) +UART_SUPPORTED = False +LANG = "zh" + +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None +PIN_MOT_GPIO = None +AUDIO_QDAI_CFG = None + +EXTINT_AI_GPIO = "GPIO19" +PWK_KEY_GPIO = "GPIO26" + +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None +PIN_WAKEUP_BT_GPIO = None + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 5 +AI_LONG_PRESS_POWER_OFF_ENABLED = False + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "已开机,您好!我是北科瑞讯智能 AI bot_name" +VAD_SILENCE_DEFAULT = 300 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = None + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/chat" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = False +UPLOAD_START_TONE_ENABLED = True +THINKING_LED_MODE = "open_red_green" +VAD_ACTIVE_BLUE_LED = False +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" +BT_VOICE_FEATURES_ENABLED = False +POWEROFF_CMD_CLOSE_ONLY = False +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " +DIALOG_BOT_OPTION = {"bot_id":"7411071327182438412","workflow_id":"7468577560454496295","use_workflow":True} +DIALOG_PROVIDER_DEFAULT = None +KEYWORDS_FROM_VOICE_TYPE = True + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = None +KEY_PRESS_TONE_DELAY_MS = 0 +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/README.md b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/README.md new file mode 100644 index 00000000..5a00599f --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/README.md @@ -0,0 +1,9 @@ +本目录用于**保留所有设备分支的配置文件**,供编译/打包阶段按参数选择。 + +运行时加载优先级仍然是: +- `usr/default_config.py`(或兼容误拼 `usr/defualt_config.py`) +- `core/default_config.py`(freeze 内置) + +这里的文件**默认不会被运行时 import**,也**不要求 freeze**;你可以在编译阶段把某个 +`configs//default_config.py` 复制为 `core/default_config.py` 来生效。 + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/csh/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/csh/default_config.py new file mode 100644 index 00000000..716c77c9 --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/csh/default_config.py @@ -0,0 +1,54 @@ +# 设备分支配置:csh +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "csh" + +LED_GPIO = ("GPIO36", "GPIO21", "GPIO19") # (R, G, B) +UART_SUPPORTED = False +LANG = "zh" + +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None +PIN_MOT_GPIO = None +AUDIO_QDAI_CFG = None + +EXTINT_AI_GPIO = "GPIO22" +PWK_KEY_GPIO = "GPIO26" + +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None +PIN_WAKEUP_BT_GPIO = None + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 5 +AI_LONG_PRESS_POWER_OFF_ENABLED = False + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "欢迎使用助手小福" +VAD_SILENCE_DEFAULT = 300 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = None + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/chat" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = False +UPLOAD_START_TONE_ENABLED = True +THINKING_LED_MODE = "open_red_green" +VAD_ACTIVE_BLUE_LED = False +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" +BT_VOICE_FEATURES_ENABLED = False +POWEROFF_CMD_CLOSE_ONLY = False +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " +DIALOG_BOT_OPTION = {"bot_id":"7490852493640384538","workflow_id":"","use_workflow":False} +DIALOG_PROVIDER_DEFAULT = None +KEYWORDS_FROM_VOICE_TYPE = False + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = None +KEY_PRESS_TONE_DELAY_MS = 0 +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/jswm/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/jswm/default_config.py new file mode 100644 index 00000000..6ff926c3 --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/jswm/default_config.py @@ -0,0 +1,53 @@ +# 设备分支配置:jswm +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "jswm" + +LED_GPIO = ("GPIO36", "GPIO44", "GPIO21") # (R, G, B) +UART_SUPPORTED = False +LANG = "zh" + +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None +PIN_MOT_GPIO = None +AUDIO_QDAI_CFG = None + +EXTINT_AI_GPIO = "GPIO26" +PWK_KEY_GPIO = "GPIO19" + +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None +PIN_WAKEUP_BT_GPIO = None + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 5 +AI_LONG_PRESS_POWER_OFF_ENABLED = True + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "我来陪你聊天了" +VAD_SILENCE_DEFAULT = 300 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = None + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/agent" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = False +UPLOAD_START_TONE_ENABLED = True +THINKING_LED_MODE = "open_red_green" +VAD_ACTIVE_BLUE_LED = False +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" +BT_VOICE_FEATURES_ENABLED = False +POWEROFF_CMD_CLOSE_ONLY = False +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " +DIALOG_BOT_OPTION = None +DIALOG_PROVIDER_DEFAULT = None +KEYWORDS_FROM_VOICE_TYPE = True + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = None +KEY_PRESS_TONE_DELAY_MS = 0 +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/jswm_BOX/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/jswm_BOX/default_config.py new file mode 100644 index 00000000..acd19569 --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/jswm_BOX/default_config.py @@ -0,0 +1,53 @@ +# 设备分支配置:jswm_BOX +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "jswm_BOX" + +LED_GPIO = ("GPIO36", "GPIO44", "GPIO21") # (R, G, B) +UART_SUPPORTED = False +LANG = "zh" + +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None +PIN_MOT_GPIO = None +AUDIO_QDAI_CFG = None + +EXTINT_AI_GPIO = "GPIO22" +PWK_KEY_GPIO = "GPIO26" + +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None +PIN_WAKEUP_BT_GPIO = None + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 5 +AI_LONG_PRESS_POWER_OFF_ENABLED = True + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "我来陪你聊天了" +VAD_SILENCE_DEFAULT = 300 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = None + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/agent" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = False +UPLOAD_START_TONE_ENABLED = True +THINKING_LED_MODE = "open_red_green" +VAD_ACTIVE_BLUE_LED = False +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" +BT_VOICE_FEATURES_ENABLED = False +POWEROFF_CMD_CLOSE_ONLY = False +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " +DIALOG_BOT_OPTION = None +DIALOG_PROVIDER_DEFAULT = None +KEYWORDS_FROM_VOICE_TYPE = True + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = None +KEY_PRESS_TONE_DELAY_MS = 0 +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/momo/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/momo/default_config.py new file mode 100644 index 00000000..4ef846b3 --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/momo/default_config.py @@ -0,0 +1,54 @@ +# 设备分支配置:momo +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "momo" + +LED_GPIO = ("GPIO36", "GPIO21", "GPIO19") # (R, G, B) +UART_SUPPORTED = False +LANG = "zh" + +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None +PIN_MOT_GPIO = None +AUDIO_QDAI_CFG = None + +EXTINT_AI_GPIO = "GPIO22" +PWK_KEY_GPIO = "GPIO26" + +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None +PIN_WAKEUP_BT_GPIO = None + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 5 +AI_LONG_PRESS_POWER_OFF_ENABLED = False + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "DuloDulo,我是上古神兽食梦貘,主人可以叫我momo,我来自《山海经》,是一只以梦为食的神秘灵兽,每当颜色朦胧、人们入睡时,我就会悄悄飞到人们的床头,用我长长的鼻子把噩梦统统吞噬掉,只留下甜甜的美梦。从今往后,就由我守护在主人身边,一起度过每一个星河璀璨的夜晚。" +VAD_SILENCE_DEFAULT = 300 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = "女" + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/chat" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = False +UPLOAD_START_TONE_ENABLED = True +THINKING_LED_MODE = "open_red_green" +VAD_ACTIVE_BLUE_LED = False +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" +BT_VOICE_FEATURES_ENABLED = False +POWEROFF_CMD_CLOSE_ONLY = False +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " +DIALOG_BOT_OPTION = {"bot_id":"7491256313561825332","workflow_id":"","use_workflow":False} +DIALOG_PROVIDER_DEFAULT = None +KEYWORDS_FROM_VOICE_TYPE = True + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = None +KEY_PRESS_TONE_DELAY_MS = 0 +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/sjgq/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/sjgq/default_config.py new file mode 100644 index 00000000..05dd4daf --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/sjgq/default_config.py @@ -0,0 +1,54 @@ +# 设备分支配置:sjgq +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "sjgq" + +LED_GPIO = ("GPIO36", "GPIO21", "GPIO19") # (R, G, B) +UART_SUPPORTED = False +LANG = "zh" + +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None +PIN_MOT_GPIO = None +AUDIO_QDAI_CFG = None + +EXTINT_AI_GPIO = "GPIO22" +PWK_KEY_GPIO = "GPIO26" + +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None +PIN_WAKEUP_BT_GPIO = None + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 5 +AI_LONG_PRESS_POWER_OFF_ENABLED = False + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "您好!我是巴马四季甘泉的智能助手。我可以为你解答各种各样的问题,像是有关巴马四季甘泉知识库、中基长寿科学产品、卫斯曼院士国际先进医疗中心的问题,还有日常生活与工作、旅游信息、健康咨询、教育与学习、情感交流、全球资讯、世界文化等方面的问题哦。你有没有这方面的问题想要问我呀?" +VAD_SILENCE_DEFAULT = 300 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = None + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/chat" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = False +UPLOAD_START_TONE_ENABLED = True +THINKING_LED_MODE = "open_red_green" +VAD_ACTIVE_BLUE_LED = False +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" +BT_VOICE_FEATURES_ENABLED = False +POWEROFF_CMD_CLOSE_ONLY = False +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " +DIALOG_BOT_OPTION = {"bot_id":"7472201279826690111","workflow_id":"472203898494500914","use_workflow":True} +DIALOG_PROVIDER_DEFAULT = None +KEYWORDS_FROM_VOICE_TYPE = False + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = None +KEY_PRESS_TONE_DELAY_MS = 0 +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/szbst/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/szbst/default_config.py new file mode 100644 index 00000000..83e79e6a --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/configs/szbst/default_config.py @@ -0,0 +1,54 @@ +# 设备分支配置:szbst +# 仅用于编译/打包阶段选择,不作为运行时加载入口。 + +DEV_TYPE = "szbst" + +LED_GPIO = ("GPIO36", "GPIO21", "GPIO19") # (R, G, B) +UART_SUPPORTED = False +LANG = "zh" + +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None +PIN_MOT_GPIO = None +AUDIO_QDAI_CFG = None + +EXTINT_AI_GPIO = "GPIO22" +PWK_KEY_GPIO = "GPIO26" + +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None +PIN_WAKEUP_BT_GPIO = None + +# ---- 按键/防抖差异 ---- +KEY_RELEASE_DEBOUNCE_COUNT = 5 +AI_LONG_PRESS_POWER_OFF_ENABLED = False + +# ---- 开机提示/语音参数默认值 ---- +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "深圳百事通来了!请问您有什么需要我帮忙的吗?" +VAD_SILENCE_DEFAULT = 300 +VC_TTS_VOICE_TYPE_DEFAULT = None +VC_TTS_VOICE_KEY_DEFAULT = None + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/chat" + +# 是否支持蓝牙 OTA +BT_OTA_ENABLED = False +UPLOAD_START_TONE_ENABLED = True +THINKING_LED_MODE = "open_red_green" +VAD_ACTIVE_BLUE_LED = False +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" +BT_VOICE_FEATURES_ENABLED = False +POWEROFF_CMD_CLOSE_ONLY = False +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " +DIALOG_BOT_OPTION = {"bot_id":"7469964258592931852","workflow_id":"7469968083063603241","use_workflow":True} +DIALOG_PROVIDER_DEFAULT = None +KEYWORDS_FROM_VOICE_TYPE = False + +# ---- 按键音/提示音策略 ---- +KEY_PRESS_TONE_FILE = None +KEY_PRESS_TONE_DELAY_MS = 0 +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/constants.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/constants.py index a3844a69..b905e290 100644 --- a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/constants.py +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/constants.py @@ -1,254 +1,274 @@ -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_ENV -# "beike" = 北科测试, "kxc" = 科学城demo -SERVER_ENV = "beike_dev" - -_SERVER_CFG = { - "beike": { - "dmp_base": "http://dmp.raisound.com/bz-api", - "amp_server": "115.190.94.208:22080", - "iot_ws_url": "ws://wsiot-nocdn.raisound.com/ws-hub/dev/v1", - }, - "kxc": { - "dmp_base": "http://kxc.raisound.com/bz-api", - "amp_server": "kxc.raisound.com/amp-api", - "iot_ws_url": "ws://kxc.raisound.com/iot-api/ws-hub/dev/v1", - }, - "beike_dev": { - "dmp_base": "http://dmp-dev.raisound.com/dmp-api", - "iot_ws_url": "ws://dmp-dev.raisound.com/iot-api/ws-hub/dev/v1", - "amp_server": "118.145.158.207:22080", - }, -} - -DMP_BASE = _SERVER_CFG[SERVER_ENV]["dmp_base"] -AMP_SERVER = _SERVER_CFG[SERVER_ENV]["amp_server"] -IOT_WS_URL = _SERVER_CFG[SERVER_ENV]["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" - +class PROTOCOL: + LK_SEND = "LK_SEND" + LK_RECV = "LK_RECV" + + PING_SEND = "PING_SEND" + PING_RECV = "PING_RECV" + + KA_SEND = "KA_SEND" + KA_RECV = "KA_RECV" + + UD_SEND = "UD_SEND" + UD_RECV = "UD_RECV" + + CR_SEND = "CR_SEND" + CR_RECV = "CR_RECV" + + AL_SEND = "AL_SEND" + AL_RECV = "AL_RECV" + + FIND_SEND = "FIND_SEND" + FIND_RECV = "FIND_RECV" + + POWEROFF_SEND = "POWEROFF_SEND" + POWEROFF_RECV = "POWEROFF_RECV" + + PHL_SEND = "PHL_SEND" + PHL_RECV = "PHL_RECV" + + TK_SEND = "TK_SEND" + TK_RECV = "TK_RECV" + + TKS_SEND = "TKS_SEND" + TKS_RECV = "TKS_RECV" + + MESSAGE_SEND = "MESSAGE_SEND" + MESSAGE_RECV = "MESSAGE_RECV" + + WT_SEND = "WT_SEND" + WT_RECV = "WT_RECV" + + REMIND_SEND = "REMIND_SEND" + REMIND_RECV = "REMIND_RECV" + + HRTSTART_SEND = "hrtstart_SEND" + HRTSTART_RECV = "hrtstart_RECV" + + HEART_SEND = "heart_SEND" + HEART_RECV = "heart_RECV" + + OXYGEN_SEND = "oxygen_SEND" + OXYGEN_RECV = "oxygen_RECV" + + OXSTART_SEND = "oxstart_SEND" + OXSTART_RECV = "oxstart_RECV" + + TEMP_SEND = "temp_SEND" + TEMP_RECV = "temp_RECV" + + DLT_SEND = "DLT_SEND" + DLT_RECV = "DLT_RECV" + + UPLOAD_SEND = "UPLOAD_SEND" + UPLOAD_RECV = "UPLOAD_RECV" + + CENTER_SEND = "CENTER_SEND" + CENTER_RECV = "CENTER_RECV" + + MONITOR_SEND = "MONITOR_SEND" + MONITOR_RECV = "MONITOR_RECV" + + SOS_SEND = "SOS_SEND" + SOS_RECV = "SOS_RECV" + + BOOTOFF_SEND = "BOOTOFF_SEND" + BOOTOFF_RECV = "BOOTOFF_RECV" + + WDSTART_SEND ="wdstart_SEND" + WDSTART_RECV ="wdstart_RECV" + + + LOWBAT_SEND = "LOWBAT_SEND" + LOWBAT_RECV = "LOWBAT_RECV" + + TIME_SEND = "Time_SEND" + TIME_RECV = "Time_RECV" + + WLKEY_SEND = "WLKEY_SEND" + WLKEY_RECV = "WLKEY_RECV" + + SILENCETIME2_SEND = "SILENCETIME2_SEND" + SILENCETIME2_RECV = "SILENCETIME2_RECV" + + KEYBRD_SEND = "KEYBRD_SEND" + KEYBRD_RECV = "KEYBRD_RECV" + + FALLDOWN_SEND = "FALLDOWN_SEND" + FALLDOWN_RECV = "FALLDOWN_RECV" + + HELP_SEND = "HELP_SEND" + HELP_RECV = "HELP_RECV" + + REMOVE_SEND = "REMOVE_SEND" + REMOVE_RECV = "REMOVE_RECV" + + BLOOD_SEND = "blood_SEND" + BLOOD_RECV = "blood_RECV" + + BLDSTART_SEND ="bldstart_SEND" + BLDSTART_RECV = "bldstart_RECV" + + BGSTART_SEND = "bgstart_SEND" + BGSTART_RECV = "bgstart_RECV" + + BLOODGLUSOCE_SEND = "bloodglucose_SEND" + BLOODGLUSOCE_RECV = "bloodglucose_RECV" + + REMIND_CH_DRINK_SEND = "REMIND_CH_DRINK_SEND" + REMIND_CH_DRINK_RECV = "REMIND_CH_DRINK_RECV" + + REMIND_CH_MEDICINE2_SEND = "REMIND_CH_MEDICINE2_SEND" + REMIND_CH_MEDICINE2_RECV = "REMIND_CH_MEDICINE2_RECV" + + REMIND_CH_HOME_SEND = "REMIND_CH_HOME_SEND" + REMIND_CH_HOME_RECV = "REMIND_CH_HOME_RECV" + + REMIND_CH_WAKEUP_SEND = "REMIND_CH_WAKEUP_SEND" + REMIND_CH_WAKEUP_RECV = "REMIND_CH_WAKEUP_RECV" + + REMIND_CH_SLEEP_SEND = "REMIND_CH_SLEEP_SEND" + REMIND_CH_SLEEP_RECV = "REMIND_CH_SLEEP_RECV" + + REMIND_CH_REST_SEND = "REMIND_CH_REST_SEND" + REMIND_CH_REST_RECV = "REMIND_CH_REST_RECV" + + SLEEP_DATA_SEND = "SleepReport_SEND" + SLEEP_DATA_RECV = "SleepReport_RECV" + + SLEEPTIME_SEND = "SLEEPTIME_SEND" + SLEEPTIME_RECV = "SLEEPTIME_RECV" + + FACTORY_SEND = "FACTORY_SEND" + FACTORY_RECV = "FACTORY_RECV" + + RESET_SEND = "RESET_SEND" + RESET_RECV = "RESET_RECV" + + REMIND_CH_SIT_SEND = "REMIND_CH_SIT_SEND" + REMIND_CH_SIT_RECV = "REMIND_CH_SIT_RECV" + + SCREEN_SHOW_SEND = "SCREEN_SHOW_SEND" + SCREEN_SHOW_RECV = "SCREEN_SHOW_RECV" + + JPREG_SEND = "JPREG_SEND" + JPREG_RECV = "JPREG_RECV" + + MEMBERS_SEND = "MEMBERS_SEND" + MEMBERS_RECV = "MEMBERS_RECV" + + CALLING_SEND = "CALLING_SEND" + CALLING_RECV = "CALLING_RECV" + + + RCALLING_SEND = "RCALLING_SEND" + RCALLING_RECV = "RCALLING_RECV" + + AGTALK_SEND = "AGTALK_SEND" + AGTALK_RECV = "AGTALK_RECV" + + RTALK_SEND = "RTALK_SEND" + RTALK_RECV = "RTALK_RECV" + + JMEMBERS_SEND = "JMEMBERS_SEND" + JMEMBERS_RECV = "JMEMBERS_RECV" + + RINGING_SEND = "RINGING_SEND" + RINGING_RECV = "RINGING_RECV" + + HANGUP_SEND = "HANGUP_SEND" + HANGUP_RECV = "HANGUP_RECV" + + CALLCANCEL_SEND ="CALLCANCEL_SEND" + CALLCANCEL_RECV = "CALLCANCEL_RECV" + + +# ---- Server/协议相关配置(统一从 default_srv.py 读取,usr 优先覆盖)---- +try: + import srv_config as _srv +except Exception: + _srv = None + +try: + import default_srv as _srv_default +except Exception: + _srv_default = None + +# 保留 _SERVER_CFG 变量名(兼容历史引用),来源为 default_srv.py(usr 优先覆盖) +try: + SERVER_ENV = "beike_dev" + if _srv: + SERVER_ENV = _srv.get_attr("SERVER_ENV", SERVER_ENV) or SERVER_ENV + elif _srv_default: + SERVER_ENV = getattr(_srv_default, "SERVER_ENV", SERVER_ENV) or SERVER_ENV +except Exception: + SERVER_ENV = "beike_dev" + +try: + if _srv: + DMP_BASE = _srv.get_addr("DMP_BASE", "") + AMP_SERVER = _srv.get_addr("AMP_SERVER", "") + IOT_WS_URL = _srv.get_addr("IOT_WS_URL", "") + else: + DMP_BASE = "" + AMP_SERVER = "" + IOT_WS_URL = "" + + # 兼容历史:提供与旧 _SERVER_CFG 相似的结构 + _SERVER_CFG = { + SERVER_ENV: { + "dmp_base": DMP_BASE, + "amp_server": AMP_SERVER, + "iot_ws_url": IOT_WS_URL, + } + } +except Exception: + # 保守兜底(若配置缺失,避免 import 阶段直接崩溃) + DMP_BASE = "" + AMP_SERVER = "" + IOT_WS_URL = "" + _SERVER_CFG = {SERVER_ENV: {"dmp_base": "", "amp_server": "", "iot_ws_url": ""}} + + +class EVENT: + CHANNEL_SOCKET_SEND = "CHANNEL_SOCKET_SEND" + START_LOCATION = "START_LOCATION" + START_LOCATION_TEST = "START_LOCATION_TEST" + READ_LOCATION = "READ_LOCATION" + CLOSE_LOCATION = "CLOSE_LOCATION" + GPSOPEN = "GPSOPEN" + GPSCLOSE = "GPSCLOSE" + GPSINFO = "GPSINFO" + WIFISCANOPEN = "WIFISCANOPEN" + WIFIINFO = "WIFIINFO" + + GET_KEY = "GET_KEY" + SET_KEY = "SET_KEY" + GET_IMEI = "GET_IMEI" + GET_CID = "GET_CID" + SET_CID = "SET_CID" + GET_IMSI = "GET_IMSI" + GET_PASSWORD = "GET_PASSWORD" + SET_PASSWORD = "SET_PASSWORD" + GET_BATTERY = "GET_BATTERY" + PERSISTENT_CONFIG_GET = "PERSISTENT_CONFIG_GET" + PERSISTENT_CONFIG_STORE = "PERSISTENT_CONFIG_STORE" + SET_PING = "SET_PING" + GET_PING = "GET_PING" + SET_CONNECT = "SET_CONNECT" + GET_CONNECT = "GET_CONNECT" + GET_STEP = "GET_STEP" + PUSH_STEP = "PUSH_STEP" + SYSTEM_SLEEP = "SYSTEM_SLEEP" + SYSTEM_UP = "SYSTEM_UP" + START_HEART = "START_HEART" + GET_HEART = "GET_HEART" + STOP_HEART = "STOP_HEART" + GET_WEAR = "GET_WEAR" + START_TEMP = "START_TEMP" + STOP_TEMP = "STOP_TEMP" + GET_TEMP = "GET_TEMP" + START_BLOOD_OXYGEN = "STARTT_BLOOD_OXYGEN" + GET_BLOOD_OXYGEN = "GET_BLOOD_OXYGEN" + STOP_BLOOD_OXYGEN = "STOP_BLOOD_OXYGEN" + CHANNEL_IOT_WEB_SEND = "CHANNEL_IOT_WEB_SEND" + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/default_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/default_config.py new file mode 100644 index 00000000..424c7b79 --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/default_config.py @@ -0,0 +1,128 @@ +# 设备侧默认配置(freeze 内置)。 +# +# 加载优先级(由 vc_config.py 执行): +# 1) usr/default_config.py(或 usr/defualt_config.py) +# 2) 本文件 default_config.py + +# 当前设备类型(编译期间确定;现场仅可用 usr/default_config.py 覆盖) +DEV_TYPE = "7PIN" + +# 当前设备配置(仅保留“设备差异项”,不要放运行态变量) +# led_gpio 使用 Pin 属性名(字符串),由 vc_config.py 转成 Pin.GPIOxx 常量。 +LED_GPIO = ("GPIO36", "GPIO44", "GPIO43") # (R, G, B) + +# LED 电平极性(是否“反向”点亮)。 +# - 默认 LED_ACTIVE_LOW=False:高电平点亮(write(1)=亮) +# - 若你的硬件是低电平点亮(write(0)=亮),将 LED_ACTIVE_LOW=True +# - 若仅某一路反相,用 LED_ACTIVE_LOW_RGB 单独配置(按 LED_GPIO 顺序 R/G/B) +LED_ACTIVE_LOW = False +LED_ACTIVE_LOW_RGB = None # 例如 (True, False, False) 表示仅红灯反相 +# LED_ACTIVE_LOW_RGB = (True, False, False) + +# 是否支持 UART 相关能力(例如 7PIN_1_5 才允许走串口) +UART_SUPPORTED = False + +# 语言/地区(如 zh/en),用于少量文案/逻辑差异 +LANG = "zh" + +# -------------------- +# 硬件差异项(由每个设备的 default_config 固定) +# -------------------- +LED_DEBUG = True +KEY_LED_DEBUG = True +HW_STATUS_DEBUG = True + +# 是否需要初始化蓝牙电源/马达/音频IIS配置等(原先仅 7PIN_1_5) +BT_POWER_MOTOR_ENABLED = False +PIN_BT_ON_GPIO = None # 例如 "GPIO31" +PIN_MOT_GPIO = None # 例如 "GPIO36" + +# audio.set_qdai_cfg(...) 参数;若为 None 则不调用 +AUDIO_QDAI_CFG = None # 例如 (1,0,0,2,0,1,1,1) + +# AI 按键中断与电源键中断引脚(ExtInt.GPIOxx) +EXTINT_AI_GPIO = "GPIO22" +PWK_KEY_GPIO = "GPIO26" + +# 蓝牙唤醒 4G/4G 唤醒蓝牙相关(原先仅 7PIN_1_5) +BT_WAKEUP_4G_ENABLED = False +EXTINT_WAKEUP_CTA1_GPIO = None # 例如 "GPIO22" +PIN_WAKEUP_BT_GPIO = None # 例如 "GPIO21" + +# -------------------- +# 按键/防抖差异 +# -------------------- + +# 释放防抖阈值(KeyAI/pwk):原代码部分设备用 3,其他用 5 +KEY_RELEASE_DEBOUNCE_COUNT = 5 + +# 是否允许 AI 键长按 8 秒触发关机逻辑(原 jswm/jswm_BOX) +AI_LONG_PRESS_POWER_OFF_ENABLED = False + +# -------------------- +# 开机提示/语音参数默认值(与具体产品绑定,编译期决定) +# -------------------- + +# 若为 None 或 POWER_ON_TONE_ENABLED=False,则不开机播报提示词 +POWER_ON_TONE_ENABLED = True +POWER_ON_TONE_DEFAULT = "你好,我来了" + +# VAD 静音阈值默认值(ms) +VAD_SILENCE_DEFAULT = 300 + +# 默认音色配置(与 ai_VC.py 中格式保持一致) +VC_TTS_VOICE_TYPE_DEFAULT = None # dict 或 None(None 表示沿用 ai_VC.py 内置兜底/存储值) +VC_TTS_VOICE_KEY_DEFAULT = None # 例如 "男"/"ç«¥" + +# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...) +VC_WS_PATH = "vc/agent" + +# 是否支持蓝牙 OTA(原先仅 7PIN_1_5 会检查 bt_ota) +BT_OTA_ENABLED = False + +# 是否在“开始上传语音”时播放成功提示音(原逻辑:非 7PIN/7PIN_1_5/7PIN_coze 才播) +UPLOAD_START_TONE_ENABLED = False + +# LLM thinking 阶段 LED 策略:flicker_blue_green / open_red_green +THINKING_LED_MODE = "flicker_blue_green" + +# 收到 vad.active 时是否强制切回蓝灯 +VAD_ACTIVE_BLUE_LED = True + +# 本地指令:切换对话模式时的提示语(是什么语言就写什么) +CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式" +CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式" + +# 蓝牙/语音留言类本地指令是否启用(原先仅 7PIN_1_5) +BT_VOICE_FEATURES_ENABLED = False + +# “关机”语音指令是否仅关闭对话(不触发 Power_off)。原逻辑:7PIN/7PIN_coze/7PIN_1_5 只 Close +POWEROFF_CMD_CLOSE_ONLY = True + +# 关键词唤醒时在 PTT 模式下播报的提示语 +KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " + +# 对话智能体/工作流默认配置(编译期确定;可在 usr/default_config.py 覆盖) +# 结构示例: +# DIALOG_BOT_OPTION = {"bot_id":"...", "workflow_id":"...", "use_workflow":True} +DIALOG_BOT_OPTION = None + +# dialog_attributes.provider 覆盖(None 表示沿用存储配置 dialog_attributes_provider) +DIALOG_PROVIDER_DEFAULT = None + +# 是否从 VC_TTS_voice_type 的 key 列表生成 ASR 热词 +KEYWORDS_FROM_VOICE_TYPE = False + +# -------------------- +# 按键音/提示音策略(设备差异项) +# -------------------- + +# AI 键按下时:若设置了该文件路径,则在“无 VC 流播放中”时播放该提示音(例如 7PIN 用 start.mp3) +KEY_PRESS_TONE_FILE = None # 例如 "U:/static/start.mp3" + +# AI 键按下时:延迟播放按键音(ms),用于规避蓝牙连接瞬间不出声等问题(例如 7PIN_1_5 取 300) +KEY_PRESS_TONE_DELAY_MS = 0 + +# PTT 提示语(单对话模式,未长按时的提示;是什么语言就写什么) +PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 " + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/default_srv.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/default_srv.py new file mode 100644 index 00000000..5ae3122e --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/default_srv.py @@ -0,0 +1,34 @@ +# 设备侧 Server 配置(freeze 内置)。 +# +# 注意: +# - `constants.py` 中固定不变的常量(事件名/枚举)继续保留在 constants.py。 +# - 本文件统一承载“协议/服务器相关的可配置项”,并支持 usr 覆盖。 + +# ---- 环境选择(服务器地址由 srv_configs/.py 承载)---- +# 服务器环境配置,切换只需修改 SERVER_ENV +# "beike" = 北科测试, "kxc" = 科学城demo +SERVER_ENV = "beike_dev" + +# ---- 默认环境地址(即使没有 srv_configs/.py 也能工作)---- +# 这里默认给出 beike_dev 的地址;若要切换环境,建议: +# - 修改 SERVER_ENV +# - 同时提供对应的 srv_configs/.py(或 usr 覆盖) +DMP_BASE = "http://dmp-dev.raisound.com/dmp-api" +AMP_SERVER = "118.145.158.207:22080" +IOT_WS_URL = "ws://dmp-dev.raisound.com/iot-api/ws-hub/dev/v1" + +# ---- DMP/认证/时间同步等(默认使用 constants.DMP_BASE 拼接)---- +DMP_TIME_PATH = "/dev/time" +DMP_ACTIVE_PATH = "/dev/auth/active" +DMP_SIGN_IN_PATH = "/dev/auth/sign_in" +DMP_TOKEN_PATH = "/dev/auth/token" +DMP_ICCID_PATH = "/dev/iccid" +DMP_DEV_CONFIG_PATH_FMT = "/dev/config/{}" # deviceId + +# ---- OTA(现网有的走 DMP_BASE,有的走 qipai 域名;先集中成可配项)---- +OTA_TASK_URL_FMT = "https://dmp-api.qipai.com/qp-dmp-api/ota/task?deviceId={}&sourceVersion={}" +OTA_RESULT_PATH_FMT = "/ota/result?deviceId={}¤tVersion={}" + +# ---- AMP/健康检查等 ---- +AMP_HEALTH_URL_FMT = "http://{}/health?task_id={}" + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/main_init.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/main_init.py index df2d8474..962d7e97 100644 --- a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/main_init.py +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/main_init.py @@ -176,6 +176,11 @@ def main_init(): app.append_manager(_ai.AI_led()) except Exception as e: usys.print_exception(e) + # 精简硬件状态采集(替代 mgr):输出 charging/battery/signal → set_led_state + try: + app.append_manager(_ai.AI_hw_status()) + except Exception as e: + usys.print_exception(e) try: app.append_manager(_ai.AI_dev()) except Exception as e: diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/protocol.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/protocol.py index 8a2aa1fb..4b898448 100644 --- a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/protocol.py +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/protocol.py @@ -4280,43 +4280,6 @@ class IOTWeb_disconnect_btProtoCol(ProtoCol): EventMesh.publish("send_disconnect_bt_mac",mac) print("recv disconnect_bt{}".format(msg)) EventMesh.publish(WEB_CMD_ENUM.DISCONNECT_BT_S) -class IOTWeb_get_chat_configProtoCol(ProtoCol): - """get_chat_config""" - TYPE = "get_chat_config" - - def send(self, event, msg): - # print("send get_chat_config{}".format(msg)) - # 通过websocket发送到服务器端 - date_tmp = utime.localtime() - time_tmp = utime.mktime(date_tmp) - get_chat_config = { - "cmd":"get_chat_config", - "ts":time_tmp, - "msg":"获取AI对话配置", - "data":None - } - send_data = b'' - send_data = protocol_send_total_data(get_chat_config) - print("send_data get_chat_config{}".format(send_data)) - EventMesh.publish("CHANNEL_IOT_WEB_SEND", send_data) - - def recv(self, event, msg): - """ - - @param event:上行下发get_chat_config - @param msg: 接收到的下行数据 - """ - # { - # "cmd":"post_rest", - # "ts":1738283829, - # "msg":"消息收到响应", - # "data":{ - # "cmd":"get_chat_config", - # "rest":"success|error", - # "msg":"收到获取AI对话配置请求" - # } - # } - print("RECV get_chat_config{}".format(msg)) #IOT金三 #接收小程序控制查找设备 class IOTWeb_find_deviceProtoCol(ProtoCol): @@ -4420,36 +4383,6 @@ class IOTWeb_switch_volumeProtoCol(ProtoCol): print("音量修改为:{}".format(volume-100)) EventMesh.publish("change_volume",volume) -#接收小程序控制设置音量 -class IOTWeb_switch_volumeProtoCol(ProtoCol): - """switch_volume""" - TYPE = "switch_volume" - - def send(self, event, msg): - # print("c{}".format(msg)) - # 通过websocket发送到服务器端 - date_tmp = utime.localtime() - time_tmp = utime.mktime(date_tmp) - come_trans = { - "msg": "设置音量", - "data": None, - "cmd": "switch_volume", - "ts": time_tmp - } - send_data = b'' - send_data = protocol_send_total_data(come_trans) - print("send_data switch_volume{}".format(send_data)) - EventMesh.publish("CHANNEL_IOT_WEB_SEND", send_data) - - def recv(self, event, msg): - """ - @param event:switch_volume - @param msg: 接收到的下行数据 - """ - volume = int(msg["data"]["target"]) + 100 - print("音量修改为:{}".format(volume-100)) - EventMesh.publish("change_volume",volume) - class LK_ProtoCol(ProtoCol): """链路保持""" TYPE = "LK" diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_config.py new file mode 100644 index 00000000..953ff027 --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_config.py @@ -0,0 +1,44 @@ +# Server 配置加载器: +# - 优先 usr/default_srv.py(或兼容误拼 usr/defualt_srv.py) +# - 否则使用 freeze 内置 default_srv.py + +def _try_import(name): + try: + return __import__(name) + except Exception: + return None + + +# 只做“优先 import usr 下文件;失败再 import 默认文件”,不做变量覆盖/合并 +_DEFAULT_SRV_MODULE = None +_DEFAULT_SRV_LOADED = 0 + + +def load_default_srv_module(): + global _DEFAULT_SRV_MODULE, _DEFAULT_SRV_LOADED + if _DEFAULT_SRV_LOADED: + return _DEFAULT_SRV_MODULE + _DEFAULT_SRV_LOADED = 1 + _DEFAULT_SRV_MODULE = ( + _try_import("usr.default_srv") + or _try_import("usr.defualt_srv") + or _try_import("default_srv") + ) + return _DEFAULT_SRV_MODULE + + +def get_attr(name, default=None): + m = load_default_srv_module() + try: + if m and hasattr(m, name): + return getattr(m, name) + except Exception: + return default + return default + + +def get_addr(name, default=None): + # 运行时只从 default_srv.py 读取地址(usr 优先覆盖)。 + # srv_configs/.py 仅保留给编译期选择/拷贝使用,不参与运行时 import。 + return get_attr(name, default) + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/README.md b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/README.md new file mode 100644 index 00000000..335adb7d --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/README.md @@ -0,0 +1,18 @@ +本目录用于**服务器环境地址配置**,按 `SERVER_ENV` 分类管理。 + +示例: +- `beike.py`:北科测试 +- `kxc.py`:科学城 demo +- `beike_dev.py`:北科开发环境 + +每个环境文件需要导出以下常量: +- `DMP_BASE` +- `AMP_SERVER` +- `IOT_WS_URL` + +本目录文件**不参与运行时加载**,仅用于编译期选择/拷贝。 + +运行时的优先级固定为: +1) `usr/default_srv.py`(或兼容误拼 `usr/defualt_srv.py`) +2) freeze 内置 `core/default_srv.py` + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/beike.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/beike.py new file mode 100644 index 00000000..1852494b --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/beike.py @@ -0,0 +1,6 @@ +# SERVER_ENV = beike(北科测试) + +DMP_BASE = "http://dmp.raisound.com/bz-api" +AMP_SERVER = "115.190.94.208:22080" +IOT_WS_URL = "ws://wsiot-nocdn.raisound.com/ws-hub/dev/v1" + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/beike_dev.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/beike_dev.py new file mode 100644 index 00000000..a6a8d2fb --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/beike_dev.py @@ -0,0 +1,6 @@ +# SERVER_ENV = beike_dev(北科开发环境) + +DMP_BASE = "http://dmp-dev.raisound.com/dmp-api" +AMP_SERVER = "118.145.158.207:22080" +IOT_WS_URL = "ws://dmp-dev.raisound.com/iot-api/ws-hub/dev/v1" + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/dev_type_url_backup.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/dev_type_url_backup.py new file mode 100644 index 00000000..f16a5650 --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/dev_type_url_backup.py @@ -0,0 +1,15 @@ +# dev_type 维度的“网络地址/接口域名”历史备份。 +# +# 说明: +# - 这些内容来源于 ai_VC.py 里注释掉的 dev_type 分支(仅做备份/编译期参考)。 +# - 运行时不加载本文件;实际运行时由 default_srv.py(可被 usr/default_srv.py 覆盖)决定 DMP_BASE 等。 + +# OTA task 接口(旧逻辑里按 dev_type 走不同域名) +OTA_TASK_URL_BY_DEV_TYPE = { + # 英文小瑞 + "7PIN_BK_EU": "http://dmp-global.raisound.com/bz-api/ota/task?deviceId={deviceId}&sourceVersion={sourceVersion}", + # 柒牌(coze 与非 coze 共用) + "7PIN": "http://ota.qipai.com/bz-cmp-api/api/task?deviceId={deviceId}&sourceVersion={sourceVersion}", + "7PIN_coze": "http://ota.qipai.com/bz-cmp-api/api/task?deviceId={deviceId}&sourceVersion={sourceVersion}", +} + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/kxc.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/kxc.py new file mode 100644 index 00000000..5c21635f --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/srv_configs/kxc.py @@ -0,0 +1,6 @@ +# SERVER_ENV = kxc(科学城 demo) + +DMP_BASE = "http://kxc.raisound.com/bz-api" +AMP_SERVER = "kxc.raisound.com/amp-api" +IOT_WS_URL = "ws://kxc.raisound.com/iot-api/ws-hub/dev/v1" + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/usr/ai_VC.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/usr/ai_VC.py deleted file mode 100644 index d0f3bb7d..00000000 --- a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/usr/ai_VC.py +++ /dev/null @@ -1,2175 +0,0 @@ -from common import Abstract, LogAdapter -import EventMesh -import uwebsocket -import usys -import gc -import urandom -import uhashlib -import ubinascii -import ujson -import osTimer -import _thread -from queue import Queue -import utime -import audio -import uos -from machine import Pin -from machine import ExtInt -from machine import WDT -import modem -import sim -import net -import base64 -import ucryptolib -import urandom as random -import request -import ql_fs -from misc import Power,USB,PowerKey -import ntptime -import machine -class AI_led(Abstract): - def __init__(self): - self.led_red = Pin(Pin.GPIO36, Pin.OUT, Pin.PULL_PD, 0) - self.led_green = Pin(Pin.GPIO21, Pin.OUT, Pin.PULL_PD, 1) - self.led_white = Pin(Pin.GPIO19, Pin.OUT, Pin.PULL_PD, 1) - EventMesh.subscribe("open_led_red",self.open_led_red) - EventMesh.subscribe("open_led_white",self.open_led_white) - EventMesh.subscribe("open_led_green",self.open_led_green) - EventMesh.subscribe("open_led_all",self.open_led_all) - EventMesh.subscribe("close_led",self.close_led) - EventMesh.publish("open_led_red") - def open_led_red(self,event,msg): - print("open_led_red") - #self.led_red.write(0) - self.led_white.write(0) - self.led_green.write(0) - self.led_red.write(1) - - def open_led_white(self,event,msg): - print("open_led_white") - self.led_red.write(0) - #self.led_white.write(0) - self.led_green.write(0) - self.led_white.write(1) - - def open_led_green(self,event,msg): - print("open_led_green") - self.led_red.write(0) - self.led_white.write(0) - #self.led_green.write(0) - self.led_green.write(1) - - def open_led_all(self,event,msg): - print("open_led_all") - #self.led_red.write(0) - self.led_white.write(1) - self.led_green.write(1) - self.led_red.write(1) - - def close_led(self,event,msg): - print("close_led") - self.led_red.write(0) - self.led_white.write(0) - self.led_green.write(0) -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'] - -class AI_dev(Abstract): - # AI - def __init__(self): - self.VBATT_tab = {"charge_full":4300,100 :4250 , 90:3994 , 80:3883, 60: 3707, 40:3604, 20:3537, 10:3486,} - self.KeyAI_status = 0 - self.KeyAI_timer_count = 0 - self.KeyAI_long_press = 0 - self.KeyAI_press = 0 - self.KeyAI_timer = osTimer() - #self.extint_AI = ExtInt(ExtInt.GPIO19,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb) - self.extint_AI = ExtInt(ExtInt.GPIO22,ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.keyAI_extint_cb) - self.extint_AI.enable() - self.pwk_key_status = 0 - self.pwk_key_timer_count = 0 - self.pwk_key_long_press = 0 - self.pwk_key_press = 0 - self.pwk_key_timer = osTimer() - #self.pwk_key = ExtInt(ExtInt.GPIO26, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_DISABLE, self.pwk_extint_cb) - self.pwk_key = ExtInt(ExtInt.GPIO41, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.pwk_extint_cb) - self.pwk_key.enable() - self.btnInfo_queue = Queue() - _thread.stack_size(10*1024) - _thread.start_new_thread(self.btnInfo_queue_thread, ()) - _thread.stack_size(8*1024) - EventMesh.subscribe("publish_AI_btnInfo",self.publish_AI_btnInfo) - EventMesh.subscribe("get_battery",self.get_battery) - EventMesh.subscribe("audio_montage_play",self.audio_montage_play) - EventMesh.subscribe("paly_iccid_imei",self.paly_iccid_imei) - EventMesh.subscribe("paly_device_res_error",self.paly_device_res_error) - - self.wdt = WDT(30) #开启看门狗 - # self.wdt_timer = osTimer() - # self.wdt_timer.start(10000, 1, self.wdt_timer_cb) - self.pk = PowerKey() - self.pk.powerKeyEventRegister(self.powerKey_callback) - self.usb = USB() - self.usb.setCallback(self.usb_event_cb) - self.usb_status = self.usb.getStatus() - self.usb_charge_flag = 0 - self.AI_dev_timer = osTimer() - self.AI_dev_timer.start(10000, 1, self.AI_dev_timer_cb) - self.aud = audio.Audio(0) - self.VC_TTS_volume = EventMesh.publish("get_storage_config","VC_TTS_volume")#音量配置 - if self.VC_TTS_volume == None: - self.VC_TTS_volume = 100 - self.aud.setVolume(self.VC_TTS_volume //10) - #self.aud.play(1,0,'U:/static/xianyikaiji.mp3')#开机音频 - #EventMesh.publish("audio_montage_play",["xianyikaiji.mp3"]) - #EventMesh.publish("publish_AI_btnInfo",{"func":self.ntptime_cb}) - def ntptime_cb(self): - #ntptime.settime(8) - print("timer:{}!!!!!!!!\r\n".format(utime.localtime())) - def usb_event_cb(self, state): - EventMesh.publish("publish_AI_btnInfo",{"func":self.usb_event,"data":state}) - def usb_event(self, state): - status = state - self.usb_charge_flag = 0 - if status == 1:#插入USB - print("charge R_CHARGE_in") - self.usb_status = 1 - self.aud.stop() - #self.aud.play(1,1,'U:/static/R_CHARGE_IN.mp3') - EventMesh.publish("audio_montage_play",["R_CHARGE_IN.mp3"]) - pass - elif status == 0:#拨出usbs - self.usb_status = 0 - self.aud.stop() - EventMesh.publish("audio_montage_play",["R_CHARGE_OUT.mp3"]) - #self.aud.play(1,1,'U:/static/R_CHARGE_OUT.mp3') - def btnInfo_queue_thread(self): - while True: - data = self.btnInfo_queue.get() - #EventMesh.debug_log("Info_queue:data = {}".format(data)) - if data != None: - try: - if "data" in data : - data["func"](data["data"]) - else : - data["func"]() - except Exception as e: - #EventMesh.debug_log("btnInfo_queue:ERROR:{}".format(e)) - usys.print_exception(e) - def publish_AI_btnInfo(self,event,msg): - self.btnInfo_queue.put(msg) - def powerKey_callback(self, status): - print("powerKey_callback:{}".format(status)) - - def pwk_extint_cb(self,args):#pwk - try: - self.pwk_key_status = int(args[1]) - if self.pwk_key_status == 0: - self.pwk_key_status = 1 - else: - self.pwk_key_status = 0 - pass - if self.pwk_key_status == 0:#按下 - if self.pwk_key_press == 0 : - self.pwk_key.disable() - self.pwk_key_press = 1 - self.pwk_key_long_press = 0 - self.pwk_key_timer.start(100, 1, self.pwk_key_timer_cb) - self.pwk_key_timer_count = 0 - #EventMesh.publish("AI_key_press") - - except Exception as e: - usys.print_exception(e) - def pwk_key_timer_cb(self, *args, **kwargs): - try: - self.pwk_key_status = self.pwk_key.read_level() - self.pwk_key_timer_count +=1 - if self.pwk_key_timer_count >= 10*3: #长按3s - #print("pwk_key_long_press {}".format(self.pwk_key_long_press)) - if self.pwk_key_long_press == 0: - self.pwk_key_long_press = 1 - #EventMesh.publish("AI_key_long_press") - 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)) - if self.pwk_key_timer_count >= 5: #防抖200ms - #EventMesh.publish("AI_key_release") - EventMesh.publish("publish_AI_btnInfo",{"func":self.pwk_key_release}) - self.pwk_key.enable() - self.pwk_key_timer.stop() - self.pwk_key_timer_count = 0 - self.pwk_key_press = 0 - - except Exception as e: - usys.print_exception(e) - - def keyAI_extint_cb(self,args):#call 2 - try: - #print("AI_btn:keyAI_extint_cb{}".format(args[1])) - self.KeyAI_status = int(args[1]) - if self.KeyAI_status == 0: - self.KeyAI_status = 1 - else: - self.KeyAI_status = 0 - - if self.KeyAI_status == 0:#按下 - if self.KeyAI_press == 0 : - self.extint_AI.disable() - self.KeyAI_press = 1 - self.KeyAI_long_press = 0 - self.KeyAI_timer.start(100, 1, self.KeyAI_timer_cb) - self.KeyAI_timer_count = 0 - #EventMesh.publish("AI_key_press") - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_key_press}) - except Exception as e: - usys.print_exception(e) - def KeyAI_timer_cb(self, *args, **kwargs): - try: - self.KeyAI_status = self.extint_AI.read_level() - self.KeyAI_timer_count +=1 - if self.KeyAI_timer_count >= 10*1: #长按3s - if self.KeyAI_long_press == 0: - self.KeyAI_long_press = 1 - #EventMesh.publish("AI_key_long_press") - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_key_long_press}) - if self.KeyAI_status == 1:#松开 - #print("KeyAI_timer_cb:{}".format(self.KeyAI_timer_count)) - if self.KeyAI_timer_count >= 5: #防抖200ms - #EventMesh.publish("AI_key_release") - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_key_release}) - self.extint_AI.enable() - self.KeyAI_timer.stop() - self.KeyAI_timer_count = 0 - self.KeyAI_press = 0 - - except Exception as e: - usys.print_exception(e) - - def AI_key_press(self): - #print("AI_key_press") - EventMesh.publish("AI_key_press") - def AI_key_long_press(self): - #print("AI_key_long_press") - EventMesh.publish("AI_key_long_press") - - def AI_key_release(self): - #print("AI_key_release") - EventMesh.publish("AI_key_release") - def pwk_key_Long_Press(self): - print("pwk_key_long_press!!!!!!!") - print("pwk_key_long_press!!!!!!!") - - # EventMesh.publish("paly_iccid_imei") - # return - EventMesh.publish("audio_montage_play",["zhengzaiguanji.mp3"]) - #self.aud.play(1,0,'U:/static/zhengzaiguanji.mp3')#关机音频 - EventMesh.publish("open_led_red") - utime.sleep_ms(3000) - Power.powerDown() - #print("AI_key_release") - EventMesh.publish("pwk_key_long_press") - - def pwk_key_release(self): - #print("pwk_key_release") - EventMesh.publish("pwk_key_release") - - def AI_dev_timer_cb(self, *args, **kwargs): - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_dev_timer_event}) - def AI_dev_timer_event(self): - self.wdt.feed() - Vbatt = Power.getVbatt() - if self.usb_charge_flag == 0 and self.usb_status == 1 and Vbatt>=self.VBATT_tab["charge_full"]:#充电充满 - 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_charge_flag == 0 and self.usb_status == 0 and Vbattself.VBATT_tab[90]: - return 100 - if Vbatt>self.VBATT_tab[80]: - return 90 - if Vbatt>self.VBATT_tab[60]: - return 80 - if Vbatt>self.VBATT_tab[40]: - return 60 - if Vbatt>self.VBATT_tab[20]: - return 40 - if Vbatt>self.VBATT_tab[10]: - return 20 - if Vbatt<=self.VBATT_tab[10]: - return 10 - def audio_montage_play(self,event,msg): - self.aud.stopPlayStream() - str_data='mp3files=' - for i in msg: - try: - str_tmp = i.replace(".mp3","") - str_data+="{}.mp3+".format(audio_buf.index(str_tmp)) - except Exception as e: - usys.print_exception(e) - str_data = str_data[:-1] - print("audio_montage_play:{}".format(str_data)) - self.aud.montage_play('U:/static/audio.bin',1,1,str_data) - def paly_iccid_imei(self,event,msg): - str_data = 'mp3files={}.mp3+'.format(audio_buf.index("liuliangtishi"))#流量提示 - imei = modem.getDevImei() - iccid = sim.getIccid() - if iccid != -1 and len(iccid) > 5: - 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]))\ - ,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])),\ - 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])),\ - 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])),\ - 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]))) - str_data += '{}.mp3+'.format(audio_buf.index("IMEIhao"))#IMEI号为: - 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]))\ - ,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])),\ - 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])),\ - 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])),\ - 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]))) - #print("str_data:{}".format(str_data)) - self.aud.montage_play('U:/static/audio.bin',1,1,str_data) - #鉴权出错,播放imei号 - def paly_device_res_error(self,event,msg): - str_data = 'mp3files={}.mp3+'.format(audio_buf.index("jianquancuowu"))#AI功能异常,请联系客户查询,设备号为: - imei = modem.getDevImei() - 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]))\ - ,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])),\ - 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])),\ - 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])),\ - 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]))) - #print("str_data:{}".format(str_data)) - self.aud.montage_play('U:/static/audio.bin',1,1,str_data) -#存储信息 -class getStorageDataManager(Abstract):#获取内存数据 - def __init__(self): - self.config_data = {} - check = ql_fs.path_exists("/usr/static/storage_file/config.json") - if check == True: - with open("/usr/static/storage_file/config.json","r") as fd: - self.config_data = ujson.load(fd) - else : - self.config_data = {'old_time': 0, 'flip_sw': 0} - pass - - def post_processor_after_instantiation(self): - EventMesh.subscribe("set_storage_data", self.set_storage_data) - EventMesh.subscribe("set_storage_config", self.set_storage_config) - EventMesh.subscribe("get_storage_data", self.get_storage_data) - EventMesh.subscribe("get_storage_config", self.get_storage_config) - - def set_storage_data(self, event, msg): - # EventMesh.debug_log("set_storage_data:{}".format(msg)) - if msg != None: - self.config_data = msg - with open("/usr/static/storage_file/config.json",'w+',encoding="utf-8") as fd: - ujson.dump(self.config_data,fd) - - - def set_storage_config(self,event,msg): - # EventMesh.debug_log("set_storage_key_data1:{}".format(msg)) - if len(msg) >= 2: - self.config_data[msg[0]]=msg[1] - # EventMesh.debug_log("set_storage_key_data2:{}".format(self.config_data[msg[0]])) - EventMesh.publish("publish_message_event_ui",{"func":self.set_storage_save,"data":0}) - def set_storage_save(self, data): - with open("/usr/static/storage_file/config.json",'w+',encoding="utf-8") as fd: - ujson.dump(self.config_data,fd) - def get_storage_data(self, event, msg): - # EventMesh.debug_log("get_storage_data:{}".format(self.config_data)) - return self.config_data - def get_storage_config(self,event,msg): - # EventMesh.debug_log("get_storage_key_data1:{}".format(msg)) - b = msg in self.config_data.keys() - if b == True: - # EventMesh.debug_log("get_storage_key_data2:{}".format(self.config_data[msg])) - return self.config_data[msg] - else : - return None - # try: - # return self.config_data[msg] - # except: - # EventMesh.debug_log("get_storage_key_data:none key:{}",msg) - # return None -#设备资源授权平台 -class device_res_author(Abstract): - - def __init__(self) : - self.deviceId = modem.getDevImei()#"876226002022574" - self.SHA1_BLOCK_SIZE = 64 - self.PAD_BLOCK_SIZE = 16 - self.SHA256 = uhashlib.sha256 - 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) - # 除去补16字节的多余字符 - self.unpad = lambda s: s[:-s[-1]] - #K01 - # self.key = b"MWrMZjdtcPhj41jWuoqFAhTmqyFluqj1" - # self.pid = "qAtdDOGXgXYjT2HGFr3a" - #G15 - # self.key = b"3LWfBicxfRZ3ZAqmZCFuvMdGUXdAFWkb" - # self.pid = "qLx4Pu4mSUQxyfVKGLXG" - #7pin - self.key = b"uKLrChwrxA1LklgBc3VwawYjUkbT3BgX" - self.pid = "cqxJZi5CNgzjS3mX21Zw" - - self.dev_res_timer = osTimer() - self.dev_res_timer.start(10000, 1, self.dev_timer_cb) - self.dev_res_timerCount = 0 - self.ud_token_timer = osTimer() - self.ud_token_timer.start(30000, 1, self.ud_token_timer_cb) - self.ud_token_timer_Count = 0 - self.dev_token = None - self.res_error_count = 0 - EventMesh.subscribe("get_dev_token", self.get_dev_token) - EventMesh.subscribe("update_dev_token", self.update_dev_token) - self.dev_active() #设备激活 - self.dev_sign_in() #设备登入 - self.ntptime_flag = 0 - - def get_dev_token(self, event, msg): - return self.dev_token - #网络校时 - def dev_NTP(self): - url = "http://dmp.raisound.com/bz-api/dev/time" - response = request.get(url) - data = response.json() - print("dev_NTP:{}".format(data)) - if data: - try: - timeSecond = data["data"]["timestamp"]//1000 - - next_alarm_time = utime.localtime(timeSecond) - print("timeSecond {} next_alarm_time {}".format(timeSecond,next_alarm_time)) - 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)) - except Exception as e: - usys.print_exception(e) - def dev_timer_cb(self, *args): #设备资源管理鉴权平台定时器 - EventMesh.publish("publish_AI_btnInfo",{"func":self.dev_timer_cb_}) - - def dev_timer_cb_(self): - #if EventMesh.DEV_RES_MANAGE_AUTHEN_PLATFORM == 1: - if self.dev_token == None: - if self.ntptime_flag == 0: - self.ntptime_flag = 1 - EventMesh.publish("publish_AI_btnInfo",{"func":self.dev_NTP}) - print("timer:{}!!!!!!!!\r\n".format(utime.localtime())) - self.dev_active() #设备激活 - self.dev_sign_in() #设备登入 - self.dev_res_timerCount+=1 - if self.dev_res_timerCount > 6: #开机一分钟内没有获取到密码和token 等下一次更新令牌在走登入 激活流程 - self.dev_res_timerCount=0 - self.dev_res_timer.stop() - def ud_token_timer_cb(self, *args): - EventMesh.publish("publish_AI_btnInfo",{"func":self.ud_token_timer_cb_}) - - def ud_token_timer_cb_(self): - #print("ud_token_timer_!!!!") - self.ud_token_timer_Count+=1 - if self.ud_token_timer_Count >= 20: #定时30*200s时更新token - self.ud_token_timer_Count = 0 - EventMesh.publish("update_dev_token") - - def get_sim_Status(self): - return sim.getStatus() - def HMAC(self,k, m): - - KEY_BLOCK = k + (b'\0' * (self.SHA1_BLOCK_SIZE - len(k))) - KEY_INNER = bytes((x ^ 0x36) for x in KEY_BLOCK) - KEY_OUTER = bytes((x ^ 0x5C) for x in KEY_BLOCK) - inner_message = KEY_INNER + m - outer_message = KEY_OUTER + self.SHA256(inner_message).digest() - return self.SHA256(outer_message) - def get_hmac_sha256(self,k, m): - data = self.HMAC(k, m).digest() - # print("HMAC(k, m).digest():", data) - # print("HMAC(k, m).digest():", ubinascii.hexlify(data)) - hex_data = ubinascii.hexlify(data) - hex_data = hex_data.decode('ascii') - return hex_data - # 加密函数 - def aes_CBC_Encrypt(self,data, key, iv): # CBC模式的加密函数,data为明文,key为16字节密钥,iv为16字节的偏移量 - key = key.encode('utf-8') - iv = iv.encode('utf-8') # CBC 模式下的偏移量 - data = self.pad(data) # 补位 - data = data.encode('utf-8') - aes = ucryptolib.aes(key,ucryptolib.MODE_CBC,iv) - result = base64.b64encode(aes.encrypt(data)) - return str(result, 'utf-8') # 以字符串的形式返回 - - # 解密函数 - def aes_CBC_Decrypt(self,data, key, iv): # CBC模式的解密函数,data为密文,key为16字节密钥 - key = key.encode('utf-8') - iv = iv.encode('utf-8') - - aes = ucryptolib.aes(key,ucryptolib.MODE_CBC,iv) #CBC模式 - - # decrypt AES解密 B64decode为base64 转码 - result = aes.decrypt(base64.b64decode(data)) - result = self.unpad(result) # 除去补16字节的多余字符 - return str(result, 'utf-8') # 以字符串的形式返回 - #激活接口 没有密码走激活 - def dev_active(self): - signal = net.csqQueryPoll() - if signal == -1 or self.get_sim_Status() != 1:#网络不正常 - print("dev_active 无 SIM卡!!!!!!!!\r\n") - return - # 签名内容: = deviceId+pid+timeStamp - dev_pass = "" - dev_pass = EventMesh.publish("get_storage_config","dev_pass") - print("dev_pass:{}\r\n".format(dev_pass)) - if dev_pass == None: - dev_pass = "" - if dev_pass == "" or dev_pass == None: - date_tmp = utime.localtime() #获取当前时间 - print("date_tmp:{}\r\n".format(date_tmp)) #转换时间戳s - timeStamp = (utime.mktime(date_tmp))*1000#获取时间戳ms - deviceId = self.deviceId #"876226002022574" #以imei号 - pid = self.pid - key = self.key - sign_data = "{}{}{}".format(deviceId,pid,timeStamp) #签名内容 - print("sign_data:{}\r\n".format(sign_data)) - sha256_hex = self.get_hmac_sha256(key,sign_data) - print("sha256_hex:{}\r\n".format(sha256_hex)) - - data = { - "deviceId":"{}".format(deviceId), #设备名 - "pid":pid, #产品PID - "sign":"{}".format(sha256_hex), #HMACSHA256签名后的数据 - "timeStamp":timeStamp, #要以ms的形式 - "signMethod":"HMACSHA256" #签名方式 HMACSHA256 - } - print(ujson.dumps(data)) - headers_T ={"Content-Type":"application/json"} - url = "http://dmp.raisound.com/bz-api/dev/auth/active" - data =ujson.dumps(data) - response = 0 - response_result = 0 - try: - response = request.put(url,data=data,headers = headers_T) - response_result = 1 - except Exception as e: - print("put error!!!!!\r\n") - response_result = 0 - - IV = "" #偏移量 - PASSWORD= "" #服务器返回后的加密内容 密码 - if response_result == 1: #访问成功ip - if response.status_code == 200: - print("headers:{}".format(response.headers)) - content = response.content - c = next(content) - # "api.xcloudtech.com" - # d_server_port = 9000 - data = ujson.loads(c) - # data = response.json() - print("data-{}".format(data)) - if data != None: - if "success" in data: - if data['success'] == True: - if "data" in data: - data_tmp = data["data"] - if "nonce" in data_tmp: #偏移量 - IV = data_tmp["nonce"] - if "password" in data_tmp: - PASSWORD = data_tmp["password"] - # EventMesh.publish("set_storage_config",["dev_pass",PASS]) - if data["code"] == 20001:#鉴权成功 - pass - elif data["code"] > 50000:#时间错误 - self.res_error_count+=1 - if self.res_error_count>=3: - self.res_error_count = 0 - EventMesh.publish("paly_device_res_error") - if data["code"] == 50003:#时间错误 - self.ntptime_flag = 0 - if PASSWORD != None and IV != None: - if len(PASSWORD) != 0 and len(IV) != 0: - password = PASSWORD - iv = IV - #解密 之后保存本地下一次登入做使用 - decrypt_data = self.aes_CBC_Decrypt(password, self.key, iv) #对服务器下发的密码进行解密 - print("decrypt_data {}".format(decrypt_data)) - EventMesh.publish("set_storage_config",["dev_pass",decrypt_data]) - - - print("IV:{}\r\n PASS:{}".format(IV,PASSWORD)) - return [response_result,PASSWORD,IV] - #随机生成16个字节的字符串作为加密的IV 偏移量 - def generate_random_string(self,length=16): - random_str = "" - chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' - for i in range(length): - random_str+=chars[random.randint(0,length)] - return random_str - - #设备登入 没有Token 走登入获取token - def dev_sign_in(self): - signal = net.csqQueryPoll() - if signal == -1 or self.get_sim_Status() != 1:#网络不正常 - print("dev_sign_in 无 SIM卡!!!!!!!!\r\n") - return - token = "" - token = self.dev_token - dev_pass = EventMesh.publish("get_storage_config","dev_pass") - #print("token:{}\r\n".format(token)) - if token == None: - token = "" - if dev_pass == None: - dev_pass = "" - if len(dev_pass) == 0:#没有密码 - return - if token == None or token == "": - if 1: #返回结果成功 - #获取本地保存的密码 - decrypt_data=EventMesh.publish("get_storage_config","dev_pass") - # decrypt_data = self.aes_CBC_Decrypt(password, self.key, iv) #对服务器下发的密码进行解密 - print("decrypt_data {}".format(decrypt_data)) - #随机生成16个字符串 设备生成做加密使用 - random_string = self.generate_random_string(16) #随机的16个字符串 - enc_iv = random_string #加密的IV偏移量 - #设备端进行密码加密 - encrypt_data = self.aes_CBC_Encrypt(decrypt_data, self.key, enc_iv) - print("encrypt_data {}".format(encrypt_data)) - - #登入数据 - deviceId = self.deviceId - sign_in_data = { - "deviceId":"{}".format(deviceId), #设备ID - "password":"{}".format(encrypt_data), #加密的数据 - "nonce":"{}".format(random_string) #随机的16个字符串 - } - print(ujson.dumps(sign_in_data)) - sign_url = "http://dmp.raisound.com/bz-api/dev/auth/sign_in" #登入地址 - headers_T ={"Content-Type":"application/json"} - response_result = 0 - response = 0 - try: - response = request.post(sign_url,data=ujson.dumps(sign_in_data),headers = headers_T) - response_result = 1 - except Exception as e: - print("post error!!!!!\r\n") - response_result = 0 - # {'msg': '', 'code': 20001, 'success': True, - # 'data': {'deviceId': '876226002022574', - # 'token': '95436a9e09fd0ff89feb8825257dca982f'} - # } - token = "" - if response_result == 1: - if response.status_code == 200: - content = response.content - c = next(content) - data = ujson.loads(c) - print("data-{}".format(data)) - if data != None: - if "success" in data: - if data['success'] == True: #登入成功 - if "data" in data: - data_tmp = data["data"] - if "token" in data_tmp: #token - self.dev_token = data_tmp["token"] - if data["code"] == 50003:#时间错误 - self.ntptime_flag = 0 - print("token:{}\r\n".format(token)) - pass - #获取新的令牌 更新token - def update_dev_token(self, event, msg): - print("update_dev_token") - dev_pass = "" - dev_pass = EventMesh.publish("get_storage_config","dev_pass") - - if dev_pass == None: - dev_pass = "" - if len(dev_pass) == 0: #没有密码走激活 - print("no dev_pass:{}\r\n".format(dev_pass)) - self.dev_active() - token = self.dev_token - if token == None: - token = "" - if len(token) == 0: #没有token走登入 - print("no dev_token:{}\r\n".format(token)) - self.dev_sign_in() - - dev_tokenip = "http://dmp.raisound.com/bz-api/dev/auth/token" #设备新令牌更新地址 - token = self.dev_token - if token == None: - token = "" - if len(token) != 0: - response_result=0 - response = 0 - headers_T = {"bz-dt":"{}".format(token)} - try: - response = request.get(dev_tokenip,headers = headers_T) - response_result = 1 - except Exception as e: - print("get error!!!!!\r\n") - response_result = 0 - if response_result == 1: - if response.status_code == 200: - try: - headers_data = response.headers - # print("headers_data!!!!! headers_data:{}\r\n".format(headers_data)) - if "bz-dt" in headers_data: #bz-dt字段是否在头部数据里面 如果有就需要更新 - bz_dt = headers_data["bz-dt"] - self.dev_token = bz_dt.replace(" ", "") #去掉所有的空格符 - print("update_dev_token:{}".format(self.dev_token)) - except Exception as e: - print("headers_data!!!!! error\r\n") - - pass - - - - -#阿里voice_chat状态枚举 -VC_State_None=0 -VC_State_Listening=1#听 -VC_State_SpeechStart=2#说开始 -VC_State_SpeechEnd=3#说结束 -VC_State_Thinking=4#想(chat) -VC_State_Responding=5#音频播放 -VC_State_TTSStart=6 -VC_State_TTSData=7 -VC_State_TTSFinish=8 -VC_State_TTSEnd=9 -VC_State_TTSError=10 -VC_State_DialogError=11 -VC_State_End=12 - -VC_record_TYPE_PCM = 0 -VC_record_TYPE_AMR = 1 -VC_play_TYPE_PCM = 0 -VC_play_TYPE_MP3 = 1 - -#websocket发送数据编号 -# AI_client_asr_num = 0 -# AI_client_chat_num = 1 -# AI_client_tts_num = 2 -AI_client_voice_chat_num = 3 -AI_client_asr_num = 4 -class AI_VC(Abstract): - # AI - - def __init__(self): - self.record_data_save_flag = 0 #是否保存录音文件 - self.record_fd = None - #self.VC_mode = 0 #0:短按连续问答模式 1:长按录音模式 - self.VC_mode = EventMesh.publish("get_storage_config","VC_mode")#音色配置 - if self.VC_mode == None : - self.VC_mode = 0 - - self.VC_server = 2 #0正式服务器,1:测试服务器1,2:测试服务器2 - 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.VC_record_samplerate = 16000 - self.VC_play_samplerate = 16000 - #女,男,童,粤,川 - 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", - 3:"aliyun::longjiaxin",4:"huoshan::zh_female_daimengchuanmei_moon_bigtts"} - #self.VC_TTS_voice_type = ["aliyun::longxiaoxia","aliyun::longnan","aliyun::longling"] - self.VC_TTS_voice_num = EventMesh.publish("get_storage_config","VC_TTS_voice_num")#音色配置 - if self.VC_TTS_voice_num == None or self.VC_TTS_voice_num>=len(self.VC_TTS_voice_type): - self.VC_TTS_voice_num = 0 - - self.VC_TTS_volume = EventMesh.publish("get_storage_config","VC_TTS_volume")#音量配置 - if self.VC_TTS_volume == None: - self.VC_TTS_volume = 100 - self.AI_audio_queue_thread_id = 0 - self.AI_send_data_queue_thread_id = 0 - - self.AI_record_tmp_queue = Queue(100) - self.AI_send_data_queue = Queue(100) - self.AI_audio_queue = Queue(100) - self.AI_TTS_str = "" - self.AI_ASR_str = "" - self.AI_ASR_flag = 0 - self.AI_ASR_str_tmp = "" - # #开始线程 - # if self.AI_audio_queue_thread_id ==0: - # self.AI_audio_queue_thread_id = _thread.start_new_thread(self.AI_audio_queue_thread, ()) - # else: - # print("AI_VC_start :AI_audio_queue_thread_id != 0 ") - # if self.AI_send_data_queue_thread_id == 0: - # self.AI_send_data_queue_thread_id = _thread.start_new_thread(self.AI_send_data_queue_thread, ()) - - self.voice_chat_state = VC_State_None #阿里ai voice_chat状态 - self.VC_dialog_id = "" - self.VC_message_id=None - self.VC_task_id =None - self.AI_client_voice_chat = None - self.AI_client_voice_chat_recv_id = 0 - self.AI_client_voice_chat_isconnect =0 - - self.asr_state = VC_State_None #阿里VC_ASR voice_chat状态 - self.VC_asr_dialog_id = "" - self.VC_asr_message_id=None - self.VC_asr_task_id =None - self.AI_client_asr = None - self.AI_client_asr_recv_id = 0 - self.AI_client_asr_isconnect =0 - - self.asr_satrt_flag = 0 - - self.record_pcm = None - self.play_pcm = None - self.VC_record_thread_id = 0 - self.pingping_timerout = 0 - - self.factory_timer = osTimer() - self._1S_timer = osTimer() - self.Audio_buf_size = 16*1024 - self.record = audio.Record() - #self.record.end_callback(self.record_callback) - self.record.gain_set(4,10) - self.aud = audio.Audio(0) - self.aud.setCallback(self.audio_cb) - #self.aud.setVolume(self.VC_TTS_volume //10) - self.audio_play_state = 1 #音频播放完状态 - self.close_timerout = 0 - self.LocalRespondingEnded_timerout = 0 - - self.play_flag = 0 - self.VC_record_state_flag = 0 - self.AI_key_long_press_flag = 0 - self.websocket_error_count = 0 - - self.tts_in_data_len = 0 - self.tts_out_data_len = 0 - EventMesh.subscribe("AI_key_press", self.AI_key_press) - EventMesh.subscribe("AI_key_release", self.AI_key_release) - EventMesh.subscribe("AI_key_long_press", self.AI_key_long_press) - EventMesh.subscribe("pwk_key_release", self.pwk_key_release) - EventMesh.subscribe("get_AI_audio_queue", self.get_AI_audio_queue) - - EventMesh.publish("close_led") - #开机提示语,如果联网失败,直接提示信号弱 - #女,男,童,粤,川 - self.bot_name = "柒先生" - if self.VC_TTS_voice_num == 0 or self.VC_TTS_voice_num == 3 or self.VC_TTS_voice_num == 4: - self.bot_name = "柒妹妹" - elif self.VC_TTS_voice_num == 1: - self.bot_name = "柒先生" - elif self.VC_TTS_voice_num == 2: - self.bot_name = "柒思思" - self.AI_TTS_str = "您好!我是柒牌 AI 智能男装生活好帮手-{}, 很高兴为您服务,我可以帮您解答日常生活、工作,旅游信息、健康咨询、教育与学习、情感交流、全球资讯等问题!请问您有什么需要我帮忙的吗?".format(self.bot_name ) - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) - - def post_processor_after_instantiation(self): - pass - def get_AI_audio_queue(self, event, msg): - return self.AI_audio_queue - def audio_cb(self,event): - if event == 0: - self.audio_play_state =1 - #EventMesh.publish("set_audio_state", 1) - print('audio-play start.') - elif event == 7: - self.audio_play_state = 0 - #EventMesh.publish("set_audio_state", 0) - print('audio-play finish.!!!!!!') - - def AI_key_press(self, event, msg):#按键按下 - print("AI_key_press") - self.aud.aud_tone_play(16,200)#播放按键音 - self.asr_satrt_flag = 1# - self.AI_TTS_str = ""#"你好,有什么吩咐" - self.AI_ASR_str = "" - self.AI_ASR_str_tmp = "" - # if self.voice_chat_state != VC_State_None: - # EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) - # EventMesh.publish("publish_AI_btnInfo",{"func":utime.sleep_ms,'data':(10)}) - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) - # self.Close() - # self.AI_VC_start() - self.AI_key_long_press_flag = 0 - - def AI_key_release(self, event, msg):#按键弹起 - print("AI_key_release123") - if self.AI_key_long_press_flag == 1 :#有长按 - self.AI_client_voice_chat_end_speech() - else : - if self.VC_mode == 1 :#长按单次问答模式 - EventMesh.publish("audio_montage_play",["key_prompt.mp3"]) - #self.aud.play(1,1,'U:/static/key_prompt.mp3')#提示请您按住中间的按钮开始讲话,讲完松开即可 - self.AI_send_data_queue.clear() - try: - self.websocket_deconnect_voice_chat() - except Exception as e: - usys.print_exception(e) - self.VC_Speech_End() - def AI_key_long_press(self, event, msg):#按键长按 - print("AI_key_long_press") - self.AI_key_long_press_flag = 1 - - def pwk_key_release(self, event, msg):#电源键短按,关闭 - print("pwk_key_release") - EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) - - -#****************************************ASR连接********************************************************************** - def websocket_connect_asr(self): - print("websocket_connect_asr:{} {}!!!!!!!!!!!!!!!!!!!!!".format(self.AI_client_asr_isconnect,_thread.threadIsRunning(self.AI_client_asr_recv_id))) - if self.AI_client_asr_isconnect == 1: - return - # 创建VC客户端 - try: - signal = net.csqQueryPoll() - if signal == -1 or sim.getStatus() != 1:#网络正常 - self.websocket_error() - return - # Headers = {'X-NLS-Token':'0c8b8f05a46f423096be64a9c4c46310'} - # self.AI_client_asr = uwebsocket.Client.connect('wss://nls-gateway-cn-beijing.aliyuncs.com/ws/v1',headers=Headers, debug=False) - if self.VC_server == 1:# - self.AI_client_asr = uwebsocket.Client.connect('ws://118.145.158.207:22080/asr/ws', debug=False)#测试环境 - elif self.VC_server == 2:# - if self.VC_TTS_voice_num <= 2: - self.AI_client_asr = uwebsocket.Client.connect('ws://118.145.158.207:22080/asr/ws?platform=aliyun&lang=zh-cn', debug=False)#普通话测试环境 - elif self.VC_TTS_voice_num == 3: - self.AI_client_asr = uwebsocket.Client.connect('ws://118.145.158.207:22080/asr/ws?platform=aliyun&lang=zh-hk', debug=False)#粤语测试环境 - elif self.VC_TTS_voice_num == 4: - self.AI_client_asr = uwebsocket.Client.connect('ws://118.145.158.207:22080/asr/ws?platform=aliyun&lang=zh-cn-sc', debug=False)#四川话测试环境 - else : - self.AI_client_asr = uwebsocket.Client.connect('ws://118.145.158.207:22080/asr/ws?platform=aliyun&lang=zh-cn', debug=False)#普通话测试环境 - else: - token = EventMesh.publish("get_dev_token") - print("token:{}".format(token)) - if token != None: - self.AI_client_asr = uwebsocket.Client.connect('ws://amp.raisound.com/asr/ws?dt={}'.format(token), debug=False) - else: - pass - return - except Exception as e: #网络连接异常 - usys.print_exception(e) - print("websocket_connect_voice_chat error!!!\r\n") - #self.connect_timerout_popup(2) - self.websocket_error() - return - if self.AI_client_asr == None: - EventMesh.publish("update_dev_token")#获取token - return - # 线程接收数据 - if self.AI_client_asr_recv_id != 0: - try: - _thread.stop_thread(self.AI_client_asr_recv_id) - except Exception as e: - usys.print_exception(e) - self.AI_client_asr_recv_id = 0 - _thread.stack_size(self.Audio_buf_size+8*1024) - self.AI_client_asr_recv_id = _thread.start_new_thread(self.AI_client_asr_recv, (self.AI_client_asr,)) - _thread.stack_size(8*1024) - self.AI_client_asr_isconnect = 1 - # - - def websocket_deconnect_asr(self): - print("websocket_deconnect_asr {}!!!!!!!".format(self.AI_client_asr_isconnect)) - print("websocket_deconnect_asr!!!!!!!") - if self.AI_client_asr_recv_id != 0:#关闭线程 - try: - _thread.stop_thread(self.AI_client_asr_recv_id) - except Exception as e: - usys.print_exception(e) - self.AI_client_asr_recv_id = 0 - if self.AI_client_asr_isconnect == 1: - self.AI_client_asr_isconnect = 0 - self.AI_client_asr.close() - print("websocket_deconnect_asr {}!!!!!!!".format(self.AI_client_asr_isconnect)) - - #websocket发送数据 - def AI_client_asr_send(self,data_str): - if isinstance(data_str, str):#是字符串 - print("ASR ASR AI_client_asr_send:{}".format(data_str)) - pass - else: - pass - #print("ASR ASR AI_client_asr_send:len:{}".format(len(data_str))) - self.AI_send_data_queue.put([AI_client_asr_num,data_str]) - #Ai VC websocket返回数据 - def AI_client_asr_recv(self,cli): - while True: - try: - # 死循环接收数据 - utime.sleep_ms(1) - recv_data = cli.recv() - self.close_timerout = 0#服务器有返回清零退出时间 - if not recv_data: - # 服务器关闭连接或客户端关闭连接 - print("AI_client_asr_recv close!!!!!!!!!!!!!!!!!!!!!!!!!!!") - #self.AI_client_voice_chat_isconnect = 0 - #self.websocket_deconnect_voice_chat() - EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_deconnect_asr}) - #EventMesh.publish("publish_AI_btnInfo",{"func":utime.sleep_ms,'data':(1500)}) - EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_connect_asr}) - break - try: - if isinstance(recv_data, str): - jsload_data = ujson.loads(recv_data) - print("ASR ASR recv_data: {}".format(jsload_data)) - if jsload_data["event"] != None: - if jsload_data["event"] == "TranscriptionStarted": #开始录音 - pass - if recv_data.find('\"result\"') == -1: - #if jsload_data["result"] == None: - #print("continue recv_data:{}".format(recv_data)) - continue - if jsload_data["result"] == None: - #print("continue recv_data:{}".format(recv_data)) - continue - if jsload_data["result"]["result"]: - #self.AI_listen_text = str(jsload_data["result"]["result"]) - text= str(jsload_data["result"]["result"]) - - - print("ASR recv self.voice_chat_state :{}".format(self.voice_chat_state)) - if self.voice_chat_state >= VC_State_TTSStart:#开始播音后不响应asr结果 - print("asr continue") - continue - EventMesh.publish("open_led_red") - if jsload_data["result"]["is_end"] == True: #asr结束 - # if text.find('你好') != -1: - # self.asr_satrt_flag = 0 - # self.AI_TTS_str = ""#"你好,有什么吩咐" - # self.AI_ASR_str = "" - # self.asr_satrt_flag = 1 - # self.aud.aud_tone_play(16,200)#播放按键音 - # # self.AI_client_asr_StopTranscription_requset()#终止前面合成 - # # self.AI_client_asr_start_requset()#开始新的合成 - # EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_deconnect_voice_chat}) - # EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) - # EventMesh.publish("open_led_red") - # continue - # #self.VC_Play_End()#关闭音频播放 - ret= self.check_text(text) - if ret == 0:#配置指令 - #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])) - self.AI_send_data_queue.clear() - EventMesh.publish("open_led_all") - try: - EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_deconnect_voice_chat}) - #EventMesh.publish("publish_AI_btnInfo",{"func":utime.sleep_ms,'data':(1500)}) - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) - except Exception as e: - usys.print_exception(e) - continue - elif ret == 1:#不处理 - pass - else:#正常asr - if self.AI_ASR_flag == 0:#d第一次识别,没有打断 - self.AI_ASR_str = text# - self.AI_ASR_str_tmp = self.AI_ASR_str - self.AI_ASR_flag = 1 - else:#第二次识别,打断了 - self.AI_ASR_str = self.AI_ASR_str_tmp+text - print("ASR ASR 打断 续集 AI_ASR_str {}".format(self.AI_ASR_str)) - self.AI_ASR_str_tmp = self.AI_ASR_str - EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init2})#关闭vc连接 - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) - - - # if self.AI_ASR_str != "":#识别过一次asr,打断当前思考或者tts播放 - # self.AI_ASR_str_tmp = self.AI_ASR_str - # print("ASR ASR 打断1 AI_ASR_str_tmp {}".format(self.AI_ASR_str_tmp)) - # self.AI_ASR_str = "" - # if self.AI_ASR_str_tmp != "": - # self.AI_ASR_str = self.AI_ASR_str_tmp +text#加上之前的数据 - # print("ASR ASR 打断 续集 AI_ASR_str {}".format(self.AI_ASR_str)) - # else: - # self.AI_ASR_str = text# - # EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) - # self.AI_ASR_str_tmp = "" - - - elif jsload_data["result"]["is_end"] == False: - if self.AI_ASR_flag ==1 :#如果已经识别过一次asr - self.AI_ASR_flag = 2 - print("asr 打断,关闭VC连接") - EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init2})#关闭vc连接 - EventMesh.publish("publish_AI_btnInfo",{"func":EventMesh.publish,"data":"open_led_red"})#关闭vc连接 - pass - except Exception as e: - usys.print_exception(e) - - except Exception as e: - usys.print_exception(e) - #self.websocket_error() - EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) - EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_error})# - break - self.AI_client_asr_isconnect = 0 - self.AI_client_asr_recv_id = 0 - print("AI_client_asr_recv END!!!!!!!!!!!!!!!!!!!!!!!!!!!") - #ASR开始会话 - def AI_client_asr_start_requset(self): - - json_data = \ - { - "header":{ - "event":"StartTranscription", - "trace_id":self.get_trace_id() - }, - "payload":{ - "format":"pcm", - "sample_rate":self.VC_record_samplerate, - } - - } - if self.VC_record_TYPE == VC_record_TYPE_AMR : - json_data["payload"]["format"]='amr' - pass - # if self.VC_mode == 1: - # json_data["payload"]["voice_detection"]='disable' - - self.AI_client_asr_send(ujson.dumps(json_data)) - #ASR终止 - def AI_client_asr_StopTranscription_requset(self): - json_data = \ - { - "header":{ - "event":"StopTranscription", - "trace_id":self.get_trace_id() - } - } - - self.AI_client_asr_send(ujson.dumps(json_data)) - - #开始录音 - def VC_Speech_Start(self): - #self.voice_chat_state = VC_State_SpeechStart - print("VC_Speech_Start VC_record_state_flag:{} self.AI_ASR_flag:{}!!!!!!!!".format(self.VC_record_state_flag,self.AI_ASR_flag)) - if self.AI_ASR_flag != 0: - return - if self.VC_record_state_flag == 0: - self.AI_client_asr_start_requset()#开始请求 - if self.VC_record_thread_id != 0: - try: - _thread.stop_thread(self.VC_record_thread_id) - except Exception as e: - usys.print_exception(e) - self.VC_record_thread_id = 0 - _thread.stack_size(self.Audio_buf_size+8*1024) - self.VC_record_thread_id = _thread.start_new_thread(self.VC_record_thread,()) - _thread.stack_size(8*1024) - print("self.VC_record_thread_id:{}".format(self.VC_record_thread_id)) - if self.VC_record_TYPE == VC_record_TYPE_AMR : - try : - self.record.stream_start(audio.Record.AMRNB, self.VC_record_samplerate, 0) - except Exception as e: - usys.print_exception(e) - elif self.VC_record_TYPE == VC_record_TYPE_PCM: - print("record_pcm.stream_read_start()!!!!!!!!!!!!") - self.record.stream_start(audio.Record.WAV, self.VC_record_samplerate, 0) - # if self.record_pcm != None: - # try: - # self.record_pcm.stream_stop() - # self.record_pcm.close() - # self.record_pcm = None - # except Exception as e: - # usys.print_exception(e) - # if self.record_pcm == None: - # ret = self.record_pcm = audio.Audio.PCM(0,1,16000,0,1,2) - # print("audio.Audio.PCM:ret:{}".format(ret)) - # ret = self.record_pcm.stream_read_start() - # print("self.record_pcm.stream_read_start:ret:{}".format(ret)) - self.VC_record_state_flag = 1 - #停止录音 - def VC_Speech_End(self): - try: - self.AI_ASR_flag = 0 - self.AI_client_asr_StopTranscription_requset()#请求停止 - if self.VC_record_TYPE == VC_record_TYPE_AMR: - self.record.stream_stop() - self.record.stop()#关闭录音 - Record_read_buf = bytearray(self.Audio_buf_size) - for i in range(10): - Record_len = self.record.stream_read(Record_read_buf, self.Audio_buf_size) - print("Record_len:!!!!!!{}".format(Record_len)) - if Record_len <= 0: - break - elif self.VC_record_TYPE == VC_record_TYPE_PCM: - self.record.stream_stop() - self.record.stop()#关闭录音 - Record_read_buf = bytearray(self.Audio_buf_size) - for i in range(10): - Record_len = self.record.stream_read(Record_read_buf, self.Audio_buf_size) - print("Record_len:!!!!!!{}".format(Record_len)) - if Record_len <= 0: - break - # if self.record_pcm != None: - # try: - # self.record_pcm.stream_stop() - # self.record_pcm.close() - # self.record_pcm = None - # except Exception as e: - # usys.print_exception(e) - except Exception as e: - usys.print_exception(e) - if self.VC_record_thread_id != 0: - try: - _thread.stop_thread(self.VC_record_thread_id) - except Exception as e: - usys.print_exception(e) - self.VC_record_thread_id = 0 - - self.VC_record_state_flag = 0 - print("VC_Speech_End VC_record_state_flag:{}!!!!!!!!".format(self.VC_record_state_flag)) - #获取录音数据 - def VC_record_thread(self): - ##return - print("VC_record_thread start!!!!!!!!!!!!!!!!!!!!\r\n") - count = 0 - # try: - # uos.remove('/usr/test.pcm') - # except Exception as e: - # usys.print_exception(e) - #record_data_queue = Queue(100) - #fd = open('/usr/test.pcm','w') - # if self.VC_record_TYPE == 1: - # h_data= [0x23,0x21 ,0x41 ,0x4D ,0x52 ,0x0A ] - # h_data_b = bytes(h_data) - # self.AI_client_voice_chat_send(h_data_b) - - count = 0 - while True: - try: - - # 死循环接收数据 - #if self.voice_chat_state == VC_State_SpeechStart: - Record_read_buf = bytearray(self.Audio_buf_size) - - Record_len = 0 - if self.VC_record_TYPE == VC_record_TYPE_PCM:#pcm - Record_len = self.record.stream_read(Record_read_buf, self.Audio_buf_size) - utime.sleep_ms(20) - - else : - - Record_len = self.record.stream_read(Record_read_buf, self.Audio_buf_size) - utime.sleep_ms(600) - - #Record_len = 1024*2 - #print("VC_record_thread:{}".format(Record_len)) - if Record_len > 0: - read_buf = bytes(Record_read_buf[:Record_len]) - if self.record_fd != None: - self.record_fd.write(read_buf) - self.AI_client_asr_send(read_buf) - - # if self.voice_chat_state != VC_State_SpeechStart:#没发送前先存起来 - # self.AI_record_tmp_queue.put(read_buf) - # else: - # while True: - # if self.AI_record_tmp_queue.empty() == True: - # break - # else: - # self.AI_client_voice_chat_send(self.AI_record_tmp_queue.get()) #发送之前存的数据 - # self.AI_client_voice_chat_send(read_buf) - #print("VC_record_thread:{}".format(len(read_buf))) - count+=len(read_buf) - # if count>=500*1024:#结束 - # self.AI_client_voice_chat_end_speech() - # break - utime.sleep_ms(40) - # if self.voice_chat_state >= VC_State_SpeechEnd: - # break - count+=1 - if count %10 == 0: - 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))) - except Exception as e: - usys.print_exception(e) - #break - - #fd.close() - print("VC_record_thread:exit") - self.VC_record_thread_id = 0#线程退出 -###################################################### VC ################################################################################### - def websocket_connect_voice_chat(self): - print("websocket_connect_voice_chat:{}!!!!!!!!!!!!!!!!!!!!!".format(self.AI_client_voice_chat_isconnect)) - if self.AI_client_voice_chat_isconnect == 1: - return - # 创建VC客户端 - try: - signal = net.csqQueryPoll() - if signal == -1 or sim.getStatus() != 1:#网络正常 - self.websocket_error() - return - # Headers = {'X-NLS-Token':'0c8b8f05a46f423096be64a9c4c46310'} - # self.AI_client_voice_chat = uwebsocket.Client.connect('wss://nls-gateway-cn-beijing.aliyuncs.com/ws/v1',headers=Headers, debug=False) - if self.VC_server == 1:# - self.AI_client_voice_chat = uwebsocket.Client.connect('ws://118.145.158.207:22080/voice-chat/ws', debug=False)#测试环境 - elif self.VC_server == 2:# - if self.VC_TTS_voice_num <= 2: - 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)#普通话测试环境 - elif self.VC_TTS_voice_num == 3: - 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)#粤语测试环境 - elif self.VC_TTS_voice_num == 4: - 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)#四川话测试环境 - else : - 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)#普通话测试环境 - else: - token = EventMesh.publish("get_dev_token") - print("token:{}".format(token)) - if token != None: - self.AI_client_voice_chat = uwebsocket.Client.connect('ws://amp.raisound.com/voice-chat/ws?dt={}'.format(token), debug=False) - else: - self.websocket_error() - return - except Exception as e: #网络连接异常 - usys.print_exception(e) - print("websocket_connect_voice_chat error!!!\r\n") - #self.connect_timerout_popup(2) - self.websocket_error() - return - print("AI_client_voice_chat:{}".format(self.AI_client_voice_chat)) - if self.AI_client_voice_chat == None: - EventMesh.publish("update_dev_token")#获取token - self.websocket_error() - return - utime.sleep_ms(20) - # 线程接收数据 - if self.AI_client_voice_chat_recv_id != 0: - try: - _thread.stop_thread(self.AI_client_voice_chat_recv_id) - except Exception as e: - usys.print_exception(e) - self.AI_client_voice_chat_recv_id = 0 - _thread.stack_size(self.Audio_buf_size+8*1024) - self.AI_client_voice_chat_recv_id = _thread.start_new_thread(self.AI_client_voice_chat_recv, (self.AI_client_voice_chat,)) - _thread.stack_size(8*1024) - self.AI_client_voice_chat_isconnect = 1 - def websocket_error(self): - print("websocket_error!!!!") - print("websocket_error!!!!") - print("websocket_error!!!!") - print("websocket_error!!!!") - self.websocket_error_count+=1 - if self.websocket_error_count <=3: - EventMesh.publish("audio_montage_play",["xinhaoruo1.mp3"]) - elif self.websocket_error_count <10 : - EventMesh.publish("audio_montage_play",["xinhaoruo2.mp3"]) - elif self.websocket_error_count >=10: - EventMesh.publish("paly_iccid_imei") - else: - EventMesh.publish("audio_montage_play",["R_SIM_FAILE.mp3"]) - #self.aud.play(1,1,'U:/static/R_SIM_FAILE.mp3') - self.AI_send_data_queue.clear() - self.AI_audio_queue.clear() - #self.VC_Speech_End() - EventMesh.publish("close_led") - try: - self.websocket_deconnect_voice_chat() - except Exception as e: - usys.print_exception(e) - try: - self.websocket_deconnect_asr() - except Exception as e: - usys.print_exception(e) - - def websocket_deconnect_voice_chat(self): - print("websocket_deconnect_voice_chat {}!!!!!!!".format(self.AI_client_voice_chat_isconnect)) - print("websocket_deconnect_voice_chat!!!!!!!") - if self.AI_client_voice_chat_recv_id != 0:#关闭线程 - try: - _thread.stop_thread(self.AI_client_voice_chat_recv_id) - except Exception as e: - usys.print_exception(e) - self.AI_client_voice_chat_recv_id = 0 - if self.AI_client_voice_chat_isconnect == 1: - self.AI_client_voice_chat_isconnect = 0 - self.AI_client_voice_chat.close() - print("websocket_deconnect_voice_chat {}!!!!!!!".format(self.AI_client_voice_chat_isconnect)) - #websocket发送ping - def AI_client_voice_chat_ping(self): - pass - if self.AI_client_voice_chat_isconnect == 1: - #self.AI_client_voice_chat.write_frame(0x09,b'ping ping') - self.AI_client_voice_chat_send("ping") - #print("websocket ping ping") - - #websocket发送数据 - def AI_client_voice_chat_send(self,data_str): - if isinstance(data_str, str):#是字符串 - print("AI_client_voice_chat_send:{}".format(data_str)) - pass - # else: - # print("AI_client_voice_chat_send:len{}".format(len(data_str))) - self.AI_send_data_queue.put([AI_client_voice_chat_num,data_str]) - - #Ai VC websocket返回数据 - def AI_client_voice_chat_recv(self,cli): - count = 0 - while True: - try: - # 死循环接收数据 - count+=1 - if self.tts_in_data_len - self.tts_out_data_len > 64*1024 or count>4: - count = 0 - utime.sleep_ms(1) - recv_data = cli.recv() - self.close_timerout = 0#服务器有返回清零退出时间 - if not recv_data: - # 服务器关闭连接或客户端关闭连接 - print("服务器主动关闭连接!!!!!!!!!!!!!!!!!!!!!!!!!!!") - #self.AI_client_voice_chat_isconnect = 0 - #self.websocket_error() - EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) - EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_error}) - #EventMesh.publish("publish_AI_btnInfo",{"func":utime.sleep_ms,'data':(1500)}) - - break - try: - self.websocket_error_count = 0 - if isinstance(recv_data, str):#返回的是字符串 - print("VC VC:recv_data:{}".format(recv_data)) - jsload_data = ujson.loads(recv_data) - #print("AI_client_voice_chat_recv jsload_data = {}".format(jsload_data)) - if jsload_data["status"] != 20000000:#返回错误 - self.websocket_error() - break - if jsload_data["event"] == "Started" :#会话开始 - payload = jsload_data["payload"] - self.VC_dialog_id = payload["dialog_id"] - self.VC_task_id = jsload_data["task_id"] - print("VC:Started!!!!!!!!\r\n") - elif jsload_data["event"] == "SpeechContent" :#asr转译 - print("VC:SpeechContent!!!!!!!!\r\n") - payload = jsload_data["payload"] - - - if(payload['finished'] == True):#asr结束 - self.voice_chat_state = VC_State_SpeechEnd - #self.VC_Speech_End()#停止录音 - text = payload["text"] - if self.check_text(text) == 0: - #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])) - self.AI_send_data_queue.clear() - EventMesh.publish("open_led_all") - try: - EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_deconnect_voice_chat}) - #EventMesh.publish("publish_AI_btnInfo",{"func":utime.sleep_ms,'data':(1500)}) - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) - except Exception as e: - usys.print_exception(e) - - pass - else: - self.AI_listen_end = 0 - - elif jsload_data["event"] == "SpeechEnded" :#服务器下发ASR说话结束 - self.voice_chat_state = VC_State_SpeechEnd - elif jsload_data["event"] == "RespondingContent" :#chat回答 - pass - # payload = jsload_data["payload"] - - # if(payload['finished'] == True):#chat回答 结束,开始tts - # self.AI_client_chat_end_flag = 1 - # pass - # else: - - # self.AI_client_chat_end_flag = 0 - # self.AI_client_tts_data_len = 0 - #utime.sleep_ms(5) - - elif jsload_data["event"] == "RespondingStarted" :#音频开始下发 - self.play_flag = 0 - self.voice_chat_state = VC_State_TTSStart - self.VC_Speech_End()#停止录音 - self.VC_Play_Start() - #self.tts_fd = open('/usr/tts_tesr.pcm','w') - pass - elif jsload_data["event"] == "RespondingEnded" :#音频下发结束 - #if self.voice_chat_state == VC_State_TTSStart: - print("RespondingEnded!!!!!!" ) - self.voice_chat_state = VC_State_TTSEnd - if self.asr_satrt_flag == 0 : - self.asr_satrt_flag =1 - #self.tts_fd.close() - #pass - elif jsload_data["event"] == "DialogStateChanged" :#状态切换事件 - payload = jsload_data["payload"] - if payload["state"] == "Listening": - self.voice_chat_state = VC_State_Listening - if self.AI_TTS_str != "" or self.AI_ASR_str != "":#有tts数据,则请求TTS数据,没有就请求开始上传语音 - self.AI_client_voice_chat_RequestToRespond() - else: - self.VC_Speech_Start()#开启线程获取录音数据 - #self.AI_client_voice_chat_send_speech()#开始上传语音 - #self.AI_client_voice_chat_RequestToRespond()#chat请求或者tts请求 - EventMesh.publish("open_led_red") - if payload["state"] == "Thinking":#准备开始TTS - self.voice_chat_state = VC_State_Thinking - - self.AI_client_tts_data_total_len = 0 - EventMesh.publish("open_led_all") - if payload["state"] == "Responding": - self.voice_chat_state = VC_State_Responding - EventMesh.publish("open_led_green") - elif jsload_data["event"] == "RequestAccepted" :#请求上传语音被允许 - #self.voice_chat_state = VC_State_Responding - #self.AI_client_voice_chat_send_speech()#开始上传语音 - pass - else:#下发音频数据 - #填充头 - #self.tts_fd.write(recv_data) - #recv_data_len = len(recv_data) - # data_len_b = recv_data_len.to_bytes(4,'little')#数据长度转16进制数组 - # h_data = [ 0x52 ,0x49 ,0x46 ,0x46 #,0x24 ,0x00 ,0x00 ,0x00 #文件标识、文件大小 - # ,0x57 ,0x41 ,0x56 ,0x45 ,0x66 ,0x6D ,0x74 ,0x20 #文件格式、格式块标识符 - # ,0x10 ,0x00 ,0x00 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x80 ,0x3E ,0x00 ,0x00 #格式块大小4、音频格式2、声道数2、采样率4 - # ,0x80 ,0x3E ,0x00 ,0x00 ,0x02 ,0x00 ,0x10 ,0x00 ,0x64 ,0x61 ,0x74 ,0x61]#每秒字节数4、数据块对齐2、位深度2、data4 - # h_data_b = bytes(h_data) - # file_len = recv_data_len+len(h_data_b)+4+4 - # file_len_b = file_len.to_bytes(4,'little')#文件长度转16进制数组 - # h_data_b = h_data_b[:4]+file_len_b+h_data_b[4:]+data_len_b - - #print("下发音频数据1:{}".format(len(recv_data))) - # # self.AI_client_tts_data_total_len += len(recv_data) - # # self.AI_client_tts_data_len += len(recv_data) - # #if self.AI_client_tts_data_total_len >10*1024: - # ret=self.AI_audio_queue.put([recv_data,""]) - # print("下发音频数据2:{}".format(len(recv_data))) - if self.voice_chat_state >= VC_State_TTSStart: - self.put_record_data([recv_data,""]) - #EventMesh.publish("publish_AI_btnInfo",{"func":self.put_record_data,"data":[recv_data,""]}) - except Exception as e: - usys.print_exception(e) - - except Exception as e: - usys.print_exception(e) - #self.websocket_error() - EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) - EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_error})# - break - self.AI_client_voice_chat_isconnect = 0 - self.AI_client_voice_chat_recv_id = 0 - print("AI_client_voice_chat_recv END!!!!!!!!!!!!!!!!!!!!!!!!!!!") - def put_record_data(self,data): - #print("下发音频数据1:{}".format(len(data[0]))) - # self.AI_client_tts_data_total_len += len(recv_data) - # self.AI_client_tts_data_len += len(recv_data) - #if self.AI_client_tts_data_total_len >10*1024: - ret=self.AI_audio_queue.put(data) - self.tts_in_data_len += len(data[0]) - print("下发音频数据2:{},{}".format(len(data[0]),self.tts_in_data_len)) - def check_text(self,text): - if len(text)>60: - return -1 - try: - if isinstance(text, str): - if text.find("更改声音") != -1: - self.VC_TTS_voice_num += 1 - if self.VC_TTS_voice_num >= len(self.VC_TTS_voice_type): - self.VC_TTS_voice_num = 0 - EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_TTS_voice_num]) - # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"]) - #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功 - self.AI_TTS_str = "更改成功" - return 0 - if text.find("声音改为") != -1 and (text.find("男声") != -1 or text.find("男生") != -1 ): - self.VC_TTS_voice_num = 1 - - EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_TTS_voice_num]) - # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"]) - #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功 - self.AI_TTS_str = "更改成功" - return 0 - if text.find("声音改为") != -1 and (text.find("女声") != -1 or text.find("女生") != -1 ): - self.VC_TTS_voice_num = 0 - - EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_TTS_voice_num]) - # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"]) - #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功 - self.AI_TTS_str = "更改成功" - return 0 - if text.find("声音改为") != -1 and (text.find("同声") != -1 or text.find("童声") != -1 ): - self.VC_TTS_voice_num = 2 - - EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_TTS_voice_num]) - # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"]) - #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功 - self.AI_TTS_str = "更改成功" - return 0 - if text.find("声音改为") != -1 and (text.find("粤语") != -1 or text.find("越野") != -1 ): - self.VC_TTS_voice_num = 3 - - EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_TTS_voice_num]) - # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"]) - #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功 - self.AI_TTS_str = "更改成功" - return 0 - if text.find("声音改为") != -1 and text.find("四川话") != -1 : - self.VC_TTS_voice_num = 4 - - EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_TTS_voice_num]) - # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"]) - #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功 - self.AI_TTS_str = "更改成功" - return 0 - if text.find("切换对话模式") != -1: - if self.VC_mode == 0: - self.VC_mode = 1 - self.AI_TTS_str = "已切换到单对话模式" - else: - self.VC_mode = 0 - self.AI_TTS_str = "已切换到长对话模式" - EventMesh.publish("set_storage_config",["VC_TTS_voice_num",self.VC_mode]) - # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"]) - #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功 - - return 0 - if text.find("音量") != -1 and text.find("加") != -1 : - self.VC_TTS_volume += 10 - if self.VC_TTS_volume > 100: - #EventMesh.publish("audio_montage_play",["yinliangyizuida.mp3"]) - #self.aud.play(1,0,'U:/static/yinliangyizuida.mp3')#音量已最大 - self.AI_TTS_str = "音量已最大" - self.VC_TTS_volume = 100 - else: - self.aud.setVolume(self.VC_TTS_volume //10) - EventMesh.publish("set_storage_config",["VC_TTS_volume",self.VC_TTS_volume]) - #EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"]) - #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#配置成功 - self.AI_TTS_str = "配置成功,当前音量 {}".format(self.VC_TTS_volume) - - return 0 - if text.find("音量") != -1 and text.find("减") != -1: - self.VC_TTS_volume -= 10 - if self.VC_TTS_volume < 0: - self.VC_TTS_volume = 0 - #EventMesh.publish("audio_montage_play",["yinliangyizuixiao.mp3"]) - #self.aud.play(1,0,'U:/static/yinliangyizuixiao.mp3')#音量已最小 - self.AI_TTS_str = "音量已最小" - else: - self.aud.setVolume(self.VC_TTS_volume //10) - EventMesh.publish("set_storage_config",["VC_TTS_volume",self.VC_TTS_volume]) - #EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"]) - #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#配置成功 - self.AI_TTS_str = "配置成功,当前音量 {}".format(self.VC_TTS_volume) - return 0 - if text.find("电量") != -1 and text.find("查询") != -1: - battery = EventMesh.publish("get_battery") - #EventMesh.publish("audio_montage_play",["dianliangshengyu{}.mp3".format(battery)]) - #self.aud.play(1,0,'U:/static/dianliangshengyu{}.mp3'.format(battery))#电量剩余 - self.AI_TTS_str = "电量剩余百分之{}".format(battery) - return 0 - if text.find("电压") != -1 and text.find("查询") != -1: - Vbatt = Power.getVbatt() - #EventMesh.publish("audio_montage_play",["dianliangshengyu{}.mp3".format(battery)]) - #self.aud.play(1,0,'U:/static/dianliangshengyu{}.mp3'.format(battery))#电量剩余 - self.AI_TTS_str = "当前电池电压{}".format(Vbatt) - return 0 - if text.find("进入工厂模式") != -1 : - self.factory_mode() - return 1 - if text.find("信号") != -1 and text.find("查询") != -1: - signal = net.csqQueryPoll() - - self.AI_TTS_str = "当前信号{}".format(signal) - return 0 - - if text.find("再见") != -1 or text.find("拜拜") != -1: - EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) - return 1 - except Exception as e: - usys.print_exception(e) - return -1 - #获取trace_id - def get_trace_id(self): - t = utime.mktime(utime.localtime()) - t = t*1000+urandom.randint(0, 1000) - md5_data = "{}".format(t)#md5签名 - sign_data = "" - hash_obj = uhashlib.md5(md5_data) - res = hash_obj.digest() - - # 转成十六进制表示 - sign_data = ubinascii.hexlify(res) - sign_data = sign_data.decode('ascii') - return sign_data - def get_new_message_id(self): - message_id = self.get_trace_id()+"aaa"+self.get_trace_id() - self.VC_message_id=message_id[:32] - return self.VC_message_id - def get_new_task_id(self): - task_id = self.get_trace_id()+"aaa"+self.get_trace_id() - self.VC_task_id=task_id[:32] - return self.VC_task_id - #开始播放声音 - def VC_Play_Start(self): - self.tts_in_data_len = 0 - self.tts_out_data_len = 0 - if self.VC_play_TYPE == VC_play_TYPE_PCM: - if self.VC_play_samplerate == 8000: - pass - elif self.VC_play_samplerate == 16000: - if self.play_pcm == None: - self.play_pcm = audio.Audio.PCM(0,1,16000,1,1,2) - #self.play_pcm.setVolume(11) - ret = self.play_pcm.stream_write_start() - print("self.record_pcm.stream_write_start:ret:{}".format(ret)) - elif self.VC_play_TYPE == VC_play_TYPE_MP3: - pass - #停止播放声音 - def VC_Play_End(self): - if self.VC_play_TYPE == VC_play_TYPE_PCM: - if self.VC_play_samplerate == 8000: - self.aud.stopPlayStream() - self.aud.stopAll() - elif self.VC_play_samplerate == 16000: - if self.play_pcm != None: - print("Close:play_pcm.close()!!!!!!!!!!!!!!!!!!") - try: - self.play_pcm.stream_stop() - self.play_pcm.close() - except Exception as e: - usys.print_exception(e) - self.play_pcm=None - self.aud.stopPlayStream() - self.aud.stopAll() - elif self.VC_play_TYPE == VC_play_TYPE_MP3: - self.aud.stopPlayStream() - self.aud.stopAll() - - def _1S_timer_cb(self,*argc): - EventMesh.publish("system_sleep_rest")#防止黑屏 - self.close_timerout += 1 - if self.close_timerout > 30:#20秒没数据就close - EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) - # print("get_audio_state !!!!!{} {} {}\r\n".format(self.play_end,EventMesh.publish("get_audio_state"),self.play_flag)) - #self.LocalRespondingEnded_timerout+=1 - if self.voice_chat_state == VC_State_TTSEnd and self.AI_audio_queue.empty() :#self.AI_audio_queue为空且tts下发结束 - self.LocalRespondingEnded_timerout += 1 - if self.LocalRespondingEnded_timerout >= 3: - self.LocalRespondingEnded_timerout = 0 - if self.VC_mode == 1 :#长按单次问答模式 - EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) - else: - #通知服务器播放结束 - self.AI_client_voice_chat_LocalRespondingEnded() - self.pingping_timerout+=1 - if self.pingping_timerout>5: - self.pingping_timerout=0 - self.AI_client_voice_chat_ping() - - #VC开始 - def AI_VC_start(self): - - self.VC_Play_End()#关闭音频播放 - - #self.aud.aud_tone_play(16,200)#播放按键音 - self.LocalRespondingEnded_timerout = 0 - self.close_timerout = 0 - self.websocket_connect_asr() - if self.AI_client_asr_isconnect == 0: - return - if self.record_data_save_flag == 1: - try: - uos.remove('/usr/record_data.pcm') - except Exception as e: - usys.print_exception(e) - self.record_fd = open('/usr/record_data.pcm','w') - #utime.sleep_ms(50) - if self.AI_client_voice_chat_isconnect == 0:#没连接的时候请求开始 - self.websocket_connect_voice_chat()#连接服务器 - self.AI_client_voice_chat_start_requset() - else: - print("self.voice_chat_state :{}".format(self.voice_chat_state )) - if self.voice_chat_state > VC_State_SpeechStart: - #客户端打断对话 - print("打断对话") - self.AI_client_voice_chat_RequestToSpeak() - elif self.voice_chat_state == VC_State_Listening: - #直接chat - print("直接chat") - self.AI_client_voice_chat_RequestToRespond() - if self.AI_client_voice_chat_isconnect == 0: - return - self.voice_chat_state = VC_State_None - if self.AI_TTS_str == "":#没有tts要播放的时候才开始录音 - #开始asr录音 - self.VC_Speech_Start() - pass - #开始线程 - if self.AI_audio_queue_thread_id ==0: - _thread.stack_size(24*1024) - self.AI_audio_queue_thread_id = _thread.start_new_thread(self.AI_audio_queue_thread, ()) - _thread.stack_size(8*1024) - print("AI_VC_start :AI_audio_queue_thread_id :{} ".format(self.AI_audio_queue_thread_id)) - else: - print("AI_VC_start :AI_audio_queue_thread_id != 0 ") - if self.AI_send_data_queue_thread_id == 0: - _thread.stack_size(self.Audio_buf_size+8*1024) - self.AI_send_data_queue_thread_id = _thread.start_new_thread(self.AI_send_data_queue_thread, ()) - _thread.stack_size(8*1024) - print("AI_VC_start :AI_send_data_queue_thread_id :{} ".format(self.AI_send_data_queue_thread_id)) - self._1S_timer.start(1000,1,self._1S_timer_cb) - self.pingping_timerout = 0 - - - #开始会话 - def AI_client_voice_chat_start_requset(self): - - json_data = \ - { - "header":{ - "trace_id":self.get_trace_id(), - "event":"Start" - }, - "payload":{ - "dialog_id":self.VC_dialog_id, - "device_id":modem.getDevImei(), - "user_agent":"python", - "in_format":"pcm", - "out_format":"mp3", - "in_sample_rate":self.VC_record_samplerate, - "sample_rate":self.VC_play_samplerate, - "space_time": 150, - "volume": str(self.VC_TTS_volume), - "voice":self.VC_TTS_voice_type[self.VC_TTS_voice_num], - "voice_detection":"enabled", - "simple_response":True, - "custom_variables":{ - "bot_name":"{}".format(self.bot_name) - } - }, - - } - if self.VC_play_TYPE == VC_play_TYPE_PCM: - json_data["payload"]["out_format"]='pcm' - if self.VC_record_TYPE == VC_record_TYPE_AMR : - json_data["payload"]["in_format"]='amr' - pass - if self.VC_mode == 1: - json_data["payload"]["voice_detection"]='disable' - self.voice_chat_state = VC_State_None - self.AI_client_voice_chat_send(ujson.dumps(json_data)) - - #开始上传语音 - def AI_client_voice_chat_send_speech(self): - json_data = \ - { - "header":{ - "trace_id":self.get_trace_id(), - "event":"SendSpeech" - }, - "payload": - { - "dialog_id":self.VC_dialog_id - } - } - self.AI_client_voice_chat_send(ujson.dumps(json_data)) - self.VC_Speech_Start()#开启线程获取录音数据 - self.voice_chat_state = VC_State_SpeechStart - #结束上传语音 - def AI_client_voice_chat_end_speech(self): - json_data = \ - { - "header":{ - "trace_id":self.get_trace_id(), - "event":"StopSpeech" - }, - "payload":{ - "dialog_id":self.VC_dialog_id - } - } - self.AI_client_voice_chat_send(ujson.dumps(json_data)) - self.VC_Speech_End()#停止线程录音 - - #通知服务器开始播放 - def AI_client_voice_chat_LocalRespondingStarted(self): - json_data = \ - { - "header":{ - "trace_id":self.get_trace_id(), - "event":"LocalRespondingStarted" - }, - "payload":{ - "dialog_id":self.VC_dialog_id - } - } - self.AI_client_voice_chat_send(ujson.dumps(json_data)) - #通知服务器播放结束 - def AI_client_voice_chat_LocalRespondingEnded(self): - json_data = \ - { - "header":{ - "trace_id":self.get_trace_id(), - "event":"LocalRespondingEnded" - }, - "payload":{ - "dialog_id":self.VC_dialog_id - } - } - EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init}) - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_voice_chat_send,"data":ujson.dumps(json_data)}) - # utime.sleep_ms(1) - # self.AI_client_voice_chat_send(ujson.dumps(json_data)) - self.voice_chat_state = VC_State_End - #客户端打断对话 - def AI_client_voice_chat_RequestToSpeak(self): - json_data = \ - { - "header":{ - "trace_id":self.get_trace_id(), - "event":"RequestToSpeak" - }, - "payload":{ - "dialog_id":self.VC_dialog_id - } - } - print("AI_client_voice_chat_RequestToSpeak!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init}) - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_voice_chat_send,"data":ujson.dumps(json_data)}) - # utime.sleep_ms(1) - #请求TTS或者chat事件 - def AI_client_voice_chat_RequestToRespond(self): - json_data = \ - { - "header":{ - "trace_id":self.get_trace_id(), - "event":"RequestToRespond" - }, - "payload":{ - "dialog_id":self.VC_dialog_id, - "type":"transcript",#prompt是跳过asr,transcript是跳过asr和大模型 - "text":"" - } - } - - print("AI_client_voice_chat_RequestToRespond!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - if self.AI_TTS_str != "": - json_data["payload"]["text"] = self.AI_TTS_str - json_data["payload"]["type"] = "transcript" - EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init}) - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_voice_chat_send,"data":ujson.dumps(json_data)}) - self.AI_TTS_str = "" - elif self.AI_ASR_str != "": - json_data["payload"]["text"] = self.AI_ASR_str - json_data["payload"]["type"] = "prompt" - EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init}) - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_voice_chat_send,"data":ujson.dumps(json_data)}) - self.AI_ASR_str = "" - # utime.sleep_ms(1) - #发送数据队列 - def AI_send_data_queue_thread(self): - print("AI_send_data_queue_thread:start") - count_t = 0 - while True: - if self.AI_send_data_queue.empty() :#不能去掉,去掉会卡死 - count_t+=1 - # if count_t%200 == 0: - # print("self.AI_send_data_queue.empty") - utime.sleep_ms(1) - else: - #data[0]是websocket连接对象编号,data[1]是数据 - #print("AI_send_data_queue_thread:get") - data = self.AI_send_data_queue.get() - #print("AI_send_data_queue_thread:num{} len{}".format(data[0],len(data[1]))) - if data != None: - try: - #data["func"](data["data"]) - # 发送数据 - #bytes_data = bytes(data[1]) - #data[0].send(data[1]) - #print("AI_send_data_queue_thread:len:{}".format(len(data[1]))) - #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))) - if data[0] == AI_client_voice_chat_num: - # if self.AI_client_voice_chat_isconnect == 0: - # try: - # self.websocket_connect_voice_chat() - # except Exception as e: #网络连接异常 - # usys.print_exception(e) - self.pingping_timerout = 0 - #print("VC: send_data len:{}".format(len(data[1]))) - if self.AI_client_voice_chat != None and self.AI_client_voice_chat_isconnect == 1: - self.AI_client_voice_chat.send(data[1]) - #print("VC: send_data end") - - if data[0] == AI_client_asr_num: - #self.pingping_timerout = 0 - #print("VC: send_data len:{}".format(len(data[1]))) - if self.AI_client_asr != None and self.AI_client_asr_isconnect == 1: - self.AI_client_asr.send(data[1]) - #print("VC: send_data end") - except Exception as e: - print("DeviceInfo_queue_thread:ERROR:{}".format(e)) - usys.print_exception(e) - if data[0] == AI_client_voice_chat_num: - #self.websocket_error() - pass - #self.websocket_deconnect_voice_chat() - self.AI_client_voice_chat_isconnect = 0 - try: - self.websocket_error() - #self.websocket_deconnect_voice_chat() - except Exception as e: #网络连接异常 - usys.print_exception(e) - if data[0] == AI_client_asr_num: - EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_connect_asr}) #重连 - - ############################################ - # 音频队列 - def AI_audio_queue_thread(self): - print("AI_audio_queue_thread start") - count = 0 - while True: - try: - # if self.AI_send_data_queue_thread_id == 0: - # break - # print("AI_audio_queue_thread") - if self.AI_audio_queue.empty() : - utime.sleep_ms(1) - count+=1 - if count%5000 == 1: - print("AI_audio_queue_thread on") - else: - data = self.AI_audio_queue.get() - self.close_timerout = 0 - if self.play_flag == 0: - self.play_flag =1 - print("AI_client_voice_chat_LocalRespondingStarted!!!") - self.AI_client_voice_chat_LocalRespondingStarted()#通知服务器开始播放 - #self.AI_client_tts_data_len=len(data) - print("\r\naudio_queue:len:{},data{}".format(len(data[0]),len(data[1]))) - if len(data[0]) > 10: - try: - if self.VC_play_TYPE == VC_play_TYPE_PCM: - if self.VC_play_samplerate == 8000: - tmp= self.aud.playStream(1,data[0] ) - elif self.VC_play_samplerate == 16000: - - - - write_buf = bytearray(data[0]) - #print("play_pcm.stream_write1!!") - if self.play_pcm != None: - ret = self.play_pcm.stream_write(write_buf,len(write_buf)) - #ret= self.aud.playStream(1, data[0])#播放音频流 - self.tts_out_data_len += ret - print("play_pcm.stream_write:{}".format(self.tts_out_data_len)) - elif self.VC_play_TYPE == VC_play_TYPE_MP3: - tmp= self.aud.playStream(3, data[0])#播放音频流 - - if tmp != 0: - print("2playStream:error tmp:{} data len:{}!!!!!!!!!!!!".format(tmp,len(data[0]))) - # # #播放失败的时候填充WAV头 - # data_len = len(data[0]) - # data_len_b = data_len.to_bytes(4,'little')#数据长度转16进制数组 - # h_data = [ 0x52 ,0x49 ,0x46 ,0x46 #,0x24 ,0x00 ,0x00 ,0x00 #文件标识、文件大小 - # ,0x57 ,0x41 ,0x56 ,0x45 ,0x66 ,0x6D ,0x74 ,0x20 #文件格式、格式块标识符 - # ,0x10 ,0x00 ,0x00 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x80 ,0x3E ,0x00 ,0x00 #格式块大小4、音频格式2、声道数2、采样率4 - # ,0x80 ,0x3E ,0x00 ,0x00 ,0x02 ,0x00 ,0x10 ,0x00 ,0x64 ,0x61 ,0x74 ,0x61]#每秒字节数4、数据块对齐2、位深度2、data4 - # h_data_b = bytes(h_data) - # file_len = data_len+len(h_data_b)+4+4 - # file_len_b = file_len.to_bytes(4,'little')#文件长度转16进制数组 - # h_data_b = h_data_b[:4]+file_len_b+h_data_b[4:]+data_len_b - # #self.aud.playStream(2, h_data_b)#播放音频流 - # tmp= self.aud.playStream(2, h_data_b+data[0])#播放音频流 - # print("3playStream:tmp:{} !!!!!!!!!!!!".format(tmp)) - - #print("出:{},{}!!!".format(len(data[0]),self.AI_client_tts_data_len)) - mem = gc.mem_free() - #print('1剩余内存RAM:{} KB'.format(mem / 1024)) - except Exception as e: - print("AI_audio_queue_thread:ERROR:") - usys.print_exception(e) - - # if self.voice_chat_state == VC_State_TTSEnd and self.AI_audio_queue.empty() :#self.AI_audio_queue为空且tts下发结束 - # #通知服务器播放结束 - # self.AI_client_voice_chat_LocalRespondingEnded() - except Exception as e: - print("AI_audio_queue_thread:ERROR:") - usys.print_exception(e) - #print("AI_audio_queue_thread:exit") - def factory_mode(self): - print("factory_mode") - EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) - EventMesh.publish("publish_AI_btnInfo",{"func":self.factory_start}) - def factory_start(self): - self.factory_timer.start(1000, 1, self.factory_timer_cb) - def factory_timer_cb(self, *args, **kwargs): - print("factory_timer_cb play......") - self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功 - - def Close(self): - print("ai_VC Close1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - self.tts_in_data_len = 0 - self.tts_out_data_len = 0 - - print("ai_VC Close1.1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - self.VC_init() - self.VC_Speech_End() - print("ai_VC Close1.2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - if self.AI_send_data_queue.empty()!=True: - self.AI_send_data_queue.clear() - self.AI_TTS_str = "" - self.AI_ASR_str = "" - self.AI_ASR_str_tmp = "" - self.AI_ASR_flag = 0 - print("ai_VC Close1.3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - try: - #销毁线程 - if self.AI_audio_queue_thread_id != 0: - try: - _thread.stop_thread(self.AI_audio_queue_thread_id) - except Exception as e: - usys.print_exception(e) - self.AI_audio_queue_thread_id = 0 - if self.AI_send_data_queue_thread_id != 0: - try: - _thread.stop_thread(self.AI_send_data_queue_thread_id) - except Exception as e: - usys.print_exception(e) - self.AI_send_data_queue_thread_id = 0 - - - except Exception as e: - usys.print_exception(e) - print("ai_VC Close2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - try: - self.websocket_deconnect_voice_chat() - except Exception as e: - usys.print_exception(e) - print("ai_VC Close3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n") - try: - self.websocket_deconnect_asr() - except Exception as e: - usys.print_exception(e) - self._1S_timer.stop() - self.factory_timer.stop() - - if self.record_data_save_flag == 1: - if self.record_fd : - self.record_fd.close() - self.record_fd = None - def VC_init2(self): - self.VC_init() - if self.AI_send_data_queue.empty()!=True: - self.AI_send_data_queue.clear() - print("ai_VC VC_init2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - try: - self.websocket_deconnect_voice_chat() - except Exception as e: - usys.print_exception(e) - print("ai_VC Close3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n") - self._1S_timer.stop() - - - def VC_init(self): - - print("VC_init:AI_send_data_queue:size:{}".format(self.AI_send_data_queue.size())) - if self.AI_audio_queue.empty()!=True: - self.AI_audio_queue.clear() - - print("VC_init2") - #self.VC_Speech_End() - print("VC_init3") - self.VC_Play_End() - print("VC_init4") - - EventMesh.publish("close_led") - # num = EventMesh.publish("get_volum_size") - # if num == None: - # num = 8 - # self.aud.setVolume(num)#恢复原始音量 - \ No newline at end of file diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/vc_config.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/vc_config.py new file mode 100644 index 00000000..68479bc2 --- /dev/null +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/vc_config.py @@ -0,0 +1,114 @@ +# 配置加载器:将 dev_type 分支逐步从 ai_VC.py 抽离出来。 +# +# 目标: +# - usr 下可覆盖(现场可改,无需重新 freeze) +# - freeze 内置默认值兜底(出厂可用) + +def _try_import(name): + try: + return __import__(name) + except Exception: + return None + + +# 只做“优先 import usr 下文件;失败再 import 默认文件”,不做变量覆盖/合并 +_DEFAULT_CFG_MODULE = None +_DEFAULT_CFG_LOADED = 0 + + +def load_default_config_module(): + global _DEFAULT_CFG_MODULE, _DEFAULT_CFG_LOADED + if _DEFAULT_CFG_LOADED: + return _DEFAULT_CFG_MODULE + _DEFAULT_CFG_LOADED = 1 + # 兼容用户描述里的拼写 defualt_config.py + _DEFAULT_CFG_MODULE = ( + _try_import("usr.default_config") + or _try_import("usr.defualt_config") + or _try_import("default_config") + ) + return _DEFAULT_CFG_MODULE + +def get_dev_type(default_dev_type="7PIN"): + m = load_default_config_module() + try: + if m and hasattr(m, "DEV_TYPE"): + return getattr(m, "DEV_TYPE") or default_dev_type + except Exception: + return default_dev_type + return default_dev_type + + +def led_gpio_tuple(Pin=None): + # 从 default_config(或 usr/default_config) 取 LED_GPIO。 + # 返回 (r_gpio, g_gpio, b_gpio) 的 Pin.GPIOxx 常量。 + if Pin is None: + try: + from machine import Pin as _Pin + Pin = _Pin + except Exception: + # 无法获取 Pin 类型时,无法做 GPIO 名称到常量的映射,直接返回常用默认值 + return (36, 21, 19) + m = load_default_config_module() + names = None + try: + if m and hasattr(m, "LED_GPIO"): + names = getattr(m, "LED_GPIO") + except Exception: + names = None + + if isinstance(names, (tuple, list)) and len(names) == 3: + try: + return (getattr(Pin, names[0]), getattr(Pin, names[1]), getattr(Pin, names[2])) + except Exception: + pass + try: + return (Pin.GPIO36, Pin.GPIO21, Pin.GPIO19) + except Exception: + return (36, 21, 19) + + +def uart_supported(): + m = load_default_config_module() + try: + if m and hasattr(m, "UART_SUPPORTED"): + return bool(getattr(m, "UART_SUPPORTED")) + except Exception: + pass + return False + + +def lang(default_lang="zh"): + m = load_default_config_module() + try: + if m and hasattr(m, "LANG"): + return getattr(m, "LANG") or default_lang + except Exception: + return default_lang + return default_lang + + +def get_attr(name, default=None): + m = load_default_config_module() + try: + if m and hasattr(m, name): + return getattr(m, name) + except Exception: + pass + return default + + +def get_int(name, default=0): + try: + v = get_attr(name, default) + return int(v) + except Exception: + return int(default) + + +def get_bool(name, default=False): + try: + return bool(get_attr(name, default)) + except Exception: + return bool(default) + diff --git a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/versions.py b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/versions.py index a8b4b6df..ab8f76c1 100644 --- a/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/versions.py +++ b/2.sdk/project/7PIN_1_5/sdk/services/microPython/ports/quectel/core/versions.py @@ -1,2 +1,2 @@ Version="V1.0" -Build_Time="2026-05-07 14:29:21" +Build_Time="2026-05-08 5:36:51" diff --git a/2.sdk/project/7PIN_1_5/sdk/system/platform/ASR_1606/boards/EG810MCN_GA_VOLTE/images/firmware_base_release_pack.zip b/2.sdk/project/7PIN_1_5/sdk/system/platform/ASR_1606/boards/EG810MCN_GA_VOLTE/images/firmware_base_release_pack.zip index 55f3cd6a..f75fe005 100644 Binary files a/2.sdk/project/7PIN_1_5/sdk/system/platform/ASR_1606/boards/EG810MCN_GA_VOLTE/images/firmware_base_release_pack.zip and b/2.sdk/project/7PIN_1_5/sdk/system/platform/ASR_1606/boards/EG810MCN_GA_VOLTE/images/firmware_base_release_pack.zip differ