2.5接口备份
authorp15692025051 <846603105@qq.com>
Tue, 8 Apr 2025 05:54:52 +0000 (13:54 +0800)
committerp15692025051 <846603105@qq.com>
Tue, 8 Apr 2025 05:54:52 +0000 (13:54 +0800)
2.sdk/project/7PIN/sdk/services/microPython/ports/quectel/core/ai_VC.py

index 82e7b17..d6de76f 100644 (file)
@@ -30,13 +30,14 @@ import machine
 import dataCall
 import constants
 import versions
-#import VAD
+import VAD
 #dev_type = "G10"
 dev_type = "7PIN_BK"#小瑞
 #dev_type = "7PIN"#柒牌
 #dev_type = 'momo'#食梦貘
 #dev_type = 'sjgq'#四季甘泉
 #dev_type = 'szbst'#深圳百事通
+
 class AI_led(Abstract):
     def __init__(self):
         if dev_type == "G10":
@@ -1159,7 +1160,7 @@ class AI_VC(Abstract):
         self.VC_30S_timer.start(30000, 1, self.VC_30S_timer_cb)
         self.get_config_timer_count = 0
         self.record_data_save_flag = 0 #是否保存录音文件
-        self.play_data_save_flag = 0 #是否保存tts数据到文件
+        self.play_data_save_flag = 0#是否保存tts数据到文件
         self.record_fd = None
         self.play_fd = None
         self.is_VC_ACK = 0 #是否开启ack应答模式
@@ -1172,7 +1173,7 @@ class AI_VC(Abstract):
             self.VC_mode = 0
         self.is_up_error= 0 #是否上传错误id
         self.Close_flag =0 #=1时,连续对话播放完音频就退出
-        self.is_llm_commands = 1#=1用大模型判断命令,=0用服务器本地插件判断命令
+        
         self.error_data = []
         self.asr_taskid  = ""
         self.VC_taskid  = ""
@@ -1201,12 +1202,13 @@ class AI_VC(Abstract):
                 self.server_ip="118.145.158.207:22082"
             if dev_type == 'momo':# 
                 self.server_ip="118.145.158.207:22080"
-            elif dev_type == "7PIN":
-                self.server_ip="sevenpin.qipai.com.cn"
+            # elif dev_type == "7PIN":
+            #     self.server_ip="sevenpin.qipai.com.cn"
 
             elif dev_type == "sjgq":
                 self.server_ip="118.145.158.207:22084"
-
+            elif dev_type == "7PIN_BK":
+                self.server_ip="amp.raisound.com"
         #开机提示音
         self.power_on_tone = EventMesh.publish("get_storage_config","power_on_tone")#
         if dev_type != "7PIN":
@@ -1230,6 +1232,8 @@ class AI_VC(Abstract):
         self.VC_play_TYPE = VC_play_TYPE_PCM #0:PCM 1:mp3 
         self.VC_record_samplerate = 16000
         self.VC_play_samplerate = 16000
+        self.VAD_data_len = 640 #10ms数据
+        self.is_VAD = 0#=1打开vad打断
         # ARG_sample_rate,             // 采样率
         # ARG_channel,                // 通道数
         # ARG_frame_size,              // 每帧字节数
@@ -1237,10 +1241,20 @@ class AI_VC(Abstract):
         # ARG_voice_time,              // 语音持续时间阈值(ms)
         # ARG_silence_time,            // 静音持续时间阈值(ms)
         # ARG_silence_start_threshold, // 静音开始阈值(ms)
-        #self.vad = VAD.VAD(self.VC_record_samplerate ,1,6400,300,50,300,100)
+        self.vad = None
+        if self.is_VAD == 1:
+            self.vad = VAD.VAD(self.VC_record_samplerate ,1,self.VAD_data_len,600,100,300,100)
         self.speech_rate = EventMesh.publish("get_storage_config","speech_rate")#语速配置
         if self.speech_rate == None:
             self.speech_rate = 0
+        
+        self.vad_silence = EventMesh.publish("get_storage_config","vad_silence")#语速配置
+        if self.vad_silence == None:
+            if dev_type == "7PIN":
+                self.vad_silence = 1500
+            else:
+                self.vad_silence = 300
+
         self.VC_TTS_voice_type = EventMesh.publish("get_storage_config","VC_TTS_voice_type")#音色配置
         if self.VC_TTS_voice_type == None or ("男" in self.VC_TTS_voice_type) == False:
             if dev_type == "G10" or  dev_type == "7PIN_BK"or dev_type == "szbst":
