补充文件
authorp15692025051 <846603105@qq.com>
Thu, 12 Jun 2025 03:36:35 +0000 (11:36 +0800)
committerp15692025051 <846603105@qq.com>
Thu, 12 Jun 2025 03:36:35 +0000 (11:36 +0800)
2.sdk/Helios_SDK/services/microPython/ports/quectel/core/motor.py
2.sdk/Helios_SDK/services/microPython/ports/quectel/core/request.py
2.sdk/Helios_SDK/services/microPython/ports/quectel/core/source/audio_audio.c
2.sdk/Helios_SDK/services/microPython/ports/quectel/core/source/modVad.c [new file with mode: 0644]
2.sdk/Helios_SDK/services/microPython/ports/quectel/core/source/modgnss.c
2.sdk/Helios_SDK/services/microPython/ports/quectel/core/source/modsocket.c
2.sdk/Helios_SDK/services/microPython/ports/quectel/core/source/mpconfigport.h
2.sdk/Helios_SDK/services/microPython/ports/quectel/core/umqtt.py
2.sdk/Helios_SDK/services/microPython/ports/quectel/core/uwebsocket.py

index 7e932af..cd31639 100644 (file)
@@ -31,8 +31,6 @@ class motorEventManager(Abstract):#马达事件
         self.motor_mode = 0#模式
         _thread.start_new_thread(self.motorInfo_queue_thread, ())
         EventMesh.subscribe("publish_message_event_motorInfo",self.publish_message_event_motorInfo)
-        EventMesh.subscribe("set_motor_time", self.set_motor_time)#设置参数
-        EventMesh.subscribe("close_motor_infor", self.close_motor_infor)#关闭马达和定时器
         pass
 
     def motorInfo_queue_thread(self):
@@ -52,14 +50,15 @@ class motorEventManager(Abstract):#马达事件
         EventMesh.publish("publish_message_event_motorInfo",{"func":self.motor_fun_cb,"data":0})  
         
     def post_processor_after_instantiation(self):
-        pass
+        EventMesh.subscribe("set_motor_time", self.set_motor_time)#设置参数
+        EventMesh.subscribe("close_motor_infor", self.close_motor_infor)#关闭马达和定时器
 
     # msg 0马达使能 1 马达振动时间100ms单位 2 震动次数 3 间隔时间振动 4 是否需要长振 5 长振时间  6间隔时间长振 7长振次数1一次 要为200ms的倍数
     def set_motor_time(self,event,msg):
-        # open_power = EventMesh.publish("get_power_on_state")#获取开机标识
-        # if open_power != None:
-        #     if open_power == 0:
-        #         return
+        open_power = EventMesh.publish("get_power_on_state")#获取开机标识
+        if open_power != None:
+            if open_power == 0:
+                return
         if msg != None:
             self.motor_enable = msg[0]
             if self.motor_enable == 1: #马达使能
@@ -79,7 +78,6 @@ class motorEventManager(Abstract):#马达事件
             EventMesh.publish("close_motor_infor")#关闭马达和定时器
             return
         if self.motor_mode == 1:#
-            
             if self.motor_total_time > 0:
                 self.motor_total_time-=1
                 if self.motor_total_time > 0:
@@ -89,10 +87,8 @@ class motorEventManager(Abstract):#马达事件
                     EventMesh.publish("close_motor_infor")#关闭马达和定时器
                     return
         elif self.motor_mode == 2:#
-            # print("motor_fun_cb:{}\r\n".format(self.motor_total_time))
             # print("self.motor_count",self.motor_count,self.motor_open_time,self.motor_close_time,self.motor_total_time)
             if self.motor_count % (self.motor_open_time) < self.motor_close_time: # 4 4 2 1%4 = 1 2%4 = 2 3%4 = 3
-                # print("motor_fun_cb MORETO:{}\r\n".format(self.motor_total_time))
                 open_motor()
             else:
                 close_motor()
@@ -103,8 +99,6 @@ class motorEventManager(Abstract):#马达事件
 
     def close_motor_infor(self,event,msg):
         print("close_motor_infor!!!")
-        if self.motor_enable == 0:#未使能马达定时器
-            return
         close_motor()
         self.motor_enable = 0#马达使能
         self.motor_total_time = 0#总的时间
index 1ce6a9a..dcb90e7 100644 (file)
@@ -162,7 +162,10 @@ def request(method, url, data=None, json=None, files=None, stream=None, decode=T
             raise ValueError("Unsupported protocol: " + proto)
 
         try:
-            ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM)
+            if ipvtype == 1:
+                ai = usocket.getaddrinfo(host, port, usocket.AF_INET6)
+            else:
+                ai = usocket.getaddrinfo(host, port, usocket.AF_INET)
         except Exception as e:
             raise IndexError("Domain name resolution error, please check network connection:" + host)
 
@@ -204,9 +207,12 @@ def request(method, url, data=None, json=None, files=None, stream=None, decode=T
             raise ValueError("Unsupported protocol: " + proto)
 
         try:
-            ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM)
+            if ipvtype == 1:
+                ai = usocket.getaddrinfo(host, port, usocket.AF_INET6)
+            else:
+                ai = usocket.getaddrinfo(host, port, usocket.AF_INET)
         except Exception as e:
-            raise IndexError("Domain name resolution error, please check network connection")
+            raise IndexError("Domain name resolution error, please check network connection ",str(e))
 
         if ipvtype == 1:
             import uos
@@ -245,7 +251,10 @@ def request(method, url, data=None, json=None, files=None, stream=None, decode=T
         except:
             raise ValueError("URL address error: " + url)
         try:
-            ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM)
+            if ipvtype == 1:
+                ai = usocket.getaddrinfo(host, port, usocket.AF_INET6)
+            else:
+                ai = usocket.getaddrinfo(host, port, usocket.AF_INET)
         except Exception as e:
             raise IndexError("Domain name resolution error, please check network connection")
 
index 0c5ea5e..b5d4d8d 100644 (file)
@@ -2496,6 +2496,7 @@ typedef struct _machine_pcm_obj_t {
        unsigned int mode;
        void* PCM_stream_ring_buf;
        char PCM_stream_RW_flag;
+       char pause_flag ;
 } machine_pcm_obj_t;
 
 const mp_obj_type_t audio_audio_pcm;
