diff --git a/bk_aidk/components/bk_factory_config/bk_factory_config.c b/bk_aidk/components/bk_factory_config/bk_factory_config.c index 87d828bb..1df3b823 100644 --- a/bk_aidk/components/bk_factory_config/bk_factory_config.c +++ b/bk_aidk/components/bk_factory_config/bk_factory_config.c @@ -38,6 +38,8 @@ const struct factory_config_t s_platform_config[] = { {"d_network_id", (void *)"\0", 1, BK_TRUE, 198}, {"d_agent_info", (void *)"\0", 1, BK_TRUE, 162}, {"bat_offset", (void *)&s_bat_offset, 4, BK_TRUE, 4}, + {"ai_ota_url", (void *)"\0", 1, BK_TRUE, 128}, + {"ai_agent_id", (void *)"\0", 1, BK_TRUE, 128}, }; static const struct factory_config_t *s_user_reg_config = NULL; @@ -218,10 +220,10 @@ static void cli_factory_read(char *pcWriteBuffer, int xWriteBufferLen, int argc, { uint32_t volume; int ret = bk_config_read("volume", (void *)&volume, sizeof(volume)); - LOGI("sram volume = %u, ret = %d\r\n", volume, ret); + LOGE("sram volume = %u, ret = %d\r\n", volume, ret); ret = bk_get_env_enhance("volume", (void *)&volume, sizeof(volume)); - LOGI("flash volume = %u, ret = %d\r\n", volume, ret); + LOGE("flash volume = %u, ret = %d\r\n", volume, ret); } @@ -260,7 +262,7 @@ void bk_factory_init(void) LOGI("first initialize factory config\r\n"); bk_factory_reset(); } else { - LOGI("factory config already initialized\r\n"); + LOGE("factory config already initialized\r\n"); bk_factory_cache_init(); } diff --git a/bk_aidk/projects/beken_wss_paopao/main/app_event.c b/bk_aidk/projects/beken_wss_paopao/main/app_event.c index c1382291..d004b451 100755 --- a/bk_aidk/projects/beken_wss_paopao/main/app_event.c +++ b/bk_aidk/projects/beken_wss_paopao/main/app_event.c @@ -96,24 +96,24 @@ void app_event_asr_evt_callback(media_app_evt_type_t event, uint32_t param) return; } - if (link_status.state != WIFI_LINKSTATE_STA_GOT_IP) + if (link_status.state == WIFI_LINKSTATE_STA_GOT_IP) { - // bk_printf("WiFi在STA模式下已获取IP"); + if (g_connected_flag) + { // zhanyu + bk_printf("MEDIA_APP_EVT_ASR_WAKEUP_IND_sent_abort_msg\n"); + sent_abort_msg(); + } + else + { + + bk_printf("beken_rtc_start~~~audio_tras_init\n"); + beken_auto_run(); + // audio_tras_init(); + } } - if (g_connected_flag) - { // zhanyu - bk_printf("MEDIA_APP_EVT_ASR_WAKEUP_IND_sent_abort_msg\n"); - sent_abort_msg(); - } - else - { - - bk_printf("beken_rtc_start~~~audio_tras_init\n"); - beken_auto_run(); - // audio_tras_init(); - } + app_event_send_msg(APP_EVT_ASR_WAKEUP, 0); break; diff --git a/bk_aidk/projects/beken_wss_paopao/main/app_main.c b/bk_aidk/projects/beken_wss_paopao/main/app_main.c index 152e3b6a..20a3dc93 100755 --- a/bk_aidk/projects/beken_wss_paopao/main/app_main.c +++ b/bk_aidk/projects/beken_wss_paopao/main/app_main.c @@ -141,125 +141,8 @@ void prepare_config_network_main() rtos_delete_thread(NULL); } -// 按键 1 的回调函数 -void volume_init(void) -{ - int volume_size = bk_config_read("volume", (void *)&volume, 4); - if (volume_size != 4) - { - BK_LOGE(TAG, "read volume config fail, use default config volume_size:%d\n", volume_size); - } - if (volume > (SPK_VOLUME_LEVEL - 1)) - { - volume = SPK_VOLUME_LEVEL - 1; - if (0 != bk_config_write("volume", (void *)&volume, 4)) - { - BK_LOGE(TAG, "storage volume: %d fail\n", volume); - } - } - - /* SPK_GAIN_MAX * [(exp(i/(SPK_VOLUME_LEVEL-1)-1)/(exp(1)-1)] */ - uint32_t step[SPK_VOLUME_LEVEL] = {0, 6, 12, 20, 28, 37, 47, 58, 71, 84, 100}; - for (uint32_t i = 0; i < SPK_VOLUME_LEVEL; i++) - { - g_volume_gain[i] = SPK_GAIN_MAX * step[i] / 100; - } -} - -void volume_increase() -{ - BK_LOGI(TAG, " volume up\r\n"); - if (volume == (SPK_VOLUME_LEVEL - 1)) - { - BK_LOGI(TAG, "volume have reached maximum volume: %d\n", SPK_GAIN_MAX); - return; - } - if (BK_OK == bk_aud_intf_set_spk_gain(g_volume_gain[volume + 1])) - { - volume += 1; - if (0 != bk_config_write("volume", (void *)&volume, 4)) - { - BK_LOGE(TAG, "storage volume: %d fail\n", volume); - } - BK_LOGI(TAG, "current volume: %d\n", volume); - } - else - { - BK_LOGI(TAG, "set volume fail\n"); - } -} - -void volume_decrease() -{ - BK_LOGI(TAG, " volume down\r\n"); - if (volume == 0) - { - BK_LOGI(TAG, "volume have reached minimum volume: 0\n"); - return; - } - if (BK_OK == bk_aud_intf_set_spk_gain(g_volume_gain[volume - 1])) - { - volume -= 1; - if (0 != bk_config_write("volume", (void *)&volume, 4)) - { - BK_LOGE(TAG, "storage volume: %d fail\n", volume); - } - BK_LOGI(TAG, "current volume: %d\n", volume); - } - else - { - BK_LOGI(TAG, "set volume fail\n"); - } -} - -void volume_set_abs(uint8_t level, uint8_t has_precision) -{ - bk_err_t ret = 0; - - BK_LOGI(TAG, "%s volume abs %d %d\n", __func__, level, has_precision); - - if (level > SPK_VOLUME_LEVEL - 1) - { - BK_LOGE(TAG, "%s invalid level %d >= %d\n", __func__, level, SPK_VOLUME_LEVEL); - level = SPK_VOLUME_LEVEL - 1; - } - - if (level == 0 && has_precision) - { - BK_LOGW(TAG, "%s set raw gain 2 because precision\n", __func__); - ret = bk_aud_intf_set_spk_gain(2); - } - else - { - ret = bk_aud_intf_set_spk_gain(g_volume_gain[level]); - } - - if (BK_OK == ret) - { - volume = level; - - if (0 != bk_config_write("volume", (void *)&volume, sizeof(volume))) - { - BK_LOGE(TAG, "%s storage volume: %d fail\n", __func__, level); - } - - BK_LOGI(TAG, "%s current volume: %d\n", __func__, level); - } - else - { - BK_LOGE(TAG, "%s set volume %d fail\n", __func__, level); - } -} - -uint32_t volume_get_current() -{ - return volume; -} - -uint32_t volume_get_level_count() -{ - return SPK_VOLUME_LEVEL; -} + + void power_off() { BK_LOGI(TAG, " power_off\r\n"); @@ -608,8 +491,6 @@ static void handle_system_event(key_event_t event) #if (CONFIG_SYS_CPU0) app_event_init(); - volume_init(); - #if CONFIG_AUD_INTF_SUPPORT_PROMPT_TONE extern bk_err_t audio_turn_on(void); int ret = audio_turn_on(); diff --git a/bk_aidk/projects/beken_wss_paopao/main/application.c b/bk_aidk/projects/beken_wss_paopao/main/application.c index 1645cf12..102dcd66 100755 --- a/bk_aidk/projects/beken_wss_paopao/main/application.c +++ b/bk_aidk/projects/beken_wss_paopao/main/application.c @@ -21,12 +21,22 @@ #include "mcp/mcp_server.h" #include "beken_rtc.h" +#if (CONFIG_SYS_CPU0) +#include "beken_config.h" +#include "aud_intf.h" +#include "bk_factory_config.h" +#if CONFIG_NETWORK_AUTO_RECONNECT +#include "bk_genie_smart_config.h" +#endif +#endif #include "iot_lamp.h" #include "iot_speaker.h" #include "iot_sleep_helper.h" #include "bat_main.h" #include "spi_led.h" #include "app_event.h" +#include "iot_ota.h" +#include #define TAG "APP" #define LOGI(...) BK_LOGI(TAG, ##__VA_ARGS__) @@ -34,7 +44,16 @@ #define LOGE(...) BK_LOGE(TAG, ##__VA_ARGS__) #define LOGD(...) BK_LOGD(TAG, ##__VA_ARGS__) +static beken_thread_t app_thread_hdl = NULL; +static app_config_t app_config; static DeviceState deviceState = kDeviceStateIdle; +app_config_t* app_get_config(){ + return &app_config; +} +void app_set_websocket_url(const char* url) { + os_memset(app_config.websocket_url, 0, sizeof(app_config.websocket_url)); + os_strcpy(app_config.websocket_url, url); +} static ReturnValue sleep_helper_set_mode_callback(const PropertyList* properties) { Property* mode_prop = property_list_get_by_name(properties, "mode"); @@ -187,6 +206,49 @@ static ReturnValue sleep_helper_get_device_status_callback(const PropertyList* p return ret; } +// 获取体温数据回调 +static ReturnValue health_get_temperature_callback(const PropertyList* properties) { + + #if 0 + cJSON* status = cJSON_CreateObject(); + cJSON* health = cJSON_CreateObject(); + cJSON_AddNumberToObject(health, "body_temperature", 38.5); + cJSON_AddItemToObject(status, "health", health); + char *jsonString = cJSON_PrintUnformatted(status); + ReturnValue ret = return_value_create_string(jsonString); + cJSON_Delete(status); + return ret; + #endif + return return_value_create_string("{\"success\":false,\"error\":\"获取体温功能正在完善,敬请期待\"}"); +} +// 获取血压数据回调 +static ReturnValue health_get_bloodpressure_callback(const PropertyList* properties) { + #if 0 + cJSON* status = cJSON_CreateObject(); + cJSON* health = cJSON_CreateObject(); + cJSON_AddNumberToObject(health, "bloodpressure", 120); + cJSON_AddItemToObject(status, "health", health); + char *jsonString = cJSON_PrintUnformatted(status); + ReturnValue ret = return_value_create_string(jsonString); + cJSON_Delete(status); + return ret; + #endif + return return_value_create_string("{\"success\":false,\"error\":\"获取血压功能正在完善,敬请期待\"}"); +} +static ReturnValue health_analysis_report_callback(const PropertyList* properties) { + #if 0 + cJSON* status = cJSON_CreateObject(); + cJSON* health = cJSON_CreateObject(); + cJSON_AddNumberToObject(health, "bloodpressure", 120); + cJSON_AddItemToObject(status, "health", health); + char *jsonString = cJSON_PrintUnformatted(status); + ReturnValue ret = return_value_create_string(jsonString); + cJSON_Delete(status); + return ret; + #endif + return return_value_create_string("{\"success\":false,\"error\":\"分析健康报告功能正在完善,敬请期待\"}"); +} + void app_mcp_init(){ McpServer* mcp_server = mcp_server_get_instance(); @@ -261,6 +323,20 @@ void app_mcp_init(){ PropertyList* props = property_list_create(); mcp_server_add_tool_with_params(mcp_server, "self.ota.update_device", "更新拍拍灯乐小牛软件,执行该指令需要和用户二次确认才允许下发这个指令,并提示大约等待3分钟后手动重启设备", props, ota_update_device_callback); } + + { + PropertyList* props = property_list_create(); + mcp_server_add_tool_with_params(mcp_server, "self.health.get_temperature", "获取用户最近温度数据", props, health_get_temperature_callback); + } + { + PropertyList* props = property_list_create(); + mcp_server_add_tool_with_params(mcp_server, "self.health.get_bloodpressure", "获取用户最近血压数据", props, health_get_bloodpressure_callback); + } + + { + PropertyList* props = property_list_create(); + mcp_server_add_tool_with_params(mcp_server, "self.health.analysis_report", "获取用户最近健康分析报告", props, health_analysis_report_callback); + } } @@ -301,6 +377,67 @@ void app_on_incoming_json(char *json_text, unsigned int size){ DeviceState app_get_device_state(){ return deviceState; } +void app_ota_check(){ + LOGE("app_ota_check\n"); + if (!ota_has_websocket_config()) + { + // 读取OTA地址 + char ota_url[128] = {0}; + memset(ota_url, 0, sizeof(ota_url)); + int ret_size = bk_config_read("ai_ota_url", (void *)&ota_url, sizeof(ota_url)); + // 判断是否是合法http地址 + if (ret_size > 0 && NULL != strstr((char *)ota_url, "http")) + { + LOGE("bk_config_read ai_ota_url (%d) :%s\n", ret_size, ota_url); + LOGE("bk_config_read ai_ota_url strlen (%d) \n", strlen(ota_url)); + } + else + { + LOGE("bk_config_read ai_ota_url fail,use defult\n"); + memset(ota_url, 0, sizeof(ota_url)); + sprintf(ota_url, "%s", APPLICATION_DEFULT_OTA_URL); + } + // 检测OTA 并且通过OTA 获取WEBSOCKET地址 + int check_version = ota_check_version(ota_url); + if (check_version == BK_OK) + { + LOGE("check_version %d\n", check_version); + LOGE("ota_has_activation_code %d\n", ota_has_activation_code()); + LOGE("ota_has_websocket_config %d\n", ota_has_websocket_config()); + + if (ota_has_activation_code()) + { + // 激活设备 + ota_register_device(); + } + + if (ota_has_websocket_config()) + { + extern bk_err_t beken_rtc_start(void); + beken_rtc_start(); + } + } + }else{ + extern bk_err_t beken_rtc_start(void); + beken_rtc_start(); + } +} + +void app_ai_agent_start(){ + bk_err_t ret = BK_OK; + ret = rtos_create_thread(&app_thread_hdl, + 4, + "OTA_CHECK", + (beken_thread_function_t)app_ota_check, + 20 * 1024, + NULL); + if (ret != kNoErr) + { + app_thread_hdl = NULL; + } +} + void app_start(){ app_mcp_init(); + //app_ai_init(); } \ No newline at end of file diff --git a/bk_aidk/projects/beken_wss_paopao/main/application.h b/bk_aidk/projects/beken_wss_paopao/main/application.h index 7495f308..3e527a8b 100755 --- a/bk_aidk/projects/beken_wss_paopao/main/application.h +++ b/bk_aidk/projects/beken_wss_paopao/main/application.h @@ -15,7 +15,8 @@ extern "C" { typedef struct { //小智AI OTA URL地址 - uint8_t ota_url[128]; + char activation_code[32]; + char websocket_url[128]; uint32_t led_brightness; uint32_t led_timeout; uint32_t sleep_timeout; @@ -79,11 +80,25 @@ typedef enum ListeningMode { * 1.1.6 * 单独添加控制灯光开关接口 和设置亮度接口分开 * 解决调用BLE设置灯光常亮时异常问题 + * + * 1.2.0 + * 更新MCP控制协议 + * 添加电池校准 + * 修复没有播声音 修正音量调整失败 + * 添加自动激活设备 */ -#define APPLICATION_VERSION "1.1.9" +#define APPLICATION_VERSION "1.2.0" #define APPLICATION_DEFULT_OTA_URL "https://xiaozhi.xa-poka.com/xiaozhi/ota/" #define APPLICATION_CONFIG_KEY_AI_URL "ai_url" +#define APPLICATION_DEFULT_OTA_ADD_DEV_URL "https://xiaozhi.xa-poka.com/xiaozhi/device/manual-add" +#define APPLICATION_DEFULT_TOKEN "test-token" +#define APPLICATION_DEFULT_PROTOCOL_VERSION 2 +/** + * https://xiaozhi.xa-poka.com/xiaozhi/device/bind/20fea9573bf54b69b685395f6b67ae72 + * 这个是默认的宝嘉小智平台默认 小宝的 AI Agent ID,如果用户没有设置,使用这个ID +*/ +#define APPLICATION_DEFULT_AI_AGENT_ID "20fea9573bf54b69b685395f6b67ae72" /** *开灯超时关闭 单位分钟 10 - 表示开灯10分钟后关闭 */ @@ -101,10 +116,14 @@ typedef enum ListeningMode { */ #define APPLICATION_IOT_PROTOCOL_MCP 1 -#define APPLICATION_DEVICE_BOARD_NAME "Poka" -void app_set_ota_url(char * ota_url); -char* app_get_ota_url(); +#define APPLICATION_DEVICE_BOARD_NAME "bread-compact-wifi-ir58" +#define APPLICATION_DEVICE_BOARD_TYPE "bread-compact-wifi" +app_config_t* app_get_config(); +void app_set_websocket_url(const char* url); + + +void app_ai_agent_start(); void app_start(); void app_set_device_state(DeviceState state); diff --git a/bk_aidk/projects/beken_wss_paopao/main/beken_sdk/beken_rtc.c b/bk_aidk/projects/beken_wss_paopao/main/beken_sdk/beken_rtc.c index d666c4ae..bd84d7c9 100755 --- a/bk_aidk/projects/beken_wss_paopao/main/beken_sdk/beken_rtc.c +++ b/bk_aidk/projects/beken_wss_paopao/main/beken_sdk/beken_rtc.c @@ -799,7 +799,7 @@ int rtc_websocket_send_text(transport web_socket, void *str, enum MsgType msgtyp BK_LOGE("WebSocket", "Invalid arguments\r\n"); return -1; } - BK_LOGE("WebSocket", "add extra str: %s\r\n", str ? "yes":"no need"); + //BK_LOGE("WebSocket", "add extra str: %s\r\n", str ? "yes":"no need"); char *buf = NULL; if (NULL == (buf = (char *)os_zalloc(BEKEN_RTC_TXT_SIZE))) { BK_LOGE("WebSocket", "alloc user context fail\r\n"); diff --git a/bk_aidk/projects/beken_wss_paopao/main/iot/iot_ota.c b/bk_aidk/projects/beken_wss_paopao/main/iot/iot_ota.c index 90fcb36c..c3d9ac08 100755 --- a/bk_aidk/projects/beken_wss_paopao/main/iot/iot_ota.c +++ b/bk_aidk/projects/beken_wss_paopao/main/iot/iot_ota.c @@ -15,6 +15,8 @@ //OTA #include "modules/ota.h" #include "spi_led.h" +#include "application.h" +#include #define TAG "ota" #define LOGI(...) BK_LOGI(TAG, ##__VA_ARGS__) @@ -28,12 +30,8 @@ #define POST_DATA_MAX_SIZE 1024 #define MAX_URL_LEN 256 -#define IOT_DEVICE_TYPE "bread-compact-wifi" #define IOT_OTA "ota" -#define IOT_OTA_VERSION "1.0.4" -//#define IOT_OTA_CHECK_URL "http://106.52.233.130:8888/ir58/ir58.json" -#define IOT_OTA_CHECK_VERSION_URL "https://xiaozhi.xa-poka.com/xiaozhi/ota/" /* static char activation_code[12]; @@ -180,7 +178,7 @@ int ota_check_version_resp_paser(char * text){ // 设备未激活 has_activation_code = 1; char *activation_code = cJSON_GetObjectItem(activation, "code")->valuestring; - BK_LOGE(TAG, "%s, activation code:%s\r\n", __func__, activation_code); + BK_LOGE(TAG, "ota activation code:%s\r\n", activation_code); } else { @@ -191,30 +189,92 @@ int ota_check_version_resp_paser(char * text){ cJSON *websocket = cJSON_GetObjectItem(json, "websocket"); if (cJSON_IsObject(websocket)) { char *websocket_url = cJSON_GetObjectItem(websocket, "url")->valuestring; - BK_LOGE(TAG, "%s, websocket_url:%s\r\n", __func__, websocket_url); + BK_LOGE(TAG, "ota websocket_url:%s\n", websocket_url); + //保存WS地址 + app_set_websocket_url(websocket_url); + BK_LOGE(TAG, "ota websocket_url:%s\n", app_get_config()->websocket_url); has_websocket_config = 1; } else { - //ESP_LOGI(TAG, "No websocket section found!"); + has_websocket_config = 0; } - + cJSON_Delete(json); return BK_OK; } +/** + * 手动实现随机UUID生成 + * 如果需要完全控制生成逻辑,可基于随机数生成符合RFC 4122的UUID v4 + */ +void generate_uuid_v4(char *uuid) { + srand(time(NULL)); + const char *hex = "0123456789abcdef"; + for (int i = 0; i < 36; i++) { + if (i == 8 || i == 13 || i == 18 || i == 23) { + uuid[i] = '-'; + } else { + uuid[i] = hex[rand() % 16]; + } + } + uuid[36] = '\0'; + // 设置版本位(第13字符为4) + uuid[14] = '4'; + // 设置变体位(第17字符为8、9、a或b) + uuid[19] = hex[8 + (rand() % 4)]; +} +static void memory_free_show(void) +{ + uint32_t total_size, free_size, mini_size; + + LOGE("%-5s %-5s %-5s %-5s %-5s\r\n", "name", "total", "free", "minimum", "peak"); + + total_size = rtos_get_total_heap_size(); + free_size = rtos_get_free_heap_size(); + mini_size = rtos_get_minimum_free_heap_size(); + LOGE("heap:\t%d\t%d\t%d\t%d\r\n", total_size, free_size, mini_size, total_size - mini_size); + +#if CONFIG_PSRAM_AS_SYS_MEMORY + total_size = rtos_get_psram_total_heap_size(); + free_size = rtos_get_psram_free_heap_size(); + mini_size = rtos_get_psram_minimum_free_heap_size(); + LOGE("psram:\t%d\t%d\t%d\t%d\r\n", total_size, free_size, mini_size, total_size - mini_size); +#endif +} /** * Specification: https://ccnphfhqs21z.feishu.cn/wiki/FjW6wZmisimNBBkov6OcmfvknVd * 根据小智的协议 联网成功后 通过OTA 检测设备是否在平台上激活 * 如果没有激活则返回验证码,然后登录小程序或者平台进行输入验证码添加设备 * * 如果激活了 返回websocket 通讯地址直接进行连接平台 - */ -int ota_check_version(){ - BK_LOGE(TAG, "Current version: %s", IOT_OTA_VERSION); + * + * POST /xiaozhi/ota/ HTTP/1.1 + Host: api.tenclass.net + Content-Type: application/json + User-Agent: bread-compact-wifi-128x64/1.0.1 + Device-Id: 11:22:33:44:55:66 + Client-Id: 7b94d69a-9808-4c59-9c9b-704333b38aff - //test_ota(); + { + "application": { + "version": "1.0.1", + "elf_sha256": "c8a8ecb6d6fbcda682494d9675cd1ead240ecf38bdde75282a42365a0e396033" + }, + "board": { + "type": "bread-compact-wifi", + "name": "bread-compact-wifi-128x64", + "ssid": "卧室", + "rssi": -55, + "channel": 1, + "ip": "192.168.1.11", + "mac": "11:22:33:44:55:66" + } + } + */ +int ota_check_version(char* ota_url){ + LOGE("ota_check_version %s\n", ota_url); //int ret = 0; struct webclient_session* session = NULL; unsigned char *buffer = NULL; @@ -222,7 +282,7 @@ int ota_check_version(){ int bytes_read, resp_status; //int content_length = -1; char *url = NULL; - url = web_strdup(IOT_OTA_CHECK_VERSION_URL); + url = web_strdup(ota_url); if(url == NULL) { BK_LOGE(TAG,"no memory for create get request uri buffer.\n"); @@ -246,9 +306,18 @@ int ota_check_version(){ /*Generate https header*/ webclient_header_fields_add(session, "Content-Type: application/json\r\n"); - webclient_header_fields_add(session, "User-Agent: bread-compact-wifi/1.0.1\r\n"); - + //User-Agent + char str_user_agent[128]={0}; + sprintf(str_user_agent,"User-Agent: %s/%s""\r\n",APPLICATION_DEVICE_BOARD_NAME,APPLICATION_VERSION); + webclient_header_fields_add(session, str_user_agent); + //Client-Id + char uuid[37]; + generate_uuid_v4(uuid); + char str_client_id[128]={0}; + sprintf(str_client_id,"Client-Id: %s\r\n",uuid); + webclient_header_fields_add(session, str_client_id); + //获取设备MAC uint8_t base_mac[BK_MAC_ADDR_LEN] = {0}; bk_get_mac(base_mac, MAC_TYPE_BASE); char device_id[64]; @@ -257,32 +326,29 @@ int ota_check_version(){ //webclient_header_fields_add(session, "Device-Id: 11:22:33:44:55:66\r\n"); webclient_header_fields_add(session, device_id); - - cJSON *ota_desc = cJSON_CreateObject(); - char mac_address[24]; - os_memset(mac_address,0,sizeof(device_id)); + os_memset(mac_address,0,sizeof(mac_address)); sprintf(mac_address, "%02X:%02X:%02X:%02X:%02X:%02X", base_mac[0], base_mac[1], base_mac[2], base_mac[3], base_mac[4], base_mac[5]); //cJSON_AddStringToObject(ota_desc, "mac_address", "11:22:33:44:55:66"); cJSON_AddStringToObject(ota_desc, "mac_address", mac_address); - cJSON_AddStringToObject(ota_desc, "chip_model_name", "BK7258"); + //cJSON_AddStringToObject(ota_desc, "chip_model_name", "BK7258"); cJSON *application = cJSON_CreateObject(); - cJSON_AddStringToObject(application, "version", IOT_OTA_VERSION); - cJSON_AddStringToObject(application, "elf_sha256", "22986216df095587c42f8aeb06b239781c68ad8df80321e260556da7fcf5f522"); + cJSON_AddStringToObject(application, "version", APPLICATION_VERSION); + cJSON_AddStringToObject(application, "elf_sha256", "c8a8ecb6d6fbcda682494d9675cd1ead240ecf38bdde75282a42365a0e396033"); //添加application属性到ota_desc cJSON_AddItemToObjectCS(ota_desc,"application",application); cJSON *board = cJSON_CreateObject(); - cJSON_AddStringToObject(board, "type", IOT_DEVICE_TYPE); - cJSON_AddStringToObject(board, "name", "iR58_xxxx"); - cJSON_AddStringToObject(board, "ssid", "1603"); - cJSON_AddNumberToObject(board, "rssi", -50); - cJSON_AddNumberToObject(board, "channel", 1); - cJSON_AddStringToObject(board, "ip", ""); - cJSON_AddStringToObject(board, "mac", "11:22:33:44:55:66"); + cJSON_AddStringToObject(board, "type", APPLICATION_DEVICE_BOARD_TYPE); + cJSON_AddStringToObject(board, "name", APPLICATION_DEVICE_BOARD_NAME); + //cJSON_AddStringToObject(board, "ssid", "1603"); + //cJSON_AddNumberToObject(board, "rssi", -50); + //cJSON_AddNumberToObject(board, "channel", 1); + //cJSON_AddStringToObject(board, "ip", ""); + cJSON_AddStringToObject(board, "mac", mac_address); cJSON_AddItemToObjectCS(ota_desc,"board",board); char *json_data = cJSON_PrintUnformatted(ota_desc); @@ -300,20 +366,177 @@ int ota_check_version(){ webclient_header_fields_add(session, "Content-Length: %d\r\n", os_strlen(post_data)); - BK_LOGE(TAG, "data_len: %d", data_len ); - BK_LOGE(TAG, "strlen: %d", strlen(json_data) ); - BK_LOGE(TAG, "json_data: %s", json_data); + BK_LOGE(TAG, "data_len: %d\n", data_len ); + BK_LOGE(TAG, "strlen: %d\n", strlen(json_data) ); + BK_LOGE(TAG, "json_data: %s\n", json_data); /* send POST request by default header */ - if ((resp_status = webclient_post(session, IOT_OTA_CHECK_VERSION_URL, post_data, data_len)) != 200) + if ((resp_status = webclient_post(session, ota_url, post_data, data_len)) != 200) + { + BK_LOGE(TAG, "webclient POST request failed, response(%d) error.\n", resp_status); + if(post_data){ + free(post_data); + } + return BK_FAIL; + } + BK_LOGE(TAG, "webclient post response data: \n"); + memset(buffer,0,RCV_BUF_SIZE); + do + { + bytes_read = webclient_read(session, buffer, RCV_BUF_SIZE); + if (bytes_read <= 0) + { + break; + } + } while (1); + BK_LOGE(TAG, "bytes_read: %d\n", bytes_read); + BK_LOGE(TAG, "buffer %s\n", buffer); + //resp_status = bk_agora_ai_agent_start_rsp_parse(buffer); + ota_check_version_resp_paser((char *)buffer); + // 释放 JSON 字符串 + if (json_data) { + free(json_data); + } + + // 释放 JSON 对象 + if (ota_desc) { + cJSON_Delete(ota_desc); // 这会递归释放所有子对象,包括 application 和 board + } + if (session) + { + webclient_close(session); + } + + if(post_data){ + free(post_data); + } + + if (buffer) + { + web_free(buffer); + } + + if (url) + { + web_free(url); + } + return BK_OK; +__exit: + if (session) + { + webclient_close(session); + } + + if(post_data){ + free(post_data); + } + + if (buffer) + { + web_free(buffer); + } + + if (url) + { + web_free(url); + } + return BK_FAIL; +} + +/* +POST https://xiaozhi.xa-poka.com/xiaozhi/device/manual-add +{ + "agentId": "f78ec9dbeff24f01b328710d738d087e", + "board": "bread-compact-wifi", + "appVersion": "1.1.9", + "macAddress": "12:22:22:33:44:56" +} +]*/ +int ota_register_device(){ + struct webclient_session* session = NULL; + unsigned char *buffer = NULL; + char *post_data = NULL; + int bytes_read, resp_status; + //int content_length = -1; + char *url = NULL; + url = web_strdup(APPLICATION_DEFULT_OTA_ADD_DEV_URL); + if(url == NULL) + { + BK_LOGE(TAG,"no memory for create get request uri buffer.\n"); + return BK_FAIL; + } + + buffer = (unsigned char *) web_malloc(1024); + if (buffer == NULL) + { + BK_LOGE(TAG,"no memory for receive buffer.\n"); + goto __exit; + + } + + /* create webclient session and set header response size */ + session = webclient_session_create(1024); + if (session == NULL) + { + goto __exit; + } + + /*Generate https header*/ + webclient_header_fields_add(session, "Content-Type: application/json\r\n"); + //User-Agent + char str_user_agent[128]={0}; + sprintf(str_user_agent,"User-Agent: %s/%s""\r\n",APPLICATION_DEVICE_BOARD_NAME,APPLICATION_VERSION); + webclient_header_fields_add(session, str_user_agent); + //Client-Id + char uuid[37]; + generate_uuid_v4(uuid); + char str_client_id[128]={0}; + sprintf(str_client_id,"Client-Id: %s\r\n",uuid); + webclient_header_fields_add(session, str_client_id); + + + cJSON *dev_desc = cJSON_CreateObject(); + //获取设备MAC + uint8_t base_mac[BK_MAC_ADDR_LEN] = {0}; + bk_get_mac(base_mac, MAC_TYPE_BASE); + char mac_address[24]; + os_memset(mac_address,0,sizeof(mac_address)); + sprintf(mac_address, "%02X:%02X:%02X:%02X:%02X:%02X", base_mac[0], base_mac[1], base_mac[2], base_mac[3], base_mac[4], base_mac[5]); + + cJSON_AddStringToObject(dev_desc, "macAddress", mac_address); + cJSON_AddStringToObject(dev_desc, "board", APPLICATION_DEVICE_BOARD_TYPE); + cJSON_AddStringToObject(dev_desc, "appVersion", APPLICATION_VERSION); + cJSON_AddStringToObject(dev_desc, "agentId", APPLICATION_DEFULT_AI_AGENT_ID); + + char *json_data = cJSON_PrintUnformatted(dev_desc); + + /*Generate data*/ + post_data = os_malloc(POST_DATA_MAX_SIZE); + if (post_data == NULL) + { + BK_LOGE(TAG, "no memory for post_data buffer\n"); + goto __exit; + } + os_memset(post_data, 0, POST_DATA_MAX_SIZE); + int data_len = 0; + data_len += os_snprintf(post_data + data_len, POST_DATA_MAX_SIZE, json_data); + + webclient_header_fields_add(session, "Content-Length: %d\r\n", os_strlen(post_data)); + + //BK_LOGE(TAG, "data_len: %d\n", data_len ); + //BK_LOGE(TAG, "strlen: %d\n", strlen(json_data) ); + BK_LOGE(TAG, "send data: %s\n", json_data); + /* send POST request by default header */ + if ((resp_status = webclient_post(session, url, post_data, data_len)) != 200) { BK_LOGE(TAG, "webclient POST request failed, response(%d) error.\n", resp_status); return BK_FAIL; } BK_LOGE(TAG, "webclient post response data: \n"); + memset(buffer,0,RCV_BUF_SIZE); do { bytes_read = webclient_read(session, buffer, RCV_BUF_SIZE); - if (bytes_read > 0) + if (bytes_read <= 0) { break; } @@ -321,8 +544,34 @@ int ota_check_version(){ BK_LOGE(TAG, "bytes_read: %d\n", bytes_read); BK_LOGE(TAG, "buffer %s.\n", buffer); - //resp_status = bk_agora_ai_agent_start_rsp_parse(buffer); - ota_check_version_resp_paser((char *)buffer); + // 释放 JSON 字符串 + if (json_data) { + free(json_data); + } + + // 释放 JSON 对象 + if (dev_desc) { + cJSON_Delete(dev_desc); + } + if (session) + { + webclient_close(session); + } + + if(post_data){ + free(post_data); + } + + if (buffer) + { + web_free(buffer); + } + + if (url) + { + web_free(url); + } + return BK_OK; __exit: if (session) diff --git a/bk_aidk/projects/beken_wss_paopao/main/iot/iot_ota.h b/bk_aidk/projects/beken_wss_paopao/main/iot/iot_ota.h index aabc297e..a119cf28 100755 --- a/bk_aidk/projects/beken_wss_paopao/main/iot/iot_ota.h +++ b/bk_aidk/projects/beken_wss_paopao/main/iot/iot_ota.h @@ -14,16 +14,13 @@ extern "C" { #include "cJSON.h" -typedef struct -{ - uint8_t device_id[6]; - char activation_code[32]; - char websocket_url[128]; -} bk_genie_device_info_t; + -int ota_check_version(); +int ota_check_version(char* ota_url); int ota_has_activation_code(); int ota_has_websocket_config(); + +int ota_register_device(); #ifdef __cplusplus } diff --git a/bk_aidk/projects/beken_wss_paopao/main/iot/iot_speaker.c b/bk_aidk/projects/beken_wss_paopao/main/iot/iot_speaker.c index 869232ee..fbb8fba1 100755 --- a/bk_aidk/projects/beken_wss_paopao/main/iot/iot_speaker.c +++ b/bk_aidk/projects/beken_wss_paopao/main/iot/iot_speaker.c @@ -17,6 +17,7 @@ #include "beken_config.h" #include "aud_intf.h" #include "bk_factory_config.h" +#include "bk_ef.h" #if CONFIG_NETWORK_AUTO_RECONNECT #include "bk_genie_smart_config.h" #endif @@ -39,6 +40,8 @@ static uint32_t g_volume_gain[SPK_VOLUME_LEVEL] = {0, 0x21, 0x22, 0x23, 0x24, 0x void speaker_volume_init(void) { int volume_size = bk_config_read("volume", (void *)&volume, 4); + + BK_LOGE(TAG, "bk_config_read volume level:%d \n", volume); if (volume_size != 4) { BK_LOGE(TAG, "read volume config fail, use default config volume_size:%d\n", volume_size); @@ -50,13 +53,11 @@ void speaker_volume_init(void) { BK_LOGE(TAG, "storage volume: %d fail\n", volume); } - }else{ - volume = volume_size; - } + } //volume = 10; bk_aud_intf_set_spk_gain(g_volume_gain[volume]); // 0x30 - BK_LOGE(TAG, "g_volume_gain: %02X \n", g_volume_gain[volume]); + BK_LOGE(TAG, "volume level:%d g_volume_gain: %02X \n", volume, g_volume_gain[volume]); //bk_config_write("volume", (void *)&volume, 4); /* SPK_GAIN_MAX * [(exp(i/(SPK_VOLUME_LEVEL-1)-1)/(exp(1)-1)] */ @@ -140,12 +141,15 @@ void speaker_volume_set_abs(uint8_t level, uint8_t has_precision) { volume = level; - if (0 != bk_config_write("volume", (void *)&volume, sizeof(volume))) + if (0 != bk_config_write("volume", (void *)&volume, 4)) { BK_LOGE(TAG, "%s storage volume: %d fail\n", __func__, level); } - BK_LOGI(TAG, "%s current volume: %d\n", __func__, level); + ef_set_env_blob("volume", (void *)&volume, sizeof(volume)); + //bk_config_sync_flash_safely(); + BK_LOGE(TAG, "%s current volume: %d\n", __func__, level); + } else { diff --git a/bk_aidk/projects/beken_wss_paopao/main/mcp/mcp_server.c b/bk_aidk/projects/beken_wss_paopao/main/mcp/mcp_server.c index ca5b3448..469e0c79 100755 --- a/bk_aidk/projects/beken_wss_paopao/main/mcp/mcp_server.c +++ b/bk_aidk/projects/beken_wss_paopao/main/mcp/mcp_server.c @@ -700,7 +700,6 @@ void mcp_server_add_tool(McpServer* server, McpTool* tool) { void mcp_server_add_tool_with_params(McpServer* server, const char* name, const char* description, PropertyList* properties, McpToolCallback callback) { if (!server || !name || !description || !callback) return; - LOGE( "!!!!properties %d\n,",properties->count); McpTool* tool = mcp_tool_create(name, description, properties, callback); if (tool) { @@ -995,7 +994,6 @@ static void mcp_send_thread_task(void *arg) break; } transport bk_rtc_ws = beken_rtc->bk_rtc_client; - // bk_printf("!!!!!!!!!!!!!!!!\n"); if(bk_rtc_ws == NULL){\ break; } diff --git a/bk_aidk/projects/beken_wss_paopao/main/smart_config/bk_genie_smart_config.c b/bk_aidk/projects/beken_wss_paopao/main/smart_config/bk_genie_smart_config.c index 32d95ab1..b35469fc 100755 --- a/bk_aidk/projects/beken_wss_paopao/main/smart_config/bk_genie_smart_config.c +++ b/bk_aidk/projects/beken_wss_paopao/main/smart_config/bk_genie_smart_config.c @@ -689,7 +689,6 @@ static int bk_genie_sconf_netif_event_cb(void *arg, event_module_t event_module, { case EVENT_NETIF_GOT_IP4: // helloyifa - BK_LOGE(TAG, "!!!!!!!!!!!!!!!!!!!!!!!\n"); result = rtos_init_timer(&led_wifi_connected_timer, 5000, led_wifi_connected, diff --git a/bk_aidk/projects/beken_wss_paopao/main/websocket_rtc_demo.c b/bk_aidk/projects/beken_wss_paopao/main/websocket_rtc_demo.c index cc007a23..9a8d7d78 100755 --- a/bk_aidk/projects/beken_wss_paopao/main/websocket_rtc_demo.c +++ b/bk_aidk/projects/beken_wss_paopao/main/websocket_rtc_demo.c @@ -651,40 +651,34 @@ static void poka_aud_tras_main(void) bk_err_t ret = BK_OK; while (1) { + //LOGE("poka_aud_tras_main !!!\n"); + if(!poka_aud_msg_que){ + break; + } poka_audio_msg_t msg; ret = rtos_pop_from_queue(&poka_aud_msg_que, &msg, BEKEN_WAIT_FOREVER); if (kNoErr == ret) { if (msg.opus_addr != NULL && msg.opus_len > 0) { - // LOGE("msg = %02x %02x len = %d \n",msg.opus_addr[0],msg.opus_addr[1],msg.opus_len); ret = bk_aud_intf_write_spk_data((uint8_t *)msg.opus_addr, msg.opus_len); - rtos_delay_milliseconds(60); - - // LOGE("rv opus len: %d \r\n", msg.opus_len); - // int32_t decoder_len = opus_decode(dec, msg.opus_addr, msg.opus_len, (int16_t *)pcm_out2, 960, 0); psram_free(msg.opus_addr); - // LOGE("decoder_len: %d \r\n", decoder_len); - // ret = bk_aud_intf_write_spk_data((uint8_t )pcm_out2, (uint32_t)decoder_len); } else { LOGE("opus_addr == null\n"); } + }else{ + LOGE("rtos_pop_from_queue == null\n"); + break; } } - /*delete msg queue */ - ret = rtos_deinit_queue(&poka_aud_msg_que); - if (ret != kNoErr) - { - LOGE("delete message queue fail\n"); - } - poka_aud_msg_que = NULL; + /* delete task */ poka_aud_thread_hdl = NULL; - LOGI("delete agora audio transfer task\n"); + LOGE("exit poka_aud_tras_main task\n"); // rtos_set_semaphore(&agora_aud_sem); rtos_delete_thread(NULL); } @@ -853,7 +847,7 @@ void rtc_websocket_event_handler(void *event_handler_arg, char *event_base, int3 break; case WEBSOCKET_EVENT_DATA: - LOGD("data from WebSocket server, len:%d op:%d\r\n", data->data_len, data->op_code); + //LOGE("data from WebSocket server, len:%d op:%d\r\n", data->data_len, data->op_code); if (data->op_code == WS_TRANSPORT_OPCODES_BINARY) { #if CONFIG_USE_G722_CODEC @@ -861,7 +855,7 @@ void rtc_websocket_event_handler(void *event_handler_arg, char *event_base, int3 #elif CONFIG_USE_OPUS_CODEC binary_data_status = 0; // 状态置为0,表示正在接收数据 last_binary_data_ms = bk_aon_rtc_get_ms(); // 记录当前毫秒数 - //poka_audio_receive_data_opus(__get_beken_rtc(), (uint8_t *)data->data_ptr, data->data_len); + poka_audio_receive_data_opus(__get_beken_rtc(), (uint8_t *)data->data_ptr, data->data_len); // rtc_websocket_audio_receive_data_opus(__get_beken_rtc(), (uint8_t *)data->data_ptr, data->data_len); #else #endif @@ -885,15 +879,24 @@ void beken_rtc_main(void) // websocket_cfg.uri = "wss://ai.aclsemi.com:9015/xiaozhi/v1/"; uint8_t base_mac[BK_MAC_ADDR_LEN] = {0}; bk_get_mac(base_mac, MAC_TYPE_BASE); - char headers[64] = {0}; + char headers[128] = {0}; memset(headers, 0, sizeof(headers)); - sprintf(headers, "Device-Id: %02X:%02X:%02X:%02X:%02X:%02X\r\n", base_mac[0], base_mac[1], base_mac[2], base_mac[3], base_mac[4], base_mac[5]); + //sprintf(headers, "Device-Id: %02X:%02X:%02X:%02X:%02X:%02X\r\n", base_mac[0], base_mac[1], base_mac[2], base_mac[3], base_mac[4], base_mac[5]); + sprintf(headers, "Device-Id: %02X:%02X:%02X:%02X:%02X:%02X\r\nAuthorization: Bearer %s\r\nProtocol-Version: %d\r\n", base_mac[0], base_mac[1], base_mac[2], base_mac[3], base_mac[4], base_mac[5], + APPLICATION_DEFULT_TOKEN,APPLICATION_DEFULT_PROTOCOL_VERSION); - bk_printf("headers = %s\r\n", headers); + //bk_printf("headers = %s\r\n", headers); + LOGE("application ws url:%s \r\n",app_get_config()->websocket_url); + //websocket_cfg.uri = app_get_config()->ws_url; websocket_cfg.headers = headers; - websocket_cfg.uri = "wss://xiaozhi.xa-poka.com/websocket/xiaozhi/v1/"; - // websocket_cfg.uri = "ws://43.139.216.160:8000/xiaozhi/v1/"; + if(strlen(app_get_config()->websocket_url)>0){ + websocket_cfg.uri = app_get_config()->websocket_url; + }else{ + websocket_cfg.uri = APPLICATION_DEFULT_OTA_URL; + } + //websocket_cfg.uri = "wss://xiaozhi.xa-poka.com/websocket/xiaozhi/v1/"; + // websocket_cfg.uri = "wss://api.tenclass.net/xiaozhi/v1/"; websocket_cfg.ws_event_handler = rtc_websocket_event_handler; rtc_session *rtc_session = rtc_websocket_create(&websocket_cfg, rtc_user_audio_rx_data_handle, &audio_info); if (rtc_session == NULL) @@ -978,12 +981,16 @@ bk_err_t beken_rtc_stop(void) rtos_deinit_semaphore(&rtc_sem); rtc_sem = NULL; + /*delete msg queue */ + rtos_deinit_queue(&poka_aud_msg_que); + + poka_aud_msg_que = NULL; + LOGE("beken_rtc_stop\r\n"); return BK_OK; } -static bk_err_t beken_rtc_start(void) +bk_err_t beken_rtc_start(void) { - bk_printf("beken_rtc_start2222~~~\n"); bk_err_t ret = BK_OK; if (rtc_runing) @@ -1009,7 +1016,7 @@ static bk_err_t beken_rtc_start(void) goto fail; } LOGI("create agoar audio tras message queue complete\n"); - /* create task to asr */ + ret = rtos_create_thread(&poka_aud_thread_hdl, 4, "poka_aud_thread_hdl", @@ -1020,7 +1027,7 @@ static bk_err_t beken_rtc_start(void) { LOGE("create poka_aud_thread task fail\n"); } - // helloyifa end + ret = rtos_create_thread(&rtc_thread_hdl, 4, "beken_rtc", @@ -1071,8 +1078,8 @@ void beken_auto_run(void) } */ //bk_https_ota_download("https://xiaozhi.xa-poka.com/xiaozhi/otaMag/download/59cc091e-eaf3-417d-a524-d5e3d95883f4"); - - beken_rtc_start(); + app_ai_agent_start(); + //beken_rtc_start(); } }