@@ -1318,37 +1332,37 @@ class AI_VC(Abstract):
                 self.VC_TTS_voice_type = {   
                                             "女":{
                                             "bot_name":"柒妹妹",
-                                            "voice":"huoshan::zh_female_wanwanxiaohe_moon_bigtts" ,
+                                            "voice":"zh_female_wanwanxiaohe_moon_bigtts" ,
                                             "lang":"zh-cn"
                                             },
                                             "男":{
                                             "bot_name":"柒先生",
-                                            "voice":"huoshan::zh_male_wennuanahu_moon_bigtts"  ,
+                                            "voice":"zh_male_wennuanahu_moon_bigtts"  ,
                                             "lang":"zh-cn"
                                             },
                                             "童":{
                                             "bot_name":"柒乐乐",
-                                            "voice":"huoshan::ICL_zh_female_huoponvhai_tob"  ,
+                                            "voice":"ICL_zh_female_huoponvhai_tob"  ,
                                             "lang":"zh-cn"
                                             },
                                             "粤":{
                                             "bot_name":"柒先生",
-                                            "voice":"huoshan::zh_female_wanqudashu_moon_bigtts" ,
+                                            "voice":"zh_female_wanqudashu_moon_bigtts" ,
                                             "lang":"zh-hk" 
                                             },
                                             "四川":{
                                             "bot_name":"柒妹妹",
-                                            "voice":"huoshan::zh_female_daimengchuanmei_moon_bigtts",
+                                            "voice":"zh_female_daimengchuanmei_moon_bigtts",
                                             "lang":"&lang=zh-cn-sc"  
                                             },
                                             "个性":{
                                             "bot_name":"柒先生",
-                                            "voice":"huoshan::zh_male_sunwukong_mars_bigtts" ,
+                                            "voice":"zh_male_sunwukong_mars_bigtts" ,
                                             "lang":"zh-cn" 
                                             },
                                             "英语":{
                                             "bot_name":"柒先生",
-                                            "voice":"huoshan::en_male_smith_mars_bigtts" ,
+                                            "voice":"en_male_smith_mars_bigtts" ,
                                             "lang":"zh-cn" 
                                             }
                                             
@@ -1380,6 +1394,9 @@ class AI_VC(Abstract):
         except Exception as e:
             usys.print_exception(e)
         #配置词
+        self.commands_mode = 2 #=1用大模型判断命令,=0用服务器本地插件判断命令 =2用设备本地判断方式
+        if dev_type == "7PIN_BK":
+            self.commands_mode = 2
         self.commands =  [
             {
                 "command": "切换音色",#命令
@@ -1660,7 +1677,7 @@ class AI_VC(Abstract):
                     usys.print_exception(e)
                 #开机提示语,如果联网失败,直接提示信号弱
                 
-                #"voice":{"女":"柒妹妹-huoshan::zh_female_wanwanxiaohe_moon_bigtts","男":"柒先生-huoshan::zh_male_wennuanahu_moon_bigtts","童":"柒乐乐huoshan::ICL_zh_female_huoponvhai_tob","广东":"柒先生-huoshan::zh_female_wanqudashu_moon_bigtts","四川":"柒妹妹-huoshan::zh_female_daimengchuanmei_moon_bigtts","个性":"柒先生-zh_male_sunwukong_mars_bigtts"}
+                
                 #EventMesh.publish("get_storage_config",["powerRestart",1])
                 powerRestart =  EventMesh.publish("get_storage_config","powerRestart")#=1非正常重启
                 if powerRestart == None:
@@ -1783,7 +1800,8 @@ class AI_VC(Abstract):
         self.get_config_timer_count = 0
         self.key_state = 1
         self.Close()
-        
+        # if dev_type == "7PIN" :
+        #     self.aud.aud_tone_play(10,200)#播放按键音
         #self.aud.aud_tone_play(10,200)#播放按键音
         self.AI_TTS_str = ""#"你好,有什么吩咐"
         self.AI_ASR_str = ""
@@ -1797,7 +1815,7 @@ class AI_VC(Abstract):
 
         self.VC_Speech_Start()    
         self.AI_VC_start() 
-        self.chenggong_tone()
+        #self.chenggong_tone()
         # self.Close()
         # self.AI_VC_start()
         self.AI_key_long_press_flag = 0
@@ -1844,8 +1862,17 @@ class AI_VC(Abstract):
     def VC_error(self, event, msg):#错误播报
         self.websocket_error()
         #EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_error}) 
+    def set_VC_record_state_flag(self,data):
         
-     #开始录音
+        self.VC_record_state_flag = data
+        print("set_VC_record_state_flag:{}".format(self.VC_record_state_flag))
+    #开始录音,不缓存,直接发
+    def VC_Speech_Start_now(self):
+        self.VC_Speech_Start()
+        if self.VC_record_state_flag  == 1:
+            self.VC_record_state_flag =2
+        print("VC_Speech_Start_now:{}".format(self.VC_record_state_flag))
+    #开始录音,先缓存到buf,等服务器响应再发
     def VC_Speech_Start(self):
         try:
             
@@ -1885,10 +1912,9 @@ class AI_VC(Abstract):
                         #     print("self.record_pcm.stream_read_start:ret:{}".format(ret))
                 except Exception as e:
                     usys.print_exception(e) 
-                if self.VC_mode == 1    :
-                    self.VC_record_state_flag = 1
-                else:
-                    self.VC_record_state_flag = 2
+                
+                self.VC_record_state_flag = 1
+                
         except Exception as e:
             self.websocket_error()
             self.VC_record_state_flag = 1
@@ -1963,6 +1989,7 @@ class AI_VC(Abstract):
         ##return
         print("VC_record_thread start!!!!!!!!!!!!!!!!!!!!\r\n")
         count = 0
+        RequestToSpeak_flag = 0
         # try:
         #     uos.remove('/usr/test.pcm')
         # except Exception as e:
@@ -1974,6 +2001,10 @@ class AI_VC(Abstract):
         #     h_data_b = bytes(h_data)
         #     self.AI_client_VC_send(h_data_b)
         AI_record_tmp_queue_len = 0
+        vad_buf = bytearray()
+        VAD_data_count = 0
+        vad_state = 0
+        self.VAD_count = 0
         while True:
             try:
                 if self.VC_record_thread_lock == 2:
@@ -1997,8 +2028,76 @@ class AI_VC(Abstract):
                 #print("VC_record_thread:{}".format(Record_len))
                 if Record_len > 0:
                     read_buf = bytes(Record_read_buf[:Record_len])
-                    # ret = self.vad.custom_vad_process(Record_read_buf,Record_len)
-                    # print("VAD检测:datalen:{},结果:{}".format(Record_len,ret))
+                    print("Record_len:{}".format(Record_len))
+                    #VAD检测
+                    if self.is_VAD == 1:
+                        vad_state = 0
+                        tmp_c = 1000
+                        while True:
+                            tmp_c -=1
+                            if tmp_c <=0:
+                                break
+                            #vad_buf_len = len(vad_buf)
+                            if VAD_data_count == 0:#没数据的时候
+                                vad_buf = Record_read_buf[:self.VAD_data_len]
+                                VAD_data_count = self.VAD_data_len
+                                self.vad.custom_vad_reset()#重置vad
+                            else:#有数据的时候
+                                if Record_len - VAD_data_count < self.VAD_data_len :#剩余长度不够一次填充,先保留,但不填算法
+                                    vad_buf = Record_read_buf[VAD_data_count:Record_len]
+                                    VAD_data_count = 0
+                                    break
+                                else:#剩余长度够填一次数据
+                                    vad_buf = Record_read_buf[VAD_data_count:VAD_data_count+self.VAD_data_len]
+                                    VAD_data_count += len(vad_buf)
+                            #print("vad_buf_len:{},{}".format(len(vad_buf),VAD_data_count))
+                            
+                            if len(vad_buf) >= self.VAD_data_len:
+                                vad_state = self.vad.custom_vad_process(vad_buf,len(vad_buf))#给vad数据
+                                #print("vad_state:{}".format(vad_state))
+                                
+                            if VAD_data_count >= Record_len:
+                                VAD_data_count = 0
+                                break
+                            if vad_state == 1:
+                                print("检测到VAD=1!!!!!!!!!!!!!")
+                                print("检测到VAD=1!!!!!!!!!!!!!")
+                                print("检测到VAD=1!!!!!!!!!!!!!")
+                                
+                                EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Play_Pause,"data":1})#停止音频
+                                # EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_RequestToSpeak})#打断
+                                # RequestToSpeak_flag = 1
+                                
+                                self.VAD_count+=1
+                                if self.VAD_count >= 20: 
+                                    EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_RequestToSpeak})#打断
+                                        
+                            else:
+                                if self.VAD_count != 0:
+                                    EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Play_Pause,"data":0})#恢复音频播放
+                                self.VAD_count  = 0
+                    if self.VC_state >= VC_State_TTSStart:
+                        pass
+                        if vad_state == 1:
+                            self.AI_record_tmp_queue.put(read_buf)#入缓存队列
+                            AI_record_tmp_queue_len += len(read_buf)
+                            
+                       
+                    else:
+                        VAD_data_count = 0
+                        if self.VC_record_state_flag <=1 :#没发送前先存起来
+                            self.AI_record_tmp_queue.put(read_buf)
+                            AI_record_tmp_queue_len += len(read_buf)
+                        else:
+                            AI_record_tmp_queue_len = 0
+                            while True:
+                                if self.AI_record_tmp_queue.empty() == True:
+                                    break
+                                else:
+                                    pass
+                                    self.AI_client_VC_send(self.AI_record_tmp_queue.get())  #发送之前存的数据
+                            self.AI_client_VC_send(read_buf)   
+                    
                     if self.record_data_save_flag == 1:
                         if self.record_fd == None:
                             try:
@@ -2015,18 +2114,7 @@ class AI_VC(Abstract):
                                 #self.record_fd = None
 
                     
-                    if self.VC_record_state_flag <=1 :#没发送前先存起来
-                        self.AI_record_tmp_queue.put(read_buf)
-                        AI_record_tmp_queue_len += len(read_buf)
-                    else:
-                        AI_record_tmp_queue_len = 0
-                        while True:
-                            if self.AI_record_tmp_queue.empty() == True:
-                                break
-                            else:
-                                pass
-                                self.AI_client_VC_send(self.AI_record_tmp_queue.get())  #发送之前存的数据
-                        self.AI_client_VC_send(read_buf)   
+                    
 
                     #print("VC_record_thread:{}".format(len(read_buf)))
                     #count+=len(read_buf)
@@ -2403,7 +2491,7 @@ class AI_VC(Abstract):
                         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.LocalRespondingEnded_timerout = 0
+                        
                         if jsload_data["event"] == "started" :#会话开始
                             #payload = jsload_data["payload"]
                             # self.VC_dialog_id = payload["dialog_id"] 
@@ -2411,11 +2499,17 @@ class AI_VC(Abstract):
                             EventMesh.publish("open_led_blue")
                             print("VC:Started!!!!!!!!\r\n")
                             if self.AI_TTS_str == "":
-                                #self.AI_client_VC_send_speech()#开始上传语音
-                                EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_send_speech})
+                                #开始上传语音
+                                
+                                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:
                                 EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_synthesis})
-                                
+                            self.VC_state =  VC_State_None   
                         elif jsload_data["event"] == "asr.started" :#asr开始 
                             self.VC_state =  VC_State_SpeechStart
                             if self.VC_mode == 1    :
@@ -2423,13 +2517,30 @@ class AI_VC(Abstract):
                             EventMesh.publish("open_led_blue")
                         elif jsload_data["event"] == "asr.result" :#asr结果
                             self.AI_ASR_str = jsload_data["payload"]["content"]
-                            if asr_led_flag == 0:
-                                asr_led_flag = 1
-                                EventMesh.publish("close_led")
-                            else :
-                                asr_led_flag = 0
-                                EventMesh.publish("open_led_blue")
-                        elif jsload_data["event"] == "asr.completed" :#asr 终止的标识     
+                            
+                            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:
+                                ret= self.check_text(self.AI_ASR_str)
+                                if ret == 0:#配置指令
+                                            
+                                    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()
+                                    self.AI_ASR_send_buf_len = 0
+                                    EventMesh.publish("open_led_all")
+                                    try:
+                                        
+                                        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)
+                                    continue
+                                elif ret == 1:#不处理
+                                    pass    
                             #self.VC_Speech_End()
                             #EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Speech_End})
                             if self.record_data_save_flag == 1:
@@ -2446,9 +2557,14 @@ class AI_VC(Abstract):
                             self.VC_state = VC_State_Thinking
                             # EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Play_Start})
                             pass
+                        elif jsload_data["event"] == "llm.delta" :#llm返回数据
+                            if self.is_VAD == 0:
+                                if self.VC_record_state_flag == 1:#llm返回数据还没停止,就先停止
+                                    EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Speech_End})
                         elif jsload_data["event"] == "tts.started" :#tts开始
-                            
-                            EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Speech_End})
+                            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()
@@ -2459,31 +2575,31 @@ class AI_VC(Abstract):
                             self.LocalRespondingEnded_timerout = 8
                             self.VC_state = VC_State_TTSEnd
                             pass
-                            # self.AI_client_VC_send_speech()#开始上传语音
-                            # self.VC_record_state_flag = 2
+
+                        elif jsload_data["event"] == "canceled" :#打断
+                            EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Speech_Start_now})#开始录音
+                            self.VC_state = VC_State_None
                         elif jsload_data["event"] == "completed" :#会话结束
                             #EventMesh.publish("open_led_green")#绿色
                             
                             self.LocalRespondingEnded_timerout = 8
                             self.VC_state = VC_State_End
                             pass
-                            # self.AI_client_VC_send_speech()#开始上传语音
-                            # self.VC_record_state_flag = 2
                         elif jsload_data["event"] == "command" :#命令匹配
                             ret = -1
                             try:
-                                if self.is_llm_commands ==1:
+                                if self.commands_mode ==1:
                                     if len(jsload_data["payload"]["functions"])>0:
                                         
                                         cmd = jsload_data["payload"]["functions"][0]["function"]["arguments"]
                                         print("llm:cmd:{}".format(cmd))
                                         cmd = ujson.loads(cmd)
                                         ret = self.check_text_llm(cmd)
-                                else:
+                                elif self.commands_mode ==0:
 
                                     cmd = jsload_data["payload"]
                                     print("server:cmd:{}".format(cmd))
-                                    ret = self.check_text(cmd)
+                                    ret = self.check_text_server(cmd)
                             except Exception as e:
                                 usys.print_exception(e)       
                             if ret == -1:
@@ -2496,20 +2612,38 @@ class AI_VC(Abstract):
                     else:#下发音频数据
                         #self.AI_ASR_str = ""#下发音频后清掉asr结果
                         
-                        if tts_led_flag == 0:
-                            tts_led_flag = 1
-                            EventMesh.publish("open_led_green")#绿色
-                        else:
-                            tts_led_flag = 0
-                            EventMesh.publish("close_led")#
+                        
+                        EventMesh.publish("open_led_green")#绿色
+                        
                         print("下发音频数据1:{}".format(len(recv_data)))
                         
                         if self.play_data_save_flag == 1:
+                            if self.play_fd ==None:
+                                try:
+                                    uos.remove('/usr/play_data.pcm')
+                                except Exception as e:
+                                    usys.print_exception(e)
+                                self.play_fd = open('/usr/play_data.pcm','w')
                             if self.play_fd !=None:
                                 self.play_fd.write(recv_data)
                         # print("下发音频数据2:{}".format(len(recv_data)))
                         #if self.VC_state >= VC_State_TTSStart:
                             #self.put_record_data([recv_data,""])
+                        if self.VC_play_TYPE == VC_play_TYPE_PCM:
+                            if self.play_pcm != None:
+                                try:
+                                    #print("play_pcm.stream_write !!!")
+                                    buf_len = self.play_pcm.stream_get_buf_len()
+                                    count_tmp = 1000
+                                    while buf_len < len(recv_data):
+                                        utime.sleep_ms(1)
+                                        count_tmp-=1
+                                        if count_tmp<=0:
+                                            break
+                                        buf_len = self.play_pcm.stream_get_buf_len()
+                                    #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)
                 except Exception as e:
@@ -2537,7 +2671,7 @@ class AI_VC(Abstract):
         ret=self.AI_audio_queue.put(data)
         self.tts_in_data_len += len(data[0])
         #print("下发音频数据2:{},{}".format(len(data[0]),self.tts_in_data_len))
-    def check_text(self,cmd):
+    def check_text_server(self,cmd):
         # if len(text)>60:
         #     return -1
         try:
@@ -2839,7 +2973,7 @@ class AI_VC(Abstract):
                         self.speech_rate += 10
                         if self.speech_rate > 50:
 
-                            self.AI_TTS_str = "语速已经是最快啦" 
+                            self.AI_TTS_str = "语速已经是最快了" 
                             self.speech_rate = 50
                         else:
                             
@@ -2854,7 +2988,7 @@ class AI_VC(Abstract):
                         self.speech_rate = -50
                         #EventMesh.publish("audio_montage_play",["yinliangyizuixiao.mp3"])
                         #self.aud.play(1,0,'U:/static/yinliangyizuixiao.mp3')#音量已最小
-                        self.AI_TTS_str = "语速已经是最慢啦"
+                        self.AI_TTS_str = "语速已经是最慢了"
                     else:
                         EventMesh.publish("set_storage_config",["speech_rate",self.speech_rate])
 
@@ -2927,6 +3061,245 @@ class AI_VC(Abstract):
                 usys.print_exception(e)
         self.AI_TTS_str  = cmd["command"]["fail_prompt"]
         return -1