@@ -2750,7 +2751,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(helios_audio_pcm___del___obj, helios_audio_pcm_
 #include "helios_ringbuf.h"
 #if 1
        //helios_ring_buf_t *PCM_stream_ring_buf = NULL;
-       char PCM_stream_is_open = 0;
+
        Helios_Thread_t PCM_stream_task_id = 0;
        typedef enum
        {
@@ -2763,41 +2764,45 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(helios_audio_pcm___del___obj, helios_audio_pcm_
        static void helios_audio_PCM_stream_task(void *self_in)
        {
                machine_pcm_obj_t *self = (machine_pcm_obj_t *)self_in;
-               
+               self->pause_flag = 0;
                //machine_pcm_obj_t *self = MP_OBJ_TO_PTR(*self_in);
                char p_data[PCM_READ_BUF_LEN]={0};
                //char *p_data  = NULL;
                while(1)
                {
-                       if(self->PCM_stream_RW_flag == PCM_STREAM_READ)
+                       if(self->pause_flag == 0)
                        {
-                               int bytes_read =Helios_PCM_Read(self->handle_read, p_data, PCM_READ_BUF_LEN);   
-                               if(bytes_read>0)
-                               {
-                                       if((helios_ring_buf_t *)self->PCM_stream_ring_buf != NULL)
-                                               helios_rb_write((helios_ring_buf_t *)self->PCM_stream_ring_buf, (unsigned char*)p_data, bytes_read);
-                               }else
+                               if(self->PCM_stream_RW_flag == PCM_STREAM_READ)
                                {
-                                       //printf("helios_audio_PCM_stream_task:READ no data\r\n");
-                               }
-                       }else if(self->PCM_stream_RW_flag == PCM_STREAM_WRITE)
-                       {
-                               int bytes_read = helios_rb_read((helios_ring_buf_t *)self->PCM_stream_ring_buf, (unsigned char*)p_data, PCM_READ_BUF_LEN);
-                               if(bytes_read>0)
+                                       int bytes_read =Helios_PCM_Read(self->handle_read, p_data, PCM_READ_BUF_LEN);   
+                                       if(bytes_read>0)
+                                       {
+                                               if((helios_ring_buf_t *)self->PCM_stream_ring_buf != NULL)
+                                                       helios_rb_write((helios_ring_buf_t *)self->PCM_stream_ring_buf, (unsigned char*)p_data, bytes_read);
+                                       }else
+                                       {
+                                               //printf("helios_audio_PCM_stream_task:READ no data\r\n");
+                                       }
+                               }else if(self->PCM_stream_RW_flag == PCM_STREAM_WRITE)
                                {
-                                       int ret = Helios_PCM_Write(self->handle_write, p_data, bytes_read);
-                                       if(ret<1)
+                                       int bytes_read = helios_rb_read((helios_ring_buf_t *)self->PCM_stream_ring_buf, (unsigned char*)p_data, PCM_READ_BUF_LEN);
+                                       if(bytes_read>0)
                                        {
-                                               //printf("helios_audio_PCM_stream_task:pcm write error\r\n");
+                                               int ret = Helios_PCM_Write(self->handle_write, p_data, bytes_read);
+                                               if(ret<1)
+                                               {
+                                                       //printf("helios_audio_PCM_stream_task:pcm write error\r\n");
+                                               }
                                        }
-                               }
 
+                               }
+                               else
+                               {
+                                       //printf("helios_audio_PCM_stream_task:NO_READ_WRITE\r\n");
+                                       //Helios_msleep(2000);
+                               }
                        }
-                       else
-                       {
-                               //printf("helios_audio_PCM_stream_task:NO_READ_WRITE\r\n");
-                               //Helios_msleep(2000);
-                       }
+                       
                        Helios_msleep(1);
                }
 
@@ -2808,7 +2813,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(helios_audio_pcm___del___obj, helios_audio_pcm_
                
                machine_pcm_obj_t *self = MP_OBJ_TO_PTR(self_in);
                self->PCM_stream_RW_flag = PCM_STREAM_READ;
-               PCM_stream_is_open = 1;
+       
+               self->pause_flag = 0;
                if(self->PCM_stream_ring_buf == NULL) {
                        self->PCM_stream_ring_buf = helios_rb_create(ring_buf_len);
                }
@@ -2845,7 +2851,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(helios_audio_pcm___del___obj, helios_audio_pcm_
                
                machine_pcm_obj_t *self = MP_OBJ_TO_PTR(self_in);
                self->PCM_stream_RW_flag = PCM_STREAM_WRITE;
-               PCM_stream_is_open = 1;
+
+               self->pause_flag = 0;
                if(self->PCM_stream_ring_buf == NULL) {
                        self->PCM_stream_ring_buf = helios_rb_create(ring_buf_len);
                }
@@ -2922,7 +2929,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(helios_audio_pcm___del___obj, helios_audio_pcm_
        {
                int ret = 0;
                machine_pcm_obj_t *self = MP_OBJ_TO_PTR(self_in);
-               PCM_stream_is_open = 0;
+
                if(PCM_stream_task_id != 0)
                        Helios_Thread_Delete(PCM_stream_task_id);
                PCM_stream_task_id = 0;
@@ -2935,6 +2942,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(helios_audio_pcm___del___obj, helios_audio_pcm_
                return mp_obj_new_int(ret);
        }
        STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_helios_audio_PCM_stream_stop_obj, helios_audio_PCM_stream_stop);
+       STATIC mp_obj_t helios_audio_PCM_stream_pause(mp_obj_t self_in,mp_obj_t pause_flag)//暂停/开始
+       {
+               machine_pcm_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+               self->pause_flag =mp_obj_get_int(pause_flag);
+               return mp_obj_new_int(1);
+       }
+       
+       STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_helios_audio_PCM_stream_pause_obj, helios_audio_PCM_stream_pause);
+       
        STATIC mp_obj_t helios_audio_pcm_rb_is_empty(mp_obj_t self_in)
        {
                int ret = 0;
@@ -2952,6 +2969,25 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(helios_audio_pcm___del___obj, helios_audio_pcm_
                return mp_obj_new_int(ret);
        }
        STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_helios_audio_pcm_rb_is_empty_obj, helios_audio_pcm_rb_is_empty);
+       //获取剩余长度
+       STATIC mp_obj_t helios_audio_pcm_rb_get_buf_len(mp_obj_t self_in)
+       {
+               int ret = 0;
+               machine_pcm_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+               // if(self->handle_write) {
+               //      ret = Helios_PCM_Reset_Write_Buffer(self->handle_write);
+               // }
+               if(self->PCM_stream_ring_buf != NULL) 
+               {
+                       ret = ring_buf_len - helios_rb_data_len((helios_ring_buf_t *)self->PCM_stream_ring_buf) ;
+                       
+               }
+                       
+               return mp_obj_new_int(ret);
+
+       }
+       STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_helios_audio_pcm_rb_get_buf_len_obj, helios_audio_pcm_rb_get_buf_len);
 #endif
 #if defined(PLAT_ASR_1606)
 STATIC mp_obj_t helios_audio_pcm_get_write_frame_count(mp_obj_t self_in)
@@ -2999,7 +3035,11 @@ STATIC const mp_rom_map_elem_t pcm_locals_dict[] = {
        { MP_ROM_QSTR(MP_QSTR_stream_read), MP_ROM_PTR(&mp_helios_audio_PCM_stream_read_obj)},
        { MP_ROM_QSTR(MP_QSTR_stream_write), MP_ROM_PTR(&mp_helios_audio_PCM_stream_write_obj)},
        { MP_ROM_QSTR(MP_QSTR_stream_stop), MP_ROM_PTR(&mp_helios_audio_PCM_stream_stop_obj)},
+       { MP_ROM_QSTR(MP_QSTR_stream_pause), MP_ROM_PTR(&mp_helios_audio_PCM_stream_pause_obj)},
+       
        { MP_ROM_QSTR(MP_QSTR_stream_is_empty), MP_ROM_PTR(&mp_helios_audio_pcm_rb_is_empty_obj)},
+       { MP_ROM_QSTR(MP_QSTR_stream_get_buf_len), MP_ROM_PTR(&mp_helios_audio_pcm_rb_get_buf_len_obj)},
+       
        
     { MP_ROM_QSTR(MP_QSTR_setVolume), MP_ROM_PTR(&helios_set_volume_obj) },
     { MP_ROM_QSTR(MP_QSTR_getVolume), MP_ROM_PTR(&helios_get_volume_obj) },
diff --git a/2.sdk/Helios_SDK/services/microPython/ports/quectel/core/source/modVad.c b/2.sdk/Helios_SDK/services/microPython/ports/quectel/core/source/modVad.c
new file mode 100644 (file)
index 0000000..dfd11a3
--- /dev/null
@@ -0,0 +1,557 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "py/runtime.h"
+#include "py/stream.h"
+
+
+#include "mperrno.h"
+#include "mphal.h"
+#include "helios_debug.h"
+#include "autoconf.h"
+#include "imsl_vad.h"
+#define QPY_WS_LOG(msg, ...)      custom_log("modvad", msg, ##__VA_ARGS__)
+#if CONFIG_VAD
+int g_vad_enabled = 1;
+// VAD参数结构体
+struct custom_vad_params {
+    int sample_rate;             // 采样率
+    int channel;                 // 通道数
+    int frame_size;              // 每帧字节数
+    int energy_threshold;        // 能量阈值
+    int voice_time;              // 语音持续时间阈值(ms)
+    int silence_time;            // 静音持续时间阈值(ms)
+    int silence_start_threshold; // 静音开始阈值(ms)
+    int current_voice_time;      // 当前语音持续时间
+    int current_silence_time;    // 当前静音持续时间
+    int is_speaking;             // 是否正在说话
+    int is_silence;              // 是否检测到静音
+    void *user_data;             // 用户数据
+    void (*on_voice_start)(void *user_data);  // 语音开始回调
+    void (*on_voice_end)(void *user_data);    // 语音结束回调
+};
+// VAD状态枚举
+typedef enum {
+    VAD_STATE_SILENCE,       // 静音状态
+    VAD_STATE_VOICE_ONSET,   // 语音开始过渡状态
+    VAD_STATE_VOICE_ACTIVE,  // 语音活跃状态
+    VAD_STATE_VOICE_FALLING  // 语音结束过渡状态
+} vad_state_t;
+
+// VAD事件枚举 - 用于接口适配
+typedef enum {
+    VAD_EVENT_NONE = 0,      // 无事件
+    VAD_EVENT_START = 1,     // VAD开始事件
+    VAD_EVENT_END = 2        // VAD结束事件
+} vad_event_t;
+
+// VAD状态结构体
+struct custom_vad_state {
+    struct custom_vad_params params;    // VAD参数
+    void *buffer;                       // 音频缓冲区
+    int buffer_size;                    // 缓冲区大小
+    int buffer_pos;                     // 缓冲区位置
+    vad_state_t state;                  // 当前VAD状态
+    int consecutive_voice_frames;       // 连续语音帧计数
+    int consecutive_silence_frames;     // 连续静音帧计数
+    int energy_history[10];             // 能量历史记录
+    int history_pos;                    // 历史记录位置
+    int adaptive_threshold;             // 自适应阈值
+    int background_energy;              // 背景噪音能量
+    vad_event_t last_event;             // 最后一个VAD事件
+    int silence_duration;               // 静音持续时间
+    int silence_detected;               // 是否检测到静音
+};
+
+// 创建VAD实例
+struct custom_vad_state *custom_vad_create(struct custom_vad_params *params)
+{
+    struct custom_vad_state *vad = (struct custom_vad_state *)malloc(sizeof(struct custom_vad_state));
+    if (!vad) {
+        return NULL;
+    }
+
+    memset(vad, 0, sizeof(struct custom_vad_state));
+    memcpy(&vad->params, params, sizeof(struct custom_vad_params));
+
+    // 计算缓冲区大小 - 这里设置为一个VAD检测帧的大小
+    vad->buffer_size = params->frame_size;
+    vad->buffer = malloc(vad->buffer_size);
+    if (!vad->buffer) {
+        free(vad);
+        return NULL;
+    }
+
+    vad->buffer_pos = 0;
+    vad->state = VAD_STATE_SILENCE;
+    vad->consecutive_voice_frames = 0;
+    vad->consecutive_silence_frames = 0;
+    vad->history_pos = 0;
+    vad->adaptive_threshold = params->energy_threshold;
+    vad->background_energy = params->energy_threshold / 2; // 初始化背景噪音能量
+    vad->last_event = VAD_EVENT_NONE;  // 初始化最后事件
+    vad->silence_duration = 0;         // 初始化静音持续时间
+    vad->silence_detected = 0;         // 初始化静音检测标志
+
+    // 初始化参数结构体中的新字段
+    vad->params.is_silence = 0;        // 初始化静音状态
+
+    // 初始化能量历史记录
+    for (int i = 0; i < 10; i++) {
+        vad->energy_history[i] = 0;
+    }
+
+    return vad;
+}
+
+// 销毁VAD实例
+void custom_vad_destroy(struct custom_vad_state *vad)
+{
+    if (vad) {
+        if (vad->buffer) {
+            free(vad->buffer);
+        }
+        free(vad);
+    }
+}
+
+// 计算PCM数据的能量值
+static int calculate_energy(const short *samples, int count)
+{
+    long long energy = 0; // 使用long long防止溢出
+    for (int i = 0; i < count; i++) {
+        energy += (long long)samples[i] * samples[i];
+    }
+    return (int)(energy / count);
+}
+
+// 更新历史能量记录和背景噪音估计
+static void update_energy_history(struct custom_vad_state *vad, int energy)
+{
+    // 更新能量历史
+    vad->energy_history[vad->history_pos] = energy;
+    vad->history_pos = (vad->history_pos + 1) % 10;
+
+    // 如果当前是静音状态,更新背景噪音估计
+    if (vad->state == VAD_STATE_SILENCE) {
+        // 平滑更新背景噪音能量 (IIR滤波)
+        vad->background_energy = (vad->background_energy * 15 + energy) / 16;
+
+        // 更新自适应阈值 (背景噪音能量的某个倍数)
+        int min_threshold = vad->params.energy_threshold / 2;
+        int adaptive = vad->background_energy * 3;
+        vad->adaptive_threshold = (adaptive > min_threshold) ? adaptive : min_threshold;
+    }
+}
+
+// 状态机处理
+static void process_state_machine(struct custom_vad_state *vad, int is_frame_voice, int frame_duration_ms)
+{
+    vad_event_t current_event = VAD_EVENT_NONE;  // 当前事件
+
+    switch (vad->state) {
+        case VAD_STATE_SILENCE:
+            if (is_frame_voice) {
+                vad->consecutive_voice_frames++;
+                vad->consecutive_silence_frames = 0;
+
+                // 需要连续多个帧检测到语音才转换状态,防止短噪音
+                if (vad->consecutive_voice_frames >= 2) {
+                    vad->state = VAD_STATE_VOICE_ONSET;
+                    //mp_printf(&mp_plat_print,"VAD State: SILENCE -> VOICE_ONSET\n");
+                }
+            } else {
+                vad->consecutive_voice_frames = 0;
+            }
+            break;
+
+        case VAD_STATE_VOICE_ONSET:
+            if (is_frame_voice) {
+                vad->consecutive_voice_frames++;
+                vad->consecutive_silence_frames = 0;
+
+                // 累积足够的语音帧后确认为语音状态
+                if (vad->consecutive_voice_frames * frame_duration_ms >= vad->params.voice_time) {
+                    vad->state = VAD_STATE_VOICE_ACTIVE;
+                    vad->params.is_speaking = 1;
+                    //mp_printf(&mp_plat_print,"VAD State: VOICE_ONSET -> VOICE_ACTIVE\n");
+
+                    // 设置VAD开始事件
+                    current_event = VAD_EVENT_START;
+
+                    // 重置静音计数和状态
+                    vad->silence_duration = 0;
+                    vad->silence_detected = 0;
+                    vad->params.is_silence = 0;
+
+                    if (vad->params.on_voice_start) {
+                        vad->params.on_voice_start(vad->params.user_data);
+                    }
+                }
+            } else {
+                vad->consecutive_silence_frames++;
+                vad->consecutive_voice_frames = 0;
+
+                // 如果快速回到静音,则回到静音状态
+                if (vad->consecutive_silence_frames >= 3) {
+                    vad->state = VAD_STATE_SILENCE;
+                    //mp_printf(&mp_plat_print,"VAD State: VOICE_ONSET -> SILENCE (false alarm)\n");
+                }
+            }
+            break;
+
+        case VAD_STATE_VOICE_ACTIVE:
+            if (!is_frame_voice) {
+                vad->consecutive_silence_frames++;
+                vad->consecutive_voice_frames = 0;
+
+                // 处理静音状态检测
+                vad->silence_duration += frame_duration_ms;
+
+                // 检测静音开始
+                if (vad->silence_duration >= vad->params.silence_start_threshold && !vad->silence_detected) {
+                    vad->silence_detected = 1;
+                    vad->params.is_silence = 1;
+                    //mp_printf(&mp_plat_print,"VAD Silence detected in VOICE_ACTIVE state\n");
+                }
+
+                // 开始检测到静音,进入结束过渡状态
+                if (vad->consecutive_silence_frames >= 2) {
+                    vad->state = VAD_STATE_VOICE_FALLING;
+                    //mp_printf(&mp_plat_print,"VAD State: VOICE_ACTIVE -> VOICE_FALLING\n");
+                }
+            } else {
+                vad->consecutive_silence_frames = 0;
+
+                // 重置静音计数和状态
+                if (vad->silence_detected) {
+                    vad->silence_duration = 0;
+                    vad->silence_detected = 0;
+                    vad->params.is_silence = 0;
+                    //mp_printf(&mp_plat_print,"VAD Silence ended in VOICE_ACTIVE state\n");
+                }
+            }
+            break;
+
+        case VAD_STATE_VOICE_FALLING:
+            if (is_frame_voice) {
+                vad->consecutive_voice_frames++;
+                vad->consecutive_silence_frames = 0;
+
+                // 如果语音恢复,回到活跃状态
+                if (vad->consecutive_voice_frames >= 1) {
+                    vad->state = VAD_STATE_VOICE_ACTIVE;
+                    //mp_printf(&mp_plat_print,"VAD State: VOICE_FALLING -> VOICE_ACTIVE (continue)\n");
+
+                    // 重置静音计数和状态
+                    if (vad->silence_detected) {
+                        vad->silence_duration = 0;
+                        vad->silence_detected = 0;
+                        vad->params.is_silence = 0;
+                        //mp_printf(&mp_plat_print,"VAD Silence ended in VOICE_FALLING state\n");
+                    }
+                }
+            } else {
+                vad->consecutive_silence_frames++;
+
+                // 处理静音状态检测
+                vad->silence_duration += frame_duration_ms;
+
+                // 检测静音开始
+                if (vad->silence_duration >= vad->params.silence_start_threshold && !vad->silence_detected) {
+                    vad->silence_detected = 1;
+                    vad->params.is_silence = 1;
+                    //mp_printf(&mp_plat_print,"VAD Silence detected in VOICE_FALLING state\n");
+                }
+
+                // 累积足够的静音确认语音结束
+                if (vad->consecutive_silence_frames * frame_duration_ms >= vad->params.silence_time) {
+                    vad->state = VAD_STATE_SILENCE;
+                    vad->params.is_speaking = 0;
+                    //mp_printf(&mp_plat_print,"VAD State: VOICE_FALLING -> SILENCE\n");
+
+                    // 设置VAD结束事件
+                    current_event = VAD_EVENT_END;
+
+                    // 重置静音状态
+                    vad->silence_detected = 0;
+                    vad->params.is_silence = 0;
+
+                    if (vad->params.on_voice_end) {
+                        vad->params.on_voice_end(vad->params.user_data);
+                    }
+                }
+            }
+            break;
+    }
+
+    // 更新最后事件
+    if (current_event != VAD_EVENT_NONE) {
+        vad->last_event = current_event;
+    }
+}
+
+// 处理音频数据
+// 返回值: 1表示检测到语音,0表示静音
+int custom_vad_process(struct custom_vad_state *vad, const void *data, int data_len)
+{
+    if (!g_vad_enabled || !vad || !data || data_len <= 0) {
+        return 0;
+    }
+
+    const short *samples = (const short *)data;
+    int sample_count = data_len / sizeof(short);
+
+    // 计算当前帧的能量
+    int energy = calculate_energy(samples, sample_count);
+
+    // 更新能量历史和背景噪音估计
+    update_energy_history(vad, energy);
+
+    // 计算当前帧的时长(毫秒)
+    int frame_duration_ms = (data_len * 1000) / (vad->params.sample_rate * vad->params.channel * sizeof(short));
+
+    // 判断当前帧是否包含语音
+    int is_frame_voice = (energy > vad->adaptive_threshold);
+
+    // 调试输出
+    //mp_printf(&mp_plat_print,"VAD energy: %d, adaptive threshold: %d, background: %d, is_voice: %d, state: %d\n",energy, vad->adaptive_threshold, vad->background_energy, is_frame_voice, vad->state);
+
+    // 运行状态机
+    process_state_machine(vad, is_frame_voice, frame_duration_ms);
+
+    return vad->params.is_speaking;
+}
+
+// 重置VAD状态
+void custom_vad_reset(struct custom_vad_state *vad)
+{
+    if (vad) {
+        vad->buffer_pos = 0;
+        vad->params.current_silence_time = 0;
+        vad->params.current_voice_time = 0;
+        vad->params.is_speaking = 0;
+        vad->state = VAD_STATE_SILENCE;
+        vad->consecutive_voice_frames = 0;
+        vad->consecutive_silence_frames = 0;
+        vad->last_event = VAD_EVENT_NONE;  // 重置事件
+        vad->silence_duration = 0;         // 重置静音持续时间
+        vad->silence_detected = 0;         // 重置静音检测标志
+        vad->params.is_silence = 0;        // 重置静音状态
+
+        // 不重置自适应阈值和背景噪音,保留学习到的环境特性
+    }
+}
+
+// 获取当前VAD状态(可用于调试)
+const char* custom_vad_get_state_name(struct custom_vad_state *vad)
+{
+    if (!vad) return "NULL";
+
+    switch (vad->state) {
+        case VAD_STATE_SILENCE: return "SILENCE";
+        case VAD_STATE_VOICE_ONSET: return "VOICE_ONSET";
+        case VAD_STATE_VOICE_ACTIVE: return "VOICE_ACTIVE";
+        case VAD_STATE_VOICE_FALLING: return "VOICE_FALLING";
+        default: return "UNKNOWN";
+    }
+}
+
+// 接口实现
+
+// VAD状态检测:返回1表示VAD start,返回2表示VAD end,0表示非VAD
+int custom_vad_detect(struct custom_vad_state *vad)
+{
+    if (!vad) {
+        return 0;
+    }
+
+    int result = vad->last_event;
+
+    // 检测结束后清除事件,确保每个事件只报告一次
+    vad->last_event = VAD_EVENT_NONE;
+
+    return result;
+}
+
+// VAD状态清除
+int custom_vad_clear(struct custom_vad_state *vad)
+{
+    if (!vad) {
+        return -1;
+    }
+
+    // 清除VAD状态和事件
+    vad->params.is_speaking = 0;
+    vad->last_event = VAD_EVENT_NONE;
+
+    // 如果当前不是静音状态,强制转换为静音状态
+    if (vad->state != VAD_STATE_SILENCE) {
+        vad->state = VAD_STATE_SILENCE;
+        vad->consecutive_voice_frames = 0;
+        vad->consecutive_silence_frames = 0;
+    }
+
+    return 0;
+}
+
+// VAD静音状态检测:返回1表示VAD静音开始,0表示非VAD静音
+int custom_vad_silence_detect(struct custom_vad_state *vad)
+{
+    if (!vad) {
+        return 0;
+    }
+
+    return vad->params.is_silence;
+}
+
+// VAD静音状态清除
+void custom_vad_silence_clear(struct custom_vad_state *vad)
+{
+    if (!vad) {
+        return;
+    }
+
+    // 清除静音相关状态
+    vad->silence_duration = 0;
+    vad->silence_detected = 0;
+    vad->params.is_silence = 0;
+}
+
+
+
+
+
+typedef struct _mp_obj_VAD_t {
+    mp_obj_base_t base;
+    struct custom_vad_state VAD;
+} mp_obj_VAD_t;
+
+
+
+STATIC mp_obj_t VAD_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
+    enum{
+        ARG_sample_rate,             // 采样率
+        ARG_channel,                // 通道数
+        ARG_frame_size,              // 每帧字节数
+        ARG_energy_threshold,        // 能量阈值
+        ARG_voice_time,              // 语音持续时间阈值(ms)
+        ARG_silence_time,            // 静音持续时间阈值(ms)
+        ARG_silence_start_threshold, // 静音开始阈值(ms)
+        
+    };
+
+    static const mp_arg_t allowed_args[] = {
+        { MP_QSTR_sample_rate, MP_ARG_INT, {.u_int = 16000}},
+        { MP_QSTR_channel, MP_ARG_INT, {.u_int = 1}},
+        { MP_QSTR_frame_size, MP_ARG_INT, {.u_int = 3200}},
+               { MP_QSTR_energy_threshold, MP_ARG_INT, {.u_int = 300}},
+        { MP_QSTR_voice_time, MP_ARG_INT, {.u_int = 50}},
+        { MP_QSTR_silence_time, MP_ARG_INT, {.u_int = 300}},
+        { MP_QSTR_silence_start_threshold, MP_ARG_INT, {.u_int = 100}},
+    };
+    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+    mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+    mp_obj_VAD_t *self = m_new_obj(mp_obj_VAD_t);
+    memset(self,0,sizeof(mp_obj_VAD_t));
+    self->base.type = type;
+
+    self->VAD.params.sample_rate = args[ARG_sample_rate].u_int;
+    self->VAD.params.channel = args[ARG_channel].u_int;
+    self->VAD.params.frame_size = args[ARG_frame_size].u_int;
+    self->VAD.params.energy_threshold = args[ARG_energy_threshold].u_int;
+    self->VAD.params.voice_time = args[ARG_voice_time].u_int;
+    self->VAD.params.silence_time = args[ARG_silence_time].u_int;
+    self->VAD.params.silence_start_threshold = args[ARG_silence_start_threshold].u_int;
+    // 计算缓冲区大小 - 这里设置为一个VAD检测帧的大小
+    self->VAD.buffer_size = self->VAD.params.frame_size;
+    ////mp_printf(&mp_plat_print"self->VAD.buffer_size = %d\r\n", self->VAD.buffer_size);
+    self->VAD.buffer = malloc(self->VAD.buffer_size);
+    if (self->VAD.buffer == NULL) {
+        
+        mp_raise_ValueError(MP_ERROR_TEXT("分配音频缓冲区失败"));
+    }
+
+    self->VAD.buffer_pos = 0;
+    self->VAD.state = VAD_STATE_SILENCE;
+    self->VAD.consecutive_voice_frames = 0;
+    self->VAD.consecutive_silence_frames = 0;
+    self->VAD.history_pos = 0;
+    self->VAD.adaptive_threshold = self->VAD.params.energy_threshold;
+    self->VAD.background_energy = self->VAD.params.energy_threshold / 2; // 初始化背景噪音能量
+    self->VAD.last_event = VAD_EVENT_NONE;  // 初始化最后事件
+    self->VAD.silence_duration = 0;         // 初始化静音持续时间
+    self->VAD.silence_detected = 0;         // 初始化静音检测标志
+
+    // 初始化参数结构体中的新字段
+    self->VAD.params.is_silence = 0;        // 初始化静音状态
+
+    // 初始化能量历史记录
+    for (int i = 0; i < 10; i++) {
+        self->VAD.energy_history[i] = 0;
+    }
+    // 启用VAD时初始化
+    struct VadConfig conf;
+    conf.sil_threshold = 63;
+    conf.energy_threshold = 10000;
+    conf.min_speech_length = 240;
+    conf.silence_detect_length = 300;
+    conf.rule1_min_tailing_silence = 480;
+    conf.rule2_min_tailing_silence = 960;
+    conf.rule3_min_tailing_silence = 960;
+    conf.vad_log_level = 2;
+    init_vad(&conf);
+
+    return MP_OBJ_FROM_PTR(self);
+
+}
+STATIC mp_obj_t mp_custom_vad_process(mp_obj_t self_in,mp_obj_t data, mp_obj_t data_len)
+{
+    mp_obj_VAD_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_buffer_info_t bufinfo;
+    mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_WRITE);
+    //(char *)bufinfo.buf;
+       int len = mp_obj_get_int(data_len);
+    int ret = custom_vad_process(&self->VAD,(void *)bufinfo.buf,len);
+    return mp_obj_new_int(ret);
+}
+STATIC const MP_DEFINE_CONST_FUN_OBJ_3(mp_custom_vad_process_obj, mp_custom_vad_process);
+
+STATIC mp_obj_t mp_custom_vad_reset(mp_obj_t self_in)
+{
+    mp_obj_VAD_t *self = MP_OBJ_TO_PTR(self_in);
+    custom_vad_reset(&self->VAD);
+    return mp_obj_new_int(1);
+}
+STATIC const MP_DEFINE_CONST_FUN_OBJ_1(mp_custom_vad_reset_obj, mp_custom_vad_reset);
+
+STATIC const mp_rom_map_elem_t VAD_locals_dict_table[] = {
+    
+    { MP_ROM_QSTR(MP_QSTR_custom_vad_process), MP_ROM_PTR(&mp_custom_vad_process_obj) },
+    { MP_ROM_QSTR(MP_QSTR_custom_vad_reset), MP_ROM_PTR(&mp_custom_vad_reset_obj) },
+
+};
+STATIC MP_DEFINE_CONST_DICT(VAD_locals_dict, VAD_locals_dict_table);
+
+
+
+STATIC const mp_obj_type_t VAD_type = {
+    { &mp_type_type },
+    .name = MP_QSTR_VAD,
+    .make_new = VAD_make_new,
+    .locals_dict = (void *)&VAD_locals_dict,
+};
+
+STATIC const mp_rom_map_elem_t VAD_module_globals_table[] = {
+    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_VAD) },
+    { MP_ROM_QSTR(MP_QSTR_VAD), MP_ROM_PTR(&VAD_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(VAD_module_globals, VAD_module_globals_table);
+
+const mp_obj_module_t mp_module_VAD = {
+    .base = { &mp_type_module },
+    .globals = (mp_obj_dict_t *)&VAD_module_globals,
+};
+#endif
\ No newline at end of file
index cc94e0c..57df20f 100644 (file)
@@ -250,16 +250,9 @@ static int _socket_getaddrinfo3(const char *nodename, const char *servname,
 #endif
 }
 
-static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struct addrinfo **resp) {
-    const struct addrinfo hints = {
-#if defined(PLAT_Qualcomm)
-        .ai_flags = AI_CANONNAME,
-#endif
-        .ai_family = AF_UNSPEC,
-        .ai_socktype = SOCK_STREAM,
-    };
-
+static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, const uint8_t family, struct addrinfo **resp) {
     mp_obj_t port = portx;
+    int res = 0;
     if (mp_obj_is_small_int(port)) {
         // This is perverse, because lwip_getaddrinfo promptly converts it back to an int, but
         // that's the API we have to work with ...
@@ -274,17 +267,41 @@ static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struc
         host_str = "0.0.0.0";
     }
 
-    MP_THREAD_GIL_EXIT();
-    int res = _socket_getaddrinfo3(host_str, port_str, &hints, resp);
-    MP_THREAD_GIL_ENTER();
+    if ((family == AF_INET) || (family == AF_INET6))
+    {
+        const struct addrinfo hints = {
+#if defined(PLAT_Qualcomm)
+            .ai_flags = AI_CANONNAME,
+#endif
+            .ai_family = family,
+            .ai_socktype = SOCK_STREAM,
+        };
+        MP_THREAD_GIL_EXIT();
+        res = _socket_getaddrinfo3(host_str, port_str, &hints, resp);
+        MP_THREAD_GIL_ENTER();
+    }
+    else
+    {
+        const struct addrinfo hints = {
+#if defined(PLAT_Qualcomm)
+            .ai_flags = AI_CANONNAME,
+#endif
+            .ai_family = AF_UNSPEC,
+            .ai_socktype = SOCK_STREAM,
+        };
+    
+        MP_THREAD_GIL_EXIT();
+        res = _socket_getaddrinfo3(host_str, port_str, &hints, resp);
+        MP_THREAD_GIL_ENTER();       
+    }
 
     return res;
 }
 
-STATIC void _socket_getaddrinfo(const mp_obj_t addrtuple, struct addrinfo **resp) {
+STATIC void _socket_getaddrinfo(const mp_obj_t addrtuple, const uint8_t type, struct addrinfo **resp) {
     mp_obj_t *elem;
     mp_obj_get_array_fixed_n(addrtuple, 2, &elem);
-    int res = _socket_getaddrinfo2(elem[0], elem[1], resp);
+    int res = _socket_getaddrinfo2(elem[0], elem[1], type, resp);
     if (res != 0) {
         mp_raise_OSError(res);
     }
@@ -535,8 +552,86 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz
 #endif
 
     return MP_OBJ_FROM_PTR(sock);
+#elif defined(PLAT_ASR_1803s)
+    if (!netif_get_default_nw())
+    {
+        Helios_DataCallInfoStruct info = {0};
+        int ret = 0;
+        int pdp = Helios_DataCall_GetCurrentPDP();
+        ret = Helios_DataCall_GetInfo(pdp, 0, &info);
+        if (ret == 0)
+        {
+            if (((info.v4.state == 1) && (sock->domain == AF_INET)) || ((info.v6.state == 1) && (sock->domain == AF_INET6)))
+            {
+                if (sock->domain == AF_INET)
+                {
+                    struct sockaddr_in server_addr;
+                    memset(&server_addr, 0, sizeof(server_addr));
+                    server_addr.sin_family = AF_INET;
+                    server_addr.sin_port = 0;
+                
+                    char ip4_ip_addr[16] = {0};
+                    inet_ntop(AF_INET, &info.v4.addr.ip, ip4_ip_addr, sizeof(ip4_ip_addr));
+                    QPY_SOCKET_LOG("[socket]make new bind IPV4 %s.\r\n", ip4_ip_addr);
+                    inet_pton(AF_INET, ip4_ip_addr, &server_addr.sin_addr.s_addr);
+                
+                    
+                    if (lwip_bind(sock->fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr_in)))
+                    {
+                        //bind failed.
+                        QPY_SOCKET_LOG("[socket]bind IPV4 failed.\r\n");
+                        exception_from_errno(errno);
+                    }
+                    else
+                    {
+                        QPY_SOCKET_LOG("[socket]bind IPV4 success.\r\n");
+                    }
+                }
+                else if (sock->domain == AF_INET6)
+                {
+                    struct sockaddr_in6 local_v6;
+                    memset(&local_v6, 0, sizeof(local_v6));
+                
+                    local_v6.sin6_family = AF_INET6;
+                    local_v6.sin6_port = 0;
+                
+                    char ip6_ip_addr[64] = {0};
+                    inet_ntop(AF_INET6, &info.v6.addr.ip, ip6_ip_addr, sizeof(ip6_ip_addr));
+                    QPY_SOCKET_LOG("[socket]make new bind IPV6 %s.\r\n", ip6_ip_addr);
+                    inet_pton(AF_INET6, ip6_ip_addr, &local_v6.sin6_addr);
+                
+                    if (lwip_bind(sock->fd, (struct sockaddr *)&local_v6, sizeof(struct sockaddr_in6)))
+                    {
+                        //bind failed.
+                        QPY_SOCKET_LOG("[socket]bind IPV6 failed.\r\n");
+                        exception_from_errno(errno);
+                    }
+                    else
+                    {
+                        QPY_SOCKET_LOG("[socket]bind IPV6 success.\r\n");
+                    }
+                }
+            }
+            else
+            {
+                QPY_SOCKET_LOG("[socket]DataCall PDP state FAIL.\r\n");
+                _socket_settimeout(sock, UINT64_MAX);
+                return MP_OBJ_FROM_PTR(sock);
+            }
+        }
+        else
+        {
+            QPY_SOCKET_LOG("[socket]DataCall GetInfo FAIL.\r\n");
+            _socket_settimeout(sock, UINT64_MAX);
+            return MP_OBJ_FROM_PTR(sock);
+        }
+    }
+    _socket_settimeout(sock, UINT64_MAX);
+
+    return MP_OBJ_FROM_PTR(sock);
+
 #else
-#if defined(PLAT_ASR) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Unisoc)
+#if defined(PLAT_ASR) || defined(PLAT_ASR_1803sc) || defined(PLAT_Unisoc)
     if (!netif_get_default_nw()) {
 #endif
        /*
@@ -551,7 +646,7 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz
         int pdp = Helios_DataCall_GetCurrentPDP();
     #if defined (PLAT_Unisoc) || defined (PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8850_R02) || defined(PLAT_Unisoc_8910_R06)
         struct netif* netif_cfg = netif_get_by_cid(pdp);
-    #elif defined (PLAT_ASR) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602)
+    #elif defined (PLAT_ASR) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602)
         struct netif* netif_cfg = netif_get_by_cid(pdp - 1);
     #endif
     #endif
@@ -566,7 +661,7 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz
                 local_v4.sin_port = 0;
     #if defined (PLAT_Unisoc) || defined(PLAT_RDA) || defined (PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8850_R02) || defined(PLAT_Unisoc_8910_R06)
                 local_v4.sin_addr.s_addr = netif_cfg->ip_addr.u_addr.ip4.addr;
-    #elif defined (PLAT_ASR) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602)
+    #elif defined (PLAT_ASR) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602)
                 local_v4.sin_addr.s_addr = netif_cfg->ip_addr.addr;
     #endif
                 if(lwip_bind(sock->fd,(struct sockaddr *)&local_v4,sizeof(struct sockaddr)))
@@ -588,7 +683,7 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz
                 const ip6_addr_t * ip6_addr_ptr = NULL;
                 ip6_addr_ptr = netif_ip6_addr(netif_cfg, 1);
                 memcpy(&local_v6.sin6_addr, ip6_addr_ptr, sizeof(ip6_addr_t));
-    #elif defined (PLAT_ASR) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602)
+    #elif defined (PLAT_ASR) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602)
                 ip6_addr_t * ip6_addr_ptr = NULL;
                 ip6_addr_ptr = netif_get_global_ip6addr(netif_cfg);
                 memcpy(&local_v6.sin6_addr, ip6_addr_ptr, sizeof(ip6_addr_t));
@@ -613,7 +708,7 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz
         }
 
         //end
-#if defined(PLAT_ASR) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Unisoc)
+#if defined(PLAT_ASR) || defined(PLAT_ASR_1803sc) || defined(PLAT_Unisoc)
     }
 #endif
     _socket_settimeout(sock, UINT64_MAX);
@@ -845,6 +940,94 @@ STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) {
         QPY_SOCKET_LOG("[socket] NOT Support.\r\n");
         mp_raise_ValueError(MP_ERROR_TEXT("[socket]Not Support IPV6 Now\r\n"));
     }
+    return mp_const_none;
+#elif defined(PLAT_ASR_1803s)
+    Helios_DataCallInfoStruct info = {0};
+    if (addr_info[0] == '\0')
+    {
+        int pdp = Helios_DataCall_GetCurrentPDP();
+        int ret = Helios_DataCall_GetInfo(pdp, 0, &info);
+        
+        if (ret == 0)
+        {
+            if (!(((info.v4.state == 1) && (self->domain == AF_INET)) || ((info.v6.state == 1) && (self->domain == AF_INET6))))
+            {
+                QPY_SOCKET_LOG("[socket] Failed DataCall Info state\r\n");
+                exception_from_errno(errno);
+            }
+        }
+        else
+        {
+            QPY_SOCKET_LOG("[socket] Failed DataCall Info\r\n");
+            exception_from_errno(errno);
+        }
+    }
+
+    if (self->domain == AF_INET)
+    {
+        struct sockaddr_in server_addr;
+        memset(&server_addr, 0, sizeof(server_addr));
+        server_addr.sin_family = AF_INET;
+        server_addr.sin_port = htons(server_port);
+    
+        if (addr_info[0] == '\0')
+        {
+            char ip4_ip_addr[16] = {0};
+            inet_ntop(AF_INET, &info.v4.addr.ip, ip4_ip_addr, sizeof(ip4_ip_addr));
+            QPY_SOCKET_LOG("[socket] bind datacall IPV4 %s.\r\n", ip4_ip_addr);
+            inet_pton(AF_INET, ip4_ip_addr, &server_addr.sin_addr.s_addr);
+        }
+        else
+        {
+            QPY_SOCKET_LOG("[socket] bind IPV4 %s.\r\n", addr_info);
+            inet_pton(AF_INET, addr_info, &server_addr.sin_addr.s_addr);
+        }
+    
+        if(lwip_bind(self->fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr_in)))
+        {
+            //bind failed.
+            QPY_SOCKET_LOG("[socket][%d]bind IPV4 failed.\r\n", server_port);
+            exception_from_errno(errno);
+        }
+        else
+        {
+            QPY_SOCKET_LOG("[socket][%d]bind IPV4 success.\r\n", server_port);
+        }
+    }
+    else if (self->domain == AF_INET6)
+    {
+        struct sockaddr_in6 local_v6;
+        memset(&local_v6, 0, sizeof(local_v6));
+    
+        local_v6.sin6_family = AF_INET6;
+        local_v6.sin6_port = htons(server_port);
+    
+        if (addr_info[0] == '\0')
+        {
+            char ip6_ip_addr[64] = {0};
+            inet_ntop(AF_INET6, &info.v6.addr.ip, ip6_ip_addr, sizeof(ip6_ip_addr));
+            QPY_SOCKET_LOG("[socket] bind datacall IPV6 %s.\r\n", ip6_ip_addr);
+            inet_pton(AF_INET6, ip6_ip_addr, &local_v6.sin6_addr);
+        }
+        else
+        {
+            QPY_SOCKET_LOG("[socket] bind IPV6 %s.\r\n", addr_info);
+            inet_pton(AF_INET6, addr_info, &local_v6.sin6_addr);
+        }
+    
+        
+        if(lwip_bind(self->fd, (struct sockaddr *)&local_v6, sizeof(struct sockaddr_in6)))
+        {
+            //bind failed.
+            QPY_SOCKET_LOG("[socket][%d]bind IPV6 failed.\r\n", server_port);
+            exception_from_errno(errno);
+        }
+        else
+        {
+            QPY_SOCKET_LOG("[socket][%d]bind IPV6 success.\r\n", server_port);
+        }
+    }
+
     return mp_const_none;
 #else
 
@@ -860,7 +1043,7 @@ STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) {
     int pdp = Helios_DataCall_GetCurrentPDP();
 #if defined (PLAT_Unisoc) || defined (PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8850_R02) || defined(PLAT_Unisoc_8910_R06)
     struct netif* netif_cfg = netif_get_by_cid(pdp);
-#elif defined (PLAT_ASR) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602)
+#elif defined (PLAT_ASR) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602)
     struct netif* netif_cfg = netif_get_by_cid(pdp - 1);
 #else
     struct netif* netif_cfg = NULL;
@@ -877,7 +1060,7 @@ STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) {
             {
 #if defined (PLAT_Unisoc) || defined(PLAT_RDA) || defined (PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8850_R02) || defined(PLAT_Unisoc_8910_R06)
                 local_v4.sin_addr.s_addr = netif_cfg->ip_addr.u_addr.ip4.addr;
-#elif defined (PLAT_ASR) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602)
+#elif defined (PLAT_ASR) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602)
                 local_v4.sin_addr.s_addr = netif_cfg->ip_addr.addr;
 #endif
             }
@@ -888,7 +1071,7 @@ STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) {
         }
         else
         {
-#if defined (PLAT_Unisoc) || defined (PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) || defined (PLAT_ASR_1803s) || defined (PLAT_ASR_1803sc) || defined (PLAT_ASR) \
+#if defined (PLAT_Unisoc) || defined (PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) || defined (PLAT_ASR_1803sc) || defined (PLAT_ASR) \
     || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ASR_1602) || defined(PLAT_RDA) || defined(PLAT_Unisoc_8910_R06)
             inet_pton(AF_INET, addr_info, &local_v4.sin_addr.s_addr);
 #endif
@@ -916,7 +1099,7 @@ STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) {
                 const ip6_addr_t * ip6_addr_ptr = NULL;
                 ip6_addr_ptr = netif_ip6_addr(netif_cfg, 1);
                 memcpy(&local_v6.sin6_addr, ip6_addr_ptr, sizeof(ip6_addr_t));
-#elif defined (PLAT_ASR) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602)
+#elif defined (PLAT_ASR) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602)
                 ip6_addr_t * ip6_addr_ptr = NULL;
                 ip6_addr_ptr = netif_get_global_ip6addr(netif_cfg);
                 memcpy(&local_v6.sin6_addr, ip6_addr_ptr, sizeof(ip6_addr_t));
@@ -929,7 +1112,7 @@ STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) {
         }
         else
         {
-#if defined (PLAT_Unisoc) || defined (PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) || defined (PLAT_ASR_1803s) || defined (PLAT_ASR_1803sc) || defined (PLAT_ASR) \
+#if defined (PLAT_Unisoc) || defined (PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) || defined (PLAT_ASR_1803sc) || defined (PLAT_ASR) \
     || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ASR_1602) || defined(PLAT_RDA) || defined(PLAT_Unisoc_8910_R06)
             inet_pton(AF_INET6, addr_info, &local_v6.sin6_addr);
 #endif
@@ -1286,7 +1469,7 @@ STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) {
 
 #else
     struct addrinfo *res;
-    _socket_getaddrinfo(arg1, &res);
+    _socket_getaddrinfo(arg1, self->type, &res);
 
 #if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718)
     mp_obj_t *elem;
@@ -2717,7 +2900,16 @@ STATIC mp_obj_t socket_getaddrinfo(size_t n_args, const mp_obj_t *args) {
     }
 #endif
     struct addrinfo *res = NULL;
-    _socket_getaddrinfo2(args[0], args[1], &res);
+
+    if (n_args == 3)
+    {
+        const int ai_family = mp_obj_get_int(args[2]);
+        _socket_getaddrinfo2(args[0], args[1], ai_family, &res);
+    }
+    else
+    {
+        _socket_getaddrinfo2(args[0], args[1], 0, &res);
+    }
     mp_obj_t ret_list = mp_obj_new_list(0, NULL);
 
     for (struct addrinfo *resi = res; resi; resi = resi->ai_next) {
index 14fc92b..5fcebf7 100644 (file)
@@ -790,6 +790,12 @@ extern const struct _mp_obj_module_t mp_module_Gsensor;
 #endif
 extern const struct _mp_obj_module_t mp_module_websocket_mask;
 #define MICROPY_PORT_BUILTIN_MODULES_WEBSOCKET_MASK            { MP_OBJ_NEW_QSTR(MP_QSTR_websocket_mask), (mp_obj_t)&mp_module_websocket_mask},
+#if CONFIG_VAD
+extern const struct _mp_obj_module_t mp_module_VAD ;
+#define MICROPY_PORT_BUILTIN_MODULES_VAD               { MP_OBJ_NEW_QSTR(MP_QSTR_VAD), (mp_obj_t)&mp_module_VAD},
+#else
+#define MICROPY_PORT_BUILTIN_MODULES_VAD
+#endif
 #if MICROPY_QPY_MODULE_GPIO_ENCODER
 extern const struct _mp_obj_type_t encoder_type;
 #define MICROPY_PORT_BUILTIN_MODULES_ENCODER           { MP_OBJ_NEW_QSTR(MP_QSTR_encoder), (mp_obj_t)&encoder_type},
@@ -957,6 +963,7 @@ extern const struct _mp_obj_type_t TiktokRTC_type;
                MICROPY_PORT_BUILTIN_MODULES_JRTC \
                MICROPY_PORT_BUILTIN_MODULES_code128\
                MICROPY_PORT_BUILTIN_MODULES_WEBSOCKET_MASK\
+               MICROPY_PORT_BUILTIN_MODULES_VAD\
                MICROPY_PORT_BUILTIN_MODULES_NETWORK \
                MICROPY_PORT_BUILTIN_MODULES_ALIPAY_COLLECTION \
                MICROPY_PORT_BUILTIN_MODULES_GPIO_ENCODER \
index 3740e03..23bb0c5 100644 (file)
@@ -142,9 +142,15 @@ class BaseMqtt(object):
             if j > 5:
                 raise ValueError("DNS Parsing NULL")
             try:
-                addrall = socket.getaddrinfo(self.server, self.port)
+                if self.ipvtype == 1:
+                    if platform == "FCM360W" or platform == "FCM362K":
+                        print("Not Support!")
+                        return
+                    addrall = socket.getaddrinfo(self.server, self.port, socket.AF_INET6)
+                else:
+                    addrall = socket.getaddrinfo(self.server, self.port, socket.AF_INET)
             except Exception as e:
-                raise ValueError("DNS Parsing '{}'".format(self.server))
+                raise ValueError("DNS Parsing '{}'{}".format(self.server,str(e)))
             if not addrall:
                 j += 1
                 utime.sleep_ms(500)
index 3bde84b..e68c636 100644 (file)
@@ -290,8 +290,8 @@ class Client(object):
 
         sock = socket.socket()
         try:
-            sock.settimeout(6)
-            addr = socket.getaddrinfo(uri.hostname, uri.port)
+            #sock.settimeout(6)
+            addr = socket.getaddrinfo(uri.hostname, uri.port, socket.AF_INET)
             sock.connect(addr[0][4])