From: azao <821478748@qq.com> Date: Mon, 15 Sep 2025 09:18:13 +0000 (+0800) Subject: 金三完美提交1 X-Git-Url: http://git.snicker.com.cn/sitemap.xml?a=commitdiff_plain;h=ddcbb4a678ea06fe486707842a587e6494dda2b4;p=mirrors%2FASR1603_G5.git 金三完美提交1 --- diff --git a/2.sdk/project/K8/ext/static/01.jpg b/2.sdk/project/K8/ext/static/01.jpg new file mode 100644 index 00000000..b4509914 Binary files /dev/null and b/2.sdk/project/K8/ext/static/01.jpg differ diff --git a/2.sdk/project/K8/ext/static/02.jpg b/2.sdk/project/K8/ext/static/02.jpg new file mode 100644 index 00000000..d4b7104c Binary files /dev/null and b/2.sdk/project/K8/ext/static/02.jpg differ diff --git a/2.sdk/project/K8/ext/static/51.jpg b/2.sdk/project/K8/ext/static/51.jpg new file mode 100644 index 00000000..25b7dde2 Binary files /dev/null and b/2.sdk/project/K8/ext/static/51.jpg differ diff --git a/2.sdk/project/K8/ext/static/52.jpg b/2.sdk/project/K8/ext/static/52.jpg new file mode 100644 index 00000000..460fdb4a Binary files /dev/null and b/2.sdk/project/K8/ext/static/52.jpg differ diff --git a/2.sdk/project/K8/ext/static/61.jpg b/2.sdk/project/K8/ext/static/61.jpg new file mode 100644 index 00000000..9d16b45b Binary files /dev/null and b/2.sdk/project/K8/ext/static/61.jpg differ diff --git a/2.sdk/project/K8/ext/static/62.jpg b/2.sdk/project/K8/ext/static/62.jpg new file mode 100644 index 00000000..0eb0ade1 Binary files /dev/null and b/2.sdk/project/K8/ext/static/62.jpg differ diff --git a/2.sdk/project/K8/ext/static/dj1.jpg b/2.sdk/project/K8/ext/static/dj1.jpg new file mode 100644 index 00000000..948a3244 Binary files /dev/null and b/2.sdk/project/K8/ext/static/dj1.jpg differ diff --git a/2.sdk/project/K8/ext/static/dj2.jpg b/2.sdk/project/K8/ext/static/dj2.jpg new file mode 100644 index 00000000..eaaeed91 Binary files /dev/null and b/2.sdk/project/K8/ext/static/dj2.jpg differ diff --git a/2.sdk/project/K8/ext/static/j1.jpg b/2.sdk/project/K8/ext/static/j1.jpg new file mode 100644 index 00000000..374f7054 Binary files /dev/null and b/2.sdk/project/K8/ext/static/j1.jpg differ diff --git a/2.sdk/project/K8/ext/static/j2.jpg b/2.sdk/project/K8/ext/static/j2.jpg new file mode 100644 index 00000000..02642bd7 Binary files /dev/null and b/2.sdk/project/K8/ext/static/j2.jpg differ diff --git a/2.sdk/project/K8/ext/static/mj1.jpg b/2.sdk/project/K8/ext/static/mj1.jpg new file mode 100644 index 00000000..b30f6170 Binary files /dev/null and b/2.sdk/project/K8/ext/static/mj1.jpg differ diff --git a/2.sdk/project/K8/ext/static/mj2.jpg b/2.sdk/project/K8/ext/static/mj2.jpg new file mode 100644 index 00000000..ca83eaad Binary files /dev/null and b/2.sdk/project/K8/ext/static/mj2.jpg differ diff --git a/2.sdk/project/K8/ext/static/zj1.jpg b/2.sdk/project/K8/ext/static/zj1.jpg new file mode 100644 index 00000000..2cdc10e4 Binary files /dev/null and b/2.sdk/project/K8/ext/static/zj1.jpg differ diff --git a/2.sdk/project/K8/ext/static/zj2.jpg b/2.sdk/project/K8/ext/static/zj2.jpg new file mode 100644 index 00000000..95f93dac Binary files /dev/null and b/2.sdk/project/K8/ext/static/zj2.jpg differ diff --git a/2.sdk/project/K8/images/customer_fs.bin b/2.sdk/project/K8/images/customer_fs.bin index 87882e52..85388b1b 100644 Binary files a/2.sdk/project/K8/images/customer_fs.bin and b/2.sdk/project/K8/images/customer_fs.bin differ diff --git a/2.sdk/project/K8/images/ext_fs.bin b/2.sdk/project/K8/images/ext_fs.bin index 783b2ac6..b5dcd173 100644 Binary files a/2.sdk/project/K8/images/ext_fs.bin and b/2.sdk/project/K8/images/ext_fs.bin differ diff --git a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/Makefile b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/Makefile index 3ea119b4..2046e7d7 100644 --- a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/Makefile +++ b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/Makefile @@ -974,6 +974,7 @@ frozen_mpy_list = $(BUILD)/_boot.mpy \ $(BUILD)/motor.mpy \ $(BUILD)/ai_VC.mpy \ $(BUILD)/ui_setting.mpy \ + $(BUILD)/ai_alarm.mpy \ endif diff --git a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ai_VC.py b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ai_VC.py index 36fbf34e..b032beb3 100644 --- a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ai_VC.py +++ b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ai_VC.py @@ -30,10 +30,17 @@ import machine import dataCall import constants import versions +import usocket +import lvgl as lv try: import VAD except Exception as e: usys.print_exception(e) +try: + import usr.ai_alarm as _ai_alarm +except Exception as e: + usys.print_exception(e) + import ai_alarm as _ai_alarm #dev_type = "G10" #dev_type = "7PIN_BK"#小瑞 #dev_type = "7PIN_BK_coze"#k扣子小瑞 @@ -262,6 +269,7 @@ class AI_dev(Abstract): EventMesh.subscribe("paly_iccid_imei",self.paly_iccid_imei) EventMesh.subscribe("paly_device_res_error",self.paly_device_res_error) EventMesh.subscribe("Power_off",self.pwk_key_Long_Press) + EventMesh.subscribe("get_usb_status",self.get_usb_status) print("AI_dev:2") self.pk = PowerKey() @@ -278,9 +286,8 @@ class AI_dev(Abstract): self.Low_power_warning_flag = 0 self.VC_TTS_volume = EventMesh.publish("get_storage_config","VC_TTS_volume")#音量配置 if self.VC_TTS_volume == None: - self.VC_TTS_volume = 110 - self.aud.setVolume(self.VC_TTS_volume // 10) - print("音量初始化DEV配置为{}".format(self.VC_TTS_volume // 10)) + 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}) @@ -288,7 +295,7 @@ class AI_dev(Abstract): #双击逻辑 self.last_time = 0 #上次时间 - self.gap_time = 2000 #双击间隔时间(ms) + self.gap_time = 1500 #双击间隔时间(ms) self.double_flag = 0 #双击标志 self.double_release_timer = osTimer()#双击释放定时器 print("AI_dev:end") @@ -297,7 +304,8 @@ class AI_dev(Abstract): 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 get_usb_status(self,event= None,msg = None): + return self.usb_status def usb_event(self, state): status = state self.usb_charge_flag = 0 @@ -305,6 +313,7 @@ class AI_dev(Abstract): print("charge R_CHARGE_in") self.usb_status = 1 VC_satrt_flag = EventMesh.publish("get_VC_satrt_flag")#获取vc是否在运行 + EventMesh.publish("send_device_information")#发送设备信息 if VC_satrt_flag == None: VC_satrt_flag = 0 if VC_satrt_flag == 0: @@ -319,6 +328,7 @@ class AI_dev(Abstract): elif status == 0:#拨出usbs self.usb_status = 0 VC_satrt_flag = EventMesh.publish("get_VC_satrt_flag")#获取vc是否在运行 + EventMesh.publish("send_device_information")#发送设备信息 if VC_satrt_flag == None: VC_satrt_flag = 0 if VC_satrt_flag == 0: @@ -444,20 +454,23 @@ class AI_dev(Abstract): self.KeyAI_timer_count = 0 EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_key_double_press}) # 启动双击释放检测计时器 - self.double_release_timer.start(500, 1, self.double_release_timeout) + self.double_release_timer.start(500, 0, self.double_release_timeout) return - - EventMesh.publish(constants.EVENT.SYSTEM_UP)#唤醒休眠 - 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") - if dev_type == "7PIN" or dev_type == "7PIN_coze" : - self.aud.aud_tone_play(10,200)#播放按键音 - EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_key_press}) - self.last_time = current_time + elif time_tiff > 0 and current_time - self.last_time > self.gap_time:#判断为单击 + EventMesh.publish(constants.EVENT.SYSTEM_UP)#唤醒休眠 + self.extint_AI.disable() + self.KeyAI_press = 1 + self.KeyAI_long_press = 0 + self.double_flag = 0 + self.KeyAI_timer.start(100, 1, self.KeyAI_timer_cb) + self.KeyAI_timer_count = 0 + #EventMesh.publish("AI_key_press") + screen_name = EventMesh.publish("get_screen_NAME") + if screen_name != "system_init" and screen_name != "poweron": + if dev_type == "7PIN" or dev_type == "7PIN_coze" : + self.aud.aud_tone_play(10,200)#播放按键音 + EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_key_press}) + self.last_time = current_time else: # 释放 if self.double_flag: # 双击释放处理 @@ -468,12 +481,15 @@ class AI_dev(Abstract): self.KeyAI_timer_count = 0 self.KeyAI_press = 0 return + except Exception as e: usys.print_exception(e) def double_release_timeout(self, *args, **kwargs):#双击释放超时处理 + print("定时器未关闭!!!!!!!!") if self.double_flag: #如果超时仍未释放,重置双击状态 self.double_flag = 0 + self.double_release_timer.stop() def AI_key_double_release(self): EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_key_double_press}) @@ -484,7 +500,7 @@ class AI_dev(Abstract): try: self.KeyAI_status = self.extint_AI.read_level() self.KeyAI_timer_count +=1 - print("self.KeyAI_timer_count = {}".format(self.KeyAI_timer_count)) + # print("self.KeyAI_timer_count = {}".format(self.KeyAI_timer_count)) if self.KeyAI_timer_count >= 10*1 : #长按1s if self.KeyAI_long_press == 0: self.KeyAI_long_press = 1 @@ -511,23 +527,6 @@ class AI_dev(Abstract): self.KeyAI_timer.stop() self.KeyAI_timer_count = 0 self.KeyAI_press = 0 - # current_time = utime.ticks_ms() - # print("current_time:{},last_time:{},current_time - self.last_time={}".format(current_time,self.last_time,current_time - self.last_time)) - # if (current_time - self.last_time <= self.gap_time):#鉴定为双击 - # print("AI_key_double_press DOUBLE DOUBLE ") - # self.double_flag = 1#切换标志位 - # self.KeyAI_long_press = 0 - # self.KeyAI_press = 0 - # self.KeyAI_timer_count = 0 - # EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_key_double_press}) - # return - # else: - # EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_key_press}) - # self.KeyAI_press = 1 - # self.KeyAI_long_press = 0 - # self.KeyAI_timer_count = 0 - - # self.last_time = current_time except Exception as e: usys.print_exception(e) @@ -554,13 +553,13 @@ class AI_dev(Abstract): self.check_rest_timer_count = 0 print("pwk_key_long_press!!!!!!!") print("pwk_key_long_press!!!!!!!") + EventMesh.publish_async("audio_montage_play",["zhengzaiguanji.mp3"]) EventMesh.publish("load_screen", {"screen": "poweroff_comfirm"})#关机画面 # EventMesh.publish("paly_iccid_imei") # return - EventMesh.publish_async("audio_montage_play",["zhengzaiguanji.mp3"]) #self.aud.play(1,0,'U:/static/zhengzaiguanji.mp3')#关机音频 EventMesh.publish("open_led_red") - utime.sleep_ms(3000) + utime.sleep_ms(4000) self.aud.stopPlayStream() self.aud.stopAll() Power.powerDown() @@ -588,23 +587,30 @@ class AI_dev(Abstract): VC_satrt_flag = 0 Vbatt = Power.getVbatt() if self.usb_status == 1 and VC_satrt_flag == 0: - EventMesh.publish("open_led_red")#充电红灯常亮 + #EventMesh.publish("open_led_red")#充电红灯常亮 + pass if self.usb_status == 1 and Vbatt>=self.VBATT_tab["charge_full"]and VC_satrt_flag == 0:#充电充满 - EventMesh.publish("open_led_green") + #EventMesh.publish("open_led_green") if self.usb_charge_flag == 0 : - EventMesh.publish("audio_montage_play",["R_CHARGE_FULL.mp3"]) - EventMesh.publish("load_screen", {"screen": "charge_full"})#满电弹窗 - #self.aud.play(1,0,'U:/static/R_CHARGE_FULL.mp3')#充电已满 - # EventMesh.publish("load_screen", {"screen": "charge_full"})#充满电弹窗 - 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") @@ -753,6 +759,7 @@ class device_res_author(Abstract): #7pin self.key = b"uKLrChwrxA1LklgBc3VwawYjUkbT3BgX" self.pid = "cqxJZi5CNgzjS3mX21Zw" + # if dev_type == 'jswm' or dev_type == 'jswm_BOX':#金三完美 # self.key = b"FuXG4ptpGbzvKbdB4vpUypisbENgy2nB" # self.pid = "DieBeXahZHLrjSnORbgN" @@ -770,6 +777,8 @@ class device_res_author(Abstract): EventMesh.subscribe("dev_active", self.dev_active) EventMesh.subscribe("dev_sign_in", self.dev_sign_in) EventMesh.subscribe("dev_NTP", self.dev_NTP) + EventMesh.subscribe("iccid_get", self.iccid_get) + EventMesh.subscribe("post_iccid", self.post_iccid) #EventMesh.publish_async("dev_NTP",thread_size = 8192) # count = 0 @@ -782,14 +791,46 @@ class device_res_author(Abstract): # break # EventMesh.publish_async("dev_active",thread_size = 8192) # EventMesh.publish_async("dev_sign_in",thread_size = 8192) - self.dev_NTP()#获取时间 self.dev_active() #设备激活 self.dev_sign_in() #设备登入 + self.post_iccid()#上报iccid + self.iccid_get()#自动充值 print("device_res_author __init__ end !!!!!!!!!!!!!!!!!") def get_dev_token(self, event, msg): return self.dev_token + #上报iccid + def post_iccid(self, event=None, msg=None): + print("post_iccid") + deviceId = self.deviceId + url = "https://dmp-dev.raisound.com/dmp-api/dev/iccid" + token = self.dev_token + if token == None: + token = "" + iccid = sim.getIccid() + headers_T = {"bz-dt":"{}".format(token),"Content-Type":"application/x-www-form-urlencoded"} + data = "deviceId={}&iccid={}".format(deviceId,iccid) + print(ujson.dumps(data)) + response = request.post(url,data=data,headers = headers_T,timeout=5) + data = response.json() + print("iccid_post:{}".format(data)) + print("end_post_iccid") + + #自动充值 + def iccid_get(self, event=None, msg=None): + print("iccid_get") + url = "https://dmp-dev.raisound.com/dmp-api/sv/iccid/charge-task?deviceId={}".format(self.deviceId) + token = self.dev_token + if token == None: + token = "" + headers_T = {"bz-dt":"{}".format(token),"Content-Type":"application/x-www-form-urlencoded"} + print("bz-dt:{}".format(token)) + response = request.get(url,headers = headers_T,timeout=5) + data = response.json() + print("iccid_get:{}".format(data)) + print("end_iccid_get") + #网络校时 def dev_NTP(self, event=None, msg=None): response = None @@ -799,6 +840,7 @@ class device_res_author(Abstract): if dev_type == "7PIN_BK_EU":#英文小瑞 url = "http://dmp-global.raisound.com/bz-api/dev/time" else: + # url = "http://dmp-dev.raisound.com/dmp-api/dev/time" url = "http://dmp.raisound.com/bz-api/dev/time" response = request.get(url,timeout=5) data = response.json() @@ -832,6 +874,8 @@ class device_res_author(Abstract): print("timer:{}!!!!!!!!\r\n".format(utime.localtime())) EventMesh.publish_async("dev_active",thread_size = 8192) EventMesh.publish_async("dev_sign_in",thread_size = 8192) + EventMesh.publish_async("post_iccid",thread_size = 8192) + EventMesh.publish_async("iccid_get",thread_size = 8192) # self.dev_active() #设备激活 # self.dev_sign_in() #设备登入 self.dev_res_timerCount+=1 @@ -929,6 +973,7 @@ class device_res_author(Abstract): if dev_type == "7PIN_BK_EU":#英文小瑞 url = "http://dmp-global.raisound.com/bz-api/dev/auth/active" else: + # url = "http://dmp-dev.raisound.com/dmp-api/dev/auth/active" url = "http://dmp.raisound.com/bz-api/dev/auth/active" data =ujson.dumps(data) response = None @@ -1040,6 +1085,7 @@ class device_res_author(Abstract): if dev_type == "7PIN_BK_EU":#英文小瑞 sign_url = "http://dmp-global.raisound.com/bz-api/dev/auth/sign_in" #登入地址 else: + # sign_url = "http://dmp-dev.raisound.com/dmp-api/dev/auth/sign_in" sign_url = "http://dmp.raisound.com/bz-api/dev/auth/sign_in" #登入地址 headers_T ={"Content-Type":"application/json"} response_result = 0 @@ -1106,6 +1152,7 @@ class device_res_author(Abstract): if dev_type == "7PIN_BK_EU":#英文小瑞 dev_tokenip = "http://dmp-global.raisound.com/bz-api/dev/auth/token" #设备新令牌更新地址 else: + # dev_tokenip = "http://dmp-dev.raisound.com/dmp-api/dev/auth/token" dev_tokenip = "http://dmp.raisound.com/bz-api/dev/auth/token" #设备新令牌更新地址 token = self.dev_token if token == None: @@ -1136,7 +1183,7 @@ class device_res_author(Abstract): except Exception as e: usys.print_exception(e) print("update_dev_token end") - + #OTA升级 class OTA(): def __init__(self): @@ -1157,7 +1204,7 @@ class OTA(): self.downloadFileVoURL2= "" try: sourceVersion = versions.Build_Time - sourceVersion = "7PIN-"+sourceVersion[:10]+"-"+sourceVersion[11:-3] + sourceVersion = "JSWM-"+sourceVersion[:10]+"-"+sourceVersion[11:-3] print("sourceVersion:{}".format(sourceVersion)) sourceVersion = sourceVersion.replace(" ", "0") print("sourceVersion2:{}".format(sourceVersion)) @@ -1221,7 +1268,7 @@ class OTA(): response = None try: currentVersion = versions.Build_Time - currentVersion = "7PIN-"+currentVersion[:10]+"-"+currentVersion[11:-3] + currentVersion = "JSWM-"+currentVersion[:10]+"-"+currentVersion[11:-3] print("currentVersion1:{}".format(currentVersion)) currentVersion = currentVersion.replace(" ", "0") print("currentVersion2:{}".format(currentVersion)) @@ -1262,7 +1309,7 @@ class OTA(): url =None if dev_type == "7PIN_BK_EU":#英文小瑞 url = "http://dmp-global.raisound.com/bz-api/dev/iccid?deviceId={}&iccid={}".format(modem.getDevImei(),iccid) - else: + else: url = "http://dmp.raisound.com/bz-api/dev/iccid?deviceId={}&iccid={}".format(modem.getDevImei(),iccid) print("{} H:{}".format(url,headers_T)) response = request.post(url,headers = headers_T,timeout=5) @@ -1308,7 +1355,6 @@ VC_play_TYPE_MP3 = 1 AI_client_VC_num = 3 AI_client_asr_num = 4 - class AI_VC(Abstract): # AI @@ -1323,6 +1369,7 @@ class AI_VC(Abstract): self.VC_30S_timer = osTimer() self.VC_30S_timer.start(30000, 1, self.VC_30S_timer_cb) self.get_config_timer_count = 0 + self.send_timer_count = 0 self.record_data_save_flag = 0 #是否保存录音文件 self.play_data_save_flag = 0#是否保存tts数据到文件 self.record_fd = None @@ -1337,12 +1384,21 @@ class AI_VC(Abstract): self.VC_mode = 0 self.is_up_error= 0 #是否上传错误id self.Close_flag =0 #=1时,连续对话播放完音频就退出 - + self.AI_alarm = _ai_alarm.AI_alarm() + + #表情变化状态以及检索词 + self.face_status = 0 # 0为正常,1为哭泣,2为愤怒,3为疑惑 + self.normal_list = ["别生气"] + self.cry_list = ["委屈","难过","伤","哭","泪","颤抖","湿润","泛红","惊慌","担忧","失落","对不起","打扰"] + self.angry_list = ["怒","生气","不耐烦"] + self.confused_list = ["疑惑","困惑","好奇"] + self.error_data = [] self.asr_taskid = "" self.VC_taskid = "" self.VC_server = 2 #0柒牌正式服务器,1:测试服务器1,2:测试服务器2 + self.server_ip = EventMesh.publish("get_storage_config","server_ip")# if self.server_ip == None: if self.VC_server == 1:# @@ -1360,13 +1416,15 @@ class AI_VC(Abstract): elif self.VC_server == 8:# self.server_ip="115.190.94.208:22080" elif self.VC_server == 86:# - self.server_ip="118.145.158.207:22086" + self.server_ip="118.145.158.207:22086" + # self.server_ip="118.145.158.207:22080" else: #self.server_ip="sevenpin.qipai.com.cn" self.server_ip="118.145.158.207:22082" if dev_type == 'jswm' or dev_type == 'jswm_BOX':# #self.server_ip="115.190.94.208:22080" - self.server_ip="118.145.158.207:22086" + # self.server_ip="118.145.158.207:22086" + self.server_ip="118.145.158.207:22080" elif dev_type == "7PIN" or dev_type == "7PIN_coze": #self.server_ip="sevenpin.qipai.com.cn" # self.server_ip="220.160.104.34" @@ -1739,7 +1797,7 @@ class AI_VC(Abstract): except Exception as e: usys.print_exception(e) #配置词 - self.commands_mode = 2 #=1用大模型判断命令,=0用服务器本地插件判断命令 =2用设备本地判断方式 + self.commands_mode = 1 #=1用大模型判断命令,=0用服务器本地插件判断命令 =2用设备本地判断方式 if dev_type == "7PIN_BK"or dev_type == "7PIN_BK_EU"or dev_type == "7PIN_BK_coze": self.commands_mode = 2 self.commands = [ @@ -1920,6 +1978,7 @@ class AI_VC(Abstract): self.AI_audio_queue = Queue(100) #self.AI_WS_connect_Queue = Queue(100) #释放用 self.AI_TTS_str = "" + self.AI_music_str = "" self.AI_ASR_str = "" self.AI_ASR_flag = 0 self.AI_ASR_str_tmp = "" @@ -1957,6 +2016,7 @@ class AI_VC(Abstract): self.AI_ASR_check_timeout = 0 self.AI_ASR_error_timeout = 0 self.VC_Thinking_timerout = 0 + self.record_pcm = None self.play_pcm = None @@ -1989,6 +2049,8 @@ class AI_VC(Abstract): self.tts_out_data_len = 0 self.VC_satrt_flag = 0 self.session_id = "" + + self.draw_result = 0#抽签结果 EventMesh.subscribe("AI_key_press", self.AI_key_press) EventMesh.subscribe("AI_key_double_press", self.AI_key_double_press) EventMesh.subscribe("AI_key_release", self.AI_key_release) @@ -1998,6 +2060,14 @@ class AI_VC(Abstract): EventMesh.subscribe("get_VC_satrt_flag", self.get_VC_satrt_flag) EventMesh.subscribe("VC_error", self.VC_error) EventMesh.subscribe("screen_get_ai", self.screen_get_ai) + EventMesh.subscribe("screen_get_draw", self.screen_get_draw) + EventMesh.subscribe("screen_get_face", self.screen_get_face) + EventMesh.subscribe("play_tts", self.play_tts) + EventMesh.subscribe("play_tts_open", self.play_tts_open) + EventMesh.subscribe("play_tts_single", self.play_tts_single) + EventMesh.subscribe("draw_handle", self.draw_handle) + EventMesh.subscribe("dmp_update", self.dmp_update) + EventMesh.subscribe("update_volume", self.update_volume) EventMesh.publish("close_led") self.bot_name = "柒先生" @@ -2026,6 +2096,7 @@ class AI_VC(Abstract): #EventMesh.publish("get_storage_config",["powerRestart",1]) + self.aud.play(1, 1, 'E:/static/R_POWER_1.mp3') #播放播放开机铃声 powerRestart = EventMesh.publish("get_storage_config","powerRestart")#=1非正常重启 if powerRestart == None: powerRestart = 0 @@ -2051,12 +2122,93 @@ class AI_VC(Abstract): return self.VC_satrt_flag def screen_get_ai(self, event=None, msg=None): return self.VC_state + def screen_get_draw(self, event=None, msg=None): + return self.draw_result + def screen_get_face(self, event=None, msg=None): + return self.face_status + def create_ordered_json(self,device_id, server_ip, signalLevel, battery): + # 按预期顺序手动拼接JSON字符串 + # 外层结构:先path,后Body + json_str = "{" + # 1. 拼接path部分(固定顺序) + json_str += '"path": {{"deviceId": "{}"}},'.format(device_id) + # 2. 拼接Body部分(按需求顺序排列) + json_str += '"Body": {' + json_str += '"wifiName": "",' + json_str += '"ipAddr": "{}",'.format(server_ip) + json_str += '"dnsAddr": "8.8.8.8",' + json_str += '"gateWayAddr": "192.168.0.1",' + json_str += '"signalLevel": "{}",'.format(signalLevel) + json_str += '"battery": "{}"'.format(battery) + json_str += "}" + # 闭合外层 + json_str += "}" + return json_str + + def dmp_update(self, event=None, msg=None): + device_id = modem.getDevImei() + signalLevel = str(net.csqQueryPoll()*3) + "%" + battery = str((EventMesh.publish("screen_get_battery"))[1]) + "%" + datacall = dataCall.getInfo(1, 0) + network_info_list = datacall[2] + # 验证是否为列表(避免数据类型错误) + if not isinstance(network_info_list, list): + print("tuple 索引2不是列表,无法提取 priDNS") + return None + + # 2. 第二步:从嵌套列表索引3获取 priDNS + pri_dns = network_info_list[3] + # 3. 验证 priDNS 有效性(可选,避免空值或无效格式) + if isinstance(pri_dns, str) and "." in pri_dns: # DNS通常含"."(如114.114.114.114) + print("dns合法") + pass + else: + print("priDNS 格式无效") + return + dmp_data = { + "wifiName": "", + "ipAddr": "{}".format(self.server_ip), + "dnsAddr": "{}".format(pri_dns), + "gateWayAddr": "192.168.0.1", + "signalLevel": "{}".format(signalLevel), + "battery": "{}".format(battery) + } + # # 生成有序JSON + # ordered_json = self.create_ordered_json(device_id, self.server_ip, signalLevel, battery) + # print(ordered_json) + token = EventMesh.publish("get_dev_token") + print("bz_dt = {}".format(token)) + headers_T ={ + "Content-Type":"application/json", + "bz-dt":"{}".format(token) + } + dmp_url = "http://app-api.raisound.com/dev/device/network/{}".format(device_id) + # dmp_url = "http://dmp.raisound.com/dmp-api/dev/device/network/{}".format(device_id) + print("url = {}".format(dmp_url)) + # dmp_data =ujson.dumps(dmp_data) + print("data_type:{},data:{}".format(type(ujson.dumps(dmp_data)),ujson.dumps(dmp_data))) + + try: + print("put") + request.put(dmp_url,data=ujson.dumps(dmp_data),headers = headers_T,timeout=5) + print("putover") + except Exception as e: + usys.print_exception(e) + print("dmp_update put error!!!!!\r\n") + + def update_volume(self,event,msg): + self.VC_TTS_volume = msg + self.aud.setVolume(self.VC_TTS_volume//10) + EventMesh.publish("set_storage_config",["VC_TTS_volume",msg]) + print("声音改为{}".format(msg)) def VC_30S_timer_cb(self, *args): # EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_30S_timer_cb_}) def VC_30S_timer_cb_(self): + # print('VC_30S_timer_cb_') self.get_config_timer_count += 1 + self.send_timer_count += 1 if self.get_config_timer_count >= 2*60*2:#2小时更新配置参数 self.get_config_timer_count = 0 try: @@ -2098,7 +2250,8 @@ class AI_VC(Abstract): elif dev_type == "7PIN" or dev_type == "7PIN_coze":#柒牌 url = "http://ota.qipai.com/bz-cmp-api/api/config/{}".format(modem.getDevImei()) else: - url = "http://dmp.raisound.com/bz-api/dev/config/{}".format(modem.getDevImei()) + url = "http://dmp-dev.raisound.com/dmp-api/dev/config/{}".format(modem.getDevImei()) + # url = "http://dmp.raisound.com/bz-api/dev/config/{}".format(modem.getDevImei()) print(url) @@ -2139,6 +2292,45 @@ class AI_VC(Abstract): usys.print_exception(e) if response != None: response.close() + def play_tts(self,event = None,msg= None): + EventMesh.publish("publish_AI_btnInfo",{"func":self.play_tts_cb,"data":msg}) + + + def play_tts_open(self,event = None,msg= None):#播报tts并开启vc + print("play_tts_open:{}".format(msg)) + self.AI_TTS_str = msg + # EventMesh.publish("AI_key_press") + EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) + + def play_tts_single(self,event, msg):#单次传递音频文本 + print("play_tts_single:{}".format(msg)) + self.AI_TTS_str = msg + EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) + self.Close_flag = 1 + def play_tts_cb(self,data): + try: + tts_str = data[0] + is_close_VC = data[1] + if tts_str != "": + self.AI_TTS_str = tts_str + if is_close_VC != None: + self.Close_flag = is_close_VC + if self.AI_VC_send_data_queue.empty()!=True: + 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") + self.AI_ASR_send_buf_len = 0 + self.VC_Speech_End() + self.websocket_deconnect_VC() + self.AI_VC_start() + + # EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Speech_End}) + # EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_deconnect_VC}) + # EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_VC_start}) + except Exception as e: + usys.print_exception(e) + pass def audio_cb(self,event): if event == 0: @@ -2151,12 +2343,18 @@ class AI_VC(Abstract): print('audio-play finish.!!!!!!') def AI_key_double_press(self, event, msg):#双击按键 print("AI_key_double_press") - self.Close_flag = 1 + # self.Close_flag = 1 self.Close() - EventMesh.publish("load_screen", {"screen": "main_menu"}) + EventMesh.publish("UI_ai_close") + EventMesh.publish("return_prev_screen") def AI_key_press(self, event, msg):#按键按下 + # 测试闹钟功能 + # EventMesh.publish("AI_alarm_open") + # EventMesh.publish("AI_add_alarm",[{"alarm_type":"单次闹钟","alarm_timestamp":1753071946,"repeat_day":"2025-07-21","repeat_min":0,"valid_time":"","alarm_timer":"12:25","alarm_content":"开会"}]) + # return print("AI_key_press") + EventMesh.publish("send_device_VC_state")#上传VC状态 self.get_config_timer_count = 0 self.key_state = 1 self.Close() @@ -2173,9 +2371,12 @@ class AI_VC(Abstract): #if self.VC_record_state_flag >1:#如果在录音,就先停止录音 self.VC_Speech_End() # return - self.VC_Speech_Start() + # self.VC_Speech_Start() self.AI_VC_start() + lv.img.cache_invalidate_src(None) + lv.img.cache_set_size(8) EventMesh.publish("load_screen", {"screen": "UI_ai"})#ai画面 + EventMesh.publish("audio_montage_play",["chenggong.mp3"]) # if dev_type != "7PIN": # self.chenggong_tone() # self.Close() @@ -2225,9 +2426,9 @@ class AI_VC(Abstract): if self.AI_ASR_flag != 0: return - if self.VC_record_state_flag == 0: - + if self.VC_record_state_flag == 0: self.VC_record_thread_close()#关闭录音线程 + _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) @@ -2449,9 +2650,14 @@ class AI_VC(Abstract): except Exception as e: usys.print_exception(e) self.record_fd = open('/usr/record_data.pcm','w') + self.record_file_len = 0 if self.record_fd != None: self.record_fd.write(read_buf) print("write record:{}".format(len(read_buf))) + self.record_file_len+=len(read_buf) + if self.record_file_len>=200*1024: + EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) + print("write record:{}".format(len(read_buf))) # count+=Record_len # if count >150*1024: # self.record_fd.close() @@ -2481,6 +2687,7 @@ class AI_VC(Abstract): print("VC_record_thread:exit") self.VC_record_thread_id = 0#线程退出 self.VC_record_thread_lock = 0 + ###################################################### VC ################################################################################### def websocket_connect_VC(self): print("websocket_connect_VC:{} e:{}!!!!!!!!!!!!!!!!!!!!!".format(self.AI_client_VC_isconnect,self.AI_client_VC_debug)) @@ -2528,16 +2735,17 @@ class AI_VC(Abstract): req_str = "vc/agent?is_auth={}".format(self.is_auth) if(token): - url = 'ws://{}/{}&dt={}'.format(self.server_ip,req_str,token) + # url = 'ws://{}/{}&dt={}'.format(self.server_ip,req_str,token) + url = 'ws://{}/vc/agent'.format(self.server_ip) else: url = 'ws://{}/{}'.format(self.server_ip,req_str) #url = 'ws://115.190.94.208:22080/vc/coze?dt={}'.format(token) - + #ws://118.145.158.207:22080/vc/agent + # url = "ws://ec2-3-81-87-67.compute-1.amazonaws.com:22080/vc/chat" print("VC VC:url{}".format(url)) self.AI_client_VC = uwebsocket.Client.connect(url, debug=True) #self.AI_WS_connect_Queue.put(self.AI_client_VC) - - + print("websocket_connect_VC:OK!!!!!!!!!!!!!!!!!!!!!") except Exception as e: #网络连接异常 usys.print_exception(e) @@ -2618,7 +2826,6 @@ class AI_VC(Abstract): print("websocket_error4") - def websocket_deconnect_VC(self): #print("websocket_deconnect_VC {}!!!!!!!".format(self.AI_client_VC_isconnect)) print("websocket_deconnect_VC!!!!!!!") @@ -2786,6 +2993,8 @@ class AI_VC(Abstract): self.AI_client_VC_recv_lock = 0 count+=1 + # if self.VC_state >= VC_State_TTSStart: + # print("self.tts_in_data_len - self.tts_out_data_len = {}".format(self.tts_in_data_len - self.tts_out_data_len)) if self.VC_state >= VC_State_TTSStart and (self.tts_in_data_len - self.tts_out_data_len > 64*1024 or count>5): count = 0 utime.sleep_ms(1) @@ -2818,8 +3027,26 @@ class AI_VC(Abstract): if isinstance(recv_data, str):#返回的是字符串 print("VC VC:recv_data:{}".format(recv_data)) jsload_data = ujson.loads(recv_data) - #print("AI_client_VC_recv jsload_data = {}".format(jsload_data)) - + # self.happy_list = ["开心","高兴","兴奋"] + # self.cry_list = ["委屈","难过","伤心","哭泣","受伤"] + # self.angry_list = ["愤怒","生气","不耐烦"] + # self.confused_list = ["疑惑","困惑"] + if jsload_data["event"] == "llm.completed":#只有类型为llm.completed的字符串可以来判断表情 + if(any(item in recv_data for item in self.cry_list)): + print("识别到哭泣") + self.face_status = 1#变为哭泣 + # elif(any(item in recv_data for item in self.cry_list)): + # print("识别到哭泣") + # self.face_status = 1#变为哭泣 + elif(any(item in recv_data for item in self.angry_list)): + self.face_status = 2#变为愤怒 + print("识别到愤怒") + elif(any(item in recv_data for item in self.confused_list)): + self.face_status = 3#变为疑惑 + print("识别到疑惑") + else: + self.face_status = 0#变为正常 + #print("face_status1={}".format(self.face_status)) if jsload_data["event"] == "started" :#会话开始 #payload = jsload_data["payload"] # self.VC_dialog_id = payload["dialog_id"] @@ -2827,18 +3054,24 @@ class AI_VC(Abstract): EventMesh.publish("open_led_blue") print("VC:Started!!!!!!!!\r\n") - if self.AI_TTS_str == "": + if self.AI_TTS_str == "" and self.AI_music_str == "": #开始上传语音 + self.draw_result = 0 if dev_type != "7PIN" and dev_type != "7PIN_coze": - self.chenggong_tone() + pass + # self.chenggong_tone() if self.VC_mode == 0 : self.VC_record_state_flag =2 else: EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_send_speech}) - else: + elif self.AI_TTS_str != "" and self.AI_music_str == "": EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_synthesis}) + + elif self.AI_TTS_str == "" and self.AI_music_str != "": + EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_sing}) + self.VC_state = VC_State_None elif jsload_data["event"] == "config.update" :#配置更新中,需要停止录音 self.VC_state = VC_State_End @@ -2855,7 +3088,7 @@ class AI_VC(Abstract): EventMesh.publish("open_led_blue") elif jsload_data["event"] == "asr.completed" :#asr 终止的标识 print("self.commands_mode:{}".format(self.commands_mode)) - if self.commands_mode ==2: + if self.commands_mode ==1: ret= self.check_text(self.AI_ASR_str) if ret == 0:#配置指令 @@ -2895,29 +3128,32 @@ class AI_VC(Abstract): if self.is_VAD == 0: if self.VC_record_state_flag == 1:#llm返回数据还没停止,就先停止 EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Speech_End}) + #print("AI_client_VC_recv jsload_data = {}".format(jsload_data)) elif jsload_data["event"] == "tts.started" :#tts开始 self.VC_state = VC_State_TTSStart if self.is_VAD == 0: EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Speech_End}) EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Play_Start}) - #self.VC_Play_Start() EventMesh.publish("open_led_green")#绿色 elif jsload_data["event"] == "tts.completed" :#tts结束 EventMesh.publish("open_led_green")#绿色 EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Play_Start}) - self.LocalRespondingEnded_timerout = 8 + self.LocalRespondingEnded_timerout = 0 self.VC_state = VC_State_TTSEnd pass elif jsload_data["event"] == "canceled" :#打断 + self.VC_Play_End()#音频设备关闭 + self.draw_result = 0 EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Speech_Start_now})#开始录音 self.VC_state = VC_State_None + EventMesh.publish("send_device_VC_state")#上传VC状态 elif jsload_data["event"] == "completed" :#会话结束 #EventMesh.publish("open_led_green")#绿色 - - self.LocalRespondingEnded_timerout = 8 + self.LocalRespondingEnded_timerout = 3 self.VC_state = VC_State_End + EventMesh.publish("send_device_VC_state")#上传VC状态 pass elif jsload_data["event"] == "command" :#命令匹配 ret = -1 @@ -2946,7 +3182,7 @@ class AI_VC(Abstract): elif jsload_data["event"] == "failed":#接口返回错误 if jsload_data["payload"]["error"] == "concurrency_limit_exceeded": EventMesh.publish("publish_AI_btnInfo",{"func":self.concurrency_limit_exceeded_tone}) - + print("错误") #utime.sleep_ms(4000) else: @@ -2987,8 +3223,9 @@ class AI_VC(Abstract): #print("buf已满,等待释放:buf_len:{},count_tmp:{}".format(buf_len,count_tmp)) except Exception as e: usys.print_exception(e) - EventMesh.publish("publish_AI_btnInfo",{"func":self.put_record_data,"data":[recv_data,""]}) - utime.sleep_ms(1) + EventMesh.publish("publish_AI_btnInfo",{"func":self.put_record_data,"data":[recv_data,""]}) + utime.sleep_ms(1) + # print("self.tts_in_data_len - self.tts_out_data_len = {}".format(self.tts_in_data_len - self.tts_out_data_len)) except Exception as e: usys.print_exception(e) @@ -3174,7 +3411,7 @@ class AI_VC(Abstract): return 0 if text.find("版本") != -1 : sourceVersion = versions.Build_Time - self.AI_TTS_str ="Mr-Seven-"+sourceVersion + self.AI_TTS_str ="JSWM-"+sourceVersion return 0 if text.find("服务器地址") != -1 : self.AI_TTS_str ="服务器地址"+self.server_ip @@ -3189,11 +3426,13 @@ class AI_VC(Abstract): if len(text)<20 and (text.find("再见") != -1 or text.find("拜拜") != -1 or text.find("关闭对话") != -1): #EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) self.AI_TTS_str = "好嘞,再见,我们下次再聊" - EventMesh.publish("load_screen", {"screen": "main_menu"}) + EventMesh.publish("UI_ai_close") + EventMesh.publish("return_prev_screen") self.Close_flag = 1 return 0 if len(text)<12 and (text.find("关机") != -1 ): EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) + utime.sleep_ms(400) EventMesh.publish("Power_off") return 1 except Exception as e: @@ -3402,10 +3641,58 @@ class AI_VC(Abstract): EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) EventMesh.publish("Power_off") return 1 + if text.find("闹钟设定") != -1: + print("闹钟设定") + alarm_timer_sta = EventMesh.publish("alarm_get_statu") + if alarm_timer_sta == 0 : + EventMesh.publish("AI_alarm_open")#开启轮询 + alarm_timer_sta = 1 + text = cmd["command"]["params_json"] + print("params_json:{}".format(text)) + + try: + alarm = ujson.loads(text) + if alarm["is_right"] == True:#大模型判断闹钟格式以及内容正确 + add_alarm_tmp = EventMesh.publish("AI_add_alarm",alarm["alarm"]) + if add_alarm_tmp[0]> 0: + self.AI_TTS_str = add_alarm_tmp[1] + return 0 + else: + pass + except Exception as e: + usys.print_exception(e) + if text.find("取消闹钟") != -1 : + EventMesh.publish("AI_delete_alarm") + EventMesh.publish("AI_alarm_close") + self.AI_TTS_str = "闹钟列表已经清空" + return 0 + if text.find("关帝灵签结果") != -1 : + #占卜师角色,把说的状态改为抽签结果 + text = cmd["command"]["params_json"] + text = ujson.loads(text) + EventMesh.publish("draw_handle",text["lots_result"]) + self.AI_TTS_str = text["lot_content"] + return 0 + if text.find("播放音乐") != -1 : + #音乐播放器角色,播放音乐 + text = cmd["command"]["params_json"] + text = ujson.loads(text) + self.AI_music_str = text["mp3"] + return 0 except Exception as e: usys.print_exception(e) self.AI_TTS_str = cmd["command"]["fail_prompt"] return -1 + def draw_handle(self,event,msg): + if msg == "大吉": + self.draw_result = 1 + elif msg == "中吉": + self.draw_result = 1 + elif msg == "吉": + self.draw_result = 1 + elif msg == "末吉": + self.draw_result = 1 + def check_text(self,text): print("check_text:len:{}".format(len(text))) if len(text)>60: @@ -3515,11 +3802,11 @@ class AI_VC(Abstract): if text.find("音量") != -1 or text.find("声音") != -1: if text.find("加") != -1 or text.find("增") != -1: self.VC_TTS_volume += 10 - if self.VC_TTS_volume > 110: + 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 = 110 + 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]) @@ -3590,7 +3877,9 @@ class AI_VC(Abstract): if text.find("服务器地址") != -1 : self.AI_TTS_str ="服务器地址"+self.server_ip return 0 - + if text.find("闹钟列表") != -1 : + EventMesh.publish("read_alarm_list") + return 0 if text.find("讲话") != -1 or text.find("说话") != -1: if text.find("å¿«") != -1 and text.find("太") == -1 : self.speech_rate += 10 @@ -3707,7 +3996,7 @@ class AI_VC(Abstract): if self.VC_Play_flag == 0: try: if self.VC_play_TYPE == VC_play_TYPE_PCM: - if self.play_pcm == None: + if self.play_pcm == None : self.play_pcm = audio.Audio.PCM(0,1,self.VC_play_samplerate,1,1,2) # self.play_pcm.setVolume(11) self.play_pcm.setVolume(self.VC_TTS_volume // 10) @@ -3767,6 +4056,7 @@ class AI_VC(Abstract): EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_error,"data":"接口超时了。请重试"}) self.ud_error(["VC",self.VC_taskid]) else: + EventMesh.publish("UI_ai_close") EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) EventMesh.publish("load_screen", {"screen": "main_menu"}) pass @@ -3784,6 +4074,7 @@ class AI_VC(Abstract): self.Close_flag = 0 EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) EventMesh.publish("load_screen", {"screen": "main_menu"}) + EventMesh.publish("send_device_VC_state")#上传VC状态 else: #utime.sleep_ms(1000) EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Play_End}) @@ -3867,15 +4158,84 @@ class AI_VC(Abstract): # self.VC_pingping_timerout = 0 # self.asr_pingping_timerout = 0 print("AI_VC_start5") + #开始会话 def AI_client_VC_start_requset(self): + print("AI_client_VC_start_requset") voice="zh_male_wennuanahu_moon_bigtts" try: voice = self.VC_TTS_voice_type[self.VC_TTS_voice_key]["voice"] except Exception as e: usys.print_exception(e) #voice="zh_female_dongmanxiaoyang_moon_bigtts" - + # #海外服务器 + # json_data = \ + # { + # "event": "start", + # "payload": { + # "simple_response": False, + # "device_id": modem.getDevImei(), + # "user_agent": "AudioClientWithAEC/1.0", + # "dialog_attributes": { + # "provider": "openai", + # "cfg": { + # "disable_empty_prompt": True, + # "greeting":{ + # "enabled": True, + # "content": "Hi! What can I do for you.", + # }, + # "openai_option": { + # "model": "gpt-4o", + # "system": { + # "type": "file", + # "content": "1567d9e19ac09269d8ce6c887494ff01" # 林悦 + # }, + # } + # } + # }, + # "outbound_attributes": { + # "provider": "azure", + # "cfg": { + # "format": "pcm", + # "sample_rate": 16000, + # "bit_rate": 16, + # "channel": 1, + # "volume": 100, + # # "voice": "en-US-AvaMultilingualNeural", #"cosyvoice-v2-amp-2f7d423",# "longjielidou", + # "voice":"zh-CN-XiaoxiaoNeural",# mandarin + # "speech_rate": 0, + # "chunk_interval_ms": 10 + # } + # }, + # "inbound_attributes": { + # "provider": "azure", + # "disable_vad": False, + # "vad_silence": 200, + # "interrupt_options": { + # "concatenate_results": True, + # "thinking_time_only": True, + # # "keyword_interrupt": True, + # # "interrupt_keywords": ["停止", "打断","打断一下", "等一下", "别说了", "打住"] + # }, + # "cfg": { + # "format": "pcm", + # "sample_rate": 16000, + # "bit_rate": 16, + # "channel": 1, + # "enable_punctuation": True, + # "enable_itn": True, + # "keywords": [ + # "停止", + # "打断", + # "打断一下", + # "等一下", + # "别说了", + # "打住" + # ] + # } + # } + # } + # } json_data = \ { "header": { @@ -3948,6 +4308,7 @@ class AI_VC(Abstract): "commands":self.commands, } } + # "bot_id":"7481164663863459850",#鸭子 # "workflow_id":"7480485093845991443", # "bot_id":"7462617881076351002",#语言助手 @@ -4058,11 +4419,7 @@ class AI_VC(Abstract): if self.VC_mode == 1:#单对话模式 self.AI_client_VC_send(ujson.dumps(json_data)) - - - - - + self.VC_state = VC_State_SpeechStart #结束上传语音 @@ -4108,7 +4465,25 @@ class AI_VC(Abstract): # if self.VC_state == VC_State_RequestToRespond: # print("AI_client_VC_RequestToRespond 重复 tts_str:{}\nasr_str:{}".format(self.AI_TTS_str,self.AI_ASR_str)) self.AI_client_VC_send(ujson.dumps(json_data)) - + + #唱歌 + def AI_client_VC_sing(self): + json_data = \ + { + "event": "audio.convert", + "payload": { + "audio_convert_request": { + "audio_url": self.AI_music_str, + "bit_depth": 16, + "channels": 1, + "sample_rate": 16000, + "target_format": "pcm" + } + } + } + + self.AI_client_VC_send(ujson.dumps(json_data)) + print("AI_client_VC_sing!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") def chenggong_tone(self): EventMesh.publish("audio_montage_play",["chenggong.mp3"]) def send_tone(self): @@ -4196,20 +4571,6 @@ class AI_VC(Abstract): 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)) mem = gc.mem_free() @@ -4241,6 +4602,7 @@ class AI_VC(Abstract): self.VC_Thinking_timerout = 0 self.VC_satrt_flag = 0 self.AI_TTS_str = "" + self.AI_music_str = "" self.AI_ASR_str = "" self.AI_ASR_str_tmp = "" self.AI_ASR_flag = 0 @@ -4252,7 +4614,7 @@ class AI_VC(Abstract): self.tts_in_data_len = 0 self.tts_out_data_len = 0 #必须先销毁线程,不然线程会容易报错 - + EventMesh.publish("send_device_VC_state")#上传VC状态 try: self.AI_audio_queue_thread_close()#销毁音频线程 except Exception as e: @@ -4261,7 +4623,6 @@ class AI_VC(Abstract): self.AI_VC_send_data_queue_thread_close()#销毁数据发送线程 except Exception as e: usys.print_exception(e) - self.VC_Speech_End() print("ai_VC Close1.1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") diff --git a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ai_alarm.py b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ai_alarm.py new file mode 100644 index 00000000..38f969d7 --- /dev/null +++ b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ai_alarm.py @@ -0,0 +1,412 @@ +#ai闹钟 +import EventMesh +import usys +import ujson +import osTimer +import utime +class AI_alarm(): + """ + sjon格式{ + "alarm_type":"重复闹钟", #闹钟类型。示例值:重复闹钟(喝水提醒,重复每天闹钟)、单次闹钟(会议提醒) + "alarm_timestamp":1750402089,#单次闹钟触发时间戳,单位:秒。只有单次闹钟有效 + "repeat_day":["周一","周二","周三","2025-06-20"],#按天循环规则。示例值:周一,周五,每天,2025-06-20(自定义日期) + "repeat_min":60,#当天是否按多少分钟循环,为0时每天只响应一次,为120时每隔2小时触发一次。示例值:120 + "valid_time":"9-18",# 当天循环有效时间,只有当repeat_min不为0时有效。repeat_min=60时,在有效时间内1小时循环响应1次。等于空值时,当天24小时有效 + "alarm_timer":"06:50",#触发时间。示例值:06:50 ,6点50分时触发闹钟 + "alarm_content":"周例会",#闹钟提醒内容。为空时,播放本地默认音频,不为空时,tts循环播放内容。示例值:"喝水提醒" + } + """ + #最多只能设置五个闹钟 + def __init__(self): + self.alarm_array = EventMesh.publish("get_storage_config","alarm_array")#读取闹钟数组 + if self.alarm_array is None: + self.alarm_array =[] + print("self.alarm_array =[]") + self.AI_alarm_timer = osTimer() + self.alarm_min_repeat_tmp = 0 + self.alarm_min_one_tmp = 0 + self.alarm_count = len(self.alarm_array)#闹钟个数 + print("闹钟个数 ={}".format(self.alarm_count)) + self.alarm_list_text = EventMesh.publish("get_storage_config","alarm_list_text")#闹钟文本列表 + if self.alarm_list_text is None: + self.alarm_list_text =[] + print("闹钟列表:{}".format(self.alarm_list_text)) + self.alarm_timer_sta = 0#alarm定时器开启状态 0为关闭,1为开启 + self.used_numbers = set()#已经被使用的闹钟编号集合 + self.circle_alarm_flag = [] #闹钟重复判断标志列表 + EventMesh.subscribe("AI_alarm_close",self.AI_alarm_close) + EventMesh.subscribe("AI_alarm_open",self.AI_alarm_open) + EventMesh.subscribe("AI_alarm_poll_extern",self.AI_alarm_poll_extern) + EventMesh.subscribe("AI_add_alarm",self.AI_add_alarm) + EventMesh.subscribe("alarm_get_statu",self.alarm_get_statu) + EventMesh.subscribe("get_have_alarm",self.get_have_alarm) + EventMesh.subscribe("AI_delete_alarm",self.AI_delete_alarm) + EventMesh.subscribe("read_alarm_list",self.read_alarm_list) + def alarm_get_statu(self,event=None,msg=None): + print("alarm_get_statu = {}".format(self.alarm_timer_sta)) + return self.alarm_timer_sta + + def AI_alarm_open(self,event=None,msg=None): + print("AI_alarm_open") + self.alarm_timer_sta = 1 + self.AI_alarm_timer.start(20000, 1, self.AI_alarm_timer_cb) + + def AI_alarm_timer_cb(self, *args): + EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_alarm_poll}) + pass + + def get_have_alarm(self,event,msg): + self.alarm_array = EventMesh.publish("get_storage_config","alarm_array")#读取闹钟数组 + if self.alarm_array ==None: + return 0 + else: + return 1 + + def AI_alarm_poll(self):#轮询调用 + is_alarm = 0 #是否触发闹钟 + alarm_TTS_str =""#闹钟播放tts字符串 + repeat_day_flag = 0 + alarm_timer_flag = 0 + # print("AI_alarm_poll111") + if len(self.alarm_array) == 0: + return + print("self.alarm_array = {}".format(self.alarm_array)) + if all(element is None for element in self.alarm_array): + print("删除所有闹钟") + self.AI_delete_alarm()#删除所有闹钟 + self.AI_alarm_close()#关闭相关定时器 + return + if len(self.alarm_array)>0: + # print("AI_alarm_poll222") + try: + now_time = utime.localtime() + old_minute = [None] * len(self.alarm_array) + cnt = -1#记录到了闹钟列表第几位 + for _alarm in self.alarm_array : + cnt += 1 + if _alarm is None: + continue + if len(self.circle_alarm_flag) >0: + print("self.circle_alarm_flag[cnt] = {}".format(self.circle_alarm_flag[cnt])) + if self.circle_alarm_flag[cnt] == 1:#已触发过一次 + if old_minute[cnt] is not None: + if now_time[4] > old_minute[cnt]: + self.circle_alarm_flag[cnt] = 0#清空标志位 + old_minute[cnt] = now_time[4] + if _alarm["alarm_type"] == "单次": + #判断闹钟数字合法 + repeat_day = _alarm["repeat_day"][0] + Y_M_D = repeat_day.split('-') + alarm_timer = _alarm["alarm_timer"] + H_M = alarm_timer.split(':') + time_tuple = utime.localtime()#获取当前日期&时间的元组 + set_year = int(Y_M_D[0]) + set_month = int(Y_M_D[1]) + set_day = int(Y_M_D[2]) + set_hour = int(H_M[0]) + set_minute = int(H_M[1]) + year_now = time_tuple[0] + month_now = time_tuple[1] + day_now = time_tuple[2] + hour_now = time_tuple[3] + minute_now = time_tuple[4] + if set_year < year_now or (set_year == year_now and set_month < month_now) or \ + (set_year == year_now and set_month == month_now and set_day < day_now): + print("闹钟日期已过期,已清除闹钟{}".format(_alarm["number"])) + self.used_numbers.remove(self.alarm_array[cnt]["number"])#从闹钟名集合中移除 + self.alarm_array.pop(cnt) + EventMesh.publish("set_storage_config",["alarm_array",self.alarm_array]) + self.alarm_list_text.pop(cnt) + EventMesh.publish("set_storage_config",["alarm_list_text",self.alarm_list_text]) + continue + if (set_year == year_now and set_month == month_now and set_day == day_now) and set_hour < hour_now or (set_hour == hour_now and set_minute < minute_now): + print("闹钟日期已过期,已清除闹钟{}".format(_alarm["number"])) + self.used_numbers.remove(self.alarm_array[cnt]["number"])#从闹钟名集合中移除 + self.alarm_array.pop(cnt) + EventMesh.publish("set_storage_config",["alarm_array",self.alarm_array]) + self.alarm_list_text.pop(cnt) + EventMesh.publish("set_storage_config",["alarm_list_text",self.alarm_list_text]) + continue + + if _alarm["alarm_type"] == "重复": + #print("AI_alarm_poll333") + weekday = now_time[6] + weekday_str = "" + if weekday == 0: + weekday_str = "周一" + elif weekday == 1: + weekday_str = "周二" + elif weekday == 2: + weekday_str = "周三" + elif weekday == 3: + weekday_str = "周四" + elif weekday == 4: + weekday_str = "周五" + elif weekday == 5: + weekday_str = "周六" + elif weekday == 6: + weekday_str = "周日" + week = _alarm["repeat_day"] + for _week in week : + if weekday_str == _week:#符合周判断 + repeat_day_flag = 1 + break + if repeat_day_flag == 0:#周不符合 + continue + if _alarm["repeat_min"] ==0: #每天只提醒一次,已添加闹钟1,周一,周二,周三,6:50分提醒您周例会 + alarm_timer = _alarm["alarm_timer"] + H_M = alarm_timer.split(':') + if len(H_M) != 2: + continue + hour = int(H_M[0]) + min = int(H_M[1]) + if hour == now_time[3] and min == now_time[4]: + alarm_timer_flag =1 + else:#时间不符合 + continue + + + if alarm_timer_flag==1:#时间符合,触发闹钟 + alarm_TTS_str += _alarm["alarm_content"] + is_alarm = 1 + break + else:#每天循环间提醒。已添加闹钟1,周一,周二,周三,9点到18点每隔60分钟提醒您喝水 + valid_time = _alarm["valid_time"] + H_H = valid_time.split('-') + if len(H_H) != 2: + continue + start_time = H_H[0].split(':') + end_time = H_H[1].split(':') + if len(start_time)<2 or len(end_time)<2: + continue + start_time_int = int(start_time) + end_time_int = int(end_time) + now_h = now_time[3] + if now_h>=start_time_int and now_h <= end_time_int:#在有效时间范围 + now_m = now_time[4] + repeat_min_int = _alarm["repeat_min"] + if (now_m + repeat_min_int)%repeat_min_int == 0 and self.alarm_min_repeat_tmp != now_m:#每分钟符合 + self.alarm_min_repeat_tmp = now_m + alarm_TTS_str += _alarm["alarm_content"] + is_alarm = 1 + continue + + else: + continue +#EventMesh.publish("AI_add_alarm",{"alarm_type":"单次闹钟","alarm_timestamp":1752739511,"repeat_day":"2025-07-17","repeat_min":0,"valid_time":"","alarm_timer":"16:05","alarm_content":"开会"}) + elif _alarm["alarm_type"] == "单次": + # print("AI_alarm_poll444") + alarm_timer = _alarm["alarm_timer"] + H_M = alarm_timer.split(':') + if len(H_M) != 2: + print("len(H_M) != 2") + continue + repeat_day = _alarm["repeat_day"][0] + Y_M_D = repeat_day.split('-') + #print("Y_M_D:{}".format(Y_M_D)) + if len(Y_M_D)<3: + print("len(Y_M_D)<3") + continue + year_int = int(Y_M_D[0]) + month_int = int(Y_M_D[1]) + day_int = int(Y_M_D[2]) + hour_int = int(H_M[0]) + minute_int = int(H_M[1]) + if year_int == now_time[0] and month_int == now_time[1]and day_int == now_time[2]and hour_int == now_time[3]and minute_int == now_time[4]: + if self.alarm_min_one_tmp != now_time[4]: + self.alarm_min_one_tmp = now_time[4] + alarm_TTS_str += _alarm["alarm_content"] + is_alarm = 1 + print("self.alarm_min_one_tmp != now_time[4]") + break #发现闹钟存在直接跳出循环 + #ret_str += "{},{}点{}分提醒您:{}。".format(_alarm["repeat_day"],H_M[0],H_M[1],_alarm["alarm_content"]) + # print("AI_alarm_poll555") + if is_alarm == 1 : + if _alarm["alarm_type"] == "重复": + if len(self.circle_alarm_flag) > 0: + if self.circle_alarm_flag[cnt] == 1:#已触发过一次 + print("闹钟已触发过一次") + return + EventMesh.publish("audio_montage_play",["chenggong.mp3"]) + EventMesh.publish("play_tts",["小瑞提醒您该{}了,小瑞提醒您该{}了,小瑞提醒您该{}了".format(alarm_TTS_str,alarm_TTS_str,alarm_TTS_str),1]) + print("闹钟提醒:小瑞提醒您该{}了,小瑞提醒您该{}了,小瑞提醒您该{}了".format(alarm_TTS_str,alarm_TTS_str,alarm_TTS_str)) + if _alarm["alarm_type"] == "单次": + self.used_numbers.remove(self.alarm_array[cnt]["number"])#从闹钟名集合中移除 + self.alarm_array.pop(cnt)#删除闹钟元素 + self.alarm_list_text.pop(cnt)#删除读闹钟列表元素 + EventMesh.publish("set_storage_config",["alarm_array",self.alarm_array]) + EventMesh.publish("set_storage_config",["alarm_list_text",self.alarm_list_text]) + elif _alarm["alarm_type"] == "重复": + required_length = cnt + 1 + current_length = len(self.circle_alarm_flag) + if current_length < required_length: + # 补充缺失的位置,用默认值(如0)填充 + self.circle_alarm_flag.extend([0] * (required_length - current_length)) + self.circle_alarm_flag[cnt] = 1 + except Exception as e: + usys.print_exception(e) + pass + + def AI_alarm_poll_extern(self,event=None,msg=None):#外部调用轮询间隔,关闭定时器调用 + self.AI_alarm_timer.stop() + EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_alarm_poll}) + + def AI_add_alarm(self,event=None,alarm_array_u=None):#添加闹钟数组 + ret = 0 + alarm_array_tmp = self.alarm_array + if alarm_array_tmp is None: + alarm_array_tmp =[] + if self.alarm_count >= 10: + tts = "闹钟列表已满,请清除闹钟后再设置" + return [1,tts] + #已添加闹钟1,周一,周二,周三,6:50分提醒您周例会 + ret_str = "已添加" + print("AI_add_alarm:{}".format(alarm_array_u)) + try: + for _alarm in alarm_array_u : + if ("alarm_content" in _alarm )and (_alarm["alarm_type" ] == "重复" or _alarm["alarm_type" ] == "单次" ):#简单的判断这个配置是合法的 + # #判断闹钟数字合法 + repeat_day = _alarm["repeat_day"][0] + Y_M_D = repeat_day.split('-') + alarm_timer = _alarm["alarm_timer"] + H_M = alarm_timer.split(':') + # time_tuple = utime.localtime()#获取当前日期&时间的元组 + # set_year = int(Y_M_D[0]) + # set_month = int(Y_M_D[1]) + # set_day = int(Y_M_D[2]) + # set_hour = int(H_M[0]) + # set_minute = int(H_M[1]) + # year_now = time_tuple[0] + # month_now = time_tuple[1] + # day_now = time_tuple[2] + # hour_now = time_tuple[3] + # minute_now = time_tuple[4] + # if set_year < year_now or (set_year == year_now and set_month < month_now) or \ + # (set_year == year_now and set_month == month_now and set_day < day_now): + # tts = "您设置的闹钟日期已过期,请重新设置" + # return [1,tts] + # if set_month > 12 or set_month < 1 or set_day > 31 or set_day <1: + # tts = "您设置的闹钟日期非法,请重新设置" + # return [1,tts] + # if set_hour < hour_now or (set_hour == hour_now and set_minute < minute_now): + # tts = "您设置的闹钟时间已过期,请重新设置" + # return [1,tts] + print(" AI_add_alarm 1111!!!") + ret +=1 + + number = 0#闹钟编号 + #计算闹钟编号 + for i in range(1, 11): + if i not in self.used_numbers:#当i不在集合中时,说明闹钟名未被添加,可以加入闹钟集合 + self.used_numbers.add(i) + number = i #为当前闹钟赋值 + break + #将键加入闹钟字典 + _alarm["number"] = number + + #加入设定列表 + alarm_array_tmp.append(_alarm) + ret_str += "闹钟{},".format(number) + self.alarm_count = len(alarm_array_tmp)#闹钟总数 + + if _alarm["alarm_type"] == "重复": + print(" AI_add_alarm 2222!!!") + if _alarm["repeat_min"] ==0: #每天只提醒一次,已添加闹钟1,周一,周二,周三,6:50分提醒您周例会 + # if len(H_M) != 2: + # tts = "闹钟信息不完整,请重新设置" + # #移出设定列表 + # alarm_array_tmp.remove(_alarm) + # ret_str = "" + # self.alarm_count = len(alarm_array_tmp)#闹钟总数 + # return [1,tts] + ret_str += "{},{}点{}分提醒您{}。".format(_alarm["repeat_day"],H_M[0],H_M[1],_alarm["alarm_content"]) + #添加闹钟描述文本 + self.alarm_list_text.append("闹钟{}:重复闹钟,{},{}点{}分提醒您{}".format(number,_alarm["repeat_day"],H_M[0],H_M[1],_alarm["alarm_content"])) + EventMesh.publish("set_storage_config",["alarm_list_text",self.alarm_list_text]) + else:#每天循环间提醒。已添加闹钟1,周一,周二,周三,9点到18点每隔60分钟提醒您喝水 + valid_time = _alarm["valid_time"] + H_H = valid_time.split('-') + # if len(H_H) != 2: + # tts = "闹钟信息不完整,请重新设置" + # #移出设定列表 + # alarm_array_tmp.remove(_alarm) + # ret_str = "" + # self.alarm_count = len(alarm_array_tmp)#闹钟总数 + # return [1,tts] + start_time = H_H[0].split(':') + end_time = H_H[1].split(':') + # if len(start_time)<2 or len(end_time)<2: + # tts = "闹钟信息不完整,请重新设置" + # #移出设定列表 + # alarm_array_tmp.remove(_alarm) + # ret_str = "" + # self.alarm_count = len(alarm_array_tmp)#闹钟总数 + # return [1,tts] + #添加闹钟描述文本 + self.alarm_list_text.append("闹钟{}:重复闹钟,{},{}点{}分到{}点{}分,每隔{}分钟提醒您{}。".format(number,_alarm["repeat_day"][0], + start_time[0],start_time[1],end_time[0],end_time[1], + _alarm["repeat_min"],_alarm["alarm_content"])) + EventMesh.publish("set_storage_config",["alarm_list_text",self.alarm_list_text]) + ret_str += "{},{}点{}分到{}点{}分,每隔{}分钟提醒您{}。".format(_alarm["repeat_day"][0], + start_time[0],start_time[1],end_time[0],end_time[1], + _alarm["repeat_min"],_alarm["alarm_content"]) + elif _alarm["alarm_type"] == "单次": + print(" AI_add_alarm 3333!!!") + # if len(H_M) != 2: + # tts = "闹钟信息不完整,请重新设置" + # #移出设定列表 + # alarm_array_tmp.remove(_alarm) + # ret_str = "" + # self.alarm_count = len(alarm_array_tmp)#闹钟总数 + # return [1,tts] + # if len(Y_M_D)<3: + # tts = "闹钟信息不完整,请重新设置" + # #移出设定列表 + # alarm_array_tmp.remove(_alarm) + # ret_str = "" + # self.alarm_count = len(alarm_array_tmp)#闹钟总数 + # return [1,tts] + #添加闹钟描述文本 + self.alarm_list_text.append("闹钟{}:单次闹钟,{}å¹´{}月{}日,{}点{}分提醒您:{}。".format(number,Y_M_D[0],Y_M_D[1],Y_M_D[2],H_M[0],H_M[1],_alarm["alarm_content"])) + EventMesh.publish("set_storage_config",["alarm_list_text",self.alarm_list_text]) + ret_str += "{}å¹´{}月{}日,{}点{}分提醒您:{}。".format(Y_M_D[0],Y_M_D[1],Y_M_D[2],H_M[0],H_M[1],_alarm["alarm_content"]) + # EventMesh.publish("play_tts_single",ret_str) + print("配置成功") + else: + return [-1] + + except Exception as e: + usys.print_exception(e) + return [-1] + + if ret != 0:#当有有效闹钟数据时 + print("保存闹钟新建数据") + self.alarm_array = alarm_array_tmp + print("self.alarm_array = {}".format(self.alarm_array)) + EventMesh.publish("set_storage_config",["alarm_array",self.alarm_array]) + return [ret,ret_str] + + def read_alarm_list(self,event=None,Num=None):#读闹钟全列表 + alarmlist_TTS_str =""#闹钟全列表播放tts字符串 + if len(self.alarm_list_text) == 0: + alarmlist_TTS_str = "当前闹钟列表没有闹钟信息" + EventMesh.publish("play_tts_single",alarmlist_TTS_str) + return + alarmlist_TTS_str += "当前闹钟信息如下:" + for count in self.alarm_list_text: + alarmlist_TTS_str += count + + EventMesh.publish("play_tts_single",alarmlist_TTS_str) + def AI_delete_alarm(self,event=None,Num=None):#删除闹钟 + self.alarm_array =[]#闹钟队列清空 + EventMesh.publish("set_storage_config",["alarm_array",self.alarm_array]) + self.alarm_list_text =[]#闹钟队列清空 + EventMesh.publish("set_storage_config",["alarm_list_text",self.alarm_list_text]) + self.alarm_count = 0 + self.used_numbers.clear()#清空闹钟名集合 + + def AI_alarm_close(self,event=None,Num=None): + print("AI_alarm_close") + self.alarm_timer_sta = 0 + self.AI_alarm_timer.stop() + diff --git a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/alarm.py b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/alarm.py index 92f1679f..14edebfe 100644 --- a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/alarm.py +++ b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/alarm.py @@ -107,7 +107,7 @@ clk_list_screen1_1.add_style(style_alarm_screen_default, lv.PART.MAIN | lv.STATE no_add_alarm_img = lv.img(clk_list_screen1_1) no_add_alarm_img.set_pos(65, 0) no_add_alarm_img.set_size(110, 140) -no_add_alarm_img.set_src("E:/static/IMAGE_IDLE_SCREEN_ALARM_ICON_NEW.png") +no_add_alarm_img.set_src("E:/static/alarm.png") no_add_alarm_img.add_style(style_img, lv.PART.MAIN | lv.STATE.DEFAULT) #暂未添加闹钟 @@ -785,9 +785,9 @@ popup_alarm_screen.add_style(style_screen, lv.PART.MAIN | lv.STATE.DEFAULT) popup_alarm_img = lv.img(popup_alarm_screen) -popup_alarm_img.set_pos(63, 60) -popup_alarm_img.set_size(110, 140) -popup_alarm_img.set_src("E:/static/IMAGE_IDLE_SCREEN_ALARM_ICON_NEW.png") +popup_alarm_img.set_pos(0, 0) +popup_alarm_img.set_size(240, 320) +popup_alarm_img.set_src("E:/static/alarm.png") popup_alarm_img.add_style(style_img, lv.PART.MAIN | lv.STATE.DEFAULT) popup_alarm_time = lv.label(popup_alarm_screen) @@ -823,7 +823,7 @@ class PopupAlarmScreen(Screen): def exit_alarm_page(self,*arges): EventMesh.publish("system_sleep_rest")#防止黑屏 self.alarm_count+=1 - if self.alarm_count > 60: + if self.alarm_count > 10: self.alarm_count = 0 self.aud.stop() self.timer.stop() diff --git a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/lcd.py b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/lcd.py index 76065ad5..b9490acd 100644 --- a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/lcd.py +++ b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/lcd.py @@ -161,13 +161,12 @@ LCD_SIZE_H = 320 # pwm.close() # 初始化lvgl lv.init() - # Register SDL display driver. disp_buf1 = lv.disp_draw_buf_t() buf1_1 = bytearray(LCD_SIZE_W * LCD_SIZE_H * 2) -#buf1_2= bytearray(LCD_SIZE_W * LCD_SIZE_H * 2) +buf1_2= bytearray(LCD_SIZE_W * LCD_SIZE_H * 2) -disp_buf1.init(buf1_1, None, len(buf1_1)) +disp_buf1.init(buf1_1, buf1_2, len(buf1_1)) disp_drv = lv.disp_drv_t() disp_drv.init() disp_drv.draw_buf = disp_buf1 @@ -177,7 +176,22 @@ disp_drv.ver_res = LCD_SIZE_H disp_drv.sw_rotate = True disp_drv.rotated = 0#旋转角度0-3 disp_drv.register() - +# lv.init() +# # Register SDL display driver. +# disp_buf1 = lv.disp_draw_buf_t() +# buf1_1 = bytearray(LCD_SIZE_W * LCD_SIZE_H * 2) +# #buf1_2= bytearray(LCD_SIZE_W * LCD_SIZE_H * 2) + +# disp_buf1.init(buf1_1, None, len(buf1_1)) +# disp_drv = lv.disp_drv_t() +# disp_drv.init() +# disp_drv.draw_buf = disp_buf1 +# disp_drv.flush_cb = lcd.lcd_write +# disp_drv.hor_res = LCD_SIZE_W +# disp_drv.ver_res = LCD_SIZE_H +# disp_drv.sw_rotate = True +# disp_drv.rotated = 0#旋转角度0-3 +# disp_drv.register() # LVGL触摸注册 @@ -262,5 +276,5 @@ power_on_label.add_style(style_font_youyuan_20_op, lv.PART.MAIN | lv.STATE.DEFAU lv.scr_load(power_on_screen) utime.sleep_ms(200) print("power_on_screen end...") -PWM_backlight = PWM(PWM.PWM1, PWM.ABOVE_MS, 6, 10) +PWM_backlight = PWM(PWM.PWM1, PWM.ABOVE_MS, 10, 10) PWM_backlight.open() diff --git a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/main_init.py b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/main_init.py index 6f8eb186..6ab80284 100644 --- a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/main_init.py +++ b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/main_init.py @@ -105,9 +105,12 @@ def main_init(): device = mgr.DeviceInfoManager() device.post_processor_after_instantiation()#订阅事件 + light = mgr.getBrightnessManager() + light.post_processor_after_instantiation() + from ui_health import HealthScreen import ui as _ui - + import ai_alarm as _al import ui_setting as _us # import ui as _ui EventMesh.debug_log("init4:{}".format(utime.localtime())) @@ -115,6 +118,8 @@ def main_init(): ui.post_processor_after_instantiation() app = watchApp() app.set_ui(ui) + #创建闹钟类 + al = _al.AI_alarm() # if EventMesh.model == "D15": # from motor import motorEventManager # app.append_manager(motorEventManager()) @@ -136,7 +141,10 @@ def main_init(): ui.add_screen(_ui.PowerOnScreen()) ui.add_screen(_us.PoweroffConfirmScreen()) ui.add_screen(_ui.chargeInScreen()) #充电已连接 - ui.add_screen(_ui.chargefullScreen()) #充电已移出 + ui.add_screen(_ui.chargefullScreen()) #充电已满 + ui.add_screen(_ui.LowPowerScreen()) #电量低 + + except Exception as e: usys.print_exception(e) @@ -183,13 +191,47 @@ def main_init(): app.append_manager(_ai.device_res_author()) except Exception as e: usys.print_exception(e) - + #IOT + try: + import usr.protocol as pro + except Exception as e: + usys.print_exception(e) + import protocol as pro + try: + app.append_manager(pro.IOT_socket_SendCmdManager()) + pcr = pro.ProtoColResolver() + pcr.add_support(pro.IOT_post_device_stateProtoCol()) + pcr.add_support(pro.IOT_FindDeviceProtoCol()) + # pcr.add_support(pro.IOTWeb_alarm_configProtoCol()) + # pcr.add_support(pro.IOTWeb_alarm_listProtoCol()) + sm = pro.SockMangager() + + sm.add_support_resolver(pcr) + app.append_manager(sm) + print("init_IOT.0:{}".format(utime.localtime())) + + except Exception as e: + usys.print_exception(e) + #endIOT try: - app.append_manager(_ai.AI_VC()) except Exception as e: usys.print_exception(e) - + try: + EventMesh.publish("dmp_update")#dmp推送 + except Exception as e: + usys.print_exception(e) + try: + EventMesh.publish("connect_iot_socket")#连接IOT + print("IOT连接成功") + except Exception as e: + usys.print_exception(e) + try: + EventMesh.publish("login_IOT")#登录IOT + EventMesh.publish("send_unbind_dev_to_iot")#开启IOT心跳包 + except Exception as e: + usys.print_exception(e) + except Exception as e: usys.print_exception(e) EventMesh.publish("load_screen", {"screen": "poweron"})#开机画面 diff --git a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/mgr.py b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/mgr.py index 9e73ed03..7801697c 100644 --- a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/mgr.py +++ b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/mgr.py @@ -1081,7 +1081,8 @@ class DeviceInfoManager(Abstract): if battery[0] == "1": if battery[1] >= 100: if self.charge_full_count > 60 and self.charge_full_count % (60*10) == 0:#每十分钟提醒一次 - EventMesh.publish("load_screen", {"screen": "charge_full"}) + # EventMesh.publish("load_screen", {"screen": "charge_full"}) + pass self.charge_full_count+=10 else: self.charge_full_count = 0 @@ -2985,7 +2986,7 @@ class getTempTimeManager(Abstract): class getBrightnessManager(Abstract):#获取亮度级别 def __init__(self): - self.level = 6#默认值6 + self.level = 10#默认值10最亮 # self.read_data = {} self.time = 5 self.PWM_backlight = None diff --git a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/protocol.py b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/protocol.py index 2ab81a55..d5fa484c 100644 --- a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/protocol.py +++ b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/protocol.py @@ -23,8 +23,12 @@ import usys import request import umqtt import modem +import versions SHA256 = uhashlib.sha256 import SecureData +import log +import ustruct + def server_init(server_type = None): #服务器选择1,防走丢,2大锤,3三基同创,4童信,5云米,6荣为 8:ds未知 dey.hinwatch. com:9968 9:183.62.239.121:31869 10:183.62.239.121:33461 if server_type == None: @@ -270,645 +274,668 @@ def mqtt_client_dev_init():#一机一密 client.error_register_cb(mqtterr_cb) return client + +import uwebsocket +import sim -class SockManager(Abstract): - def __init__(self): - self.sock = None - self.resolver = None - self.run_flag = False - self.lost_conn_check_time = 5 * 60 * 30 - self.monitor_timer = osTimer() - self.publish_timer = osTimer() - self.reconnect_timer = osTimer() - self.mqtt_recv_timer = osTimer() - self.reconnect_time = 1000 - self.reconnect_flag = 0 - self.connect_tmp = 0 - server_data = server_init() - # EventMesh.debug_log("SockManager:server_data:{}".format(server_data)) - # self.server_addr = server_data[0] - # self.server_port = server_data[1] - self.server_addr = "" - self.server_port = "" - self.device_id = "" - self.device_key = "" - self.product_key = gewu_init() - self.deviceSecret = "" - self.client = 0 - self.client_dev = 0 - self.client_state = 0 - self.mqtt_client_count = 0 - ip_infor = {} - ip_infor = EventMesh.publish("get_new_ip_com") - EventMesh.debug_log("ip_infor1:{} \n\n\n".format(ip_infor)) - - if ip_infor != None: #已经改过服务器 - self.server_addr = ip_infor[0] - self.server_port = ip_infor[1] - else: - self.server_addr = server_data[0] - self.server_port = server_data[1] +class WEB_CMD_ENUM: + POST_DEVICE_STATE_R_CMD = "post_device_state_R" + POST_DEVICE_STATE_S_CMD = "post_device_state_S" - EventMesh.debug_log("server_addr:{} server_port:{}".format(self.server_addr,self.server_port)) - _thread.stack_size((9+3)*1024) - _thread.start_new_thread(self.connect, ()) - _thread.stack_size(8*1024) - - - self.socket_send_queue = Queue() - _thread.stack_size((9+2)*1024) - _thread.start_new_thread(self.socket_send_queue_thread, ()) - _thread.stack_size(8*1024) - EventMesh.subscribe("set_device_id",self.set_device_id) - EventMesh.subscribe("set_device_key",self.set_device_key) - EventMesh.subscribe("set_product_key",self.set_product_key) + POST_DEVICE_INFOR_R_CMD = "POST_DEVICE_INFOR_R_CMD" + POST_DEVICE_INFOR_S_CMD = "POST_DEVICE_INFOR_S_CMD" - EventMesh.subscribe("get_device_id",self.get_device_id) - EventMesh.subscribe("get_device_key",self.get_device_key) - EventMesh.subscribe("get_product_key",self.get_product_key) + POST_ALARM_R_CMD = "post_alarm_R" + POST_ALARM_S_CMD = "post_alarm_S" - EventMesh.subscribe("set_deviceSecret",self.set_deviceSecret) + FIND_DEVCE_R_CMD = "find_device_R" + FIND_DEVCE_S_CMD = "find_device_S" - EventMesh.subscribe("get_deviceSecret",self.get_deviceSecret) - if EventMesh.platform == "gewu": - str = "deviceSecret:" - buf = bytearray(32+len(str)) - length = SecureData.Read(2, buf, 32+len(str)) - deviceSecret = buf.decode() - print(type(deviceSecret)) - if deviceSecret != "": - if "deviceSecret" in deviceSecret: - self.deviceSecret = deviceSecret.split(":")[1] - else: - self.deviceSecret = " " - if EventMesh.platform == "gewu": - self.client = mqtt_client_pro_init() + ALARM_CONFIG_R_CMD = "alarm_config_R" + ALARM_CONFIG_S_CMD = "alarm_config_S" - def post_processor_after_instantiation(self): - EventMesh.subscribe("get_mqtt_pro_connect_state",self.get_mqtt_pro_connect_state) - EventMesh.subscribe("get_mqtt_dev_connect_state",self.get_mqtt_dev_connect_state) - EventMesh.subscribe(constants.EVENT.CHANNEL_SOCKET_SEND, self.send) - self.monitor_timer.start(7 * 60 * 1000, 1, self.check) + ALARM_LIST_R_CMD = "alarm_list_R" + ALARM_LIST_S_CMD = "alarm_list_S" - def add_support_resolver(self, resolver): - self.resolver = resolver + UNBIND_DEV_R="unbind_dev_R" + UNBIND_DEV_S="unbind_dev_S" - def initialization(self, *args, **kwargs): - _thread.stack_size(16*1024) - _thread.start_new_thread(self.recv, ()) - _thread.stack_size(8*1024) - - def set_device_id(self,event,msg): - self.device_id = str(msg) + DEVICE_SHAKE_STATE_R_CMD = "device_shake_state_R" + DEVICE_SHAKE_STATE_S_CMD = "device_shake_state_S" + +class IOT_socket_SendCmdManager(Abstract): + # + def __init__(self): + self.send_data = "" + self.time_tmp = 0 + def post_processor_after_instantiation(self): + EventMesh.subscribe("GET_IOT_SEND_CMD", self.get_iot_send_cmd) + print("IOTSendCmdManager") + #调用:device_state=EventMesh.publish("GET_IOT_SEND_CMD",WEB_CMD_ENUM.POST_DEVICE_INFOR_S_CMD) + # print("device_state{}".format(device_state)) + def get_iot_send_cmd(self, event, msg):#获取准备发送的值 + date_tmp = utime.localtime() + self.time_tmp = utime.mktime(date_tmp) + if msg == WEB_CMD_ENUM.POST_DEVICE_STATE_S_CMD:#设备VC状态 + self.send_data = self.device_report_state_send_data() + return self.send_data + elif msg == WEB_CMD_ENUM.POST_DEVICE_INFOR_S_CMD:#设备信息 + self.send_data = self.device_information_send_data() + return self.send_data + elif msg == WEB_CMD_ENUM.POST_DEVICE_INFOR_S_CMD:#聊天内容 + self.send_data = self.device_information_send_data() + return self.send_data - def get_device_id(self,event,msg): + # 设备对话内容上报数据格式 + def device_talk_send_data(self): + print("device_talk_send_data") + infor_send_data = { + "cmd":"chat_text", + "data": + { + "device_id":modem.getDevImei(),#设备号 + "type":"req:请求说的话;res:响应的内容", + "text":"用户说话内容", + "createTime":"时间戳" + } + } + return infor_send_data + + # 设备信息上报数据格式 + def device_information_send_data(self): + print("device_information_send_data") + battery_state = (EventMesh.publish("screen_get_battery"))[0] + battery = (EventMesh.publish("screen_get_battery"))[1] + if battery >= 100 or battery == None: + battery = 100 + VC_TTS_volume = EventMesh.publish("get_storage_config","VC_TTS_volume")#音量配置 + if VC_TTS_volume == None: + VC_TTS_volume =100 + sourceVersion =versions.Build_Time + Timeversion ="JSWM-"+sourceVersion + infor_send_data = { + "data":{ + "version":Timeversion,#版本号 + "charge":battery_state,#0表示未充电,1表示充电中 + "current_role_name":"",#当前音色的name + "volume":str(VC_TTS_volume),#百分比数值 + "wifi_rssi":str(net.csqQueryPoll()//6),#wifi强弱:0,1,2,3,4,5。转成这几个梯度 + "battery":str(battery),#电量 + "device_id":modem.getDevImei(),#设备号 + }, + "cmd":"device_info" + } + return infor_send_data + + #设备上报VC状态 + def device_report_state_send_data(self): + ai_status = EventMesh.publish("screen_get_ai") + if EventMesh.publish("get_VC_satrt_flag") == 1:#获取vc是否在运行 + if ai_status < 6 : + target_status = "listening" + elif ai_status == 6: + target_status = "thinking" + elif ai_status >= 8: + target_status = "speaking" + else: + target_status = "idle" + + device_report_data ={ + "data":{ + "device_id":modem.getDevImei(), + "state":target_status + }, + "cmd":"chat_state" + } + return device_report_data +def extract_target_number(json_str): + # 查找"target":"的起始位置 + start_key = '"target":"' + start_idx = json_str.find(start_key) + if start_idx == -1: + print("未找到 target 字段") + return None # 未找到目标字段 + + # 计算数字的起始位置(跳过"target":") + num_start = start_idx + len(start_key) + + # 从数字起始位置开始,查找结束的双引号(") + num_end = json_str.find('"', num_start) + if num_end == -1: + print("未找到数字的结束位置") + return None # 格式异常 + + # 截取数字字符串(从num_start到num_end) + number_str = json_str[num_start:num_end] + + # 转换为整数(如果需要浮点数,可改为float(number_str)) + try: + return int(number_str) + except ValueError: + print("截取的内容不是有效数字") + return None + +def playload_data(data): + print("data = {}".format(data)) + if isinstance(data, bytes) == 0 : + print("data类型错误") + return - return self.device_id - def set_device_key(self,event,msg): - self.device_key = str(msg) + if data[0] != 0xff or data[1] !=0xfe: + print("data格式错误,重新登录") + EventMesh.publish("login_IOT")#登录IOT return - def get_device_key(self,event,msg): + payload_len_bytes = data [3:5] + payload_len = ustruct.unpack ('H', payload_len_bytes)[0] + # print ("解析到 Payload 长度:{} 字节".format(payload_len)) + + payload = data [5 : 5+ payload_len] + try: + json_str = payload.decode ('utf-8') + except UnicodeDecodeError: + try: + json_str = payload.decode ('gbk') + print ("提示:Payload 使用 GBK 编码") + except UnicodeDecodeError: + print ("Payload 解码失败") + return + # json_str = "\"" + json_str + "\"" + if type(json_str) is str and len(json_str)>5: + print ("解析出的 JSON 字符串:{}".format(json_str) + "-"*50) + if "get_device_state" in json_str: + EventMesh.publish("send_device_information")#发送设备信息 + EventMesh.publish("send_device_VC_state")#上传VC状态 + print("get_device_state") + elif "find_device" in json_str: + EventMesh.publish("play_tts_single","我在这呀,我在这呀") + print("find_device") + elif "renew_device" in json_str:#更新对话模式 重启 + EventMesh.publish("play_tts_single","更新配置中,设备将自动重启") + print("renew_device") + utime.sleep_ms(3000) + EventMesh.publish("Power_off") + elif "switch_volume" in json_str: + volume = int(extract_target_number(json_str)) + print("switch_volume = {}".format(volume)) + EventMesh.publish("update_volume",volume) + elif "switch_brightness" in json_str: + light = int(extract_target_number(json_str))//10 + print("switch_brightness") + EventMesh.publish("set_brightness_level",light) + elif "setup_role" in json_str: + EventMesh.publish("play_tts_open","角色正在切换") + print("setup_role") + EventMesh.publish("load_screen", {"screen": "UI_ai"})#ai画面 - return self.device_key - - def set_product_key(self,event,msg): - self.product_key = str(msg) - def get_product_key(self,event,msg): + # data_dict = ujson.loads(json_str) + # if isinstance(data_dict, dict): + # #下面做小程序下发指令类型判断 + # data = data_dict["cmd"] + # if data is "get_device_state": + # EventMesh.publish("send_device_information")#发送设备信息 + # print("get_device_state") + # elif data is "find_device": + # EventMesh.publish("play_tts_single","我在这呀,我在这呀") + # print("find_device") + # else: + # print("JSON数据不是字典类型") - return self.product_key - def set_deviceSecret(self,event,msg): - if EventMesh.platform == "gewu": - self.deviceSecret = str(msg) - deviceSecret_tmp = "deviceSecret:{}".format(msg) - SecureData.Store(2, deviceSecret_tmp, len(deviceSecret_tmp)) - - def get_deviceSecret(self,event,msg): - return self.deviceSecret + +date_tmp = utime.localtime() +time_tmp = utime.mktime(date_tmp) +MAGIC = (0xfffe).to_bytes(2,"big") +VERSION = (0x01).to_bytes(1,"big")#"03".encode('utf-8') +TYPE = (0x03).to_bytes(1,"big") +DATA_LEN = (0x00000000).to_bytes(4,"big") +#magic+version+type+playload_len+playload +def protocol_send_total_data(data): + MAGIC = (0xfffe).to_bytes(2,"big") + VERSION = (0x01).to_bytes(1,"big")#"03".encode('utf-8') + TYPE = (0x03).to_bytes(1,"big") + HR_JSON = ujson.dumps(data) + GPS_JSON_b = HR_JSON.encode('utf-8') + DATA_LEN = (len(HR_JSON)).to_bytes(4,"big") + heards_infor = b'' + heards_infor = MAGIC+VERSION+TYPE+DATA_LEN+GPS_JSON_b + return heards_infor + +DEFIEN_HR_REPORT_TIME = 5*60 +DEFINE_TIME_COUNT = 5 +DEFIEN_LOCATION_REPORT_TIME = 5 +WEB_CONNECT_MAX_COUNT = 10 #默认重连次数 + +PROJECT_NAME = "JSWM" +PROJECT_VERSION = "1.0.0" +checknet = checkNet.CheckNetwork(PROJECT_NAME, PROJECT_VERSION) +# 设置日志输出级别 +log.basicConfig(level=log.INFO) +socket_log = log.getLogger("SOCKET") +class SockMangager(Abstract): + def __init__(self): + self.thread_buf_size = 8*1024 + self.iot_soc_send_queue = Queue(100) + self.iot_protoclo_recv_id=None + self.connect_timer = osTimer() + self.connect_timer_count = 0 + self.hr_report_timer = osTimer() + self.resolver = None + self.send_device_time = 0 + self.vbat_buf = [] + self.network_state = 0 + self.socket_send_queue_id = None + self.bat_count = 0 + self.reconnect_count = 0 #连续重连次数 默认十次 不过就不重连了 等下一个心跳重连 + self._1S_timer = osTimer() + self._5S_timer = osTimer() + self.timer_id = 0 + self.start_voice_flag = 0 + self.IOT_sock = None + self.sock_lock = _thread.allocate_lock() # 初始化锁 + #对话状态,一秒检查一次 + self.last_data = None # 保存上一次的数据状态 + self.current_data = None # 当前数据 + + self.send_recv_flag = 0#线程开启状态 + EventMesh.subscribe("REPORT_ALARM_TO_IOT",self.report_alarm_to_iot) + + def report_alarm_to_iot(self,event,msg): + EventMesh.publish(WEB_CMD_ENUM.POST_ALARM_S_CMD,msg) + pass + def usb_event_cb(self, state): + status = state + def post_processor_after_instantiation(self): + EventMesh.subscribe("CHANNEL_IOT_SEND",self.user_send)#发送数据的函数!!重要 + EventMesh.subscribe("GET_IOT_PROTOCOL_CILENT",self.get_IOT_sock) + EventMesh.subscribe("close_socket_timer",self.close_socket_timer) + EventMesh.subscribe("connect_iot_socket",self.connect_iot_socket_cb)#使用socket连接iot平台 + EventMesh.subscribe("login_IOT",self.login_IOT)#登录iot平台 + EventMesh.subscribe("heart_IOT",self.heart_IOt)#心跳包 + EventMesh.subscribe("send_device_information",self.send_device_information)#上报设备信息 + EventMesh.subscribe("send_device_VC_state",self.send_device_VC_state)#上报VC状态 + EventMesh.subscribe("send_unbind_dev_to_iot",self.send_unbind_dev_to_iot)#心跳包定时器开启 + self.reconnect_count = 0 + self.deviceReadState = "" + # self.connect_timer.start(2000,0,self.iot_connect_timerCb) + + def send_device_information(self,event,msg): + EventMesh.publish("publish_AI_btnInfo",{"func":self.send_packet_iot,"data":WEB_CMD_ENUM.POST_DEVICE_INFOR_S_CMD})#上报设备信息 + def send_device_VC_state(self,event,msg): + EventMesh.publish("publish_AI_btnInfo",{"func":self.send_packet_iot,"data":WEB_CMD_ENUM.POST_DEVICE_STATE_S_CMD})#上报VC状态 + + def send_unbind_dev_to_iot(self,event,msg): + self._5S_timer.start(30000,1,self._1M_timer_cb) + self._1S_timer.start(1000,1,self._1S_timer_cb) + def _1M_timer_cb(self,*argc): + EventMesh.publish("heart_IOT")#开启IOT心跳包 + EventMesh.publish("send_device_information")#发送设备信息 + pass - def connect(self): - EventMesh.debug_log("connect1{}:{}".format(self.server_addr, self.server_port)) - if EventMesh.publish("get_sim_Status") != 1: #没sim - return - try: - if(self.sock != None) : - self.sock.close() - self.sock = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM) - #self.sock.setblocking(False) &self.sock.settimeout(0)不阻塞 - self.sock.connect((self.server_addr, self.server_port)) - - self.publish_timer.start(2000, 1, self.publish_timer_cb) - if EventMesh.platform == "gewu": - self.mqtt_client_count = 0 - self.mqtt_recv_timer.start(5000, 1, self.mqtt_recv_timer_cb) - - utime.sleep_ms(500) - EventMesh.publish(constants.PROTOCOL.LK_SEND) - # 发送数据 - - - except Exception as e: - usys.print_exception(e) - self.run_flag = False + def initialization(self, *args): + pass + def connect_iot_socket_cb(self,event,msg): + self.connect_iot_socket() + def add_support_resolver(self, resolver): + self.resolver = resolver + def hr_report_event(self, *args, **kwargs): + EventMesh.publish("publish_AI_btnInfo",{"func":self.hr_report_event_cb}) #self.connect_iot_websocket() + def hr_report_event_cb(self): + """电池平均值""" + temp = Power.getVbatt() + if self.bat_count < 10: + self.vbat_buf.append(temp) + self.bat_count += 1 else: - self.run_flag = True - EventMesh.debug_log("connect2{}:{}".format(self.server_addr, self.server_port)) - self.reconnect_flag = 0 - def publish_timer_cb(self, *args): - self.authen_set() - - def authen_set(self): - sever_state = EventMesh.publish("get_server_state")#获取修改服务器状态 - # print("sever_state{}".format(sever_state)) - if sever_state != None: - if sever_state == 0: - imei = EventMesh.publish(constants.EVENT.GET_IMEI) - server_data = EventMesh.publish("get_new_key_pid")#获取pid和key - key_data = "" - pid_data = "" - if server_data != None: - key_data = server_data[0] - pid_data = server_data[1] - else: - server_data = server_init() - key_data = server_data[2] - pid_data = server_data[3] - - # server_data = server_init() - # key_data = server_data[2] - # pid_data = server_data[3] - - sonce_data = str(urandom.getrandbits(32))#随机生成32位的随机数 - md5_data = "{}*{}*{}*{}".format(imei,pid_data,sonce_data,key_data)#md5签名 - sign_data = "" - hash_obj = uhashlib.md5(md5_data) - res = hash_obj.digest() - - # 转成十六进制表示 - sign_data = ubinascii.hexlify(res) - sign_data = sign_data.decode('ascii') - # print("sign_data:{} sonce_data:{}".format(md5_data,sign_data)) - # sign_data = MD5_head - # http://8.134.110.49:31379/dev/device/check?imei=&bid=sonce=sign= - # ip_addr = "test.iot.api.thisiot.com" - # ip_addr = "app.api.thisiot.com" - # http://app.api.thisiot.com/ - url = "http://app.api.thisiot.com/dev/device/check?imei={}&bid={}&sonce={}&sign={}".format(imei,pid_data,sonce_data,sign_data) - - # print("url:{}".format(url)) - response = request.get(url) - data_tmp ={} - # d_server_addr = "device.miwitracker.com" - # d_server_port = 8505 - # d_md5_key = "" - # d_PID = "3G" - # response.content = {'protocolType': '', 'host': 'device.miwitracker.com', 'secretKey': '', 'port': 8505, 'bid': '3G', 'extJsonStr': ''} - # response.status_code=200 - print("test-{}".format(response.status_code)) - if response.status_code == 200: - content = response.content - c = next(content) - # "api.xcloudtech.com" - # d_server_port = 9000 - jsload_data = ujson.loads(c) - print("jsload_data-{}".format(jsload_data)) - # jsload_data = {'data':'111','protocolType':'', 'host':'device.miwitracker.com', 'secretKey': 'bZld0ALsZTt15tKEZhOlLPgbsO75BLTP', 'port':8505, 'bid': '3G', 'extJsonStr': ''} - # ujson.loads(c) - - if "success" in jsload_data: - success = jsload_data["success"] - if success == True:#合法设备 - if "data" in jsload_data: - data_tmp = jsload_data["data"]#返回的数据 - print("data_tmp:{}".format(data_tmp)) - code = jsload_data["code"] - if code == 20000:#合法的设备 - protocloType = data_tmp["protocolType"]#协议类型 - host = data_tmp["host"]#服务骑地址 - secretKey = data_tmp["secretKey"]# - pid = data_tmp["bid"]#产品型号 - port = data_tmp["port"]#端口号 - - - - if host != '' and (port != '' and port != -1): - if host != '': - self.server_addr = host - EventMesh.publish("set_ip",str(self.server_addr)) - - if port != '' and port != -1: - self.server_port = port - EventMesh.publish("set_com",self.server_port) - EventMesh.publish("set_new_key", str(secretKey))#获取pid和key - EventMesh.publish("set_new_pid",str(pid))#获取pid和key - # self.reconnect_timer_cb()#重连设备 - print("self.reconnect_flag",self.reconnect_flag) - self.reconnect_flag = 0 - self.reconnect()#重连设备 - self.publish_timer.stop() - EventMesh.publish("set_server_state",1)#获取修改服务器状态 - else: - self.publish_timer.stop() - - - - def mqtt_recv_timer_cb(self, *args): - self.mqtt_clien_cb() + for i in range(9): + self.vbat_buf[i] = self.vbat_buf[i+1] + self.vbat_buf[9] = temp + curr_count = len(self.vbat_buf) + bat_total_value = 0 + for i in range(curr_count): + bat_total_value += self.vbat_buf[i] + bat_total_value = bat_total_value//curr_count#一分钟更新一次电量 10个平均值 + EventMesh.publish("AI_alarm_start") #检查是否有闹钟需要提醒 + # self.alarm_test() + EventMesh.publish("set_curr_battery_level",bat_total_value) + # EventMesh.publish("publish_AI_btnInfo",{"func":self.hr_report_publish_event,"data":0}) + if self.send_device_time < DEFIEN_LOCATION_REPORT_TIME : + self.send_device_time+=DEFINE_TIME_COUNT + else: + device_state=EventMesh.publish("GET_IOT_SEND_CMD",WEB_CMD_ENUM.POST_DEVICE_INFOR_S_CMD) + print("device_information{}".format(device_state)) + # EventMesh.publish(WEB_CMD_ENUM.POST_DEVICE_INFOR_S_CMD,device_state) #上报设备信息 + EventMesh.publish("publish_AI_btnInfo",{"func":self.send_packet_iot,"data":WEB_CMD_ENUM.POST_DEVICE_INFOR_S_CMD})#上报设备信息 + + def iot_connect_timerCb(self,*argc): + self.connect_iot_socket() + + def connect_iot_socket(self): + if EventMesh.publish("get_voice_record_flag") == 1: + EventMesh.publish("stop_voice_record") + print("connect_iot_socket !!!!") + # self.iot_close_therad() + stagecode, subcode = checknet.wait_network_connected(30) + if stagecode == 3 and subcode == 1: + socket_log.info('Network connection successful!') - - def mqtt_clien_cb(self): - if EventMesh.platform != "gewu": + if self.reconnect_count >= WEB_CONNECT_MAX_COUNT: #重连次数大于10次不在进重连只有下发心跳才重新连接 return - # 需要加密的数据 - get_deviceSecret = EventMesh.publish("get_deviceSecret") - if get_deviceSecret != None: - if self.mqtt_client_count == 0: - self.mqtt_client_count = 1 - self.mqtt_recv_timer.stop() - get_deviceSecret = EventMesh.publish("get_deviceSecret")#获取设备的秘钥 只获取一次 - print("get_deviceSecret{}".format(get_deviceSecret)) - if get_deviceSecret == '':#如果为空就获取一次 - # print("self.client:{}".format(self.client)) - mqtt_connect = -1 - try: - mqtt_connect = self.client.connect() - except Exception as e: - print(e) - mqtt_connect = -1 - print("mqtt_connect:{}".format(mqtt_connect)) - if mqtt_connect == 0 : - # 订阅主题 - get_device_id = EventMesh.publish(constants.EVENT.GET_IMEI) - get_deviceKey = EventMesh.publish(constants.EVENT.GET_IMEI) - get_productKey = gewu_init() - #$sys/{productKey}/{deviceKey}/ext/regist - client_msg = "$sys/{}/{}/ext/regist".format(get_productKey,get_deviceKey) - # client_msg = "$sys/cu1shld45y4hjr1L/866610001011658/ext/regist" - subscribe_msg = client_msg.encode('ascii') - print(subscribe_msg) - - self.client.subscribe(subscribe_msg,0)#订阅消息主题 - - - self.client.wait_msg() # 阻塞函数,监听消息 - utime.sleep(5) - get_deviceSecret = EventMesh.publish("get_deviceSecret") - if get_deviceSecret != '': - self.client.disconnect() - self.client_dev = mqtt_client_dev_init() - print(self.client_dev) - # mqtt_connect = self.client_dev.connect() - try: - mqtt_connect = self.client_dev.connect() - except Exception as e: - print(e) - mqtt_connect = -1 - if mqtt_connect == 0: - # $sys/cu1shld45y4hjr1L/bOOSGN5FlXEjt15/property/batch_reply - msg_reply = "$sys/{}/{}/property/batch_reply".format(get_productKey,get_deviceKey) - sub_msg = msg_reply.encode('ascii') - self.client_dev.subscribe(sub_msg,0)#订阅消息主题 - print("Connected to dmp-mqtt.cuiot.cn, subscribed to /public/TEST/quecpython topic") - # 发布消息 - # UnicodeHexStr_To_Utf8Str(str_data) - date_tmp = utime.localtime() - time_tmp = utime.mktime(date_tmp)#需要转换成毫秒级别 - updataTime = "{}".format(time_tmp*1000) - # imei_tmp= modem.getDevImei() - imei_tmp = EventMesh.publish(constants.EVENT.GET_IMEI) - bat_tmp = EventMesh.publish("screen_get_battery") - imei = "{}".format(imei_tmp) - power = 0 - power = int(bat_tmp[1]) - hr = 0 - hr = EventMesh.publish("get_old_hr_data") - if hr == None: - hr = 0 - deviceTime = "{}".format(time_tmp) - manufactury = "fengda" - DeviceState = "online" - - data_info = { - "messageId":"0", - "params": { - "data": [ - { - "key":"deviceOffOn", - "value": { - "deviceStatus":"Poweron", - "updateTime":updataTime, - "Imei":imei - } - - }, - { - "key":"HeartRate", - "value":{ - "heartRate":hr, - "updateTme":updataTime, - "Imei":imei - } - }, - { - "key":"powerSavingMode", - "value":0 - }, - { - "key":"IMEI", - "value":imei - }, - { - "key":"DEVICE_TIME", - "value":deviceTime - }, - { - "key":"MANUFACTURER", - "value":manufactury - }, - { - "key":"REMAINING_POWER", - "value":power - }, - { - "key":"DeviceState", - "value":DeviceState - } - ] - } - } - - data_json = ujson.dumps(data_info) - # print("data_json:{}",data_json) - # $sys/cu1shld45y4hjr1L/{deviceKey}/property/batch - msg_pub = "$sys/{}/{}/property/batch".format(get_productKey,get_deviceKey) - pub_msg = msg_pub.encode('ascii') - self.client_dev.publish(pub_msg,data_json,0)#publis主题内容 - - print("Publish topic: /public/TEST/quecpython758, msg: my name is Quecpython") - pass + token = EventMesh.publish("get_dev_token") + # token = "9548860f973bffe39e1679db3110e223cb" + print("token:{}".format(token)) + if self.IOT_sock is not None: + print("socket已连接") + return + try: + if token != None: + self.connect_timer_count = 0 + #创建一个socket实例 + self.IOT_sock = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM) + try: + #建立连接 + self.IOT_sock.connect(('iot.socket.thisiot.com', 7777)) + #设置为阻塞 + self.IOT_sock.setblocking(True) + socket_log.info("IOT 连接建立") + except Exception as e: + print("再次连接") + self.IOT_sock.connect(('iot.socket.thisiot.com', 7777)) + #设置为非阻塞 + self.IOT_sock.setblocking(False) + + if self.send_recv_flag == 0:#线程未开启过 + self.send_recv_flag = 1 + self.reconnect_count = 0 + _thread.stack_size(self.thread_buf_size+8*1024) #_thread.stack_size(16*1024) + self.socket_send_queue_id = _thread.start_new_thread(self.socket_send_queue_thread, ()) + _thread.stack_size(8*1024) + + _thread.stack_size(self.thread_buf_size+8*1024) + self.iot_protoclo_recv_id = _thread.start_new_thread(self.iot_protocol_recv, ()) + _thread.stack_size(8*1024) + socket_log.info("self.IOT_sock thread init!!!!!!!!!") + + if self.IOT_sock != None: + self.start_voice_flag = 1 else: - mqtt_dev_connect = -1 - mqtt_ret_connect = -1 - mqtt_pro_connect = -1 - if self.client_dev == 0: - self.client_dev = mqtt_client_dev_init() - try: - mqtt_dev_connect = self.client_dev.connect() - except Exception as e: - print("erro!{}".format(e)) - mqtt_dev_connect = -2 - # Server Actively FIN Disconnected.Need Check Connection parameters - err_dis = "FIN Disconnected" in str(e) - err_parm1 = "107" in str(e) - err_parm2 = "4" in str(e) - # print("err_parm1!{} {} {} {}".format(err_parm1,err_parm2,err_info,err_dis)) - # Connect Error='4' MQTT Connect error= - if err_dis == True or err_parm1 == True or err_parm2 == True: - mqtt_dev_connect = -1 - - - if mqtt_dev_connect != 0:#连接参数错误可能是deviceScrete出错重新获取 + self.start_voice_flag = 0 - try: - mqtt_ret_connect = self.client.connect()#重新获取deviceScrete - except Exception as e: - print(e) - mqtt_ret_connect = -1 - # mqtt_connect = self.client.connect() - print("mqtt_ret_connect:{}".format(mqtt_ret_connect)) - if mqtt_ret_connect == 0: - # 订阅主题 - get_device_id = EventMesh.publish(constants.EVENT.GET_IMEI) - get_deviceKey = EventMesh.publish(constants.EVENT.GET_IMEI) - get_productKey = gewu_init() - #$sys/{productKey}/{deviceKey}/ext/regist - client_msg = "$sys/{}/{}/ext/regist".format(get_productKey,get_deviceKey) - # client_msg = "$sys/cu1shld45y4hjr1L/866610001011658/ext/regist" - subscribe_msg = client_msg.encode('ascii') - print(subscribe_msg) - - self.client.subscribe(subscribe_msg,0)#订阅消息主题 - - self.client.wait_msg() # 阻塞函数,监听消息 - utime.sleep(5) - - self.client.disconnect() - self.client_dev = mqtt_client_dev_init() - # print(self.client_dev) - try: - mqtt_pro_connect = self.client_dev.connect() - except Exception as e: - print(e) - mqtt_pro_connect = -1 - # print("no deviceScret!!!!!!!{}".format(self.client_dev)) - # 设备秘钥不为空 重连获取设备失败不连接 第一次连接失败不连接不发送数据 - if EventMesh.publish("get_deviceSecret") != "" and (mqtt_pro_connect == 0 or mqtt_dev_connect == 0): - get_device_id = EventMesh.publish(constants.EVENT.GET_IMEI) - get_deviceKey = EventMesh.publish(constants.EVENT.GET_IMEI) - get_productKey = gewu_init() - # $sys/cu1shld45y4hjr1L/bOOSGN5FlXEjt15/property/batch_reply - msg_reply = "$sys/{}/{}/property/batch_reply".format(get_productKey,get_deviceKey) - sub_msg = msg_reply.encode('ascii') - # print(" deviceScret!!!!!!!{} msg_reply:{} sub_msg:{}".format(self.client_dev,msg_reply,sub_msg)) - self.client_dev.subscribe(sub_msg,0)#订阅消息主题 - print("Connected to dmp-mqtt.cuiot.cn, subscribed to /public/TEST/quecpython topic") - # 发布消息 - # UnicodeHexStr_To_Utf8Str(str_data) - date_tmp = utime.localtime() - time_tmp = utime.mktime(date_tmp)#需要转换成毫秒级别 - updataTime = "{}".format(time_tmp*1000) - imei_tmp = EventMesh.publish(constants.EVENT.GET_IMEI) - imei = "{}".format(imei_tmp) - bat_tmp = EventMesh.publish("screen_get_battery") - power = 0 - power = int(bat_tmp[1]) - hr = 0 - hr = EventMesh.publish("get_old_hr_data") - if hr == None: - hr = 0 - deviceTime = "{}".format(time_tmp) - manufactury = "fengda" - DeviceState = "online" - - data_info = { - "messageId":"0", - "params": { - "data": [ - { - "key":"deviceOffOn", - "value": { - "deviceStatus":"Poweron", - "updateTime":updataTime, - "Imei":imei - } - - }, - { - "key":"HeartRate", - "value":{ - "heartRate":hr, - "updateTme":updataTime, - "Imei":imei - } - }, - { - "key":"powerSavingMode", - "value":0 - }, - { - "key":"IMEI", - "value":imei - }, - { - "key":"DEVICE_TIME", - "value":deviceTime - }, - { - "key":"MANUFACTURER", - "value":manufactury - }, - { - "key":"REMAINING_POWER", - "value":power - }, - { - "key":"DeviceState", - "value":DeviceState - } - ] - } - } - - data_json = ujson.dumps(data_info) - # print("data_json:{}",data_json) - # $sys/cu1shld45y4hjr1L/{deviceKey}/property/batch - msg_pub = "$sys/{}/{}/property/batch".format(get_productKey,get_deviceKey) - pub_msg = msg_pub.encode('ascii') - self.client_dev.publish(pub_msg,data_json,0)#publis主题内容 - - print("Publish topic: /public/TEST/quecpython758, msg: my name is Quecpython") - - def get_mqtt_pro_connect_state(self,event,msg): - return self.client - def get_mqtt_dev_connect_state(self,event,msg): - return self.client_dev - - def check(self, *args): - if (not self.run_flag) or (self.connect_tmp == 0) : #7分钟无数据读取,则认为是掉线了 - EventMesh.debug_log("tcp reconnect!!!!!!!!!!!!!!!!!!") - EventMesh.publish(constants.EVENT.SET_CONNECT,0) #标记断网 - self.reconnect() - self.connect_tmp = 0 - def reconnect(self): - if(self.reconnect_flag == 1): - return - self.reconnect_flag = 1 - self.reconnect_timer.start(self.reconnect_time, 0, self.reconnect_timer_cb) - if self.reconnect_time < 600*1000: - self.reconnect_time += 30*1000 - - def reconnect_timer_cb(self, *args): - _thread.stack_size((9+1)*1024) - _thread.start_new_thread(self.connect, ()) - _thread.stack_size(8*1024) + print("self.IOT_sock {} self.start_voice_flag:{}".format(self.IOT_sock,self.start_voice_flag)) + if self.IOT_sock != None: + if self.timer_id == 0: + # self.hr_report_timer.start(DEFINE_TIME_COUNT*1000, 1, self.hr_report_event) + self.timer_id=1 + else: + print("没有token!!!!!!!!!!") + self.connect_timer_count+=1 + if self.connect_timer_count <= 10: + print("IOT重连定时器开启") + self.connect_timer.start(5000,0,self.iot_connect_timerCb) + pass + except Exception as e: + self.IOT_sock = None + print("connect_iot_socket error") + def heart_IOt(self,event,msg): + print("heart_IOT.....") + #Header + header = ustruct.pack('>H', 0xFFFE) # 使用大端模式 + #Type + packet_type = ustruct.pack('B', 0x02) + #拼接 + heart_packet = header + packet_type + EventMesh.publish("CHANNEL_IOT_SEND", heart_packet) + # print("心跳发送数据包:{}".format(heart_packet)) + + def send_packet_iot(self,data):#发送数据给iot,data为接口json数据 + #Header + header = ustruct.pack('>H', 0xFFFE) # 使用大端模式 + #Type + packet_type = ustruct.pack('B', 0x03) + #字典转为json字符串 + json_str = EventMesh.publish("GET_IOT_SEND_CMD", data) + json_str = ujson.dumps(json_str) + #字符串转为二进制数据Payload + payload = json_str.encode('utf-8') + #PayloadLen + payloadLen = ustruct.pack('H', len(payload)) + #CRC16(2字节,基于pay字段计算) + crc = self.crc16(payload) + print("crc的长度为{}".format(len(crc))) + #拼接 + full_packet = header + packet_type + payloadLen + payload+ crc + EventMesh.publish("CHANNEL_IOT_SEND", full_packet) + print("发送更新数据包:{}".format(full_packet)) + + def login_IOT(self,event,msg): + print("登录中") + #Header + header = ustruct.pack('>H', 0xFFFE) # 使用大端模式 + #Type + packet_type = ustruct.pack('B', 0x00) + #设备ID + device_id_bytes = modem.getDevImei().encode('utf-8')[:20] # 转为字节并截断到20字节 + device_id = bytes_ljust(device_id_bytes, 20, b'\x00') + #令牌 + token_bytes = EventMesh.publish("get_dev_token").encode('utf-8')[:36] # 转为字节并截断 + token_padded = bytes_ljust(token_bytes, 36, b'\x00') + #拼接 + body = header + packet_type + device_id + token_padded + #CRC16(2字节,基于上述所有字段计算) + crc = self.crc16(body) + # 完整数据包 + full_packet = body + crc + EventMesh.publish("CHANNEL_IOT_SEND", full_packet) + print("登录发送数据包:{}".format(full_packet)) + + + def crc16(self, data): + """计算CRC16校验值(MODBUS RTU模式)""" + crc = 0xFFFF + for byte in data: + crc ^= byte + for _ in range(8): + if crc & 0x0001: + crc >>= 1 + crc ^= 0xA001 + else: + crc >>= 1 + # 返回2字节小端模式 + return ustruct.pack(' 15 : - break - utime.sleep(1) - if(self.sock.getsocketsta() == 4):# - try: - self.sock.send(data) - EventMesh.debug_log("TCP:send data3 len:{}".format(len(data))) - except Exception as e: - self.reconnect() - self.socket_send_queue.put(data)#重新把数据加回队列 - #EventMesh.debug_log("socket_send_queue_thread2:ERROR:") - #usys.print_exception(e) + EventMesh.debug_log("socket:send error") + EventMesh.publish("publish_AI_btnInfo",{"func":self.connect_iot_socket}) break - else :#连接错误 - EventMesh.debug_log("socket_send_queue_thread:ERROR:reconnect") - self.reconnect() - utime.sleep(1) + + + def iot_protocol_recv(self): + while True: + # 死循环接收数据 + # with self.sock_lock: # 警告:不能加锁,不然会导致线程超长延时 + socket_flag = self.IOT_sock.getsocketsta() + print("socket_flag = {}".format(socket_flag)) + try: + data = self.IOT_sock.recv(256) + if isinstance(data, bytes) and len(data)>10: + playload_data(data) + socket_log.info("IOT_recv = {} ,len = {}".format(self.bytes_to_hex(data),len(data))) + if self.IOT_sock == None: + print("socket关闭退出send线程") + return + except Exception as e: + print("cli break") + print("异常是:{}".format(e)) + # EventMesh.publish("connect_iot_websocket_cb") + EventMesh.publish("publish_AI_btnInfo",{"func":self.connect_iot_socket}) + break + self.iot_protoclo_recv_id =None + def decode_with_multiple_encodings(self, data): + #尝试多种常见编码格式解码,返回第一个成功的结果 + # 常见编码格式列表(按优先级排序,根据实际场景调整) + encodings = ['utf-8', 'gbk', 'latin-1', 'utf-16', 'gb2312'] + + for encoding in encodings: + try: + # 尝试用当前编码解码,errors='strict'严格模式(确保无乱码) + return data.decode(encoding, errors='strict') + except UnicodeDecodeError: + continue # 解码失败,尝试下一种编码 + return None # 所有编码都失败 + + # bytes转十六进制字符串 + def bytes_to_hex(self, data): + #将bytes类型转换为十六进制字符串(如b'\x03\x01' -> '0301') + hex_chars = '0123456789abcdef' + hex_str = '' + for b in data: + # 处理每个字节的高4位和低4位 + hex_str += hex_chars[(b >> 4) & 0x0F] # 高4位 + hex_str += hex_chars[b & 0x0F] # 低4位 + return hex_str + + def iot_send_queue_close(self): + if self.socket_send_queue_id != None: + if self.iot_soc_send_queue.empty()!=True: + self.iot_soc_send_queue.clear() + try: + _thread.stop_thread(self.socket_send_queue_id) + except Exception as e: + print("iot_protoclo_recv_id !!!!!!!!") + print("iot_protoclo_recv_id 1111!!!!!!!!") + self.socket_send_queue_id = None + + def iot_protoclo_recv_close_therad(self): + if self.iot_protoclo_recv_id != None: + try: + _thread.stop_thread(self.iot_protoclo_recv_id) + except Exception as e: + print("self.iot_protoclo_recv_id !!!!!!!!") + self.iot_protoclo_recv_id = None + if self.IOT_sock != None: + try: + print("关闭socket") + self.IOT_sock.close() + except Exception as e: + print("关闭socket失败") + self.IOT_sock = None + + + + def iot_close_therad(self): + try: + self.iot_send_queue_close() + except Exception as e: + print("iot_send_queue_close error!!!!!!!!") - def send(self, topic, msg): + try: + self.iot_protoclo_recv_close_therad() + except Exception as e: + print("iot_protoclo_recv_close_therad error!!!!!!!!") + self.start_voice_flag = 0 + print("iot_close_therad") + + def get_IOT_sock(self,event,msg): + return self.IOT_sock + def user_send(self,event,data): + # EventMesh.debug_log("TCP:send data:{}".format(msg)) # EventMesh.debug_log("TCP:send data:{}".format(msg)) - if EventMesh.publish("get_sim_Status") != 1: #没sim,则不发送 - EventMesh.publish(constants.EVENT.SET_CONNECT, 0)#标记断网 - EventMesh.debug_log("dataCall not connect") + sim_state = sim.getStatus() + if sim.getStatus() != 1:#网络不正常 + print("无 sim卡") return else : try: - self.socket_send_queue.put(msg) + if self.start_voice_flag == 0: #如果关闭了就需要重新再 + EventMesh.publish("publish_AI_btnInfo",{"func":self.connect_iot_socket}) + return + if data != None: + if len(data) != 0: + self.iot_soc_send_queue.put(data) + # EventMesh.debug_log("self.socket_send_queue.put:success:{}".format(len(data))) except Exception as e: EventMesh.debug_log("self.socket_send_queue.put:ERROR:") usys.print_exception(e) - # self.run_flag = False - - def recv(self): - data = b'' - while True: + + return + sim_state = sim.getStatus() + if sim_state != 1 or self.network_state == 0: #没sim,则不发送 ,没联网 + return + else : try: - r = b'' - r = self.sock.recv(1024*5) + if self.IOT_sock != None: + EventMesh.publish("publish_AI_btnInfo",{"func":self.iot_protocol_send_cb,"data":data}) + else: + print("reconnect1 {}".format(data)) + EventMesh.publish("publish_AI_btnInfo",{"func":self.connect_iot_socket}) - if not r: - self.run_flag = False - self.reconnect() - - data = data + r - EventMesh.debug_log("TCP recv: data:len:{}".format(len(data))) - # EventMesh.debug_log("TCP recv: data:{}".format(data)) - if data[-1] != 0x5d and len(data)<20*1024: #']': - continue - self.connect_tmp = 1 #有数据,就认为是连接状态 - self.reconnect_time = 1000 - EventMesh.publish(constants.EVENT.SET_CONNECT, 1) - data_str = data.decode('ascii') - data_str = data_str.split(']') - if len(data_str) < 3 : - self.resolver.handler(data) - else : - for i in range(len(data_str)-1): - self.resolver.handler(data_str[i]) - - data = b'' - except Exception as e: - #EventMesh.debug_log("TCP:ERROR:recv:") - #usys.print_exception(e) - self.run_flag = False - self.reconnect() + except Exception as e: + print("senc data err reconnect{}".format(data)) + EventMesh.publish("publish_AI_btnInfo",{"func":self.connect_iot_socket}) - data = b'' - utime.sleep(2) - - - + def iot_protocol_send_cb(self,data): + try: + if data != None: + print("socket connect success:{} self.IOT_sock:{}".format(data,self.IOT_sock)) + if self.IOT_sock != None: + self.IOT_sock.send(data) + self.reconnect_count = 0 + print("socket send success") + else: + print("reconnect2 {}".format(data)) + # EventMesh.publish("connect_iot_socket_cb") + EventMesh.publish("publish_AI_btnInfo",{"func":self.connect_iot_socket}) + except Exception as e: + print("发送失败 重新连接") + self.reconnect_count+=1 + # EventMesh.publish("connect_iot_socket_cb") + EventMesh.publish("publish_AI_btnInfo",{"func":self.connect_iot_socket}) + +def bytes_ljust(data, length, fill_byte=b'\x00'): + """ + 手动实现bytes的ljust功能:将字节流填充到指定长度,不足部分用fill_byte在右侧填充 + :param data: 原始字节流(bytes) + :param length: 目标长度(int) + :param fill_byte: 填充字节(默认空字节b'\x00') + :return: 填充后的字节流(bytes) + """ + if len(data) >= length: + # 若原始长度已超过目标长度,直接截断到指定长度 + return data[:length] + else: + # 计算需要填充的长度,用fill_byte补齐 + padding = fill_byte * (length - len(data)) + return data + padding + class NetManager(Abstract): THRESHOLD = 10 @@ -948,7 +975,6 @@ class NetManager(Abstract): def get_network_state(self, topic, msg): return self.network_state - class ProtoCol(Abstract): TYPE = "" HEADER = "#@{}@#;" @@ -1050,7 +1076,72 @@ class ProtoCol(Abstract): #EventMesh.debug_log(res) #EventMesh.debug_log(MD5_head) return MD5_head +#查找设备 +class IOT_FindDeviceProtoCol(ProtoCol): + """find_device""" + TYPE = "find_device" + def send(self, event, msg): + # print("send locafind_devicetion{}".format(msg)) + # 通过websocket发送到服务器端 + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp) + find_device = { + "cmd":"dispatch_rest", + "ts":time_tmp, + "msg":"消息收到响应", + "data":{ + "cmd":"find_device", + "rest":"success", + "msg":"收到查找设备指令" + } + } + send_data = b'' + send_data = protocol_send_total_data(find_device) + print("send_data find_device{}".format(send_data)) + EventMesh.publish("CHANNEL_IOT_SEND", send_data) + + def recv(self, event, msg): + """ + + @param event:定位信息下发 + @param msg: 接收到的下行数据 + """ + alarm_TTS_str="在这呢" + base_sentence = "{}".format(alarm_TTS_str) + repeat_sentence = (base_sentence + ",") * 3 # 重复5次并加逗号分隔 + final_sentence = repeat_sentence.rstrip(",") + + EventMesh.publish("play_tts",[final_sentence,1]) #播放tts闹钟文本内容 + print("recv find_device{}".format(msg)) + EventMesh.publish(WEB_CMD_ENUM.FIND_DEVCE_S_CMD) + +#上报设备VC状态 +class IOT_post_device_stateProtoCol(ProtoCol): + """post_device_state""" + TYPE = "post_device_state" + + def send(self, event, msg): + print("send post_device_state{}".format(msg)) + # 通过websocket发送到服务器端 + + send_data = b'' + send_data = protocol_send_total_data(msg) + EventMesh.publish("CHANNEL_IOT_SEND",send_data) + + def recv(self, event, msg): + """ + + @param event:mpost_device_state + @param msg: 接收到的下行数据 + """ + # locate_now = { + # "cmd":"locate_duration", + # "ts":1738283829, + # "msg":"下发定位周期", + # "data":300,0表示关 + # } + print("send post_device_state{}".format(msg)) class LK_ProtoCol(ProtoCol): """链路保持""" TYPE = "LK" @@ -1605,12 +1696,6 @@ class REMIND_ProtoCol(ProtoCol):#普通闹钟 EventMesh.publish(constants.PROTOCOL.REMIND_SEND) EventMesh.publish("clear_normal_alarm") - - - - - - class HRSTART_ProtoCol(ProtoCol): """心率频率数据""" TYPE = "hrtstart" @@ -3747,13 +3832,7 @@ class ProtoColResolver(object): try: if len(data) > 0: #EventMesh.debug_log("handler:{}".format(len(data))) - data_tmp = data.decode('ascii') - data_tmp = data_tmp.split(']')[0] #去掉] - ProtoCol_type = data_tmp.split('*')[3] #拿到协议标识 - ProtoCol_type = ProtoCol_type.split(',')[0] - ProtoCol_type = "%s_RECV"%(ProtoCol_type) - # EventMesh.debug_log("ProtoColResolver:ProtoCol_type:%s\r\ndata:%s"%(ProtoCol_type,data)) - EventMesh.publish(ProtoCol_type, data) #返回协议read + playload_data(data) except Exception as e: EventMesh.debug_log("handler:ERROR:") usys.print_exception(e) diff --git a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ui.py b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ui.py index 87f71dfd..a88f6af0 100644 --- a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ui.py +++ b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ui.py @@ -23,6 +23,7 @@ from queue import Queue from machine import RTC import usys from Gsensor import SC7A20 + def audio_cb(event): if event == 0: EventMesh.publish("set_audio_state", 1) @@ -1721,6 +1722,9 @@ class chargefullScreen(Screen):#充电已满弹窗提示 energe_img.add_style(style_img, lv.PART.MAIN | lv.STATE.DEFAULT) self.meta = self.charge_full_screen + + + def post_processor_after_initialization(self): self.count = 0 self.timer.start(1*1000,1,self.fun) @@ -1732,10 +1736,10 @@ class chargefullScreen(Screen):#充电已满弹窗提示 def fun(self,*argc): EventMesh.publish("system_sleep_rest")#防止黑屏 self.count+=1 - if self.count > 2*60: + if self.count > 5: self.count = 0 self.timer.stop() - #EventMesh.publish("return_prev_screen") + EventMesh.publish("load_screen", {"screen": "main_menu"}) def done_click(self): EventMesh.publish("return_prev_screen") @@ -1755,7 +1759,8 @@ ui_screen.add_style(style_screen, lv.PART.MAIN | lv.STATE.DEFAULT) ai_img = lv.img(ui_screen) ai_img.set_pos(0, 0) ai_img.set_size(240, 320) -ai_img.set_src("E:/static/listen.png") +# ai_img.set_src("E:/static/listen.jpg") +ai_img.set_src("E:/static/01.jpg") ai_img.add_style(style_img, lv.PART.MAIN | lv.STATE.DEFAULT) class UI_ai(Screen): NAME = "UI_ai" @@ -1765,14 +1770,44 @@ class UI_ai(Screen): print("UI_ai:__init__") self.meta = ui_screen self.timer = osTimer() - + self.image_sequences = { + # 为不同face_status定义图片序列,格式: [(图片路径, 显示时长), ...] + 0: [("E:/static/61.jpg", 0.5), #平常说 + ("E:/static/62.jpg", 0.5)], + # 1: [("E:/static/dj1.jpg", 0.5), #大吉 + # ("E:/static/dj2.jpg", 0.5)], + # 2: [("E:/static/zj1.jpg", 0.5),#中吉 + # ("E:/static/zj2.jpg", 0.5)], + # 3: [("E:/static/j1.jpg", 0.5), #吉 + # ("E:/static/j2.jpg", 0.5)], + # 4: [("E:/static/mj1.jpg", 0.5), #末吉 + # ("E:/static/mj2.jpg", 0.5)], + 1: [("E:/static/61.jpg", 0.5), #大吉 + ("E:/static/62.jpg", 0.5)], + 2: [("E:/static/61.jpg", 0.5),#中吉 + ("E:/static/62.jpg", 0.5)], + 3: [("E:/static/61.jpg", 0.5), #吉 + ("E:/static/62.jpg", 0.5)], + 4: [("E:/static/61.jpg", 0.5), #末吉 + ("E:/static/62.jpg", 0.5)], + 5: [("E:/static/01.jpg", 0.5), + ("E:/static/02.jpg", 0.5)],#听 + 6: [("E:/static/51.jpg", 0.5), + ("E:/static/52.jpg", 0.5)],#思考 + } + self.current_sequence = None + self.sequence_thread = None + self.running = False + #硬件资源缓存标识,记录当前加载的图片路径 + self.current_image_path = None def initialization(self): print("UI_ai:initialization") #获取ai状态 ai_status = EventMesh.publish("screen_get_ai") if ai_status: - self.__ai_vc(None, ai_status) - self.timer.start(500,1, self.timerout_update) + self.__ai_vc(None, ai_status,0) + self.timer.start(2000,1, self.timerout_update) + EventMesh.subscribe("UI_ai_close",self.UI_ai_close) def timerout_update(self, *args): EventMesh.publish("publish_message_event_ui",{"func":self.timerout_update_cb,"data":0}) @@ -1781,19 +1816,117 @@ class UI_ai(Screen): EventMesh.publish("system_sleep_rest")#防止黑屏 #获取ai状态 ai_status = EventMesh.publish("screen_get_ai") + draw_status = EventMesh.publish("screen_get_draw") + # print ("draw_status = {}".format(draw_status)) # print("ai_status = {}".format(ai_status)) - self.__ai_vc(None, ai_status) - def __ai_vc(self, event, msg): + self.__ai_vc(None, ai_status,draw_status) + + def __ai_vc(self, event, msg,draw_status): #msg = 1:listen,2:think,3:speak + # 记录上一次的face_status,避免重复启动 + if not hasattr(self, "last_face_status"): + self.last_face_status = -1 # 初始化 + target_status = None if msg < 6: - ai_img.set_src("E:/static/listen.png")#正在听 + target_status = 5 elif msg == 6: - ai_img.set_src("E:/static/think.png")#正在想 + target_status = 6 elif msg == 8: - ai_img.set_src("E:/static/speak.png")#正在说 - # elif msg == 14: - # ai_img.set_src("E:/static/listen.png")#正在听 - pass + target_status = draw_status + + # 仅当状态变化时,才启动新线程 + if target_status is not None and target_status != self.last_face_status: + lv.img.cache_invalidate_src(None) + lv.img.cache_set_size(8) + EventMesh.publish("publish_message_event_ui", {"func": self.start_sequence, "data": target_status}) + self.last_face_status = target_status # 更新状态 + def UI_ai_close(self,event,msg): + if self.running: + self.stop_sequence() + self.timer.stop() + lv.img.cache_invalidate_src(None) + lv.img.cache_set_size(8) + + def start_sequence(self, face_status): + #停止当前序列(确保旧线程退出) + if self.running: + self.stop_sequence() + #强制等待旧线程彻底退出(延长等待时间+主动清理) + start_wait = utime.time() + while self.sequence_thread is not None: + utime.sleep(0.05) # 更短间隔检测 + if utime.time() - start_wait > 2: # 延长等待至2秒 + print("警告:旧线程超时未退出,强制清理") + self.sequence_thread = None # 强制重置标识 + break + + # 启动新线程前清理硬件资源 + if self.current_image_path: + self.current_image_path = None # 重置路径记录 + + #启动新线程 + if face_status in self.image_sequences: + self.current_sequence = self.image_sequences[face_status] + self.running = True + self.sequence_thread = _thread.start_new_thread(self._play_sequence, ()) + print("启动新线程") + + def stop_sequence(self): + #停止当前图片序列轮播 + self.running = False # 仅设置标志位,让线程自然退出 + # 等待线程退出(最多等待1秒,避免无限阻塞) + start_wait = utime.time() + while self.sequence_thread is not None and utime.time() - start_wait < 2: + utime.sleep(0.1) # 短休眠等待 + def _play_sequence(self): + try: + while self.running: + current = list(self.current_sequence) + if not current: + utime.sleep(0.1) + continue + for image_path, duration in current: + if not self.running: + break + # 硬件操作添加超时和详细日志 + try: + # 记录开始时间,防止set_src无限阻塞 + set_start = utime.time() + ai_img.set_src(image_path) + # 检查set_src是否耗时过长 + # 记录当前图片路径,用于后续清理 + self.current_image_path = image_path + if utime.time() - set_start > 1: + print("警告:set_src()耗时过长") + except OSError as e: # 捕获硬件相关错误 + print("硬件错误:设置图片失败") + # 发生硬件错误后,暂停轮播避免持续冲突 + self.running = False + break + except Exception as e: + print("未知错误:设置图片失败") + continue + + # 分段休眠逻辑保持,但增加超时保护 + start_time = utime.time() + sleep_ok = True + while utime.time() - start_time < duration: + if not self.running: + sleep_ok = False + break + utime.sleep(0.05) + if not sleep_ok: + break + utime.sleep(0.1) + except Exception as e: + print("轮播线程异常(致命)") + finally: + # 加锁确保线程安全 + self.running = False + self.sequence_thread = None + self.current_image_path = None + print("轮播线程已退出并释放资源") + def post_processor_before_initialization(self): pass def post_processor_after_initialization(self): @@ -1804,6 +1937,7 @@ class UI_ai(Screen): return self.meta def Close(self): self.timer.stop() + EventMesh.publish("return_prev_screen") message_popup_screen = None message_popup_title = None #信息弹窗 @@ -5910,8 +6044,8 @@ class LowPowerScreen(Screen): Lowpower_screen.add_style(style_screen, lv.PART.MAIN|lv.STATE.DEFAULT) #进入图片 Lowpower_screen_img = lv.img(Lowpower_screen) - Lowpower_screen_img.set_pos(int(40),int(45)) - Lowpower_screen_img.set_size(160,230) + Lowpower_screen_img.set_pos(int(0),int(0)) + Lowpower_screen_img.set_size(240,320) Lowpower_screen_img.set_scrollbar_mode(lv.SCROLLBAR_MODE.OFF) Lowpower_screen_img.add_flag(lv.obj.FLAG.CLICKABLE) Lowpower_screen_img.set_src("E:/static/low_power.png") @@ -6460,14 +6594,15 @@ class chargeInScreen(Screen): # charge_in_screen_label.set_long_mode(lv.label.LONG.WRAP) # charge_in_screen_label.set_style_text_align(lv.TEXT_ALIGN.CENTER, 0) - charge_out_img = lv.img(self.charge_in_screen) - charge_out_img.set_size(240, 320) - charge_out_img.set_src("E:/static/charge_in.png") - charge_out_img.add_flag(lv.obj.FLAG.CLICKABLE) - charge_out_img.add_style(style_img, lv.PART.MAIN | lv.STATE.DEFAULT) - charge_out_img.set_pos(0, 0) + charge_in_img = lv.img(self.charge_in_screen) + charge_in_img.set_size(240, 320) + charge_in_img.set_src("E:/static/charge_in.png") + charge_in_img.add_flag(lv.obj.FLAG.CLICKABLE) + charge_in_img.add_style(style_img, lv.PART.MAIN | lv.STATE.DEFAULT) + charge_in_img.set_pos(0, 0) self.meta = self.charge_in_screen + def post_processor_after_initialization(self): @@ -6482,7 +6617,8 @@ class chargeInScreen(Screen): self.count+=1 if self.count >= 5: self.count = 0 - EventMesh.publish("return_prev_screen") + self.timer.stop() + EventMesh.publish("load_screen", {"screen": "main_menu"}) def done_left_to_right(self): @@ -6817,7 +6953,7 @@ class UI(object): self.rotate_flag = 0 #0为原来的,1为垂直翻转后的 if self.level == None: - self.level = 6 + self.level = 10 self.PWM_backlight = PWM(PWM.PWM1, PWM.ABOVE_MS, self.level, 10) self.PWM_backlight.open() self.gsensor = SC7A20() @@ -6832,12 +6968,16 @@ class UI(object): def set_rotation(self,angle):#软件设置屏幕方向 global disp_drv PWM_backlight.close() + if disp_drv.rotated == angle: + return disp_drv.rotated = angle # 重新注册驱动 disp_drv.register() + lv.img.cache_invalidate_src(None) + lv.img.cache_set_size(8) # 刷新屏幕 lv.scr_load(lv.scr_act()) - utime.sleep_ms(200) + utime.sleep_ms(750) PWM_backlight.open() def gsensor_cb(self, para): @@ -7113,13 +7253,16 @@ class UI(object): utime.sleep_ms(60) self.level = EventMesh.publish("get_brightness_level") if self.level == None: - self.level = 6 + self.level = 10 elif self.level > 10: self.level = 10 elif self.level <= 0: self.level = 1 + EventMesh.publish("load_screen", {"screen": "main_menu"}) + utime.sleep_ms(150) self.PWM_backlight = PWM(PWM.PWM1, PWM.ABOVE_MS, self.level, 10) self.PWM_backlight.open() + self.sleep_lock = 0 @@ -7139,6 +7282,14 @@ class UI(object): self.PWM_backlight.open() #lcd_ctrl.write(0) # + #检测闹钟是否还存在,若存在不关闭定时器,若没有闹钟则关闭定时器 + + get_have_alarm = EventMesh.publish("get_have_alarm") + if get_have_alarm == 0:#不存在闹钟 + alarm_timer_sta = EventMesh.publish("alarm_get_statu")#看定时器是否开启 + if alarm_timer_sta == 1 :#当定时器开启时 + EventMesh.publish("AI_alarm_close")#关闭轮询 + alarm_timer_sta = 0 lv.autoSleep(1) pm.autosleep(1) pm.sclkEx_set(1, 1, 5) @@ -7149,6 +7300,7 @@ class UI(object): EventMesh.publish("set_lcd_state",self.sleep_flag) self.sleep_lock = 0 self.screen.lcd_off() + self.screen.Close() self.system_sleep_timer.stop() EventMesh.publish("Hsensor_set_sleep") #让系统更快休眠 @@ -7237,7 +7389,7 @@ class UI(object): if self.screen_old != None : self.screen_old.Close() #先关闭上一次界面 self.lv.img.cache_invalidate_src(None) #清img cache - self.lv.img.cache_set_size(16) #开img cache + self.lv.img.cache_set_size(8) #开img cache if self.screen.meta_type != "popup": #只要当前界面不是弹窗界面都要保存当前界面 if self.screen_old.meta_type != "popup":#上个界面也不为弹窗界面 self.screen_prev = self.screen_old #第二种方式 @@ -7251,21 +7403,25 @@ class UI(object): print("load_screen:post_processor_before_initialization") self.screen.post_processor_before_initialization() self.screen_old = self.screen + utime.sleep_ms(100) print("load_screen:initialization") self.screen.initialization() print("load_screen.load()1") + self.screen.load() #print("load_screen.load()2") self.lv.scr_load(self.screen.get_meta()) - #print("load_screen.load()3") - - self.screen.post_processor_after_initialization() - #print("load_screen.load()4") if self.screen_prev == None: if self.screen.meta_type != "popup": self.screen_prev = self.screen + #print("load_screen.load()3") self.__lcd_on() + utime.sleep_ms(100) + self.screen.post_processor_after_initialization() + #print("load_screen.load()4") + + # self.__lcd_on() #print("load_screen.load()5") mem = gc.mem_free() #print('2剩余内存RAM:{} KB'.format(mem / 1024)) diff --git a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ui_WatchFaceScreen.py b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ui_WatchFaceScreen.py index 74a9de8a..6eeab823 100644 --- a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ui_WatchFaceScreen.py +++ b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/ui_WatchFaceScreen.py @@ -139,7 +139,7 @@ def get_week(msg): watchface1_time1_text = lv.label(Watchface1) -watchface1_time1_text.set_pos(30, 139) +watchface1_time1_text.set_pos(30, 110) watchface1_time1_text.set_size(240, 71) watchface1_time1_text.set_align(lv.TEXT_ALIGN.LEFT) watchface1_time1_text.set_text("{}:{}".format("%02d"%(hour),"%02d"%(min))) @@ -179,14 +179,14 @@ status_img3.add_style(style_watchface_img_default, lv.PART.MAIN|lv.STATE.DEFAULT #日期 watchface1_date_span = lv.label(Watchface1) -watchface1_date_span.set_pos(8, 122) -watchface1_date_span.set_size(140, 30) +watchface1_date_span.set_pos(85, 191) +watchface1_date_span.set_size(140, 50) watchface1_date_span.set_align(lv.TEXT_ALIGN.LEFT) watchface1_date_span.set_text("") watchface1_date_span.add_style(style_font_youyuan_28, lv.PART.MAIN|lv.STATE.DEFAULT) #星期 watchface1_week_span = lv.label(Watchface1) -watchface1_week_span.set_pos(8, 160) +watchface1_week_span.set_pos(85, 230) watchface1_week_span.set_size(100, 30) watchface1_week_span.set_align(lv.TEXT_ALIGN.LEFT) watchface1_week_span.set_text("") @@ -260,6 +260,7 @@ class WatchFace1(): self.__stepValue(None, step) def timerout_update(self): + # print("主界面定时器在更新") signal = EventMesh.publish("screen_get_sig") if signal: self.__signal(None, signal) @@ -288,9 +289,8 @@ class WatchFace1(): def __time(self, event, msg): #时间 watchface1_time1_text.set_text("{}:{}".format("%02d"%(msg[0][0]),"%02d"%(msg[0][1]))) - - # watchface1_date_span.set_text(msg[2])#日期 - # watchface1_week_span.set_text(msg[3]) #星期 + watchface1_date_span.set_text(msg[2])#日期 + watchface1_week_span.set_text(msg[3]) #星期 def __signal(self, event, msg): #print("__signal_cb:",str(msg)) diff --git a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/versions.py b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/versions.py index c80ca3ab..171f844d 100644 --- a/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/versions.py +++ b/2.sdk/project/K8/sdk/services/microPython/ports/quectel/core/versions.py @@ -1,2 +1,2 @@ Version="V1.0" -Build_Time="2025-06-27 17:53:06" +Build_Time="2025-09-12 17:53:45" diff --git a/2.sdk/project/K8/sdk/system/platform/ASR_1606/boards/EG810MCN_GA_VOLTE/images/firmware_base_release_pack.zip b/2.sdk/project/K8/sdk/system/platform/ASR_1606/boards/EG810MCN_GA_VOLTE/images/firmware_base_release_pack.zip index 14def223..166374e3 100644 Binary files a/2.sdk/project/K8/sdk/system/platform/ASR_1606/boards/EG810MCN_GA_VOLTE/images/firmware_base_release_pack.zip and b/2.sdk/project/K8/sdk/system/platform/ASR_1606/boards/EG810MCN_GA_VOLTE/images/firmware_base_release_pack.zip differ diff --git a/2.sdk/project/K8/usr/audio_gain.nvm b/2.sdk/project/K8/usr/audio_gain.nvm new file mode 100644 index 00000000..f34e83b8 Binary files /dev/null and b/2.sdk/project/K8/usr/audio_gain.nvm differ diff --git a/2.sdk/project/K8/usr/audio_ve.nvm b/2.sdk/project/K8/usr/audio_ve.nvm index a33dd45a..43ef7f6c 100644 Binary files a/2.sdk/project/K8/usr/audio_ve.nvm and b/2.sdk/project/K8/usr/audio_ve.nvm differ diff --git a/2.sdk/project/K8/usr/static/0.png b/2.sdk/project/K8/usr/static/0.png new file mode 100644 index 00000000..28b2f12e Binary files /dev/null and b/2.sdk/project/K8/usr/static/0.png differ diff --git a/2.sdk/project/K8/usr/static/1.png b/2.sdk/project/K8/usr/static/1.png new file mode 100644 index 00000000..92910b15 Binary files /dev/null and b/2.sdk/project/K8/usr/static/1.png differ diff --git a/2.sdk/project/K8/usr/static/100.png b/2.sdk/project/K8/usr/static/100.png new file mode 100644 index 00000000..6c15fbd3 Binary files /dev/null and b/2.sdk/project/K8/usr/static/100.png differ diff --git a/2.sdk/project/K8/usr/static/2.png b/2.sdk/project/K8/usr/static/2.png new file mode 100644 index 00000000..9d84e33b Binary files /dev/null and b/2.sdk/project/K8/usr/static/2.png differ diff --git a/2.sdk/project/K8/usr/static/20.png b/2.sdk/project/K8/usr/static/20.png new file mode 100644 index 00000000..5637e71a Binary files /dev/null and b/2.sdk/project/K8/usr/static/20.png differ diff --git a/2.sdk/project/K8/usr/static/3.png b/2.sdk/project/K8/usr/static/3.png new file mode 100644 index 00000000..9cc577d6 Binary files /dev/null and b/2.sdk/project/K8/usr/static/3.png differ diff --git a/2.sdk/project/K8/usr/static/4.png b/2.sdk/project/K8/usr/static/4.png new file mode 100644 index 00000000..bf44f21d Binary files /dev/null and b/2.sdk/project/K8/usr/static/4.png differ diff --git a/2.sdk/project/K8/usr/static/40.png b/2.sdk/project/K8/usr/static/40.png new file mode 100644 index 00000000..96bb25e8 Binary files /dev/null and b/2.sdk/project/K8/usr/static/40.png differ diff --git a/2.sdk/project/K8/usr/static/60.png b/2.sdk/project/K8/usr/static/60.png new file mode 100644 index 00000000..bed90192 Binary files /dev/null and b/2.sdk/project/K8/usr/static/60.png differ diff --git a/2.sdk/project/K8/usr/static/80.png b/2.sdk/project/K8/usr/static/80.png new file mode 100644 index 00000000..80378a4f Binary files /dev/null and b/2.sdk/project/K8/usr/static/80.png differ diff --git a/2.sdk/project/K8/usr/static/isconnect.png b/2.sdk/project/K8/usr/static/isconnect.png new file mode 100644 index 00000000..551708fe Binary files /dev/null and b/2.sdk/project/K8/usr/static/isconnect.png differ diff --git a/2.sdk/project/K8/usr/static/nosim.png b/2.sdk/project/K8/usr/static/nosim.png new file mode 100644 index 00000000..6288a73f Binary files /dev/null and b/2.sdk/project/K8/usr/static/nosim.png differ diff --git a/2.sdk/project/K8/usr/static/notconnect.png b/2.sdk/project/K8/usr/static/notconnect.png new file mode 100644 index 00000000..515ac2dc Binary files /dev/null and b/2.sdk/project/K8/usr/static/notconnect.png differ diff --git a/2.sdk/project/K8/usr/static/open.PNG b/2.sdk/project/K8/usr/static/open.PNG new file mode 100644 index 00000000..9dab238c Binary files /dev/null and b/2.sdk/project/K8/usr/static/open.PNG differ