+    def check_text(self,text):
+        print("check_text:len:{}".format(len(text)))
+        if len(text)>60:
+            return -1
+        try:
+            if isinstance(text, str): 
+                if text.find("声音") != -1 and text.find("改") != -1:
+                    try:
+                        for key in self.VC_TTS_voice_type:
+                            if  text.find(key) != -1 :
+                                self.VC_TTS_voice_key = key
+                                EventMesh.publish("set_storage_config",["VC_TTS_voice_key",self.VC_TTS_voice_key])
+                                self.AI_TTS_str = "更改成功" 
+                                return 0
+                    except Exception as e:
+                        usys.print_exception(e)    
+                    if  text.find("男") != -1 :
+                        if "男" in self.VC_TTS_voice_type:
+                            self.VC_TTS_voice_key = "男"
+                            EventMesh.publish("set_storage_config",["VC_TTS_voice_key",self.VC_TTS_voice_key])
+                            # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])
+                            #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功
+                            self.AI_TTS_str = "更改成功" 
+                            return 0
+                    if text.find("女") != -1 :
+                        if "女" in self.VC_TTS_voice_type:
+                            self.VC_TTS_voice_key = "女"
+                            EventMesh.publish("set_storage_config",["VC_TTS_voice_key",self.VC_TTS_voice_key])
+                            # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])
+                            #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功
+                            self.AI_TTS_str = "更改成功" 
+                            return 0
+                    if text.find("同声") != -1 or text.find("童") != -1 :
+                        if "童" in self.VC_TTS_voice_type:
+                            self.VC_TTS_voice_key = "童"
+                            EventMesh.publish("set_storage_config",["VC_TTS_voice_key",self.VC_TTS_voice_key])
+                            # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])
+                            #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功
+                            self.AI_TTS_str = "更改成功" 
+                            return 0
+                    if text.find("粤") != -1 or text.find("越野") != -1 or text.find("广东话") != -1:
+                        if "粤" in self.VC_TTS_voice_type:
+                            self.VC_TTS_voice_key = "粤"
+                            EventMesh.publish("set_storage_config",["VC_TTS_voice_key",self.VC_TTS_voice_key])
+                            # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])
+                            #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功
+                            self.AI_TTS_str = "更改成功" 
+                            return 0
+                    if text.find("四川") != -1 :
+                        if "四川" in self.VC_TTS_voice_type:
+                            self.VC_TTS_voice_key = "四川"
+                            EventMesh.publish("set_storage_config",["VC_TTS_voice_key",self.VC_TTS_voice_key])
+                            # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])
+                            #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功
+                            self.AI_TTS_str = "更改成功" 
+                            return 0
+                    if text.find("个性") != -1 :
+                        if "个性" in self.VC_TTS_voice_type:
+                            self.VC_TTS_voice_key = "个性"
+                            EventMesh.publish("set_storage_config",["VC_TTS_voice_key",self.VC_TTS_voice_key])
+                            # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])
+                            #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功
+                            self.AI_TTS_str = "更改成功" 
+                            return 0
+                    if text.find("英语") != -1 :
+                        if "英语" in self.VC_TTS_voice_type:
+                            self.VC_TTS_voice_key = "英语"
+                            EventMesh.publish("set_storage_config",["VC_TTS_voice_key",self.VC_TTS_voice_key])
+                            # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])
+                            #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功
+                            self.AI_TTS_str = "更改成功" 
+                            return 0
+                    self.AI_TTS_str = "更改失败,没找到对应声音" 
+                    return 0
+                if text.find("切换对话模式") != -1:
+                    if self.VC_mode == 0:
+                       self.VC_mode = 1
+                       self.AI_TTS_str = "已切换到单对话模式" 
+                    else:
+                        self.VC_mode = 0 
+                        self.AI_TTS_str = "已切换到长对话模式" 
+                    EventMesh.publish("set_storage_config",["VC_mode",self.VC_mode])
+                    # EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])
+                    #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#切换成功
+
+                    return 0
+                if text.find("音量") != -1:
+                    if  text.find("加") != -1 :
+                        self.VC_TTS_volume += 10
+                        if self.VC_TTS_volume > 100:
+                            #EventMesh.publish("audio_montage_play",["yinliangyizuida.mp3"])
+                            #self.aud.play(1,0,'U:/static/yinliangyizuida.mp3')#音量已最大
+                            self.AI_TTS_str = "音量已最大" 
+                            self.VC_TTS_volume = 100
+                        else:
+                            self.aud.setVolume(self.VC_TTS_volume //10)
+                            EventMesh.publish("set_storage_config",["VC_TTS_volume",self.VC_TTS_volume])
+                            #EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])
+                            #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#配置成功
+                            self.AI_TTS_str = "配置成功,当前音量 {}".format(self.VC_TTS_volume)
+                            
+                        return 0
+                    if text.find("减") != -1:
+                        self.VC_TTS_volume -= 10
+                        if self.VC_TTS_volume < 0:
+                            self.VC_TTS_volume = 0
+                            #EventMesh.publish("audio_montage_play",["yinliangyizuixiao.mp3"])
+                            #self.aud.play(1,0,'U:/static/yinliangyizuixiao.mp3')#音量已最小
+                            self.AI_TTS_str = "音量已最小"
+                        else:
+                            self.aud.setVolume(self.VC_TTS_volume //10)
+                            EventMesh.publish("set_storage_config",["VC_TTS_volume",self.VC_TTS_volume])
+                            #EventMesh.publish("audio_montage_play",["peizhichenggong.mp3"])
+                            #self.aud.play(1,0,'U:/static/peizhichenggong.mp3')#配置成功
+                            self.AI_TTS_str = "配置成功,当前音量 {}".format(self.VC_TTS_volume)
+                        return 0
+                
+                if text.find("进入工厂模式") != -1 :
+                    self.factory_mode()
+                    return 1
+                if text.find("查询") != -1:
+
+                    if text.find("信号") != -1 :
+                        signal = net.csqQueryPoll()
+                        
+                        self.AI_TTS_str = "当前信号{}".format(signal)
+                        return 0
+                    if text.find("电量") != -1 :
+                        battery = EventMesh.publish("get_battery")
+                        print("电量查询:{}".format(battery))
+                        #EventMesh.publish("audio_montage_play",["dianliangshengyu{}.mp3".format(battery)])
+                        #self.aud.play(1,0,'U:/static/dianliangshengyu{}.mp3'.format(battery))#电量剩余
+                        self.AI_TTS_str = "电量剩余百分之{}".format(battery)
+                        return 0
+                    if text.find("电压") != -1 :
+                        Vbatt = Power.getVbatt()
+                        #EventMesh.publish("audio_montage_play",["dianliangshengyu{}.mp3".format(battery)])
+                        #self.aud.play(1,0,'U:/static/dianliangshengyu{}.mp3'.format(battery))#电量剩余
+                        self.AI_TTS_str = "当前电池电压{}".format(Vbatt)
+                        return 0
+
+                    if text.find("卡号") != -1 :
+                        iccid = sim.getIccid()
+                        if iccid != -1 and len(iccid) > 5:
+                            print("iccid{}".format(iccid))
+                            self.AI_TTS_str = "当前卡号为:{}".format(iccid)
+                        else:
+                            self.AI_TTS_str = "卡号查询失败"
+                        return 0
+                    if text.find("设备号") != -1 :
+                        imei = modem.getDevImei()
+                        if imei != -1 and len(imei) > 5:
+                            print("IMEI:{}".format(imei))
+                            self.AI_TTS_str = "当前设备号为:{}".format(imei)
+                        else:
+                            self.AI_TTS_str = "设备号查询失败"
+                        return 0
+                    if text.find("版本") != -1 :
+                        sourceVersion = versions.Build_Time
+                        self.AI_TTS_str ="Mr-Seven-"+sourceVersion
+                        return 0
+                    if text.find("服务器地址") != -1 :
+                        self.AI_TTS_str ="服务器地址"+self.server_ip
+                        return 0
+                
+                if text.find("讲话") != -1:
+                    if text.find("快") != -1 and text.find("太") == -1 :
+                        self.speech_rate += 10
+                        if self.speech_rate > 50:
+
+                            self.AI_TTS_str = "语速已经是最快了" 
+                            self.speech_rate = 50
+                        else:
+                            
+                            EventMesh.publish("set_storage_config",["speech_rate",self.speech_rate])
+
+                            self.AI_TTS_str = "明白,语速已经调快了,当前语速是{}".format(self.speech_rate)
+                            
+                        return 0
+                    if text.find("慢") != -1 and text.find("太") == -1 :
+                        self.speech_rate -= 10
+                        if self.speech_rate < -50:
+                            self.speech_rate = -50
+                            #EventMesh.publish("audio_montage_play",["yinliangyizuixiao.mp3"])
+                            #self.aud.play(1,0,'U:/static/yinliangyizuixiao.mp3')#音量已最小
+                            self.AI_TTS_str = "语速已经是最慢了"
+                        else:
+                            EventMesh.publish("set_storage_config",["speech_rate",self.speech_rate])
+
+                            self.AI_TTS_str = "明白,语速已经调慢了,当前语速是{}".format(self.speech_rate)
+                        return 0
+                if text.find("聆听") != -1:
+                    if text.find("快") != -1 and text.find("太") == -1 :
+                        self.vad_silence -= 200
+                        if self.vad_silence < 100:
+
+                            self.AI_TTS_str = "已经是最快了" 
+                            self.vad_silence = 100
+                        else:
+                            self.AI_TTS_str = "配置成功,当前语音断句速度是{}毫秒".format(self.vad_silence)
+                        EventMesh.publish("set_storage_config",["speech_rate",self.vad_silence])   
+                        return 0
+                    if text.find("慢") != -1 and text.find("太") == -1 :
+                        self.vad_silence += 200
+                        if self.vad_silence > 2000:
+                            self.vad_silence = 2000
+                            #EventMesh.publish("audio_montage_play",["yinliangyizuixiao.mp3"])
+                            #self.aud.play(1,0,'U:/static/yinliangyizuixiao.mp3')#音量已最小
+                            self.AI_TTS_str = "已经是最慢了"
+                        else:
+                            self.AI_TTS_str = "配置成功,当前语音断句速度是{}毫秒".format(self.vad_silence)
+                        EventMesh.publish("set_storage_config",["speech_rate",self.vad_silence])
+                        return 0
+                if text.find("升级") != -1 and (text.find("OTA") != -1 or text.find("ota") != -1):
+                    if self.ai_OTA.min_sys_ota()==1:
+                        self.AI_TTS_str = "有新版本,准备开始升级,升级过程会多次重启设备,请保证流量充足及电量充足"
+                    else:
+                        self.AI_TTS_str = "当前已是最新版本"
+                    return 0
+                
+                if len(text)<16 and (text.find("再见") != -1 or text.find("拜拜") != -1 or text.find("关闭对话") != -1):
+                    #EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) 
+                    if dev_type != "7PIN":#柒牌
+                        self.AI_TTS_str = "好嘞,再见,我们下次再聊"
+                        self.Close_flag = 1
+                        return 0
+                    else:
+                        EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) 
+                        return 1
+                if len(text)<12 and (text.find("关机") != -1 ):
+                    if dev_type == "7PIN":#柒牌
+                        EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) 
+                        return 1
+                    EventMesh.publish("publish_AI_btnInfo",{"func":self.Close}) 
+                    EventMesh.publish("Power_off")
+                    return 1
+        except Exception as e:
+                usys.print_exception(e)
+        return -1
     #获取trace_id
     def get_trace_id(self):
         t = utime.mktime(utime.localtime())
@@ -2980,8 +3353,15 @@ class AI_VC(Abstract):
             except Exception as e:
                 self.VC_Play_End()
                 usys.print_exception(e)
-        
-
+    #暂停/继续声音播放   Pause_flag = 1暂停
+    def VC_Play_Pause(self,Pause_flag):
+        try:
+            if self.VC_play_TYPE == VC_play_TYPE_PCM:
+                if self.play_pcm != None:    
+                    self.play_pcm.stream_pause(Pause_flag)
+        except Exception as e:
+            self.VC_Play_End()
+            usys.print_exception(e)
     #停止播放声音
     def VC_Play_End(self):
         self.VC_Play_flag = 0
@@ -3003,7 +3383,10 @@ class AI_VC(Abstract):
         elif self.VC_play_TYPE == VC_play_TYPE_MP3:
             self.aud.stopPlayStream()
             self.aud.stopAll()
-   
+        if self.AI_audio_queue.empty()!=True:
+            self.AI_audio_queue.clear()
+        
+
     def _1S_timer_cb(self,*argc):
         EventMesh.publish("publish_AI_btnInfo",{"func":self._1S_timer_cb_}) 
 
@@ -3036,7 +3419,8 @@ class AI_VC(Abstract):
                         #utime.sleep_ms(1000)
                         EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Play_End})
                         #EventMesh.publish("publish_AI_btnInfo",{"func":self.chenggong_tone})
-                        EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_send_speech})#开始录音
+                        EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Speech_Start_now})#开始录音
+                        self.VC_state = VC_State_None
                     #通知服务器播放结束
                     #self.AI_client_VC_LocalRespondingEnded()
 
@@ -3079,24 +3463,7 @@ class AI_VC(Abstract):
             #utime.sleep_ms(50)
         else:
             print("self.VC_state :{}".format(self.VC_state ))
-            # if self.VC_state > VC_State_SpeechStart:
-            #     #客户端打断对话
-            #     print("打断对话")
-            #     # self.websocket_deconnect_VC()
-            #     # self.websocket_connect_VC()#连接服务器
-            #     # self.AI_client_VC_start_requset()
-            #     #self.AI_client_VC_RequestToSpeak()
-            # elif self.VC_state == VC_State_Listening:
-            #     #直接chat
-            #     print("直接chat")
-            #     # self.AI_client_VC_RequestToRespond()
-            #     return 
-            # else:
-            #     print("异常状态")
-                #self.AI_client_VC_RequestToSpeak()
-        #         self.websocket_deconnect_VC()
-        #         self.websocket_connect_VC()#连接服务器
-        #         self.AI_client_VC_start_requset()
+            
         if self.AI_client_VC_isconnect == 0:
             return
         self.AI_client_VC_start_requset()
@@ -3105,11 +3472,9 @@ class AI_VC(Abstract):
         self.VC_state = VC_State_None
         if self.AI_TTS_str == "":#没有tts要播放的时候才开始录音
             #开始asr录音
-            if self.VC_mode == 1:#单对话模式
-                self.VC_Speech_Start()#开启线程获取录音数据
-            else :
-                self.VC_Speech_Start()#开启线程获取录音数据
-                self.VC_record_state_flag = 2
+            self.VC_Speech_Start()#开启线程获取录音数据
+           
+                
         #     pass
         print("AI_VC_start4")
         #self.VC_Play_Start()
@@ -3135,12 +3500,12 @@ class AI_VC(Abstract):
         print("AI_VC_start5")
     #开始会话
     def AI_client_VC_start_requset(self):
-        voice="huoshan::zh_male_wennuanahu_moon_bigtts"
+        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="huoshan::zh_female_dongmanxiaoyang_moon_bigtts"
+        #voice="zh_female_dongmanxiaoyang_moon_bigtts"
  
         json_data = \
         {
@@ -3160,18 +3525,16 @@ class AI_VC(Abstract):
                         "custom_variables": {
                             "name": self.bot_name,
                             },
-                        # "greeting":{
-                        #     "enabled":True,
-                        #     "content":"小瑞来陪你聊天了!"
-                        # }
+                        "greeting":{
+                            "enabled":False,
+                            "content":""
+                        },
                         "bot_option": {
                             "use_workflow": True,
-                            "bot_id":"7481164663863459850",#鸭子
-                            "workflow_id":"7480485093845991443",
-                            # "bot_id":"7462617881076351002",#语言助手
-                            # "workflow_id":"7462621757327196187",
-                            # "bot_id":"7469964258592931852",#深圳百事通
-                            # "workflow_id":"7469968083063603241",
+                            
+                            "bot_id":"7462617881076351002",#语言助手
+                            "workflow_id":"7462621757327196187",
+                           
                         }
                     }
                 },
@@ -3184,15 +3547,16 @@ class AI_VC(Abstract):
                         "channel": 1,
                         "volume": self.VC_TTS_volume,
                         #"voice": "7426720361732980745",
-                        "voice": voice,
+                        "voice": voice,#音色
                         "speech_rate": self.speech_rate,#语速
+                        "chunk_interval_ms": 100,  # 配置每段音频入队间隔时间 100ms
                     }
                 },
                 "inbound_attributes": {
-                    #"provider": "xun-fei",#
-                    "provider": "volcengine",
+                    "provider": "xun-fei",#
+                    #"provider": "volcengine",
                     "disable_vad":True,
-                    "vad_silence":300,
+                    "vad_silence":self.vad_silence,
                     "interrupt_options":{
                         "concatenate_results":True,
                         "thinking_time_only": True,
@@ -3201,13 +3565,46 @@ class AI_VC(Abstract):
                         "format": "pcm",
                         "sample_rate": self.VC_record_samplerate,
                         "bit_rate": 16,
-                        "channel": 1
+                        "channel": 1,
+                        "enable_punctuation": True,
+                        "enable_itn":True
                     }
                 },
                 "commands":self.commands,
             }
         }
-        if self.is_llm_commands ==1:
+        # "bot_id":"7481164663863459850",#鸭子
+        # "workflow_id":"7480485093845991443",
+        # "bot_id":"7462617881076351002",#语言助手
+        # "workflow_id":"7462621757327196187",
+        # "bot_id":"7469964258592931852",#深圳百事通
+        # "workflow_id":"7469968083063603241",
+        # "bot_id":"7411071327182438412",#柒牌
+        # "workflow_id":"7469049680291610636",
+        if dev_type == "7PIN_BK":#小瑞
+            # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7462617881076351002"#语言助手
+            # json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7462621757327196187"
+            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7486697248416989193"#极简
+            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7486698347416649778"
+            #json_data["payload"]["dialog_attributes"]["provider"]="doubao"#豆包
+            json_data["payload"]["inbound_attributes"]["provider"]="volcengine"#火山
+            #json_data["payload"]["inbound_attributes"]["vad_silence"] = 200
+
+        elif dev_type == "7PIN":#柒牌
+            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7411071327182438412"#
+            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7469049680291610636"
+            #json_data["payload"]["inbound_attributes"]["vad_silence"] = 1000
+        #
+        elif dev_type == 'momo':#食梦貘
+            pass
+        elif dev_type == 'sjgq':#四季甘泉
+            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7472201279826690111"
+            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="472203898494500914"
+            pass
+        elif dev_type == 'szbst':#深圳百事通
+            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["bot_id"]="7469964258592931852"
+            json_data["payload"]["dialog_attributes"]["cfg"]["bot_option"]["workflow_id"]="7469968083063603241"
+        if self.commands_mode !=0:
             json_data["payload"]["commands"] = []
         if self.VC_mode == 0:#长对话模式打开vad
             json_data["payload"]["inbound_attributes"]["disable_vad"] = False
@@ -3226,14 +3623,9 @@ class AI_VC(Abstract):
         
         if self.VC_mode == 1:#单对话模式
             self.AI_client_VC_send(ujson.dumps(json_data))
-            EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Speech_Start})
-            #self.VC_Speech_Start()#开启线程获取录音数据
-        else :
-            #EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Play_End})
-            EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_Speech_Start})
+        
 
-            # self.VC_Play_End()
-            # self.VC_Speech_Start()#开启线程获取录音数据
+            
             
         
         
@@ -3255,19 +3647,18 @@ class AI_VC(Abstract):
     def AI_client_VC_RequestToSpeak(self):
         json_data = \
         {
-            "header":{
-                "trace_id":self.get_trace_id(),
-                "event":"RequestToSpeak"
-                },
-            "payload":{
-                "dialog_id":self.VC_dialog_id,
-                "session_id": self.session_id ,
-                }
+            "event": "cancel",
+            "payload": {}
         }
         print("AI_client_VC_RequestToSpeak!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init}) 
-        EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_send,"data":ujson.dumps(json_data)}) 
+        # EventMesh.publish("publish_AI_btnInfo",{"func":self.VC_init}) 
+        # EventMesh.publish("publish_AI_btnInfo",{"func":self.AI_client_VC_send,"data":ujson.dumps(json_data)}) 
         # utime.sleep_ms(1)
+        self.websocket_deconnect_VC()
+        self.AI_audio_queue_thread_close()
+        self.VC_state = VC_State_None
+        #self.Close()
+        self.AI_VC_start() 
     #TTS播放
     def AI_client_VC_synthesis(self):
         json_data = \
@@ -3355,13 +3746,13 @@ class AI_VC(Abstract):
                                 #     tmp= self.aud.playStream(1,data[0] )
                                 # else:
                                     write_buf = bytearray(data[0])
-                                    print("play_pcm.stream_write1 len:{}".format(len(write_buf)))
+                                    #print("play_pcm.stream_write1 len:{}".format(len(write_buf)))
                                     if self.play_pcm != None:
                                         #print("play_pcm.stream_write !!!")
                                         ret = self.play_pcm.stream_write(write_buf,len(write_buf))
                                         #ret= self.aud.playStream(1, data[0])#播放音频流
                                         self.tts_out_data_len += ret
-                                        #print("play_pcm.stream_write:{}".format(self.tts_out_data_len))
+                                        #print("play_pcm.stream_write2:{}".format(self.tts_out_data_len))
                             elif self.VC_play_TYPE == VC_play_TYPE_MP3:
                                 tmp= self.aud.playStream(3, data[0])#播放音频流
                                 
@@ -3463,6 +3854,7 @@ class AI_VC(Abstract):
         if self.play_data_save_flag == 1:
             if self.play_fd !=None:
                 self.play_fd.close()
+                self.play_fd = None
         print("ai_VC Close3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n")
         
         if self.AI_VC_send_data_queue.empty()!=True: