add softap provision

This commit is contained in:
shchen 2021-04-19 11:04:43 +08:00
parent 6c02d7cfeb
commit 493201cbc0
44 changed files with 3638 additions and 799 deletions

View File

@ -1,204 +0,0 @@
==========
准备
==========
1. 硬件BL602模块一个Windows PC一台装有配网app的安卓手机一台USB转串口线一根。
2. 软件烧写工具烧录的sdk_app_ble_sync.bin文件路径Bouffalolab_BL602_Evaluation_Package/App_Demos/sdk_app_ble_sync/build_out/sdk_app_ble_sync.bin串口工具putty。(\ `下载链接 <https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html>`__\)
.. figure:: picture/image1.png
:align: center
Putty下载
===========
烧录
===========
连接
======
BL602模块的相关引脚连接如下图所示其中图1是模块的正面图其标号1处用跳线帽短接标号2处将左边两根排针短接标号3处将上面的两根排针短接图2是模块的背面图烧录时将IO8和HI两根排针短接烧录完成后将IO8和LOW两根排针短接并重新上电。用USB转串口线连接PC和模块此时模块上的电源灯常亮表明模块通电正常。
.. figure:: picture/image2.png
:align: center
正面
.. figure:: picture/image3.png
:align: center
背面
软件下载
============
打开烧写工具Bouffalo Lab Dev Cube 中的BLFlashEnv.exechip type选择BL602/604打开后界面参数参考下图配置
.. figure:: picture/image4.png
:align: center
烧写工具界面
.. figure:: picture/image5.png
:align: center
烧写成功
其中图3的左框中COM Port选项根据实际串口情况选择右击我的电脑->管理->设备管理器->端口查看端口号模块是双串口选择端口号较小的右框中的相关路径依据实际情况选择。配置完成后点击Download按钮下载下载成功如图4所示。
putty配置
=============
将IO8和LOW两根排针短接并重新上电打开putty工具设置对应的端口号波特率设定为2000000 bps。
.. figure:: picture/image6.png
:align: center
Putty
==============
App配网步骤
==============
1. 在putty中输入“reboot”命令重启模块模块上电后会自动开启ble广播等待手机APP连接配网串口打印如下所示
.. figure:: picture/image7.png
:align: center
开启ble广播log
2. 打开配网APPAPP自动搜索蓝牙设备需手机蓝牙已开启)搜索到设备名“BL602-BLE-DEV”
.. figure:: picture/image8.png
:align: center
手机搜索到的蓝牙设备
3. 点击该设备名然后点击APP中的“连接”APP会显示连接模块蓝牙的状态串口中会打印设备连接成功的log
.. figure:: picture/image9.png
:align: center
APP显示的蓝牙状态
.. figure:: picture/image10.png
:align: center
蓝牙连接成功log
4. 点击“扫描”等待数秒后APP会显示模块扫描到的WiFi设备列表用户可以通过扫描出来的设备列表选择相应的WiFi进行连接连接成功后页面红色字体部分为模块的WiFi相关信息此状态暂时不会自动更新需要用户点击“状态”选项手动更新)。用户可以点击“断开wifi”选项使模块断开WiFi连接。
.. figure:: picture/image11.png
:align: center
APP显示模块扫描到的WiFi列表
.. figure:: picture/image12.png
:align: center
模块扫描的WiFi列表log
.. figure:: picture/image13.png
:align: center
连接WiFi
.. figure:: picture/image14.png
:align: center
模块成功连接WiFi的log
.. figure:: picture/image15.png
:align: center
APP显示WiFi连接成功通过点击“状态”更新后模块的WiFi信息)
.. figure:: picture/image16.png
:align: center
断开WiFi连接
.. figure:: picture/image17.png
:align: center
模块断开WiFi连接log
5. 当用户确定配网完成时不需要再使用配网功能可以使用“blsync_ble_stop”命令将其关闭如需重新配网请重复步骤1-5。
.. figure:: picture/image18.png
:align: center
关闭BLE
========================
微信小程序配网步骤
========================
1. 在putty中输入“reboot”命令重启模块模块上电运行会自动开启ble广播串口打印如下所示
.. figure:: picture/image19.png
:align: center
开启ble广播log
2. 打开微信扫描下图二维码,点击“搜索”(需手机蓝牙已开启)搜索到设备名“BL602-BLE-DEV”点击“BL602-BLE-DEV”连接设备连接成功后界面上出现操作WiFi相关的功能
.. figure:: picture/image20.png
:align: center
配网二维码
.. figure:: picture/image21.png
:align: center
搜到的设备
.. figure:: picture/image22.png
:align: center
连接设备成功
.. figure:: picture/image23.png
:align: center
蓝牙连接成功log
3. 点击小程序中的“获取WiFi列表”小程序会回显获取到的WiFi列表用户可以通过扫描出来的设备列表对需要配网的WiFi进行连接点击需要连接的WiFi名称接着在输入框输入WiFi密码点击“发送密码”即可连接WiFi
.. figure:: picture/image24.png
:align: center
模块扫描到的WiFi列表
.. figure:: picture/image25.png
:align: center
连接WiFi成功
.. figure:: picture/image26.png
:align: center
模块成功连接WiFi的log
4. 点击小程序中的“更新WiFi状态”按钮获取WiFi当前的连接状态
.. figure:: picture/image27.png
:align: center
更新WiFi连接状态
5. 点击断开WiFi按钮即可断开WiFi再次点击”获取状态“按钮可以获取当前WiFi已经断开
.. figure:: picture/image28.png
:align: center
断开WiFi
.. figure:: picture/image29.png
:align: center
模块断开WiFi连接log
6. 当用户确定配网完成时不需要再使用配网功能可以使用“blsync_ble_stop”命令将其关闭如需重新配网请重复步骤1-6。
.. figure:: picture/image30.png
:align: center
关闭BLE

View File

@ -23,7 +23,7 @@ COMPONENTS_BLSYS := bltime blfdt blmtd blota bloop loopadc looprt loopset
COMPONENTS_VFS := romfs
COMPONENTS_BLE := blecontroller blestack
INCLUDE_COMPONENTS += freertos_riscv_ram bl602 bl602_std bl602_wifi bl602_wifidrv hal_drv lwip lwip_dhcpd mbedtls vfs yloop utils cli httpc netutils blog blog_testc blsync_ble cjson qcloud_iot_c_sdk
INCLUDE_COMPONENTS += freertos_riscv_ram bl602 bl602_std bl602_wifi bl602_wifidrv hal_drv lwip lwip_dhcpd mbedtls vfs yloop utils cli httpc netutils blog blog_testc cjson qcloud_iot_c_sdk
INCLUDE_COMPONENTS += easyflash4
INCLUDE_COMPONENTS += $(COMPONENTS_NETWORK)
INCLUDE_COMPONENTS += $(COMPONENTS_BLSYS)

View File

@ -2,11 +2,11 @@
1.设备配网
如何使用此例程请参考目录下的[用户手册](BLE_Use_ Manual.pdf)进行BLE配网或者使用wifi_sta_connect的命令行配置
目前仅仅支持SoftAp模式配网
2.腾讯云平台接入
此demo已经完成了腾讯云平台的接入用户只需要修改腾讯三元组即可配置好在配网之后发送tencent命令即可运行
此demo已经完成了腾讯云平台的接入用户只需要修改腾讯三元组即可配置好在配网之后会自动运行,在云端和腾讯连连上可以看到设备上报信息
sg_product_id : product Id
@ -14,17 +14,3 @@ sg_device_name : device name
sg_product_secret : product secret for device dynamic Registration
这三个信息可以在云平台的设备信息里面查到:
![deviceinfo](deviceinfo.jpg)
如何构建一个产品和具体上报信息json适配可以参考腾讯云平台的接入文档
腾讯云官方文档:[腾讯云]https://cloud.tencent.com/document/product/1081/44921
此工程的使用的Sensor芯片为北京中科银河芯科技的GXHT3X Humidity and Temperature Sensor。
北京中科银河芯科技有限公司是依托中国科学院微电子研究所雄厚的人才和科研技术资源成立的技术创新驱动型企业公司面向汽车电子、智能制造、物联网、工业领域、消费电子领域的产业需求致力于温度、湿度、水分、压力、电子标签等传感芯片设计、开发、销售并提供相关技术咨询和技术服务。如需了解更多请访问http://gxcas.com/

View File

@ -18,6 +18,17 @@ COMPONENT_SRCS := platform/HAL_Device_freertos.c \
platform/HAL_Timer_freertos.c \
platform/HAL_TLS_mbedtls.c \
platform/HAL_UDP_lwip.c \
platform/HAL_Airkiss.c \
platform/HAL_BTCombo_config.c \
platform/HAL_Wifi_api.c \
platform/HAL_Soft_ap.c \
platform/HAL_Smart_config.c \
platform/HAL_Simple_config.c \
sdk_src/qcloud_wifi_config.c \
sdk_src/qcloud_wifi_config_comm_service.c \
sdk_src/qcloud_wifi_config_device_bind.c \
sdk_src/qcloud_wifi_config_error_handle.c \
sdk_src/qcloud_wifi_config_log_handle.c \
sdk_src/asr_client.c \
sdk_src/data_template_action.c \
sdk_src/data_template_client.c \

View File

@ -21,3 +21,4 @@
/* #undef GATEWAY_DYN_BIND_SUBDEV_ENABLED */
#define ASR_ENABLED
#define RESOURCE_UPDATE_ENABLED
#define WIFI_CONFIG_ENABLED

View File

@ -25,7 +25,7 @@
extern "C" {
#endif
#define PATH_MAX 1024
#define PATH_MAX 4096
/* Max size of cert/key file full path */
#define FILE_PATH_MAX_LEN 256

View File

@ -141,6 +141,42 @@ int HAL_MutexTryLock(_IN_ void *mutex);
*/
void HAL_MutexUnlock(_IN_ void *mutex);
#ifdef WIFI_CONFIG_ENABLED
/**
* @brief create queue
* @param queue_length queue length
* @param queue_item_size queue item size
*
* @return NULL or queue handle
*/
void *HAL_QueueCreate(unsigned long queue_length, unsigned long queue_item_size);
/**
* @brief destory queue
* @param queue_handle
*
* @return void
*/
void HAL_QueueDestory(void *queue_handle);
/**
* @brief destory queue
* @param queue_handle
*
* @return 0 is success other failue
*/
uint32_t HAL_QueueReset(void *queue_handle);
/**
* @brief get queue item count
* @param queue_handle
*
* @return 0 is success other failue
*/
unsigned long HAL_QueueItemWaitingCount(void *queue_handle);
unsigned long HAL_QueueItemPop(void *queue_handle, void *const item_buffer, uint32_t wait_timeout);
unsigned long HAL_QueueItemPush(void *queue_handle, void *const item_buffer, uint32_t wait_timeout);
#endif // WIFI_CONFIG_ENABLED
/**
* @brief Malloc memory
*
@ -552,6 +588,17 @@ int HAL_UDP_Read(uintptr_t fd, unsigned char *data, unsigned int len);
int HAL_UDP_ReadTimeout(uintptr_t fd, unsigned char *p_data, unsigned int datalen, unsigned int timeout_ms);
#endif // COAP_COMM_ENABLED
#ifdef WIFI_CONFIG_ENABLED
int HAL_UDP_CreateBind(const char *host, unsigned short port);
int HAL_UDP_WriteTo(uintptr_t fd, const unsigned char *p_data, unsigned int datalen, char *host, unsigned short port);
void HAL_UDP_Close(uintptr_t fd);
char *HAL_UDP_GetErrnoStr();
int HAL_UDP_GetErrno();
int HAL_UDP_ReadTimeoutPeerInfo(uintptr_t fd, unsigned char *p_data, unsigned int datalen, unsigned int timeout_ms,
char *recv_ip_addr, unsigned char recv_addr_len, unsigned short *recv_port);
#endif // WIFI_CONFIG_ENABLED
#ifdef LOG_UPLOAD
/* Functions for saving/reading logs into/from NVS(files/FLASH) after log upload
* fail/recover */

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) 2020 Tencent Cloud. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "qcloud_iot_import.h"
#include "qcloud_iot_export.h"
#include "qutils_timer.h"
#include "qcloud_wifi_config.h"
#include "qcloud_wifi_config_internal.h"
#if WIFI_PROV_AIRKISS_CONFIG_ENABLE
static bool sg_airkiss_start = false; // airkiss config start flag
static eWiFiConfigState ap_connect_state = WIFI_CONFIG_ING;
void set_airkiss_config_state(eWiFiConfigState state)
{
ap_connect_state = state;
}
static eWiFiConfigState get_airkiss_config_state(void)
{
return ap_connect_state;
}
// loop check connect ap result
static void airkiss_task(void *params)
{
uint32_t time_count = WIFI_CONFIG_WAIT_TIME_MS / WIFI_CONFIG_BLINK_TIME_MS;
WifiConfigEventCallBack wifi_config_event_cb = (WifiConfigEventCallBack)params;
while ((true == sg_airkiss_start) && (--time_count)) {
// check airkiss config result, call set_airkiss_config_state set result
if (WIFI_CONFIG_SUCCESS == get_airkiss_config_state() && true == HAL_Wifi_IsConnected()) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_SUCCESS, NULL);
break;
} else if (WIFI_CONFIG_FAIL == get_airkiss_config_state()) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_FAILED, NULL);
break;
}
HAL_SleepMs(WIFI_CONFIG_BLINK_TIME_MS);
if (time_count % 10 == 0) {
Log_d("airkiss_task running!");
}
}
Log_d("task end connect_success :%d, task_run :%d, time_count:%d", get_airkiss_config_state(), sg_airkiss_start,
time_count);
if (0 == time_count) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_TIMEOUT, NULL);
}
HAL_AirkissConfig_Stop();
}
static int _airkiss_task_start(void *params)
{
static ThreadParams thread_params;
thread_params.thread_func = airkiss_task;
thread_params.thread_name = "airkiss_task";
thread_params.stack_size = 8192;
thread_params.priority = 3;
thread_params.user_arg = params;
int ret = HAL_ThreadCreate(&thread_params);
if (QCLOUD_RET_SUCCESS != ret) {
Log_e("HAL_ThreadCreate(airkiss_task) failed!");
return -1;
}
return 0;
}
int start_device_airkiss(void)
{
return QCLOUD_RET_SUCCESS;
}
int stop_device_airkiss(void)
{
return QCLOUD_RET_SUCCESS;
}
#endif
/**
* @brief Start airkiss
*
* @param params is NULL
* @event_cb wifi config event callback, success to bind device
*
* @return 0 when success, or err code for failure
*/
int HAL_AirkissConfig_Start(void *params, WifiConfigEventCallBack event_cb)
{
int ret = QCLOUD_RET_SUCCESS;
#if WIFI_PROV_AIRKISS_CONFIG_ENABLE
// TO-DO device platform start airkiss
ret = start_device_airkiss();
if (QCLOUD_RET_SUCCESS != ret) {
Log_e("start airkiss config failed! ret:%d", ret);
return ret;
}
sg_airkiss_start = true;
set_airkiss_config_state(WIFI_CONFIG_ING);
ret = _airkiss_task_start(event_cb);
if (QCLOUD_RET_SUCCESS != ret) {
HAL_AirkissConfig_Stop();
}
#endif
return ret;
}
/**
* @brief Stop WiFi config and device binding process
*/
int HAL_AirkissConfig_Stop(void)
{
int ret = QCLOUD_RET_SUCCESS;
#if WIFI_PROV_AIRKISS_CONFIG_ENABLE
set_airkiss_config_state(WIFI_CONFIG_ING);
if (true == sg_airkiss_start) {
Log_i("HAL_AirkissConfig_Stop");
sg_airkiss_start = false;
// TO-DO device platform stop airkiss
ret = stop_device_airkiss();
}
#endif
return ret;
}

View File

@ -0,0 +1,192 @@
/*
* Copyright (c) 2020 Tencent Cloud. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "qcloud_iot_export.h"
#include "qutils_timer.h"
#include "qcloud_wifi_config.h"
#include "qcloud_wifi_config_internal.h"
#if WIFI_PROV_BT_COMBO_CONFIG_ENABLE
static bool sg_bt_combo_config_start = false;
static eWiFiConfigState ap_connect_state = WIFI_CONFIG_ING;
void set_bt_combo_config_state(eWiFiConfigState state)
{
ap_connect_state = state;
}
static eWiFiConfigState get_bt_combo_config_state(void)
{
return ap_connect_state;
}
static int bt_combo_send_message(char *buff, int buff_len)
{
// TO-DO
return QCLOUD_RET_SUCCESS;
}
static void bt_combo_report_wificonn_success()
{
// TO-DO subtype 0x04
}
static int bt_combo_report_bind_result(int token_status)
{
int ret = QCLOUD_ERR_FAILURE;
char json_str[256] = {0};
DeviceInfo devinfo;
ret = HAL_GetDevInfo(&devinfo);
if (ret != QCLOUD_RET_SUCCESS) {
Log_e("load dev info failed: %d", ret);
return -1;
}
HAL_Snprintf(json_str, sizeof(json_str), "{\"status\":%d,\"productID\":\"%s\",\"deviceName\":\"%s\"}\r\n",
token_status, devinfo.product_id, devinfo.device_name);
// TO-DO BLE Send json_str to wechat applet subtype 0x05
bt_combo_send_message(json_str, strlen(json_str));
return ret;
}
static void bt_combo_config_task(void *params)
{
WifiConfigEventCallBack wifi_config_event_cb = params;
int bind_reply_code = 0;
uint32_t time_count = WIFI_CONFIG_WAIT_TIME_MS / WIFI_CONFIG_BLINK_TIME_MS;
while ((true == sg_bt_combo_config_start) && (--time_count)) {
// check bt combo config result, call set_bt_combo_apconn_state set result
// call set_bt_combo_token_state set token is getted
if ((WIFI_CONFIG_SUCCESS == get_bt_combo_config_state()) && (true == HAL_Wifi_IsConnected())) {
bt_combo_report_wificonn_success();
wifi_config_event_cb(EVENT_WIFI_CONFIG_SUCCESS, NULL);
if (true == qiot_device_bind_get_cloud_reply_code(&bind_reply_code)) {
bt_combo_report_bind_result(bind_reply_code);
}
break;
} else if (WIFI_CONFIG_FAIL == get_bt_combo_config_state()) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_FAILED, NULL);
break;
}
HAL_SleepMs(WIFI_CONFIG_BLINK_TIME_MS);
if (time_count % 10 == 0) {
Log_d("bt combo task running!");
}
}
Log_d("task end connect_success :%d, task_run :%d", get_bt_combo_config_state(), sg_bt_combo_config_start);
if (0 == time_count) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_TIMEOUT, NULL);
}
HAL_BTComboConfig_Stop();
}
int _bt_combo_config_task_start(void *params)
{
static ThreadParams thread_params;
thread_params.thread_func = bt_combo_config_task;
thread_params.thread_name = "bt_combo_config_task";
thread_params.stack_size = 8192;
thread_params.priority = 3;
thread_params.user_arg = params;
int ret = HAL_ThreadCreate(&thread_params);
if (QCLOUD_RET_SUCCESS != ret) {
Log_e("HAL_ThreadCreate(_bt_combo_config_task_start) failed!");
return -1;
}
return 0;
}
int start_device_btcomboconfig(void)
{
// TO-DO
return QCLOUD_RET_SUCCESS;
}
int stop_device_btcomboconfig(void)
{
// TO-DO
return QCLOUD_RET_SUCCESS;
}
#endif
/**
* @brief Start bt combo config
*
* @param params is null
*
* @return 0 when success, or err code for failure
*/
int HAL_BTComboConfig_Start(void *params, WifiConfigEventCallBack event_cb)
{
int ret = QCLOUD_RET_SUCCESS;
#if WIFI_PROV_BT_COMBO_CONFIG_ENABLE
set_bt_combo_config_state(WIFI_CONFIG_ING);
// TO-DO device platform start bt combo config
ret = start_device_btcomboconfig();
if (QCLOUD_RET_SUCCESS != ret) {
Log_e("start bt combo config failed! ret:%d", ret);
return ret;
}
sg_bt_combo_config_start = true;
ret = _bt_combo_config_task_start(event_cb);
if (QCLOUD_RET_SUCCESS != ret) {
HAL_BTComboConfig_Stop();
}
#endif
return ret;
}
/**
* @brief Stop WiFi config and device binding process
*/
int HAL_BTComboConfig_Stop(void)
{
int ret = QCLOUD_RET_SUCCESS;
#if WIFI_PROV_BT_COMBO_CONFIG_ENABLE
set_bt_combo_config_state(WIFI_CONFIG_ING);
if (sg_bt_combo_config_start) {
Log_i("HAL_BTComboConfig_Stop");
sg_bt_combo_config_start = false;
// TO-DO device platform stop bt combo config
ret = stop_device_btcomboconfig();
}
#endif
return ret;
}

View File

@ -35,17 +35,17 @@
#ifdef DEBUG_DEV_INFO_USED
/* product Id */
static char sg_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "US0JEK629P"; //shchen
static char sg_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "FJD7FK7ESY"; //shchen
/* device name */
static char sg_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "BL602";
static char sg_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "BL602_LIGHT";
/* region */
static char sg_region[MAX_SIZE_OF_REGION + 1] = "china";
#ifdef DEV_DYN_REG_ENABLED
/* product secret for device dynamic Registration */
static char sg_product_secret[MAX_SIZE_OF_PRODUCT_SECRET + 1] = "yggBSwXfvg6zrxf+VU9+vQ==";
static char sg_product_secret[MAX_SIZE_OF_PRODUCT_SECRET + 1] = "FV/wUl3M5yEOudHTtsQlEg==";
#endif
@ -56,7 +56,7 @@ static char sg_device_cert_file_name[MAX_SIZE_OF_DEVICE_CERT_FILE_NAME + 1] = "Y
static char sg_device_privatekey_file_name[MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME + 1] = "YOUR_DEVICE_NAME_private.key";
#else
/* device secret of PSK device */
static char sg_device_secret[MAX_SIZE_OF_DEVICE_SECRET + 1] = "yggBSwXfvg6zrxf+VU9+vQ==";
static char sg_device_secret[MAX_SIZE_OF_DEVICE_SECRET + 1] = "FV/wUl3M5yEOudHTtsQlEg==";
#endif
#ifdef GATEWAY_ENABLED

View File

@ -36,6 +36,61 @@
#endif
// TODO platform dependant
#ifdef WIFI_CONFIG_ENABLED
void *HAL_QueueCreate(unsigned long queue_length, unsigned long queue_item_size)
{
QueueHandle_t queue_handle = NULL;
queue_handle = xQueueCreate(queue_length, queue_item_size);
if (NULL == queue_handle) {
return NULL;
} else {
return (void *)queue_handle;
}
}
void HAL_QueueDestory(void *queue_handle)
{
vQueueDelete(queue_handle);
}
uint32_t HAL_QueueReset(void *queue_handle)
{
if (pdPASS == xQueueReset(queue_handle)) {
return QCLOUD_RET_SUCCESS;
} else {
return QCLOUD_ERR_FAILURE;
}
}
unsigned long HAL_QueueItemWaitingCount(void *queue_handle)
{
if (pdPASS == uxQueueMessagesWaiting(queue_handle)) {
return QCLOUD_RET_SUCCESS;
} else {
return QCLOUD_ERR_FAILURE;
}
}
unsigned long HAL_QueueItemPop(void *queue_handle, void *const item_buffer, uint32_t wait_timeout)
{
if (pdPASS == xQueueReceive(queue_handle, item_buffer, wait_timeout)) {
return QCLOUD_RET_SUCCESS;
} else {
return QCLOUD_ERR_FAILURE;
}
}
unsigned long HAL_QueueItemPush(void *queue_handle, void *const item_buffer, uint32_t wait_timeout)
{
if (pdPASS == xQueueSend(queue_handle, item_buffer, wait_timeout)) {
return QCLOUD_RET_SUCCESS;
} else {
return QCLOUD_ERR_FAILURE;
}
}
#endif
void HAL_SleepMs(_IN_ uint32_t ms)
{
TickType_t ticks = ms / portTICK_PERIOD_MS;
@ -159,7 +214,7 @@ void HAL_MutexUnlock(_IN_ void *mutex)
#endif
}
#ifdef MULTITHREAD_ENABLED
#if ((defined MULTITHREAD_ENABLED) || (defined WIFI_CONFIG_ENABLED))
// platform-dependant thread routine/entry function
static void _HAL_thread_func_wrapper_(void *ptr)
@ -192,6 +247,12 @@ int HAL_ThreadCreate(ThreadParams *params)
return QCLOUD_RET_SUCCESS;
}
int HAL_ThreadDestroy(void *thread_t)
{
vTaskDelete(thread_t);
return 0;
}
#endif
#if defined(PLATFORM_HAS_CMSIS) && defined(AT_TCP_ENABLED)

View File

@ -0,0 +1,154 @@
/*
* Copyright (c) 2020 Tencent Cloud. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "qcloud_iot_export.h"
#include "qutils_timer.h"
#include "qcloud_wifi_config.h"
#include "qcloud_wifi_config_internal.h"
#if WIFI_PROV_SIMPLE_CONFIG_ENABLE
static bool sg_simple_config_start = false;
static eWiFiConfigState ap_connect_state = WIFI_CONFIG_ING;
void set_simple_config_state(eWiFiConfigState state)
{
ap_connect_state = state;
}
static eWiFiConfigState get_simple_config_state(void)
{
return ap_connect_state;
}
static void simple_config_task(void *params)
{
WifiConfigEventCallBack wifi_config_event_cb = params;
uint32_t time_count = (WIFI_CONFIG_WAIT_TIME_MS / WIFI_CONFIG_BLINK_TIME_MS);
while ((true == sg_simple_config_start) && (--time_count)) {
// check simple config result, call set_simple_config_state set result
if (WIFI_CONFIG_SUCCESS == get_simple_config_state() && true == HAL_Wifi_IsConnected()) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_SUCCESS, NULL);
break;
} else if (WIFI_CONFIG_FAIL == get_simple_config_state()) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_FAILED, NULL);
break;
}
HAL_SleepMs(WIFI_CONFIG_BLINK_TIME_MS);
if (time_count % 10 == 0) {
Log_d("simple_config_task running!");
}
}
Log_d("task end connect_success :%d, task_run :%d, time_count:%d", get_simple_config_state(),
sg_simple_config_start, time_count);
if (0 == time_count) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_TIMEOUT, NULL);
}
HAL_SmartConfig_Stop();
return;
}
static int _simple_config_task_start(void *params)
{
static ThreadParams thread_params;
thread_params.thread_func = simple_config_task;
thread_params.thread_name = "simple_config_task";
thread_params.stack_size = 8192;
thread_params.priority = 3;
thread_params.user_arg = params;
int ret = HAL_ThreadCreate(&thread_params);
if (QCLOUD_RET_SUCCESS != ret) {
Log_e("HAL_ThreadCreate(simple_config_task) failed!");
return -1;
}
return 0;
}
int start_device_simpleconfig(void)
{
return QCLOUD_RET_SUCCESS;
}
int stop_device_simpleconfig(void)
{
return QCLOUD_RET_SUCCESS;
}
#endif
/**
* @brief Start simple config
*
* @param params is NULL
*
* @return 0 when success, or err code for failure
*/
int HAL_SimpleConfig_Start(void *params, WifiConfigEventCallBack event_cb)
{
int ret = QCLOUD_RET_SUCCESS;
#if WIFI_PROV_SIMPLE_CONFIG_ENABLE
// TO-DO device platform start simple config
ret = start_device_simpleconfig();
if (QCLOUD_RET_SUCCESS != ret) {
Log_d("simple smart config failed!, ret:%d", ret);
return ret;
}
set_simple_config_state(WIFI_CONFIG_ING);
sg_simple_config_start = true;
ret = _simple_config_task_start(event_cb);
if (QCLOUD_RET_SUCCESS != ret) {
HAL_SimpleConfig_Stop();
}
#endif
return ret;
}
/**
* @brief Stop WiFi config and device binding process
*/
int HAL_SimpleConfig_Stop(void)
{
int ret = QCLOUD_RET_SUCCESS;
#if WIFI_PROV_SIMPLE_CONFIG_ENABLE
set_simple_config_state(WIFI_CONFIG_ING);
if (true == sg_simple_config_start) {
Log_i("simple config stop");
sg_simple_config_start = false;
// TO-DO device platform stop smart config
ret = stop_device_simpleconfig();
}
#endif
return ret;
}

View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2020 Tencent Cloud. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "qcloud_iot_export.h"
#include "qutils_timer.h"
#include "qcloud_wifi_config.h"
#include "qcloud_wifi_config_internal.h"
#if WIFI_PROV_SMART_CONFIG_ENABLE
static bool sg_smart_config_start = false;
static eWiFiConfigState ap_connect_state = WIFI_CONFIG_ING;
void set_smart_config_state(eWiFiConfigState state)
{
ap_connect_state = state;
}
static eWiFiConfigState get_smart_config_state(void)
{
return ap_connect_state;
}
static void smart_config_task(void *params)
{
WifiConfigEventCallBack wifi_config_event_cb = params;
uint32_t time_count = (WIFI_CONFIG_WAIT_TIME_MS / WIFI_CONFIG_BLINK_TIME_MS);
while ((true == sg_smart_config_start) && (--time_count)) {
// check smart config result, call set_smart_config_state set result
if (WIFI_CONFIG_SUCCESS == get_smart_config_state() && true == HAL_Wifi_IsConnected()) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_SUCCESS, NULL);
break;
} else if (WIFI_CONFIG_FAIL == get_smart_config_state()) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_FAILED, NULL);
break;
}
HAL_SleepMs(WIFI_CONFIG_BLINK_TIME_MS);
if (time_count % 10 == 0) {
Log_d("smart_config_task running!");
}
}
Log_d("task end connect_success :%d, task_run :%d, time_count:%d", get_smart_config_state(), sg_smart_config_start,
time_count);
if (0 == time_count) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_TIMEOUT, NULL);
}
HAL_SmartConfig_Stop();
return;
}
static int _smart_config_task_start(void *params)
{
static ThreadParams thread_params;
thread_params.thread_func = smart_config_task;
thread_params.thread_name = "smart_config_task";
thread_params.stack_size = 8192;
thread_params.priority = 3;
thread_params.user_arg = params;
int ret = HAL_ThreadCreate(&thread_params);
if (QCLOUD_RET_SUCCESS != ret) {
Log_e("HAL_ThreadCreate(smart_config_task) failed!");
return -1;
}
return 0;
}
int start_device_smartconfig(void)
{
return QCLOUD_RET_SUCCESS;
}
int stop_device_smartconfig(void)
{
return QCLOUD_RET_SUCCESS;
}
#endif
/**
* @brief Start smart config
*
* @param params is NULL
*
* @return 0 when success, or err code for failure
*/
int HAL_SmartConfig_Start(void *params, WifiConfigEventCallBack event_cb)
{
int ret = QCLOUD_RET_SUCCESS;
#if WIFI_PROV_SMART_CONFIG_ENABLE
// TO-DO device platform start smart config
ret = start_device_smartconfig();
if (QCLOUD_RET_SUCCESS != ret) {
Log_e("start smart config failed! ret:%d", ret);
return ret;
}
set_smart_config_state(WIFI_CONFIG_ING);
sg_smart_config_start = true;
ret = _smart_config_task_start(event_cb);
if (QCLOUD_RET_SUCCESS != ret) {
HAL_SmartConfig_Stop();
}
#endif
return ret;
}
/**
* @brief Stop WiFi config and device binding process
*/
int HAL_SmartConfig_Stop(void)
{
int ret = QCLOUD_RET_SUCCESS;
#if WIFI_PROV_SMART_CONFIG_ENABLE
set_smart_config_state(WIFI_CONFIG_ING);
if (true == sg_smart_config_start) {
Log_i("HAL_SmartConfig_Stop");
sg_smart_config_start = false;
// TO-DO device platform stop smart config
ret = stop_device_smartconfig();
}
#endif
return ret;
}

View File

@ -0,0 +1,158 @@
/*
* Copyright (c) 2020 Tencent Cloud. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "qcloud_iot_export.h"
#include "qutils_timer.h"
#include "qcloud_wifi_config.h"
#include "qcloud_wifi_config_internal.h"
#include <bl60x_fw_api.h>
#include <wifi_mgmr_ext.h>
#if WIFI_PROV_SOFT_AP_ENABLE
static bool sg_soft_ap_start = false;
static uint8_t sg_soft_ap_done = WIFI_CONFIG_ING;
void set_soft_ap_config_result(eWiFiConfigState result)
{
sg_soft_ap_done = result;
}
static eWiFiConfigState get_soft_ap_config_result(void)
{
return sg_soft_ap_done;
}
static void _soft_ap_config_task(void *para)
{
uint32_t time_count = WIFI_CONFIG_WAIT_TIME_MS / WIFI_CONFIG_BLINK_TIME_MS;
WifiConfigEventCallBack wifi_config_event_cb = para;
while ((true == sg_soft_ap_start) && (--time_count)) {
if (WIFI_CONFIG_SUCCESS == get_soft_ap_config_result() && (true == HAL_Wifi_IsConnected())) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_SUCCESS, NULL);
break;
} else if (WIFI_CONFIG_FAIL == get_soft_ap_config_result()) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_FAILED, NULL);
break;
}
HAL_SleepMs(WIFI_CONFIG_BLINK_TIME_MS);
if (time_count % 10 == 0) {
Log_d("soft_ap_task running!");
}
}
if (0 == time_count) {
wifi_config_event_cb(EVENT_WIFI_CONFIG_TIMEOUT, NULL);
}
return;
}
static int _soft_ap_task_start(void *params)
{
static ThreadParams thread_params;
thread_params.thread_func = _soft_ap_config_task;
thread_params.thread_name = "_soft_ap_config_task";
thread_params.stack_size = 8192;
thread_params.priority = 2;
thread_params.user_arg = params;
int ret = HAL_ThreadCreate(&thread_params);
if (QCLOUD_RET_SUCCESS != ret) {
Log_e("HAL_ThreadCreate(_soft_ap_task_start) failed!");
return -1;
}
return 0;
}
#endif
int start_device_softAP(const char *ssid, const char *psw, uint8_t ch)
{
wifi_interface_t wifi_interface;
printf("ssid=%s\n",ssid);
printf("psw=%s\n",psw);
wifi_interface = wifi_mgmr_ap_enable();
wifi_mgmr_ap_start(wifi_interface, ssid, 0, psw, ch);
return QCLOUD_RET_SUCCESS;
}
int stop_device_softAP(void)
{
wifi_mgmr_ap_stop(NULL);
return QCLOUD_RET_SUCCESS;
}
/**
* @brief Start softAP config
*
* @param params See eSimpleConfigParams
*
* @return 0 when success, or err code for failure
*/
int HAL_SoftApProvision_Start(void *params, WifiConfigEventCallBack event_cb)
{
int ret = QCLOUD_RET_SUCCESS;
#if WIFI_PROV_SOFT_AP_ENABLE
eSoftApConfigParams *apConfig = (eSoftApConfigParams *)params;
(void)apConfig;
set_soft_ap_config_result(WIFI_CONFIG_ING);
ret = start_device_softAP(apConfig->ssid, apConfig->psw, apConfig->ch);
if (QCLOUD_RET_SUCCESS == ret) {
Log_d("start softAP success!");
ret = _soft_ap_task_start(event_cb);
}
if (QCLOUD_RET_SUCCESS != ret) {
HAL_SoftApProvision_Stop();
return ret;
}
sg_soft_ap_start = true;
#endif
return ret;
}
/**
* @brief Stop WiFi config and device binding process
*/
int HAL_SoftApProvision_Stop(void)
{
int ret = QCLOUD_RET_SUCCESS;
#if WIFI_PROV_SOFT_AP_ENABLE
set_soft_ap_config_result(WIFI_CONFIG_FAIL);
if (true == sg_soft_ap_start) {
Log_i("HAL_AirkissConfig_Stop");
sg_soft_ap_start = false;
ret = stop_device_softAP();
}
#endif
return ret;
}

View File

@ -63,7 +63,7 @@ uintptr_t HAL_TCP_Connect(const char *host, uint16_t port)
ret = getaddrinfo(host, port_str, &hints, &addr_list);
if (ret) {
printf("getaddrinfo(%s:%s) error", STRING_PTR_PRINT_SANITY_CHECK(host), port_str);
Log_e("getaddrinfo(%s:%s) error", STRING_PTR_PRINT_SANITY_CHECK(host), port_str);
return 0;
}
@ -126,7 +126,7 @@ int HAL_TCP_Write(uintptr_t fd, const unsigned char *buf, uint32_t len, uint32_t
uint32_t len_sent;
uint32_t t_end, t_left;
fd_set sets;
printf("HAL_TCP_Write\n");
fd -= LWIP_SOCKET_FD_SHIFT;
t_end = HAL_GetTimeMs() + timeout_ms;

View File

@ -335,7 +335,7 @@ int HAL_TLS_Write(uintptr_t handle, unsigned char *msg, size_t totalLen, uint32_
while (!expired(&timer) &&
(write_rc = mbedtls_ssl_write(&(pParams->ssl), msg + written_so_far, totalLen - written_so_far)) <= 0) {
if (write_rc != MBEDTLS_ERR_SSL_WANT_READ && write_rc != MBEDTLS_ERR_SSL_WANT_WRITE) {
printf("HAL_TLS_write failed 0x%04x", write_rc < 0 ? -write_rc : write_rc);
Log_e("HAL_TLS_write failed 0x%04x", write_rc < 0 ? -write_rc : write_rc);
errorFlag = true;
break;
}
@ -349,11 +349,8 @@ int HAL_TLS_Write(uintptr_t handle, unsigned char *msg, size_t totalLen, uint32_
*written_len = written_so_far;
if (errorFlag) {
printf("QCLOUD_ERR_SSL_WRITE");
return QCLOUD_ERR_SSL_WRITE;
} else if (expired(&timer) && written_so_far != totalLen) {
printf("QCLOUD_ERR_SSL_WRITE_TIMEOUT");
return QCLOUD_ERR_SSL_WRITE_TIMEOUT;
}

View File

@ -162,5 +162,167 @@ int HAL_UDP_ReadTimeout(uintptr_t fd, unsigned char *p_data, unsigned int datale
/* This call will not block */
return HAL_UDP_Read(fd, p_data, datalen);
}
#endif
#ifdef WIFI_CONFIG_ENABLED
/* lwIP socket handle start from 0 */
#define WIFI_LWIP_SOCKET_FD_SHIFT 3
int HAL_UDP_CreateBind(const char *host, unsigned short port)
{
#define NETWORK_ADDR_LEN (16)
int ret;
struct addrinfo hints, *addr_list, *cur;
int fd = 0;
char port_str[6] = {0};
HAL_Snprintf(port_str, 6, "%d", port);
memset((char *)&hints, 0x00, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM;
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_UDP;
Log_d("establish udp connection with server(host=%s port=%s)", host, port_str);
if (getaddrinfo(host, port_str, &hints, &addr_list) != 0) {
Log_e("getaddrinfo error,errno:%s", strerror(errno));
return 0;
}
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
if (fd < 0) {
ret = 0;
continue;
}
Log_d("establish udp connection with server(host=%d port=%d)", ((struct sockaddr_in *)cur->ai_addr)->sin_addr,
((struct sockaddr_in *)cur->ai_addr)->sin_port);
if (0 == bind(fd, cur->ai_addr, cur->ai_addrlen)) {
ret = fd + WIFI_LWIP_SOCKET_FD_SHIFT;
break;
}
close(fd);
ret = 0;
}
if (0 == ret) {
Log_e("fail to establish udp");
} else {
Log_d("success to establish udp, fd=%d", ret);
}
freeaddrinfo(addr_list);
Log_i("HAL_UDP_Connect fd:%d", ret);
return (uintptr_t)ret;
#undef NETWORK_ADDR_LEN
}
int HAL_UDP_ReadTimeoutPeerInfo(uintptr_t fd, unsigned char *p_data, unsigned int datalen, unsigned int timeout_ms,
char *recv_ip_addr, unsigned char recv_addr_len, unsigned short *recv_port)
{
int ret;
struct timeval tv;
fd_set read_fds;
int socket_id = -1;
struct sockaddr_in source_addr;
uint addrLen = sizeof(source_addr);
int len = 0;
Log_i("HAL_UDP_ReadTimeoutPeerInfo fd:%d", fd);
fd -= WIFI_LWIP_SOCKET_FD_SHIFT;
socket_id = (int)fd;
if (socket_id < 0) {
return -1;
}
FD_ZERO(&read_fds);
FD_SET(socket_id, &read_fds);
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
ret = select(socket_id + 1, &read_fds, NULL, NULL, timeout_ms == 0 ? NULL : &tv);
/* Zero fds ready means we timed out */
if (ret == 0) {
return 0; /* receive timeout */
}
if (ret < 0) {
if (errno == EINTR) {
return -3; /* want read */
}
return QCLOUD_ERR_SSL_READ; /* receive failed */
}
/* This call will not block */
len = recvfrom((int)fd, p_data, datalen, MSG_DONTWAIT, (struct sockaddr *)&source_addr, &addrLen);
inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, recv_ip_addr, recv_addr_len - 1);
*recv_port = ntohs(source_addr.sin_port);
return len;
}
int HAL_UDP_GetErrno()
{
return errno;
}
char *HAL_UDP_GetErrnoStr()
{
return strerror(errno);
}
int HAL_UDP_WriteTo(uintptr_t fd, const unsigned char *p_data, unsigned int datalen, char *host, unsigned short port)
{
int rc = -1;
struct addrinfo hints, *addr_list;
char port_str[6] = {0};
HAL_Snprintf(port_str, 6, "%d", port);
fd -= WIFI_LWIP_SOCKET_FD_SHIFT;
memset((char *)&hints, 0x00, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM;
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_UDP;
Log_i("HAL_UDP_WriteTo host:%s, port:%d, fd:%d", host, port, fd);
if ((rc = getaddrinfo(host, port_str, &hints, &addr_list)) != 0) {
Log_e("getaddrinfo error,errno:%s, rc:%d", strerror(errno), rc);
return 0;
}
Log_d("HAL_UDP_WriteTo(host=%d port=%d)", ((struct sockaddr_in *)addr_list->ai_addr)->sin_addr,
((struct sockaddr_in *)addr_list->ai_addr)->sin_port);
rc = sendto(fd, p_data, datalen, 0, addr_list->ai_addr, addr_list->ai_addrlen);
freeaddrinfo(addr_list);
return rc;
}
void HAL_UDP_Close(uintptr_t fd)
{
long socket_id = -1;
fd -= WIFI_LWIP_SOCKET_FD_SHIFT;
socket_id = (int)fd;
close(socket_id);
}
#endif

View File

@ -0,0 +1,77 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub
available.
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights
reserved.
* Licensed under the MIT License (the "License"); you may not use this file
except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software
distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND,
* either express or implied. See the License for the specific language
governing permissions and
* limitations under the License.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "qcloud_iot_export.h"
#include "qcloud_iot_import.h"
#include "qcloud_wifi_config.h"
#include <bl60x_fw_api.h>
#include <wifi_mgmr_ext.h>
static void wifi_connect(char *ssidname, char *password)
{
wifi_interface_t wifi_interface;
wifi_interface = wifi_mgmr_sta_enable();
wifi_mgmr_sta_connect(wifi_interface, ssidname, password, NULL, NULL, 0, 0);
}
int HAL_Wifi_StaConnect(const char *ssid, const char *psw, uint8_t channel)
{
Log_i("STA to connect SSID:%s PASSWORD:%s CHANNEL:%d", ssid, psw, channel);
wifi_connect(ssid,psw);
return QCLOUD_RET_SUCCESS;
}
bool q_cloud_IsConnected=0;
bool HAL_Wifi_IsConnected(void)
{
if(q_cloud_IsConnected==1)
return true;
return false;
}
int HAL_Wifi_read_err_log(uint32_t offset, void *log, size_t log_size)
{
Log_i("HAL_Wifi_check_err_log");
return QCLOUD_RET_SUCCESS;
}
int HAL_Wifi_write_err_log(uint32_t offset, void *log, size_t log_size)
{
Log_i("HAL_Wifi_check_err_log");
return QCLOUD_RET_SUCCESS;
}
int HAL_Wifi_clear_err_log(void)
{
Log_i("HAL_Wifi_clear_err_log");
return QCLOUD_RET_SUCCESS;
}

View File

@ -76,7 +76,7 @@ struct Network {
/*
* Init network stack
*/
int network_init(Network *pNetwork);
int qcloud_iot_network_init(Network *pNetwork);
/* return the handle */
int is_network_connected(Network *pNetwork);

View File

@ -22,7 +22,8 @@
#define QCLOUD_IOT_COMMON_H_
/* IoT C-SDK APPID */
#define QCLOUD_IOT_DEVICE_SDK_APPID "21010406"
#define QCLOUD_IOT_DEVICE_SDK_APPID "21010406"
#define QCLOUD_IOT_DEVICE_SDK_APPID_LEN (sizeof(QCLOUD_IOT_DEVICE_SDK_APPID) - 1)
/* MQTT server domain */
#define QCLOUD_IOT_MQTT_DIRECT_DOMAIN "iotcloud.tencentdevices.com"

View File

@ -0,0 +1,305 @@
/*
* Copyright (c) 2020 Tencent Cloud. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef __QCLOUD_IOT_WIFI_CONFIG_H__
#define __QCLOUD_IOT_WIFI_CONFIG_H__
#ifdef __cplusplus
extern "C" {
#endif
#define WIFI_ERR_LOG_POST 1
#define WIFI_LOG_UPLOAD 1
#define WIFI_PROV_SOFT_AP_ENABLE 1 ///< wifi provisioning method: device AP, need Wechat Applets
#define WIFI_PROV_SMART_CONFIG_ENABLE 0 ///< wifi provisioning method: smart config, need Wechat Applets
#define WIFI_PROV_AIRKISS_CONFIG_ENABLE 0 ///< wifi provisioning method: airkiss, need Wechat Applets
#define WIFI_PROV_SIMPLE_CONFIG_ENABLE 0 ///< wifi provisioning method: simple config, need Wechat Applets
#define WIFI_PROV_BT_COMBO_CONFIG_ENABLE 0 ///< wifi provisioning method: bt combo config, need Wechat Applets
#define MAX_SSID_LEN 32 // max ssid len
#define MAX_PSK_LEN 65 // max psk len
typedef enum {
WIFI_CONFIG_TYPE_SOFT_AP = 0, /* Soft ap */
WIFI_CONFIG_TYPE_SMART_CONFIG = 1, /* Smart config*/
WIFI_CONFIG_TYPE_AIRKISS = 2, /* Airkiss */
WIFI_CONFIG_TYPE_SIMPLE_CONFIG = 3, /* Simple config */
WIFI_CONFIG_TYPE_BT_COMBO = 4, /* BT Combo config */
} eWiFiConfigType;
typedef enum {
RET_WIFI_CONFIG_START_SUCCESS = 0,
ERR_UNKNOWN_WIFI_CONFIG_TYPE = -1,
ERR_UNSUPPORTED_WIFI_CONFIG_TYPE = -2,
ERR_WIFI_CONFIG_START_FAILED = -3,
ERR_COMM_SERVICE_START_FAILED = -4
} eWiFiConfigErrCode;
typedef enum {
RESULT_WIFI_CONFIG_SUCCESS, /* WiFi config success */
RESULT_WIFI_CONFIG_FAILED, /* WiFi config failed */
RESULT_WIFI_CONFIG_TIMEOUT /* WiFi config timeout */
} eWiFiConfigResult;
typedef void (*WifiConfigResultCallBack)(eWiFiConfigResult result, void *usr_data);
typedef enum {
EVENT_WIFI_CONFIG_SUCCESS = 0, /* WiFi config success */
EVENT_WIFI_CONFIG_FAILED = 1, /* WiFi config failed */
EVENT_WIFI_CONFIG_TIMEOUT = 2, /* WiFi config timeout */
} eWiFiConfigEvent;
typedef enum {
WIFI_CONFIG_ING = 0, /* WiFi config ING*/
WIFI_CONFIG_FAIL = 1, /* WiFi config FAIL */
WIFI_CONFIG_SUCCESS = 2, /* WiFi config SUCCESS */
} eWiFiConfigState;
typedef void (*WifiConfigEventCallBack)(eWiFiConfigEvent event, void *usr_data);
/**
* @brief Start WiFi config and device binding process
*
* @param type @see eWiFiConfigType, only WIFI_CONFIG_TYPE_SIMPLE_CONFIG is supported now
* @param params @see rtk_simple_config.h
* @param result_cb callback to get wifi config result
*
* @return @see eWiFiConfigErrCode
*/
int qiot_wifi_config_start(eWiFiConfigType type, void *params, WifiConfigResultCallBack result_cb);
/**
* @brief Stop WiFi config and device binding process immediately
*/
void qiot_wifi_config_stop(void);
/**
* @brief Send wifi config log to mini program
*/
int qiot_wifi_config_send_log(void);
/**
* @brief set the ap ssid and psk fetched by wifi config
*/
void qiot_wifi_ap_info_set(const uint8_t *ssid, const uint8_t *psw);
/**
* @brief get the ap ssid and psk fetched by wifi config
*/
void qiot_wifi_ap_info_get(uint8_t *ssid, int ssid_buff_len, uint8_t *psk, int psk_buff_len);
/**
* @brief set device token and notify to bind device
*
* @param token from wechat applet
*
*/
void qiot_device_bind_set_token(const char *token);
/**
* @brief get bind device cloud reply code
*
* @param bind_reply_code 0 is success other is fail, send it to wechat applet
*
* @return recv cloud platform reply device bind msg is true, other return false happen error
*/
bool qiot_device_bind_get_cloud_reply_code(int *bind_reply_code);
/**
* @brief device start to connect ap, include switch mode to sta, disconnect ap, connect ap
*
* @param ssid connect ap ssid
* @param psw connect ap ssid->password
* @param channel connect ap in channel
*
* @return 0 is fun proc success, other fun proc failed
*/
int HAL_Wifi_StaConnect(const char *ssid, const char *psw, uint8_t channel);
/**
* @brief get station connect ap result
*
* @param void
*
* @return true is get ip; other is false
*/
bool HAL_Wifi_IsConnected(void);
typedef struct {
const char *ssid;
const char *psw;
uint8_t ch;
} eSoftApConfigParams;
/**
* @brief Start softAP provision
*
* @param params See eSoftApConfigParams
* @event_cb wifi config event callback, success to bind device
*
* @return 0 when success, or err code for failure
*/
int HAL_SoftApProvision_Start(void *params, WifiConfigEventCallBack event_cb);
/**
* @brief Stop softAp WiFi provision and device binding process
*/
int HAL_SoftApProvision_Stop(void);
/**
* @brief start device softap
* @param ssid softap ssid
* @param psw softap pws
* @param ch softap channel
*
* @return 0 when success, or err code for failuer
*/
int start_device_softAP(const char *ssid, const char *psw, uint8_t ch);
/**
* @brief start device softap
*
* @return 0 when success, or err code for failuer
*/
int stop_device_softAP(void);
/**
* @brief Start airkiss
*
* @param params is NULL
* @event_cb wifi config event callback, success to bind device
*
* @return 0 when success, or err code for failure
*/
int HAL_AirkissConfig_Start(void *params, WifiConfigEventCallBack event_cb);
/**
* @brief Stop airkiss and device binding process
*/
int HAL_AirkissConfig_Stop(void);
/**
* @brief set airkiss config state
*
* @param eWiFiConfigStatee, ing,succ,fail
*
* @return null
*/
void set_airkiss_config_state(eWiFiConfigState state);
/**
* @brief Start smart config
*
* @param params is NULL
* @event_cb wifi config event callback, success to bind device
*
* @return 0 when success, or err code for failure
*/
int HAL_SmartConfig_Start(void *params, WifiConfigEventCallBack event_cb);
/**
* @brief Stop SmartConfig and device binding process
*/
int HAL_SmartConfig_Stop(void);
/**
* @brief set smart config state
*
* @param eWiFiConfigState ing,succ,fail
*
* @return null
*/
void set_smart_config_state(eWiFiConfigState state);
/**
* @brief Start simple config
*
* @param params is NULL
* @event_cb wifi config event callback, success to bind device
*
* @return 0 when success, or err code for failure
*/
int HAL_SimpleConfig_Start(void *params, WifiConfigEventCallBack event_cb);
/**
* @brief Stop simple config and device binding process
*/
int HAL_SimpleConfig_Stop(void);
/**
* @brief set simple config state
*
* @param eWiFiConfigState ing,succ,fail
*
* @return null
*/
void set_simple_config_state(eWiFiConfigState state);
/**
* @brief Start bt combo config
*
* @param params is NULL
* @event_cb wifi config event callback, success to bind device
*
* @return 0 when success, or err code for failure
*/
int HAL_BTComboConfig_Start(void *params, WifiConfigEventCallBack event_cb);
/**
* @brief Stop bt combo config and device binding process
*/
int HAL_BTComboConfig_Stop(void);
/**
* @brief set bt combo config state
*
* @param eWiFiConfigState ing,succ,fail
*
* @return null
*/
void set_bt_combo_config_state(eWiFiConfigState state);
/**
* @brief get wifi config err log from saved
*
* @param offset log read start position
* @param log err log get buff
* @param log_size err log buff size
*
* @return 0 when success, or err code for failure
*/
int HAL_Wifi_read_err_log(uint32_t offset, void *log, size_t log_size);
/**
* @brief save wifi config err log
*
* @param offset log write start position
* @param log err log buff
* @param log_size err log buff size
*
* @return 0 when success, or err code for failure
*/
int HAL_Wifi_write_err_log(uint32_t offset, void *log, size_t log_size);
/**
* @brief clear saved all log
*
* @param is NULL
*
* @return 0 when success, or err code for failure
*/
int HAL_Wifi_clear_err_log(void);
#ifdef __cplusplus
}
#endif
#endif //__QCLOUD_WIFI_CONFIG_H__

View File

@ -0,0 +1,143 @@
/*
* Copyright (c) 2020 Tencent Cloud. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef __QCLOUD_WIFI_CONFIG_INTERNAL_H__
#define __QCLOUD_WIFI_CONFIG_INTERNAL_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include "qcloud_wifi_config.h"
#define SOFTAP_BOARDING_VERSION "2.0"
#define APP_SERVER_PORT (8266)
#define LOG_SERVER_PORT (9876)
#define SOFT_AP_BLINK_TIME_MS (300)
#define WIFI_CONFIG_BLINK_TIME_MS (200)
#define WIFI_CONFIG_WAIT_TIME_MS (300 * 1000) /*300 seconds*/
#define WIFI_CONFIG_HALF_TIME_MS (50 * 1000) /*50 seconds*/
#define SELECT_WAIT_TIME_SECONDS (3) /*seconds*/
#define WAIT_CNT_5MIN_SECONDS (300) /*5 minutes*/
#define COMM_SERVER_TASK_NAME "comm_server_task"
#define COMM_SERVER_TASK_STACK_BYTES 4096
#define COMM_SERVER_TASK_PRIO 1
#define MAX_TOKEN_LENGTH 32
#define MAX_TVS_CLIENT_ID_LENGTH 512
#define MAX_TVS_AUTH_RESP_INFO_LENGTH 128
/* unified socket type for TCP/UDP */
typedef struct {
int socket_id;
char * peer_addr;
unsigned short port;
} comm_peer_t;
typedef enum {
CMD_TOKEN_ONLY = 0, /* Token only for smartconfig */
CMD_SSID_PW_TOKEN = 1, /* SSID/PW/TOKEN for softAP */
CMD_DEVICE_REPLY = 2, /* device reply */
CMD_LOG_QUERY = 3, /* app query log */
CMD_AUTHINFO_QUERY = 4, /* query auth info */
CMD_AUTHINFO_REPLY = 5, /* reply auth info */
} eWiFiConfigCmd;
typedef enum {
SUCCESS_TYPE = 0,
ERR_MQTT_CONNECT = 1,
ERR_APP_CMD = 2,
ERR_BD_STOP = 3,
ERR_OS_TASK = 4,
ERR_OS_QUEUE = 5,
ERR_WIFI_STA_INIT = 6,
ERR_WIFI_AP_INIT = 7,
ERR_WIFI_START = 8,
ERR_WIFI_CONFIG = 9,
ERR_WIFI_CONNECT = 10,
ERR_WIFI_DISCONNECT = 11,
ERR_WIFI_AP_STA = 12,
ERR_SC_START = 13,
ERR_SC_DATA = 14,
ERR_SOCKET_OPEN = 15,
ERR_SOCKET_BIND = 16,
ERR_SOCKET_LISTEN = 17,
ERR_SOCKET_FCNTL = 18,
ERR_SOCKET_ACCEPT = 19,
ERR_SOCKET_RECV = 20,
ERR_SOCKET_SELECT = 21,
ERR_SOCKET_SEND = 22,
ERR_TOKEN_SEND = 23,
ERR_TOKEN_REPLY = 24,
} eErrLogType;
typedef enum {
ERR_SC_APP_STOP = 101,
ERR_SC_AT_STOP = 102,
ERR_SC_EXEC_TIMEOUT = 103,
ERR_SC_INVALID_DATA = 104,
ERR_APP_CMD_JSON_FORMAT = 201,
ERR_APP_CMD_TIMESTAMP = 202,
ERR_APP_CMD_SIGNATURE = 203,
ERR_APP_CMD_AP_INFO = 204,
ERR_JSON_PRINT = 205,
ERR_COMM_TASK_ERR = 206,
} eErrLogSubType;
typedef enum {
CUR_ERR = 0, /* current connect error */
PRE_ERR = 1, /* previous connect error */
} eErrRecordType;
int qiot_comm_service_start(void);
void qiot_comm_service_stop(void);
int qiot_device_bind(void);
//============================ WiFi config error handling ===========================//
int init_error_log_queue(void);
int push_error_log(uint16_t err_id, int32_t err_sub_id);
bool is_config_error_happen(void);
int app_send_error_log(comm_peer_t *peer, uint8_t record, uint16_t err_id, int32_t err_sub_id);
int get_and_post_error_log(comm_peer_t *peer);
int save_error_log(void);
//============================ WiFi config error handling ===========================//
//============================ WiFi running log upload ===========================//
int init_dev_log_queue(void);
void delete_dev_log_queue(void);
int push_dev_log(const char *func, const int line, const char *fmt, ...);
int app_send_dev_log(comm_peer_t *peer);
int qiot_log_service_start(void);
void qiot_log_service_stop(void);
void set_soft_ap_config_result(eWiFiConfigState result);
#if WIFI_LOG_UPLOAD
#define PUSH_LOG(fmt, ...) push_dev_log(__FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
#else
#define PUSH_LOG(...)
#endif
//============================ WiFi running log upload ===========================//
#ifdef __cplusplus
}
#endif
#endif //__WIFI_CONFIG_INTERNAL_H__

View File

@ -261,9 +261,9 @@ static void _mqtt_yield_thread(void *ptr)
int rc = QCLOUD_RET_SUCCESS;
Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)ptr;
Log_d("start mqtt_yield_thread...");
Log_d("start mqtt_yield_thread...");
while (mqtt_client->yield_thread_running) {
int rc = qcloud_iot_mqtt_yield(mqtt_client, 200);
rc = qcloud_iot_mqtt_yield(mqtt_client, 200);
#ifdef LOG_UPLOAD
/* do instant log uploading if MQTT communication error */
@ -292,21 +292,20 @@ static void _mqtt_yield_thread(void *ptr)
#ifdef LOG_UPLOAD
IOT_Log_Upload(true);
#endif
}
int IOT_MQTT_StartLoop(void *pClient)
{
POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL);
Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient;
ThreadParams thread_params = {0};
thread_params.thread_func = _mqtt_yield_thread;
thread_params.thread_name = "mqtt_yield_thread";
thread_params.user_arg = pClient;
thread_params.stack_size = 4096;
thread_params.priority = 1;
mqtt_client->yield_thread_running = true;
Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient;
ThreadParams thread_params = {0};
thread_params.thread_func = _mqtt_yield_thread;
thread_params.thread_name = "mqtt_yield_thread";
thread_params.user_arg = pClient;
thread_params.stack_size = 4096;
thread_params.priority = 1;
mqtt_client->yield_thread_running = true;
int rc = HAL_ThreadCreate(&thread_params);
if (rc) {
@ -322,8 +321,8 @@ void IOT_MQTT_StopLoop(void *pClient)
{
POINTER_SANITY_CHECK_RTN(pClient);
Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient;
mqtt_client->yield_thread_running = false;
Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient;
mqtt_client->yield_thread_running = false;
HAL_SleepMs(1000);
return;
}
@ -561,8 +560,6 @@ int qcloud_iot_mqtt_reset_network_disconnected_count(Qcloud_IoT_Client *pClient)
IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
}
#ifdef __cplusplus
}
#endif

View File

@ -130,15 +130,9 @@ static int _serialize_connect_packet(unsigned char *buf, size_t buf_len, MQTTCon
if (cur_timesec <= 0 || MAX_ACCESS_EXPIRE_TIMEOUT <= 0) {
cur_timesec = LONG_MAX;
}
long cur_timesec_bak = cur_timesec;
int cur_timesec_len = 0;
while (cur_timesec_bak != 0) {
cur_timesec_bak /= 10;
++cur_timesec_len;
}
int username_len =
strlen(options->client_id) + strlen(QCLOUD_IOT_DEVICE_SDK_APPID) + MAX_CONN_ID_LEN + cur_timesec_len + 4;
// 20 for timestampe length & delimiter
int username_len = strlen(options->client_id) + QCLOUD_IOT_DEVICE_SDK_APPID_LEN + MAX_CONN_ID_LEN + 20;
options->username = (char *)HAL_Malloc(username_len);
if (options->username == NULL) {
Log_e("malloc username failed!");

View File

@ -55,7 +55,7 @@ int qcloud_iot_mqtt_network_init(Network *pNetwork)
pNetwork->type = NETWORK_TCP;
#endif
rc = network_init(pNetwork);
rc = qcloud_iot_network_init(pNetwork);
pNetwork->is_connected = qcloud_iot_mqtt_tls_is_connected;
return rc;

View File

@ -39,7 +39,7 @@ int is_network_at_connected(Network *pNetwork)
}
#endif
int network_init(Network *pNetwork)
int qcloud_iot_network_init(Network *pNetwork)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);

View File

@ -0,0 +1,184 @@
/*
* Copyright (c) 2020 Tencent Cloud. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "qcloud_iot_export_log.h"
#include "qcloud_wifi_config.h"
#include "qcloud_wifi_config_internal.h"
static char sg_ssid[MAX_SSID_LEN + 1];
static char sg_psk[MAX_PSK_LEN + 1];
typedef struct {
int (*config_start)(void *, WifiConfigEventCallBack);
int (*config_stop)(void);
} WiFiConfigMethod;
static WiFiConfigMethod sg_wifi_config_methods[] = {
{HAL_SoftApProvision_Start, HAL_SoftApProvision_Stop}, // WIFI_CONFIG_TYPE_SOFT_AP
{HAL_SmartConfig_Start, HAL_SmartConfig_Stop}, // WIFI_CONFIG_TYPE_SMART_CONFIG
{HAL_AirkissConfig_Start, HAL_AirkissConfig_Stop}, // WIFI_CONFIG_TYPE_AIRKISS
{HAL_SimpleConfig_Start, HAL_SimpleConfig_Stop}, // WIFI_CONFIG_TYPE_SIMPLE_CONFIG
{HAL_BTComboConfig_Start, HAL_BTComboConfig_Stop} // WIFI_CONFIG_TYPE_BTCombo_CONFIG
};
static WiFiConfigMethod * sg_wifi_config_method_now = NULL;
static WifiConfigResultCallBack sg_wifi_config_result_cb = NULL;
static void _qiot_wifi_config_event_cb(eWiFiConfigEvent event, void *usr_data)
{
switch (event) {
case EVENT_WIFI_CONFIG_SUCCESS:
if (qiot_device_bind()) {
Log_e("Device bind failed!");
sg_wifi_config_result_cb(RESULT_WIFI_CONFIG_FAILED, NULL);
} else {
Log_d("Device bind success!");
sg_wifi_config_result_cb(RESULT_WIFI_CONFIG_SUCCESS, NULL);
}
break;
case EVENT_WIFI_CONFIG_FAILED:
Log_e("Wifi config failed!");
sg_wifi_config_result_cb(RESULT_WIFI_CONFIG_FAILED, NULL);
break;
case EVENT_WIFI_CONFIG_TIMEOUT:
Log_e("Wifi config timeout!");
sg_wifi_config_result_cb(RESULT_WIFI_CONFIG_TIMEOUT, NULL);
break;
default:
Log_e("Unknown wifi config error!");
sg_wifi_config_result_cb(RESULT_WIFI_CONFIG_FAILED, NULL);
break;
}
}
/**
* @brief Start WiFi config and device binding process
*
* @param type WiFi config type, only WIFI_CONFIG_TYPE_SIMPLE_CONFIG is supported now
* @param params See rtk_simple_config.h
* @param result_cb callback to get wifi config result
*
* @return 0 when success, or err code for failure
*/
int qiot_wifi_config_start(eWiFiConfigType type, void *params, WifiConfigResultCallBack result_cb)
{
if (type < WIFI_CONFIG_TYPE_SOFT_AP || type > WIFI_CONFIG_TYPE_BT_COMBO) {
Log_e("Unknown wifi config type!");
return ERR_UNKNOWN_WIFI_CONFIG_TYPE;
}
if (init_dev_log_queue()) {
Log_e("Init dev log queue failed!");
return ERR_WIFI_CONFIG_START_FAILED;
}
if (init_error_log_queue()) {
Log_e("Init error log queue failed!");
return ERR_WIFI_CONFIG_START_FAILED;
}
sg_wifi_config_method_now = &sg_wifi_config_methods[type];
if (!sg_wifi_config_method_now->config_start) {
sg_wifi_config_method_now = NULL;
Log_e("Unsupported wifi config type!");
return ERR_UNSUPPORTED_WIFI_CONFIG_TYPE;
}
sg_wifi_config_result_cb = result_cb;
if (sg_wifi_config_method_now->config_start(params, _qiot_wifi_config_event_cb)) {
sg_wifi_config_method_now = NULL;
Log_e("Wifi Config start failed!");
return ERR_WIFI_CONFIG_START_FAILED;
}
if (qiot_comm_service_start()) {
sg_wifi_config_method_now->config_stop();
sg_wifi_config_method_now = NULL;
Log_e("Comm service start failed!");
return ERR_COMM_SERVICE_START_FAILED;
}
return RET_WIFI_CONFIG_START_SUCCESS;
}
/**
* @brief Stop WiFi config and device binding process
*/
void qiot_wifi_config_stop(void)
{
qiot_comm_service_stop();
}
/**
* @brief Send wifi config log to app
*/
int qiot_wifi_config_send_log(void)
{
#if WIFI_LOG_UPLOAD
#define LOG_SOFTAP_CH 6
int ret;
Log_e("start softAP for log");
ret = start_device_softAP("ESP-LOG-QUERY", "86013388", LOG_SOFTAP_CH);
if (ret) {
Log_e("start_softAP failed: %d", ret);
goto err_eixt;
}
ret = qiot_log_service_start();
if (ret) {
Log_e("qiot_log_service_start failed: %d", ret);
}
return 0;
err_eixt:
stop_device_softAP();
delete_dev_log_queue();
return ret;
#undef LOG_SOFTAP_CH
#else
return 0;
#endif
}
void qiot_wifi_ap_info_set(const uint8_t *ssid, const uint8_t *psw)
{
memset(sg_ssid, '\0', MAX_SSID_LEN);
memset(sg_psk, '\0', MAX_PSK_LEN);
memcpy(sg_ssid, ssid, MAX_SSID_LEN);
memcpy(sg_psk, psw, MAX_PSK_LEN);
}
void qiot_wifi_ap_info_get(uint8_t *ssid, int ssid_buff_len, uint8_t *psk, int psk_buff_len)
{
memset(ssid, '\0', ssid_buff_len);
memset(psk, '\0', psk_buff_len);
memcpy(ssid, sg_ssid, MAX_SSID_LEN);
memcpy(psk, sg_psk, MAX_PSK_LEN);
}

View File

@ -0,0 +1,345 @@
/*
* Copyright (c) 2020 Tencent Cloud. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "cJSON.h"
#include "qcloud_iot_export.h"
#include "qcloud_iot_import.h"
#include "qcloud_wifi_config.h"
#include "qcloud_wifi_config_internal.h"
static bool sg_comm_task_run = false;
static int _app_reply_dev_info(comm_peer_t *peer)
{
int ret;
DeviceInfo devinfo;
cJSON_Hooks memoryHook;
memoryHook.malloc_fn = (void *(*)(size_t))HAL_Malloc;
memoryHook.free_fn = (void (*)(void *))HAL_Free;
cJSON_InitHooks(&memoryHook);
ret = HAL_GetDevInfo(&devinfo);
if (ret) {
Log_e("load dev info failed: %d", ret);
app_send_error_log(peer, CUR_ERR, ERR_APP_CMD, ret);
return -1;
}
cJSON *reply_json = cJSON_CreateObject();
cJSON_AddNumberToObject(reply_json, "cmdType", (int)CMD_DEVICE_REPLY);
cJSON_AddStringToObject(reply_json, "productId", devinfo.product_id);
cJSON_AddStringToObject(reply_json, "deviceName", devinfo.device_name);
cJSON_AddStringToObject(reply_json, "protoVersion", SOFTAP_BOARDING_VERSION);
char *json_str=NULL;
json_str= cJSON_Print(reply_json);
if (!json_str) {
Log_e("cJSON_PrintPreallocated failed!");
cJSON_Delete(reply_json);
app_send_error_log(peer, CUR_ERR, ERR_APP_CMD, ERR_JSON_PRINT);
return -1;
}
/* append msg delimiter */
// strcat(json_str, "\r\n");
cJSON_Delete(reply_json);
HAL_Printf("Report dev info(%d): %s", strlen(json_str), json_str);
int udp_resend_cnt = 3;
udp_resend:
ret = HAL_UDP_WriteTo(peer->socket_id, (unsigned char *)json_str, strlen(json_str), peer->peer_addr, peer->port);
if (ret < 0) {
HAL_Free(json_str);
Log_e("send error: %s", HAL_UDP_GetErrnoStr());
push_error_log(ERR_SOCKET_SEND, HAL_UDP_GetErrno());
return -1;
}
/* UDP packet could be lost, send it again */
/* NOT necessary for TCP */
if (peer->peer_addr != NULL && --udp_resend_cnt) {
HAL_SleepMs(1000);
goto udp_resend;
}
HAL_Printf("Report dev info: %s", json_str);
HAL_Free(json_str);
return 0;
}
#if 0
static int _app_reply_auth_reqinfo(comm_peer_t *peer)
{
int ret;
cJSON_Hooks memoryHook;
memoryHook.malloc_fn = HAL_Malloc;
memoryHook.free_fn = HAL_Free;
cJSON_InitHooks(&memoryHook);
char tvs_productId[MAX_SIZE_OF_TVS_PRODUCT_ID + 1] = {0};
char tvs_dsn[MAX_SIZE_OF_TVS_DEVICE_NAME + 1] = {0};
HAL_GetTvsInfo(tvs_productId, tvs_dsn);
cJSON *reply_json = cJSON_CreateObject();
cJSON_AddNumberToObject(reply_json, "cmdType", (int)CMD_AUTHINFO_REPLY);
cJSON_AddStringToObject(reply_json, "pid", tvs_productId);
cJSON_AddStringToObject(reply_json, "dsn", tvs_dsn);
char authReqInfos[150] = {0};
tvs_authorize_manager_build_auth_req(authReqInfos,sizeof(authReqInfos));
cJSON_AddStringToObject(reply_json, "authReqInfo", authReqInfos);
char *json_str = cJSON_Print(reply_json);
if (!json_str) {
Log_e("cJSON_PrintPreallocated failed!");
cJSON_Delete(reply_json);
app_send_error_log(peer, CUR_ERR, ERR_APP_CMD, ERR_JSON_PRINT);
return -1;
}
/* append msg delimiter */
// strcat(json_str, "\r\n");
cJSON_Delete(reply_json);
HAL_Printf("Reply auth reqinfo(%d): %s", strlen(json_str), json_str);
int udp_resend_cnt = 3;
udp_resend:
ret = HAL_UDP_WriteTo(peer->socket_id, json_str, strlen(json_str), peer->peer_addr , peer->port);
if (ret < 0) {
HAL_Free(json_str);
Log_e("send error: %s", HAL_UDP_GetErrnoStr());
push_error_log(ERR_SOCKET_SEND, HAL_UDP_GetErrno());
return -1;
}
/* UDP packet could be lost, send it again */
/* NOT necessary for TCP */
if (peer->peer_addr != NULL && --udp_resend_cnt) {
HAL_SleepMs(1000);
goto udp_resend;
}
HAL_Printf("Reply auth reqinfo: %s", json_str);
HAL_Free(json_str);
return 0;
}
#endif
static int _app_handle_recv_data(comm_peer_t *peer, char *pdata, int len)
{
int ret = 0;
cJSON *root = cJSON_Parse(pdata);
if (!root) {
Log_e("Parsing JSON Error: [%s]", cJSON_GetErrorPtr());
app_send_error_log(peer, CUR_ERR, ERR_APP_CMD, ERR_APP_CMD_JSON_FORMAT);
return -1;
}
cJSON *cmd_json = cJSON_GetObjectItem(root, "cmdType");
if (cmd_json == NULL) {
Log_e("Invalid cmd JSON: %s", pdata);
cJSON_Delete(root);
app_send_error_log(peer, CUR_ERR, ERR_APP_CMD, ERR_APP_CMD_JSON_FORMAT);
return -1;
}
int cmd = cmd_json->valueint;
switch (cmd) {
/* Token only for simple config */
case CMD_TOKEN_ONLY: {
cJSON *token_json = cJSON_GetObjectItem(root, "token");
if (token_json) {
// set device bind token
qiot_device_bind_set_token(token_json->valuestring);
ret = _app_reply_dev_info(peer);
// sleep a while before exit
HAL_SleepMs(1000);
/* 0: need to wait for next cmd
* 1: Everything OK and we've finished the job */
return (ret == 0);
} else {
cJSON_Delete(root);
Log_e("invlaid token!");
app_send_error_log(peer, CUR_ERR, ERR_APP_CMD, ERR_APP_CMD_AP_INFO);
return -1;
}
} break;
/* SSID/PW/TOKEN for softAP */
case CMD_SSID_PW_TOKEN: {
cJSON *ssid_json = cJSON_GetObjectItem(root, "ssid");
cJSON *psw_json = cJSON_GetObjectItem(root, "password");
cJSON *token_json = cJSON_GetObjectItem(root, "token");
if (ssid_json && psw_json && token_json) {
// parse token and connect to ap
qiot_device_bind_set_token(token_json->valuestring);
_app_reply_dev_info(peer);
// sleep a while before changing to STA mode
HAL_SleepMs(3000);
Log_i("STA to connect SSID:%s PASSWORD:%s", ssid_json->valuestring, psw_json->valuestring);
PUSH_LOG("SSID:%s|PSW:%s|TOKEN:%s", ssid_json->valuestring, psw_json->valuestring,
token_json->valuestring);
ret = HAL_Wifi_StaConnect(ssid_json->valuestring, psw_json->valuestring, 0);
if (ret) {
Log_e("wifi_sta_connect failed: %d", ret);
PUSH_LOG("wifi_sta_connect failed: %d", ret);
app_send_error_log(peer, CUR_ERR, ERR_WIFI_AP_STA, ret);
cJSON_Delete(root);
#if WIFI_PROV_SOFT_AP_ENABLE
set_soft_ap_config_result(WIFI_CONFIG_FAIL);
#endif
return -1;
} else {
Log_d("wifi_sta_connect success");
#if WIFI_PROV_SOFT_AP_ENABLE
set_soft_ap_config_result(WIFI_CONFIG_SUCCESS);
#endif
}
cJSON_Delete(root);
/* return 1 as device alreay switch to STA mode and unable to recv cmd anymore
* 1: Everything OK and we've finished the job */
return 1;
} else {
cJSON_Delete(root);
Log_e("invlaid ssid/password/token!");
app_send_error_log(peer, CUR_ERR, ERR_APP_CMD, ERR_APP_CMD_AP_INFO);
return -1;
}
} break;
case CMD_LOG_QUERY:
ret = app_send_dev_log(peer);
Log_i("app_send_dev_log ret: %d", ret);
return 1;
case CMD_AUTHINFO_QUERY:
// ret = _app_reply_auth_reqinfo(peer);
Log_i("_app_reply_auth_reqinfo ret: %d", ret);
return ret;
default: {
cJSON_Delete(root);
Log_e("Unknown cmd: %d", cmd);
app_send_error_log(peer, CUR_ERR, ERR_APP_CMD, ERR_APP_CMD_JSON_FORMAT);
} break;
}
return -1;
}
static void _qiot_comm_service_task(void *pvParameters)
{
int ret, server_socket = -1;
char addr_str[128] = {0};
char rx_buffer[1024] = {0};
comm_peer_t peer_client = {0};
int select_err_cnt = 0;
/* stay longer than 5 minutes to handle error log */
uint32_t server_count = WAIT_CNT_5MIN_SECONDS / SELECT_WAIT_TIME_SECONDS + 5;
server_socket = HAL_UDP_CreateBind("0.0.0.0", APP_SERVER_PORT);
if (server_socket < 0) {
Log_e("Unable to create socket: errno %d", HAL_UDP_GetErrno());
push_error_log(ERR_SOCKET_OPEN, HAL_UDP_GetErrno());
goto end_of_task;
}
Log_i("UDP server socket listening...");
while (sg_comm_task_run && --server_count) {
ret =
HAL_UDP_ReadTimeoutPeerInfo(server_socket, (unsigned char *)rx_buffer, sizeof(rx_buffer) - 1,
SELECT_WAIT_TIME_SECONDS * 1000, addr_str, sizeof(addr_str), &peer_client.port);
if (ret > 0) {
select_err_cnt = 0;
// Get the sender's ip address as string
peer_client.socket_id = server_socket;
peer_client.peer_addr = addr_str;
rx_buffer[ret] = '\0';
Log_i("Received %d bytes from <%s:%u> msg: %s", ret, peer_client.peer_addr, peer_client.port, rx_buffer);
// send error log here, otherwise no chance for previous error
get_and_post_error_log(&peer_client);
ret = _app_handle_recv_data(&peer_client, rx_buffer, ret);
if (ret == 1) {
Log_w("Finish app cmd handling.");
break;
}
get_and_post_error_log(&peer_client);
continue;
} else if (0 == ret) {
select_err_cnt = 0;
Log_d("wait for read...");
if (peer_client.peer_addr != NULL) {
get_and_post_error_log(&peer_client);
}
continue;
} else {
select_err_cnt++;
Log_w("select-recv error: %d, cnt: %d", HAL_UDP_GetErrno(), select_err_cnt);
if (select_err_cnt > 3) {
Log_e("select-recv error: %d, cnt: %d", HAL_UDP_GetErrno(), select_err_cnt);
push_error_log(ERR_SOCKET_SELECT, HAL_UDP_GetErrno());
break;
}
HAL_SleepMs(500);
}
}
end_of_task:
if (server_socket != -1) {
Log_w("Shutting down UDP server socket");
HAL_UDP_Close(server_socket);
}
sg_comm_task_run = false;
Log_i("UDP server task quit");
}
int qiot_comm_service_start(void)
{
sg_comm_task_run = true;
static ThreadParams params;
params.thread_func = _qiot_comm_service_task;
params.thread_name = COMM_SERVER_TASK_NAME;
params.stack_size = COMM_SERVER_TASK_STACK_BYTES;
params.priority = COMM_SERVER_TASK_PRIO;
params.user_arg = NULL;
int ret = HAL_ThreadCreate(&params);
if (ret != QCLOUD_RET_SUCCESS) {
Log_e("create comm_server_task failed: %d", ret);
PUSH_LOG("create comm_server_task failed: %d", ret);
push_error_log(ERR_OS_TASK, ret);
return -1;
}
return 0;
}
void qiot_comm_service_stop(void)
{
sg_comm_task_run = false;
}

View File

@ -0,0 +1,417 @@
/*
* Copyright (c) 2020 Tencent Cloud. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "cJSON.h"
#include "qcloud_iot_export.h"
#include "qcloud_iot_import.h"
#include "qcloud_wifi_config.h"
#include "qcloud_wifi_config_internal.h"
static bool sg_token_received = false;
static char sg_token_str[MAX_TOKEN_LENGTH + 4] = {0};
static int sg_bind_reply_code = -1;
typedef struct {
bool sub_ready;
bool send_ready;
int reply_code;
} TokenHandleData;
static void _mqtt_event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg)
{
MQTTMessage * mqtt_messge = (MQTTMessage *)msg->msg;
uintptr_t packet_id = (uintptr_t)msg->msg;
TokenHandleData *app_data = (TokenHandleData *)handle_context;
switch (msg->event_type) {
case MQTT_EVENT_DISCONNECT:
Log_i("MQTT disconnect.");
break;
case MQTT_EVENT_RECONNECT:
Log_i("MQTT reconnect.");
break;
case MQTT_EVENT_PUBLISH_RECVEIVED:
Log_i("unhandled msg arrived: topic=%s", mqtt_messge->ptopic);
break;
case MQTT_EVENT_SUBCRIBE_SUCCESS:
Log_d("mqtt topic subscribe success");
app_data->sub_ready = true;
break;
case MQTT_EVENT_SUBCRIBE_TIMEOUT:
Log_i("mqtt topic subscribe timeout");
app_data->sub_ready = false;
break;
case MQTT_EVENT_SUBCRIBE_NACK:
Log_i("mqtt topic subscribe NACK");
app_data->sub_ready = false;
break;
case MQTT_EVENT_PUBLISH_SUCCESS:
Log_i("publish success, packet-id=%u", (unsigned int)packet_id);
app_data->send_ready = true;
break;
case MQTT_EVENT_PUBLISH_TIMEOUT:
Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id);
app_data->send_ready = false;
break;
case MQTT_EVENT_PUBLISH_NACK:
Log_i("publish nack, packet-id=%u", (unsigned int)packet_id);
app_data->send_ready = false;
break;
default:
Log_i("unknown event type: %d", msg->event_type);
break;
}
}
// callback when MQTT msg arrives
static void _on_message_callback(void *pClient, MQTTMessage *message, void *userData)
{
if (message == NULL) {
Log_e("msg null");
return;
}
if (message->topic_len == 0 && message->payload_len == 0) {
Log_e("length zero");
return;
}
Log_i("recv msg topic: %s", message->ptopic);
uint32_t msg_topic_len = message->payload_len + 4;
char * buf = (char *)HAL_Malloc(msg_topic_len);
if (buf == NULL) {
Log_e("malloc %u bytes failed", msg_topic_len);
return;
}
memset(buf, 0, msg_topic_len);
memcpy(buf, message->payload, message->payload_len);
Log_i("msg payload: %s", buf);
cJSON *root = cJSON_Parse(buf);
if (!root) {
Log_e("Parsing JSON Error");
push_error_log(ERR_TOKEN_REPLY, ERR_APP_CMD_JSON_FORMAT);
} else {
cJSON *code_json = cJSON_GetObjectItem(root, "code");
if (code_json) {
TokenHandleData *app_data = (TokenHandleData *)userData;
app_data->reply_code = code_json->valueint;
Log_d("token reply code = %d", code_json->valueint);
sg_bind_reply_code = app_data->reply_code;
if (app_data->reply_code)
push_error_log(ERR_TOKEN_REPLY, app_data->reply_code);
} else {
Log_e("Parsing reply code Error");
push_error_log(ERR_TOKEN_REPLY, ERR_APP_CMD_JSON_FORMAT);
}
cJSON_Delete(root);
}
HAL_Free(buf);
}
// subscrib MQTT topic
static int _subscribe_topic_wait_result(void *client, DeviceInfo *dev_info, TokenHandleData *app_data)
{
char topic_name[128] = {0};
int size = HAL_Snprintf(topic_name, sizeof(topic_name), "$thing/down/service/%s/%s", dev_info->product_id,
dev_info->device_name);
if (size < 0 || size > sizeof(topic_name) - 1) {
Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name));
return QCLOUD_ERR_FAILURE;
}
SubscribeParams sub_params = DEFAULT_SUB_PARAMS;
sub_params.qos = QOS0;
sub_params.on_message_handler = _on_message_callback;
sub_params.user_data = (void *)app_data;
int rc = IOT_MQTT_Subscribe(client, topic_name, &sub_params);
if (rc < 0) {
Log_e("MQTT subscribe failed: %d", rc);
return rc;
}
int wait_cnt = 2;
while (!app_data->sub_ready && (wait_cnt-- > 0)) {
// wait for subscription result
rc = IOT_MQTT_Yield(client, 1000);
if (rc) {
Log_e("MQTT error: %d", rc);
return rc;
}
}
if (wait_cnt > 0) {
return QCLOUD_RET_SUCCESS;
} else {
Log_w("wait for subscribe result timeout!");
return QCLOUD_ERR_FAILURE;
}
}
// publish MQTT msg
static int _publish_token_msg(void *client, DeviceInfo *dev_info, char *token_str)
{
char topic_name[128] = {0};
int size = HAL_Snprintf(topic_name, sizeof(topic_name), "$thing/up/service/%s/%s", dev_info->product_id,
dev_info->device_name);
if (size < 0 || size > sizeof(topic_name) - 1) {
Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name));
return QCLOUD_ERR_FAILURE;
}
PublishParams pub_params = DEFAULT_PUB_PARAMS;
pub_params.qos = QOS1;
char topic_content[256] = {0};
size = HAL_Snprintf(topic_content, sizeof(topic_content),
"{\"method\":\"app_bind_token\",\"clientToken\":\"%s-%u\",\"params\": {\"token\":\"%s\"}}",
dev_info->device_name, HAL_GetTimeMs(), token_str);
if (size < 0 || size > sizeof(topic_content) - 1) {
Log_e("payload content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_content));
return QCLOUD_ERR_MALLOC;
}
pub_params.payload = topic_content;
pub_params.payload_len = strlen(topic_content);
return IOT_MQTT_Publish(client, topic_name, &pub_params);
}
// send token data via mqtt publishing
static int _send_token_wait_reply(void *client, DeviceInfo *dev_info, TokenHandleData *app_data)
{
int ret = 0;
int wait_cnt = 20;
// for smartconfig, we need to wait for the token data from app
while (!sg_token_received && (wait_cnt-- > 0)) {
IOT_MQTT_Yield(client, 1000);
Log_i("wait for token data...");
}
if (!sg_token_received) {
Log_e("Wait for token data timeout");
return QCLOUD_ERR_INVAL;
}
wait_cnt = 3;
publish_token:
ret = _publish_token_msg(client, dev_info, sg_token_str);
if (ret < 0 && (wait_cnt-- > 0)) {
Log_e("Client publish token failed: %d", ret);
if (IOT_MQTT_IsConnected(client)) {
IOT_MQTT_Yield(client, 500);
} else {
Log_e("Wifi or MQTT lost connection! Wait and retry!");
IOT_MQTT_Yield(client, 2000);
}
goto publish_token;
}
if (ret < 0)
return ret;
wait_cnt = 5;
while (!app_data->send_ready && (wait_cnt-- > 0)) {
IOT_MQTT_Yield(client, 1000);
Log_i("wait for token sending result...");
}
ret = 0;
if (!app_data->send_ready) {
Log_e("Client publish token timeout");
ret = QCLOUD_ERR_FAILURE;
}
return ret;
}
// get the device info or do device dynamic register
static int _get_reg_dev_info(DeviceInfo *dev_info)
{
int ret = HAL_GetDevInfo(dev_info);
if (ret) {
Log_e("HAL_GetDevInfo error: %d", ret);
return ret;
}
// just a sample to show if we need to do dynamic register
// if dev_info->device_secret == "YOUR_IOT_PSK", there is no device secret for now
// dev_info->product_secret != "YOUR_PRODUCT_SECRET", we have product secret and can do dynamic register
#ifdef DEV_DYN_REG_ENABLED
#ifdef AUTH_MODE_CERT
/* just demo the cert/key files are empty */
if ((0 != strcmp(dev_info->dev_cert_file_name, "YOUR_DEVICE_CERT_FILE_NAME")) &&
(0 != strcmp(dev_info->dev_key_file_name, "YOUR_DEVICE_PRIVATE_KEY_FILE_NAME"))) {
Log_d("dev Cert exist %s-%s", dev_info->dev_cert_file_name, dev_info->dev_key_file_name);
return QCLOUD_RET_SUCCESS;
}
Log_d("dev Cert not exist, do dyn reg!");
#else
/* just demo the PSK is empty */
if (0 != strcmp(dev_info->device_secret, "YOUR_IOT_PSK")) {
Log_d("dev psk exist");
return QCLOUD_RET_SUCCESS;
}
Log_d("dev psk not exist, do dyn reg!");
if (0 == strcmp(dev_info->device_secret, "YOUR_PRODUCT_SECRET")) {
Log_d("product secret not exist, please set it , dyn reg need");
return QCLOUD_RET_SUCCESS;
}
#endif
ret = IOT_DynReg_Device(dev_info);
if (ret) {
Log_e("dynamic register device failed: %d", ret);
return ret;
}
// save the dev info
ret = HAL_SetDevInfo(dev_info);
if (ret) {
Log_e("HAL_SetDevInfo failed: %d", ret);
return ret;
}
// delay a while
HAL_SleepMs(500);
#endif
return QCLOUD_RET_SUCCESS;
}
// setup mqtt connection and return client handle
static void *_setup_mqtt_connect(DeviceInfo *dev_info, TokenHandleData *app_data)
{
MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS;
init_params.device_name = dev_info->device_name;
init_params.product_id = dev_info->product_id;
#ifdef AUTH_MODE_CERT
init_params.cert_file = dev_info->dev_cert_file_name;
init_params.key_file = dev_info->dev_key_file_name;
#else
init_params.device_secret = dev_info->device_secret;
#endif
init_params.event_handle.h_fp = _mqtt_event_handler;
init_params.event_handle.context = (void *)app_data;
void *client = IOT_MQTT_Construct(&init_params);
if (client) {
Log_i("Cloud Device Construct Success");
}
return client;
}
// send mqtt token to iot explorer
static int _mqtt_send_token(void)
{
// get the device info or do device dynamic register
DeviceInfo dev_info;
int ret = _get_reg_dev_info(&dev_info);
if (ret) {
Log_e("Get device info failed: %d", ret);
return ret;
}
// token handle data
TokenHandleData app_data;
app_data.sub_ready = false;
app_data.send_ready = false;
app_data.reply_code = 404;
sg_bind_reply_code = app_data.reply_code;
// mqtt connection
void *client = _setup_mqtt_connect(&dev_info, &app_data);
if (client == NULL) {
ret = IOT_MQTT_GetErrCode();
Log_e("Cloud Device Construct Failed: %d", ret);
push_error_log(ERR_MQTT_CONNECT, ret);
return ret;
}
// subscribe token reply topic
ret = _subscribe_topic_wait_result(client, &dev_info, &app_data);
if (ret < 0) {
Log_w("Client Subscribe Topic Failed: %d", ret);
}
// publish token msg and wait for reply
int retry_cnt = 2;
do {
ret = _send_token_wait_reply(client, &dev_info, &app_data);
IOT_MQTT_Yield(client, 1000);
} while (ret && retry_cnt--);
if (ret)
push_error_log(ERR_TOKEN_SEND, ret);
IOT_MQTT_Destroy(&client);
// sleep 5 seconds to avoid frequent MQTT connection
if (ret == 0)
HAL_SleepMs(5000);
return ret;
}
int qiot_device_bind(void)
{
Log_d("device bind start");
int ret = _mqtt_send_token();
if (ret) {
Log_e("WIFI_MQTT_CONNECT_FAILED: %d", ret);
PUSH_LOG("WIFI_MQTT_CONNECT_FAILED: %d", ret);
} else {
Log_i("WIFI_MQTT_CONNECT_SUCCESS");
PUSH_LOG("WIFI_MQTT_CONNECT_SUCCESS");
}
return ret;
}
void qiot_device_bind_set_token(const char *token)
{
sg_token_received = true;
strncpy(sg_token_str, token, MAX_TOKEN_LENGTH);
}
bool qiot_device_bind_get_cloud_reply_code(int *bind_reply_code)
{
*bind_reply_code = sg_bind_reply_code;
Log_w("Device bind cloud reply code: %d", sg_bind_reply_code);
return sg_bind_reply_code == -1 ? false : true;
}

View File

@ -0,0 +1,348 @@
/*
* Copyright (c) 2020 Tencent Cloud. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <string.h>
#include <stdint.h>
#include "cJSON.h"
#include "qcloud_iot_export_log.h"
#include "qcloud_iot_export_error.h"
#include "qcloud_iot_import.h"
#include "qcloud_wifi_config.h"
#include "qcloud_wifi_config_internal.h"
/************** WiFi config error msg collect and post feature ******************/
#if WIFI_ERR_LOG_POST
static const char *g_err_log[] = {
"Everything OK!", /* SUCCESS_TYPE = 0,*/
"MQTT connect error!", /* ERR_MQTT_CONNECT = 1, */
"APP command error!", /* ERR_APP_CMD = 2,*/
"WIFI boarding stop!", /* ERR_BD_STOP = 3,*/
"RTOS task error!", /* ERR_OS_TASK = 4,*/
"RTOS queue error!", /* ERR_OS_QUEUE = 5,*/
"WIFI STA init error!", /* ERR_WIFI_STA_INIT = 6,*/
"WIFI AP init error!", /* ERR_WIFI_AP_INIT = 7,*/
"WIFI start error!", /* ERR_WIFI_START = 8,*/
"WIFI config error!", /* ERR_WIFI_CONFIG = 9,*/
"WIFI connect error!", /* ERR_WIFI_CONNECT = 10,*/
"WIFI disconnect error!", /* ERR_WIFI_DISCONNECT = 11,*/
"WIFI AP STA error!", /* ERR_WIFI_AP_STA = 12,*/
"ESP smartconfig start error!", /* ERR_SC_START = 13,*/
"ESP smartconfig data error!", /* ERR_SC_DATA = 14, */
"SRV socket open error!", /* ERR_SOCKET_OPEN = 15,*/
"SRV socket bind error!", /* ERR_SOCKET_BIND = 16,*/
"SRV socket listen error!", /* ERR_SOCKET_LISTEN = 17,*/
"SRV socket fcntl error!", /* ERR_SOCKET_FCNTL = 18,*/
"SRV socket accept error!", /* ERR_SOCKET_ACCEPT = 19,*/
"SRV socket recv error!", /* ERR_SOCKET_RECV = 20,*/
"SRV socket select error!", /* ERR_SOCKET_SELECT = 21,*/
"SRV socket send error!", /* ERR_SOCKET_SEND = 22,*/
"MQTT Token send error!", /* ERR_TOKEN_SEND = 23,*/
"MQTT Token reply error!", /* ERR_TOKEN_REPLY = 24,*/
};
typedef struct {
uint8_t record;
uint8_t reserved;
uint16_t err_id; /* error msg Id */
int32_t err_sub_id; /* error msg sub Id */
} err_log_t;
typedef struct {
uint32_t magic_header; /* VALID_MAGIC_CODE for valid info */
uint32_t log_cnt;
err_log_t err_log[0];
} save_err_log_t;
#define ERR_LOG_QUEUE_SIZE 16
#define VALID_MAGIC_CODE 0xF00DBEEF
/* FreeRTOS msg queue */
static void *g_err_log_queue = NULL;
static int check_err_log(uint32_t *log_cnt)
{
int ret;
uint32_t header, msg_cnt;
ret = HAL_Wifi_read_err_log(0, (uint32_t *)&header, sizeof(uint32_t));
if (QCLOUD_RET_SUCCESS != ret) {
Log_e(" wifi log read error: %d", ret);
return (int)ret;
}
/* not a valid log */
if (header != VALID_MAGIC_CODE) {
Log_i("invalid magic code: 0x%x", header);
return 0;
}
ret = HAL_Wifi_read_err_log(sizeof(uint32_t), (uint32_t *)&msg_cnt, sizeof(uint32_t));
if (QCLOUD_RET_SUCCESS != ret) {
Log_e("wifi log read error: %d", ret);
return (int)ret;
}
*log_cnt = msg_cnt;
return 0;
}
static int load_err_log(void *log, size_t log_size)
{
int ret;
size_t log_offset = 2 * sizeof(uint32_t);
ret = HAL_Wifi_read_err_log(log_offset, (uint32_t *)log, log_size);
if (QCLOUD_RET_SUCCESS != ret) {
Log_e("wifi log read error: %d", ret);
return ret;
}
return 0;
}
static int save_err_log(void *log, size_t log_size)
{
int ret;
ret = HAL_Wifi_write_err_log(0, (uint32_t *)log, log_size);
if (QCLOUD_RET_SUCCESS != ret) {
Log_e("wifi log write error: %d", ret);
return ret;
}
return 0;
}
static int clear_err_log(void)
{
return HAL_Wifi_clear_err_log();
}
int handle_saved_error_log(void)
{
uint32_t log_cnt = 0;
if (check_err_log(&log_cnt)) {
Log_e("check error log cnt failed");
return -1;
}
if (log_cnt == 0)
return 0;
if (log_cnt > ERR_LOG_QUEUE_SIZE) {
Log_e("invalid log cnt: %u", log_cnt);
return -1;
}
size_t log_size = log_cnt * sizeof(err_log_t);
err_log_t *log_src = (err_log_t *)HAL_Malloc(log_size);
if (log_src == NULL) {
Log_e("malloc failed");
return -1;
}
if (load_err_log(log_src, log_size)) {
HAL_Free(log_src);
Log_e("load error log failed");
return -1;
}
clear_err_log();
uint32_t i = 0;
do {
/* change the record type to previous error */
log_src[i].record = PRE_ERR;
Log_i("Handle Previous Error: %s (%u, %d)", g_err_log[log_src[i].err_id], log_src[i].err_id,
log_src[i].err_sub_id);
/* unblocking send */
int ret = HAL_QueueItemPush(g_err_log_queue, &log_src[i], 0);
if (ret != QCLOUD_RET_SUCCESS) {
Log_e("xQueueGenericSend failed: %d", ret);
HAL_Free(log_src);
return ERR_OS_QUEUE;
}
i++;
} while (i < log_cnt);
HAL_Free(log_src);
return 0;
}
#endif // WIFI_ERR_LOG_POST
// error happen flag
static bool sg_error_happen = false;
int init_error_log_queue(void)
{
sg_error_happen = false;
#if WIFI_ERR_LOG_POST
if (g_err_log_queue) {
Log_d("re-enter, reset queue");
HAL_QueueReset(g_err_log_queue);
return 0;
}
g_err_log_queue = HAL_QueueCreate(ERR_LOG_QUEUE_SIZE, sizeof(err_log_t));
if (g_err_log_queue == NULL) {
Log_e("HAL_QueueCreate failed");
return ERR_OS_QUEUE;
}
handle_saved_error_log();
#endif
return 0;
}
int push_error_log(uint16_t err_id, int32_t err_sub_id)
{
sg_error_happen = true;
#if WIFI_ERR_LOG_POST
if (g_err_log_queue == NULL) {
Log_e("log queue not initialized and push_error_log called");
return ERR_OS_QUEUE;
}
err_log_t err_log = {.record = CUR_ERR, .err_id = err_id, .err_sub_id = err_sub_id};
Log_e("Boarding error happen: %s (%u, %d)", g_err_log[err_log.err_id], err_log.err_id, err_log.err_sub_id);
/* unblocking send */
int ret = HAL_QueueItemPush(g_err_log_queue, &err_log, 0);
if (ret != QCLOUD_RET_SUCCESS) {
Log_e("HAL_QueueItemPush failed: %d", ret);
return ERR_OS_QUEUE;
}
#else
Log_e("error happen, err_id: %u err_sub_id: %d", err_id, err_sub_id);
#endif
return 0;
}
bool is_config_error_happen(void)
{
return sg_error_happen;
}
int app_send_error_log(comm_peer_t *peer, uint8_t record, uint16_t err_id, int32_t err_sub_id)
{
#if WIFI_ERR_LOG_POST
int ret;
char msg_str[64] = {0};
//char json_str[128] = {0};
char *json_str=NULL;
HAL_Snprintf(msg_str, sizeof(msg_str), "%s (%u, %d)", g_err_log[err_id], err_id, err_sub_id);
cJSON *reply_json = cJSON_CreateObject();
cJSON_AddNumberToObject(reply_json, "cmdType", (int)CMD_DEVICE_REPLY);
cJSON_AddStringToObject(reply_json, "deviceReply", record == CUR_ERR ? "Current_Error" : "Previous_Error");
cJSON_AddStringToObject(reply_json, "log", msg_str);
#if 0
if (0 == cJSON_PrintPreallocated(reply_json, json_str, sizeof(json_str), 0)) {
Log_e("cJSON_PrintPreallocated failed!");
cJSON_Delete(reply_json);
return -1;
}
#endif
json_str= cJSON_Print(reply_json);
if (!json_str)
{
Log_e("cJSON_PrintPreallocated failed!");
cJSON_Delete(reply_json);
app_send_error_log(peer, CUR_ERR, ERR_APP_CMD, ERR_JSON_PRINT);
return -1;
}
/* append msg delimiter */
strcat(json_str, "\r\n");
ret = HAL_UDP_WriteTo(peer->socket_id, (unsigned char *)json_str, strlen(json_str), peer->peer_addr, peer->port);
if (ret < 0) {
Log_e("send error: %s", HAL_UDP_GetErrnoStr());
} else
Log_w("send error msg: %s", json_str);
cJSON_Delete(reply_json);
return ret;
#else
return 0;
#endif
}
int get_and_post_error_log(comm_peer_t *peer)
{
int err_cnt = 0;
#if WIFI_ERR_LOG_POST
err_log_t err_msg;
int rc = QCLOUD_RET_SUCCESS;
do {
if (QCLOUD_RET_SUCCESS == (rc = HAL_QueueItemPop(g_err_log_queue, &err_msg, 0))) {
app_send_error_log(peer, err_msg.record, err_msg.err_id, err_msg.err_sub_id);
if (err_msg.record == CUR_ERR)
err_cnt++;
}
} while (rc == QCLOUD_RET_SUCCESS);
#endif
return err_cnt;
}
int save_error_log(void)
{
#if WIFI_ERR_LOG_POST
int rc = QCLOUD_RET_SUCCESS;
uint32_t log_cnt = (uint32_t)HAL_QueueItemWaitingCount(g_err_log_queue);
if (log_cnt == 0)
return 0;
size_t log_size = 2 * sizeof(uint32_t) + log_cnt * sizeof(err_log_t);
save_err_log_t *log_src = (save_err_log_t *)HAL_Malloc(log_size);
if (log_src == NULL) {
Log_e("malloc failed");
return -1;
}
uint32_t i = 0, j = 0;
do {
if (QCLOUD_RET_SUCCESS == (rc = HAL_QueueItemPop(g_err_log_queue, &log_src->err_log[i], 0))) {
/* only save current error */
if (log_src->err_log[i].record == CUR_ERR) {
Log_w("Save unhandled Current Error %u: %s (%u, %d)", j + 1, g_err_log[log_src->err_log[i].err_id],
log_src->err_log[i].err_id, log_src->err_log[i].err_sub_id);
j++;
} else {
Log_w("Discard Previous Error: %s (%u, %d)", g_err_log[log_src->err_log[i].err_id],
log_src->err_log[i].err_id, log_src->err_log[i].err_sub_id);
}
i++;
}
} while (i < log_cnt && rc == QCLOUD_RET_SUCCESS);
HAL_QueueDestory(g_err_log_queue);
log_src->magic_header = VALID_MAGIC_CODE;
log_src->log_cnt = j;
log_size = 2 * sizeof(uint32_t) + log_src->log_cnt * sizeof(err_log_t);
if (log_size != save_err_log(log_src, log_size)) {
HAL_Free(log_src);
Log_e("save error log to flash failed");
return -1;
}
HAL_Free(log_src);
#endif
return 0;
}

View File

@ -0,0 +1,246 @@
/*
* Copyright (c) 2020 Tencent Cloud. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <string.h>
#include "cJSON.h"
#include "qcloud_iot_export_log.h"
#include "qcloud_iot_export_error.h"
#include "qcloud_iot_import.h"
#include "qcloud_wifi_config.h"
#include "qcloud_wifi_config_internal.h"
/************** WiFi config error msg collect and post feature ******************/
#define LOG_QUEUE_SIZE 10
#define LOG_ITEM_SIZE 128
#define LOG_SERVER_TASK_NAME "log_server_task"
#define LOG_SERVER_TASK_STACK_BYTES 4096
#define LOG_SERVER_TASK_PRIO 1
/* msg queue */
#if WIFI_LOG_UPLOAD
static void *sg_dev_log_queue = NULL;
static bool sg_log_task_run = false;
#endif
int init_dev_log_queue(void)
{
#if WIFI_LOG_UPLOAD
if (sg_dev_log_queue) {
Log_d("re-enter, reset queue");
HAL_QueueReset(sg_dev_log_queue);
return 0;
}
sg_dev_log_queue = HAL_QueueCreate(LOG_QUEUE_SIZE, LOG_ITEM_SIZE);
if (sg_dev_log_queue == NULL) {
Log_e("xQueueCreate failed");
return ERR_OS_QUEUE;
}
#endif
return 0;
}
void delete_dev_log_queue(void)
{
#if WIFI_LOG_UPLOAD
HAL_QueueDestory(sg_dev_log_queue);
sg_dev_log_queue = NULL;
#endif
}
int push_dev_log(const char *func, const int line, const char *fmt, ...)
{
#if WIFI_LOG_UPLOAD
if (sg_dev_log_queue == NULL) {
Log_e("log queue not initialized!");
return ERR_OS_QUEUE;
}
char log_buf[LOG_ITEM_SIZE];
memset(log_buf, 0, LOG_ITEM_SIZE);
// only keep the latest LOG_QUEUE_SIZE log
uint32_t log_cnt = (uint32_t)HAL_QueueItemWaitingCount(sg_dev_log_queue);
if (log_cnt == LOG_QUEUE_SIZE) {
// pop the oldest one
HAL_QueueItemPop(sg_dev_log_queue, log_buf, 0);
HAL_Printf("<<< POP LOG: %s", log_buf);
}
char *o = log_buf;
memset(log_buf, 0, LOG_ITEM_SIZE);
o += HAL_Snprintf(o, LOG_ITEM_SIZE, "%u|%s(%d): ", HAL_GetTimeMs(), func, line);
va_list ap;
va_start(ap, fmt);
HAL_Vsnprintf(o, LOG_ITEM_SIZE - 3 - strlen(log_buf), fmt, ap);
va_end(ap);
strcat(log_buf, "\r\n");
/* unblocking send */
int ret = HAL_QueueItemPush(sg_dev_log_queue, log_buf, 0);
if (ret != QCLOUD_RET_SUCCESS) {
Log_e("HAL_QueueItemPush failed: %d", ret);
return ERR_OS_QUEUE;
}
#endif
return 0;
}
int app_send_dev_log(comm_peer_t *peer)
{
int ret = 0;
#if WIFI_LOG_UPLOAD
if (sg_dev_log_queue == NULL) {
Log_e("log queue not initialized!");
return ERR_OS_QUEUE;
}
uint32_t log_cnt = (uint32_t)HAL_QueueItemWaitingCount(sg_dev_log_queue);
if (log_cnt == 0)
return 0;
size_t max_len = (log_cnt * LOG_ITEM_SIZE) + 32;
char * json_buf = HAL_Malloc(max_len);
if (json_buf == NULL) {
Log_e("malloc failed!");
return -1;
}
memset(json_buf, 0, max_len);
char log_buf[LOG_ITEM_SIZE];
int rc;
do {
memset(log_buf, 0, LOG_ITEM_SIZE);
rc = HAL_QueueItemPop(sg_dev_log_queue, log_buf, 0);
if (rc == QCLOUD_RET_SUCCESS) {
strcat(json_buf, log_buf);
}
} while (rc == QCLOUD_RET_SUCCESS);
HAL_Printf("to reply: %s\r\n", json_buf);
int i = 0;
for (i = 0; i < 2; i++) {
ret =
HAL_UDP_WriteTo(peer->socket_id, (unsigned char *)json_buf, strlen(json_buf), peer->peer_addr, peer->port);
if (ret < 0) {
Log_e("send error: %s", HAL_UDP_GetErrnoStr());
break;
}
HAL_SleepMs(500);
}
HAL_Free(json_buf);
#endif
return ret;
}
#if WIFI_LOG_UPLOAD
static void log_server_task(void *pvParameters)
{
int ret, server_socket = -1;
char rx_buffer[256] = {0};
/* stay 6 minutes to handle log */
uint32_t server_count = 360 / SELECT_WAIT_TIME_SECONDS;
server_socket = HAL_UDP_CreateBind("0.0.0.0", LOG_SERVER_PORT);
Log_i("LOG server socket waiting recv msg...");
char peer_client_addr[128] = {0};
unsigned short peer_client_port = 0;
comm_peer_t peer = {0};
int select_err_cnt = 0;
while (sg_log_task_run && --server_count) {
int len = HAL_UDP_ReadTimeoutPeerInfo(server_socket, (unsigned char *)rx_buffer, sizeof(rx_buffer) - 1,
SELECT_WAIT_TIME_SECONDS * 1000, peer_client_addr,
sizeof(peer_client_addr), &peer_client_port);
// Error occured during receiving
if (len > 0) {
select_err_cnt = 0;
// Get the sender's ip address as string
rx_buffer[len] = '0';
Log_i("Received %d bytes from <%s:%u> msg: %s", len, peer_client_addr, peer_client_port, rx_buffer);
if (strncmp(rx_buffer, "{\"cmdType\":3}", 12) == 0) {
peer.socket_id = server_socket;
peer.peer_addr = peer_client_addr;
peer.port = peer_client_port;
ret = app_send_dev_log(&peer);
Log_i("app_send_dev_log ret: %d", ret);
break;
}
} else if (0 == len) {
select_err_cnt = 0;
Log_d("wait for read...");
continue;
} else {
select_err_cnt++;
Log_w("select-recv error: %d, cnt: %d, ret: %d", HAL_UDP_GetErrno(), select_err_cnt, len);
HAL_SleepMs(500);
}
}
if (server_socket != -1) {
Log_w("close LOG server socket");
HAL_UDP_Close(server_socket);
}
stop_device_softAP();
sg_log_task_run = false;
Log_i("LOG server task quit");
}
#endif
int qiot_log_service_start(void)
{
#if WIFI_LOG_UPLOAD
sg_log_task_run = true;
static ThreadParams params;
params.thread_func = log_server_task;
params.thread_name = LOG_SERVER_TASK_NAME;
params.stack_size = LOG_SERVER_TASK_STACK_BYTES;
params.priority = LOG_SERVER_TASK_PRIO;
params.user_arg = NULL;
int ret = HAL_ThreadCreate(&params);
if (ret != QCLOUD_RET_SUCCESS) {
Log_e("create log_server_task failed: %d", ret);
PUSH_LOG("create log_server_task failed: %d", ret);
push_error_log(ERR_OS_TASK, ret);
sg_log_task_run = false;
return QCLOUD_ERR_FAILURE;
}
#endif
return QCLOUD_RET_SUCCESS;
}
void qiot_log_service_stop(void)
{
#if WIFI_LOG_UPLOAD
sg_log_task_run = false;
#endif
}

View File

@ -711,7 +711,7 @@ static int _http_network_init(Network *pNetwork, const char *host, int port, con
pNetwork->host = host;
pNetwork->port = port;
rc = network_init(pNetwork);
rc = qcloud_iot_network_init(pNetwork);
return rc;
}

View File

@ -69,7 +69,7 @@ static char *_get_service_mqtt_topic_info(void)
static Service_Event_Struct_t *_get_service_event_handle(eServiceEvent evt)
{
if ( evt >= sizeof(sg_service_event_map) / sizeof(sg_service_event_map[0])) {
if (evt < 0 || evt >= sizeof(sg_service_event_map) / sizeof(sg_service_event_map[0])) {
return NULL;
}
@ -78,7 +78,7 @@ static Service_Event_Struct_t *_get_service_event_handle(eServiceEvent evt)
static int _set_service_event_handle(eServiceEvent evt, OnServiceMessageCallback callback, void *context)
{
if (evt >= sizeof(sg_service_event_map) / sizeof(sg_service_event_map[0])) {
if (evt < 0 || evt >= sizeof(sg_service_event_map) / sizeof(sg_service_event_map[0])) {
return QCLOUD_ERR_INVAL;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1,129 +0,0 @@
/*
* Copyright (c) 2020 Bouffalolab.
*
* This file is part of
* *** Bouffalolab Software Dev Kit ***
* (see www.bouffalolab.com).
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "blsync_ble_app.h"
#include "wifi_prov_api.h"
#include <FreeRTOS.h>
#include <task.h>
#include "blsync_ble.h"
#include "bluetooth.h"
#include "ble_cli_cmds.h"
#include "hci_driver.h"
#include "ble_lib_api.h"
static bl_ble_sync_t *gp_index = NULL;
static void wifiprov_connect_ap_ind(struct wifi_conn *info)
{
extern int wifi_mgmr_status_code_clean_internal();
wifi_mgmr_status_code_clean_internal();
printf("Recevied indication to connect to AP\r\n");
wifi_prov_api_event_trigger_connect(info);
}
static void wifiprov_disc_from_ap_ind(void)
{
printf("Recevied indication to disconnect to AP\r\n");
wifi_prov_api_event_trigger_disconnect();
}
static void wifiprov_wifi_scan(void(*complete)(void *))
{
printf("Recevied indication to wifi scan\r\n");
wifi_prov_api_event_trigger_scan(complete);
}
static void wifiprov_api_state_get(void(*state_get)(void *))
{
printf("Recevied indication to wifi state get\r\n");
wifi_prov_api_event_state_get(state_get);
}
static void blesync_complete_cb (void *p_arg)
{
bl_ble_sync_t *p_index = (bl_ble_sync_t *)p_arg;
bl_ble_sync_stop(p_index);
vPortFree(p_index);
}
static struct blesync_wifi_func WifiProv_conn_callback = {
.local_connect_remote_ap = wifiprov_connect_ap_ind,
.local_disconnect_remote_ap = wifiprov_disc_from_ap_ind,
.local_wifi_scan = wifiprov_wifi_scan,
.local_wifi_state_get = wifiprov_api_state_get,
};
static void blsync_init(int err)
{
if (err != 0) {
return;
}
if (gp_index != NULL) {
printf("blsync already started\r\n");
return;
}
ble_cli_register();
gp_index = pvPortMalloc(sizeof(bl_ble_sync_t));
if (gp_index == NULL) {
return;
}
bl_ble_sync_start(gp_index,
&WifiProv_conn_callback,
blesync_complete_cb,
(void *)gp_index);
}
static void ble_stack_start(void)
{
// Initialize BLE controller
ble_controller_init(configMAX_PRIORITIES - 1);
// Initialize BLE Host stack
hci_driver_init();
bt_enable(blsync_init);
}
void blsync_ble_start (void)
{
static uint8_t stack_started = 0;
if (stack_started == 1) {
blsync_init(0);
return;
}
ble_stack_start();
stack_started = 1;
}
void blsync_ble_stop (void)
{
bl_ble_sync_stop(gp_index);
vPortFree(gp_index);
gp_index = NULL;
}

View File

@ -1,37 +0,0 @@
/*
* Copyright (c) 2020 Bouffalolab.
*
* This file is part of
* *** Bouffalolab Software Dev Kit ***
* (see www.bouffalolab.com).
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __BLE_SYNC_H_
#define __BLE_SYNC_H_
void blsync_ble_start (void);
void blsync_ble_stop (void);
#endif

View File

@ -27,23 +27,17 @@
#include <task.h>
#include <stdio.h>
#include <string.h>
#include <bl_i2c.h>
#include <semphr.h>
#include <hal_i2c.h>
#define GXHT3X_ADDR 0x45
extern TaskHandle_t q_cloud_demo_task;
#ifdef AUTH_MODE_CERT
static char sg_cert_file[PATH_MAX + 1]; // full path of device cert file
static char sg_key_file[PATH_MAX + 1]; // full path of device key file
#endif
static DeviceInfo sg_devInfo;
static Timer sg_reportTimer;
#define DATA_TEMPLATE_WITHOUT_STRUCT 1
/* anis color control codes */
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
@ -58,125 +52,92 @@ static size_t sg_data_report_buffersize = sizeof(sg_data_report_buffer) /
/*data_config.c can be generated by tools/codegen.py -c xx/product.json*/
/*-----------------data config start -------------------*/
#define TOTAL_PROPERTY_COUNT 2
static sDataPoint sg_DataTemplate[TOTAL_PROPERTY_COUNT];
#define TOTAL_PROPERTY_COUNT 5
#define MAX_STR_NAME_LEN (64)
static sDataPoint sg_DataTemplate[TOTAL_PROPERTY_COUNT];
typedef enum {
eCOLOR_RED = 0,
eCOLOR_GREEN = 1,
eCOLOR_BLUE = 2,
} eColor;
typedef struct _ProductDataDefine {
TYPE_DEF_TEMPLATE_FLOAT m_Temperature_DATA;
TYPE_DEF_TEMPLATE_FLOAT m_Humidity_DATA;
TYPE_DEF_TEMPLATE_BOOL m_light_switch;
TYPE_DEF_TEMPLATE_ENUM m_color;
TYPE_DEF_TEMPLATE_INT m_brightness;
TYPE_DEF_TEMPLATE_STRING m_name[MAX_STR_NAME_LEN + 1];
TYPE_DEF_TEMPLATE_OBJECT m_position;
} ProductDataDefine;
static ProductDataDefine sg_ProductData;
static ProductDataDefine sg_ProductData;
#define TOTAL_PROPERTY_STRUCT_POSITION_COUNT 2
static sDataPoint sg_StructTemplatePosition[TOTAL_PROPERTY_STRUCT_POSITION_COUNT];
typedef struct _StructDefinePosition {
TYPE_DEF_TEMPLATE_INT m_longitude;
TYPE_DEF_TEMPLATE_INT m_latitude;
} StructDefinePosition;
static StructDefinePosition sg_StructDataPosition;
static void _init_struct_position(void)
{
sg_StructDataPosition.m_longitude = 1;
sg_StructTemplatePosition[0].data_property.data = &sg_StructDataPosition.m_longitude;
sg_StructTemplatePosition[0].data_property.key = "longitude";
sg_StructTemplatePosition[0].data_property.type = TYPE_TEMPLATE_INT;
sg_StructTemplatePosition[0].state = eCHANGED;
sg_StructDataPosition.m_latitude = 1;
sg_StructTemplatePosition[1].data_property.data = &sg_StructDataPosition.m_latitude;
sg_StructTemplatePosition[1].data_property.key = "latitude";
sg_StructTemplatePosition[1].data_property.type = TYPE_TEMPLATE_INT;
sg_StructTemplatePosition[1].state = eCHANGED;
};
static void _init_data_template(void)
{
memset((void *)&sg_ProductData, 0, sizeof(ProductDataDefine));
sg_ProductData.m_Temperature_DATA = 0;
sg_DataTemplate[0].data_property.data = &sg_ProductData.m_Temperature_DATA;
sg_DataTemplate[0].data_property.key = "Temperature_DATA";
sg_DataTemplate[0].data_property.type = TYPE_TEMPLATE_FLOAT;
sg_DataTemplate[0].state = eCHANGED;
sg_ProductData.m_light_switch = 0;
sg_DataTemplate[0].data_property.key = "power_switch";
sg_DataTemplate[0].data_property.data = &sg_ProductData.m_light_switch;
sg_DataTemplate[0].data_property.type = TYPE_TEMPLATE_BOOL;
sg_ProductData.m_Humidity_DATA = 0;
sg_DataTemplate[1].data_property.data = &sg_ProductData.m_Humidity_DATA;
sg_DataTemplate[1].data_property.key = "Humidity_DATA";
sg_DataTemplate[1].data_property.type = TYPE_TEMPLATE_FLOAT;
sg_DataTemplate[1].state = eCHANGED;
sg_ProductData.m_color = eCOLOR_RED;
sg_DataTemplate[1].data_property.key = "color";
sg_DataTemplate[1].data_property.data = &sg_ProductData.m_color;
sg_DataTemplate[1].data_property.type = TYPE_TEMPLATE_ENUM;
sg_ProductData.m_brightness = 0;
sg_DataTemplate[2].data_property.key = "brightness";
sg_DataTemplate[2].data_property.data = &sg_ProductData.m_brightness;
sg_DataTemplate[2].data_property.type = TYPE_TEMPLATE_INT;
strncpy(sg_ProductData.m_name, sg_devInfo.device_name, MAX_STR_NAME_LEN);
sg_ProductData.m_name[strlen(sg_devInfo.device_name)] = '\0';
sg_DataTemplate[3].data_property.key = "name";
sg_DataTemplate[3].data_property.data = sg_ProductData.m_name;
sg_DataTemplate[3].data_property.data_buff_len = MAX_STR_NAME_LEN;
sg_DataTemplate[3].data_property.type = TYPE_TEMPLATE_STRING;
_init_struct_position();
sg_ProductData.m_position = (void *)&sg_StructTemplatePosition;
sg_DataTemplate[4].data_property.data = sg_ProductData.m_position;
sg_DataTemplate[4].data_property.struct_obj_num = TOTAL_PROPERTY_STRUCT_POSITION_COUNT;
sg_DataTemplate[4].data_property.key = "position";
sg_DataTemplate[4].data_property.type = TYPE_TEMPLATE_JOBJECT;
sg_DataTemplate[4].state = eCHANGED;
};
void GXHT3X_GetData(void)
{
i2c_msg_t init_msg[2];
uint8_t init_buf[2];
uint8_t sensor_buf[6];
uint16_t tem;
uint16_t hum;
float Temperature=0;
float Humidity=0;
memset(sensor_buf, 0, 6);
init_buf[0]=0x2C;
init_buf[1]=0x10;
init_msg[0].addr = GXHT3X_ADDR;
init_msg[0].subflag = 0;
init_msg[0].subaddr = 0;
init_msg[0].buf = init_buf;
init_msg[0].direct = I2C_M_WRITE;
init_msg[0].block = I2C_M_NO_BLOCK;
init_msg[0].len = 2;
init_msg[0].idex = 0;
init_msg[0].sublen = 0;
init_msg[0].i2cx = 0;
i2c_transfer_msgs_block(init_msg, 1, 0);
vTaskDelay(100);
init_msg[0].addr = GXHT3X_ADDR;
init_msg[0].subflag = 0;
init_msg[0].subaddr = 0;
init_msg[0].buf = sensor_buf;
init_msg[0].direct = I2C_M_READ;
init_msg[0].block = I2C_M_NO_BLOCK;
init_msg[0].len = 6;
init_msg[0].idex = 0;
init_msg[0].sublen = 0;
init_msg[0].i2cx = 0;
i2c_transfer_msgs_block(init_msg, 1, 0);
tem = ((sensor_buf[0]<<8) | sensor_buf[1]);//温度拼接
hum = ((sensor_buf[3]<<8) | sensor_buf[4]);//湿度拼接
Temperature= (((175.0*(float)tem)/65535.0)-45.0) ;// T = -45 + 175 * tem / (2^16-1)
Humidity= ((100.0*(float)hum)/65535.0);// RH = hum*100 / (2^16-1)
if((Temperature>=-20)&&(Temperature<=125)&&(Humidity>=0)&&(Humidity<=100))//过滤错误数据
{
Log_i("sensor data ok\n");
memset((void *)&sg_ProductData, 0, sizeof(ProductDataDefine));
Log_i("Temperature:%6.2f*C Humidity%6.2f%% \n",Temperature,Humidity);
memset((void *)&sg_ProductData, 0, sizeof(ProductDataDefine));
sg_ProductData.m_Temperature_DATA = Temperature;
sg_DataTemplate[0].data_property.data = &sg_ProductData.m_Temperature_DATA;
sg_DataTemplate[0].data_property.key = "Temperature_DATA";
sg_DataTemplate[0].data_property.type = TYPE_TEMPLATE_FLOAT;
sg_DataTemplate[0].state = eCHANGED;
sg_ProductData.m_Humidity_DATA = Humidity;
sg_DataTemplate[1].data_property.data = &sg_ProductData.m_Humidity_DATA;
sg_DataTemplate[1].data_property.key = "Humidity_DATA";
sg_DataTemplate[1].data_property.type = TYPE_TEMPLATE_FLOAT;
sg_DataTemplate[1].state = eCHANGED;
}else{
Log_e("sensor data error\n");
}
}
/*-----------------data config end -------------------*/
/*event_config.c can be generated by tools/codegen.py -c xx/product.json*/
/*-----------------event config start -------------------*/
#ifdef EVENT_POST_ENABLED
#ifdef EVENT_POST_ENABLED
#define EVENT_COUNTS (3)
#define MAX_EVENT_STR_MESSAGE_LEN (64)
#define MAX_EVENT_STR_NAME_LEN (64)
@ -565,17 +526,92 @@ static void set_property_state(void *pProperyData, eDataState state)
/* demo for light logic deal */
static void deal_down_stream_user_logic(void *client, ProductDataDefine *light)
{
int i;
const char *ansi_color = NULL;
const char *ansi_color_name = NULL;
char brightness_bar[] = "||||||||||||||||||||";
int brightness_bar_len = strlen(brightness_bar);
/* light color */
switch (light->m_color) {
case eCOLOR_RED:
ansi_color = ANSI_COLOR_RED;
ansi_color_name = " RED ";
break;
case eCOLOR_GREEN:
ansi_color = ANSI_COLOR_GREEN;
ansi_color_name = "GREEN";
break;
case eCOLOR_BLUE:
ansi_color = ANSI_COLOR_BLUE;
ansi_color_name = " BLUE";
break;
default:
ansi_color = ANSI_COLOR_YELLOW;
ansi_color_name = "UNKNOWN";
break;
}
/* light brightness bar */
brightness_bar_len =
(light->m_brightness >= 100) ? brightness_bar_len : (int)((light->m_brightness * brightness_bar_len) / 100);
for (i = brightness_bar_len; i < strlen(brightness_bar); i++) {
brightness_bar[i] = '-';
}
if (light->m_light_switch) {
/* light is on , show with the properties*/
HAL_Printf("%s[ lighting ]|[color:%s]|[brightness:%s]|[%s]\n" ANSI_COLOR_RESET, ansi_color, ansi_color_name,
brightness_bar, light->m_name);
} else {
/* light is off */
HAL_Printf(ANSI_COLOR_YELLOW "[ light is off ]|[color:%s]|[brightness:%s]|[%s]\n" ANSI_COLOR_RESET,
ansi_color_name, brightness_bar, light->m_name);
}
if (eCHANGED == get_property_state(&light->m_light_switch)) {
#ifdef EVENT_POST_ENABLED
if (light->m_light_switch) {
*(TYPE_DEF_TEMPLATE_BOOL *)g_events[0].pEventData[0].data = 1;
memset((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, 0, MAX_EVENT_STR_MESSAGE_LEN);
strcpy((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, "light on");
} else {
*(TYPE_DEF_TEMPLATE_BOOL *)g_events[0].pEventData[0].data = 0;
memset((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, 0, MAX_EVENT_STR_MESSAGE_LEN);
strcpy((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, "light off");
}
// switch state changed set EVENT0 flag, the events will be posted by
// eventPostCheck
IOT_Event_setFlag(client, FLAG_EVENT0);
#else
Log_d("light switch state changed");
#endif
}
if (eCHANGED == get_property_state(light->m_position)) {
Log_d("light longitude: %d, latitude: %d", sg_StructDataPosition.m_longitude, sg_StructDataPosition.m_latitude);
}
}
/*example for cycle report, you can delete this for your needs*/
static void cycle_report(Timer *reportTimer)
{
int i;
if (expired(reportTimer)) {
for (i = 0; i < TOTAL_PROPERTY_COUNT - DATA_TEMPLATE_WITHOUT_STRUCT; i++) {
set_property_state(sg_DataTemplate[i].data_property.data, eCHANGED);
countdown_ms(reportTimer, 5000);
}
}
}
/*get local property data, like sensor data*/
static void _refresh_local_property(void)
{
GXHT3X_GetData();
set_property_state(sg_DataTemplate[0].data_property.data, eCHANGED);
set_property_state(sg_DataTemplate[1].data_property.data, eCHANGED);
// add your local property refresh logic, cycle report for example
cycle_report(&sg_reportTimer);
}
/*find propery need report*/
@ -630,23 +666,23 @@ static int _get_sys_info(void *handle, char *pJsonDoc, size_t sizeOfBuffer)
return IOT_Template_JSON_ConstructSysInfo(handle, pJsonDoc, sizeOfBuffer, plat_info, self_info);
}
int bl_qcloud_main(void *arg)
void bl_qcloud_main(void)
{
DeviceProperty *pReportDataList[TOTAL_PROPERTY_COUNT];
sReplyPara replyPara;
int ReportCont;
int rc;
void *client=NULL;
// init log level
IOT_Log_Set_Level(eLOG_DEBUG);
// init connection
// parse arguments for device info file
// init connection
TemplateInitParams init_params = DEFAULT_TEMPLATE_INIT_PARAMS;
rc = _setup_connect_init_params(&init_params);
if (rc != QCLOUD_RET_SUCCESS) {
Log_e("init params err,rc=%d", rc);
return rc;
goto exit_1;
}
#ifdef LOG_UPLOAD
@ -657,12 +693,12 @@ int bl_qcloud_main(void *arg)
}
#endif
void *client = IOT_Template_Construct(&init_params, NULL);
client = IOT_Template_Construct(&init_params, NULL);
if (client != NULL) {
Log_i("Cloud Device Construct Success");
} else {
Log_e("Cloud Device Construct Failed");
return QCLOUD_ERR_FAILURE;
goto exit_1;
}
#ifdef MULTITHREAD_ENABLED
@ -718,7 +754,8 @@ int bl_qcloud_main(void *arg)
Log_d("Get data status success");
}
// init a timer for cycle report, you could delete it or not for your needs
InitTimer(&sg_reportTimer);
while (IOT_Template_IsConnected(client) || rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT ||
rc == QCLOUD_RET_MQTT_RECONNECTED || QCLOUD_RET_SUCCESS == rc) {
@ -773,17 +810,18 @@ int bl_qcloud_main(void *arg)
HAL_SleepMs(1000);
}
exit_1:
q_cloud_demo_task = NULL;
vTaskDelete(NULL);
exit:
#ifdef MULTITHREAD_ENABLED
IOT_Template_Stop_Yield_Thread(client);
#endif
rc = IOT_Template_Destroy(client);
#ifdef LOG_UPLOAD
IOT_Log_Upload(true);
IOT_Log_Fini_Uploader();
#endif
return rc;
q_cloud_demo_task = NULL;
vTaskDelete(NULL);
}

View File

@ -82,8 +82,6 @@
#include <libfdt.h>
#include <blog.h>
#include "blsync_ble_app.h"
#define CODE_CLI_BLSYNC_START 0x01
#define CODE_CLI_BLSYNC_STOP 0x02
@ -417,41 +415,11 @@ static void wifiprov_wifi_state_get(void *p_arg)
state_get_cb(&state);
}
}
static void event_cb_i2c_event(input_event_t *event, void *private_data)
{
switch (event->code) {
case CODE_I2C_END:
{
printf("TRANS FINISH %lld\r\n", aos_now_ms());
}
break;
case CODE_I2C_ARB:
{
printf("TRANS ERROR ARB %lld\r\n", aos_now_ms());
}
break;
case CODE_I2C_NAK:
{
printf("TRANS ERROR NAK %lld\r\n", aos_now_ms());
}
break;
case CODE_I2C_FER:
{
printf("TRANS ERROR FER %lld\r\n", aos_now_ms());
}
break;
default:
{
printf("[I2C] [EVT] Unknown code %u, %lld\r\n", event->code, aos_now_ms());
}
}
}
static void event_cb_wifi_event(input_event_t *event, void *private_data)
{
struct _wifi_conn *conn_info;
static char *ssid;
static char *password;
extern bool q_cloud_IsConnected;
switch (event->code) {
case CODE_WIFI_ON_INIT_DONE:
{
@ -462,26 +430,34 @@ static void event_cb_wifi_event(input_event_t *event, void *private_data)
case CODE_WIFI_ON_MGMR_DONE:
{
printf("[APP] [EVT] MGMR DONE %lld\r\n", aos_now_ms());
_connect_wifi();
extern void Q_Cloud_Config_Net_Start(void) ;
Q_Cloud_Config_Net_Start();
}
break;
case CODE_WIFI_ON_MGMR_DENOISE:
{
printf("[APP] [EVT] Microwave Denoise is ON %lld\r\n", aos_now_ms());
}
break;
case CODE_WIFI_ON_SCAN_DONE:
{
printf("[APP] [EVT] SCAN Done %lld, SCAN Result: %s\r\n",
aos_now_ms(),
WIFI_SCAN_DONE_EVENT_OK == event->value ? "OK" : "Busy now"
);
printf("[APP] [EVT] SCAN Done %lld\r\n", aos_now_ms());
wifi_mgmr_cli_scanlist();
}
break;
case CODE_WIFI_ON_SCAN_DONE_ONJOIN:
{
printf("[APP] [EVT] SCAN On Join %lld\r\n", aos_now_ms());
}
break;
case CODE_WIFI_ON_DISCONNECT:
{
printf("[APP] [EVT] disconnect %lld, Reason: %s\r\n",
aos_now_ms(),
wifi_mgmr_status_code_str(event->value)
);
vTaskDelay(1000);
wifi_mgmr_sta_disable(NULL);
q_cloud_IsConnected=0;
}
break;
case CODE_WIFI_ON_CONNECTING:
@ -508,35 +484,72 @@ static void event_cb_wifi_event(input_event_t *event, void *private_data)
{
printf("[APP] [EVT] GOT IP %lld\r\n", aos_now_ms());
printf("[SYS] Memory left is %d Bytes\r\n", xPortGetFreeHeapSize());
q_cloud_IsConnected=1;
}
break;
case CODE_WIFI_ON_EMERGENCY_MAC:
{
printf("[APP] [EVT] EMERGENCY MAC %lld\r\n", aos_now_ms());
hal_reboot();//one way of handling emergency is reboot. Maybe we should also consider solutions
}
break;
case CODE_WIFI_ON_PROV_SSID:
{
printf("[APP] [EVT] [PROV] [SSID] %lld: %s\r\n",
aos_now_ms(),
event->value ? (const char*)event->value : "UNKNOWN"
);
if (ssid) {
vPortFree(ssid);
ssid = NULL;
}
ssid = (char*)event->value;
}
break;
case CODE_WIFI_ON_PROV_BSSID:
{
printf("[APP] [EVT] [PROV] [BSSID] %lld: %s\r\n",
aos_now_ms(),
event->value ? (const char*)event->value : "UNKNOWN"
);
if (event->value) {
vPortFree((void*)event->value);
}
}
break;
case CODE_WIFI_ON_PROV_PASSWD:
{
printf("[APP] [EVT] [PROV] [PASSWD] %lld: %s\r\n", aos_now_ms(),
event->value ? (const char*)event->value : "UNKNOWN"
);
if (password) {
vPortFree(password);
password = NULL;
}
password = (char*)event->value;
}
break;
case CODE_WIFI_ON_PROV_CONNECT:
{
printf("[APP] [EVT] [PROV] [CONNECT] %lld\r\n", aos_now_ms());
conn_info = (struct _wifi_conn *)event->value;
wifi_sta_connect(conn_info->ssid, conn_info->pask);
printf("connecting to %s:%s...\r\n", ssid, password);
wifi_sta_connect(ssid, password);
}
break;
case CODE_WIFI_ON_PROV_DISCONNECT:
{
printf("[APP] [EVT] [PROV] [DISCONNECT] %lld\r\n", aos_now_ms());
wifi_mgmr_sta_disconnect();
vTaskDelay(1000);
wifi_mgmr_sta_disable(NULL);
}
break;
case CODE_WIFI_ON_PROV_SCAN_START:
case CODE_WIFI_ON_AP_STA_ADD:
{
printf("[APP] [EVT] [PROV] [SCAN] %lld\r\n", aos_now_ms());
wifiprov_scan((void *)event->value);
printf("[APP] [EVT] [AP] [ADD] %lld, sta idx is %lu\r\n", aos_now_ms(), (uint32_t)event->value);
}
break;
case CODE_WIFI_ON_PROV_STATE_GET:
case CODE_WIFI_ON_AP_STA_DEL:
{
printf("[APP] [EVT] [PROV] [STATE] %lld\r\n", aos_now_ms());
wifiprov_wifi_state_get((void *)event->value);
printf("[APP] [EVT] [AP] [DEL] %lld, sta idx is %lu\r\n", aos_now_ms(), (uint32_t)event->value);
}
break;
default:
@ -547,27 +560,6 @@ static void event_cb_wifi_event(input_event_t *event, void *private_data)
}
}
static void event_cb_cli(input_event_t *event, void *p_arg)
{
char *cmd1 = "ble_init\r\n";
char *cmd2 = "ble_start_adv 0 0 0x100 0x100\r\n";
char *cmd3 = "ble_stop_adv\r\n";
switch (event->code) {
case CODE_CLI_BLSYNC_START :
aos_cli_input_direct(cmd1, strlen(cmd1));
aos_cli_input_direct(cmd2, strlen(cmd2));
break;
case CODE_CLI_BLSYNC_STOP :
aos_cli_input_direct(cmd3, strlen(cmd3));
blsync_ble_stop();
printf("blsync ble stop\r\n");
break;
default :
break;
}
}
static void __attribute__((unused)) cmd_aws(char *buf, int len, int argc, char **argv)
{
void aws_main_entry(void *arg);
@ -576,9 +568,6 @@ void aws_main_entry(void *arg);
static void __attribute__((unused)) cmd_tencent(char *buf, int len, int argc, char **argv){
extern int bl_qcloud_main(void *arg);
xTaskCreate(bl_qcloud_main, (char*)"tencent cloud", 4096, NULL, 16, NULL);
//my_light_main();
}
#define MAXBUF 128
#define BUFFER_SIZE (12*1024)
@ -609,20 +598,9 @@ static void stack_wifi(void)
}
static void stack_ble (void)
{
blsync_ble_start();
}
static void cmd_blsync_ble_start(char *buf, int len, int argc, char **argv)
{
stack_wifi();
vTaskDelay(1000);
stack_ble();
vTaskDelay(1000);
aos_post_event(EV_CLI, CODE_CLI_BLSYNC_START, 0);
}
static void cmd_blsync_ble_stop(char *buf, int len, int argc, char **argv)
{
@ -630,8 +608,6 @@ static void cmd_blsync_ble_stop(char *buf, int len, int argc, char **argv)
}
const static struct cli_command cmds_user[] STATIC_CLI_CMD_ATTRIBUTE = {
{ "blsync_ble_start", "blsync ble start", cmd_blsync_ble_start},
{ "blsync_ble_stop", "blsync ble stop", cmd_blsync_ble_stop},
{ "tencent" , "tencent test", cmd_tencent },
};
@ -669,27 +645,6 @@ static void __opt_feature_init(void)
#endif
}
static void app_delayed_action_bleadv(void *arg)
{
char *cmd1 = "ble_init\r\n";
char *cmd2 = "ble_start_adv 0 0 0x100 0x100\r\n";
aos_cli_input_direct(cmd1, strlen(cmd1));
aos_cli_input_direct(cmd2, strlen(cmd2));
}
static void app_delayed_action_wifi(void *arg)
{
stack_wifi();
aos_post_delayed_action(1000, app_delayed_action_bleadv, NULL);
}
static void app_delayed_action_ble(void *arg)
{
stack_ble();
aos_post_delayed_action(1000, app_delayed_action_wifi, NULL);
}
static void aos_loop_proc(void *pvParameters)
{
int fd_console;
@ -730,12 +685,8 @@ static void aos_loop_proc(void *pvParameters)
aos_register_event_filter(EV_WIFI, event_cb_wifi_event, NULL);
aos_register_event_filter(EV_CLI, event_cb_cli, NULL);
aos_post_delayed_action(1000, app_delayed_action_ble, NULL);
aos_register_event_filter(EV_I2C, event_cb_i2c_event, NULL);
stack_wifi();
vTaskDelay(1000);
hal_i2c_init(0, 500);
aos_loop_run();

View File

@ -0,0 +1,207 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub
available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file
except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software
distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND,
* either express or implied. See the License for the specific language
governing permissions and
* limitations under the License.
*
*/
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <FreeRTOS.h>
#include <task.h>
#include "qcloud_iot_export.h"
#include "qcloud_iot_import.h"
#include "qutils_getopt.h"
#include "lite-utils.h"
#include "qutils_timer.h"
#include <hal_hwtimer.h>
#include "qcloud_wifi_config.h"
#include "qcloud_wifi_config_internal.h"
#if !(WIFI_PROV_SOFT_AP_ENABLE || WIFI_PROV_SMART_CONFIG_ENABLE || WIFI_PROV_AIRKISS_CONFIG_ENABLE || \
WIFI_PROV_SIMPLE_CONFIG_ENABLE || WIFI_PROV_BT_COMBO_CONFIG_ENABLE)
#error "Please choose one set to 1 of them in qcloud_wifi_config.h"
#endif
static bool wifi_config_result_success = false;
#ifdef AUTH_MODE_CERT
static char sg_cert_file[PATH_MAX + 1 + 1024]; // full path of device cert file
static char sg_key_file[PATH_MAX + 1 + 1024]; // full path of device key file
#endif
static TaskHandle_t q_cloud_netconfig_task = NULL;
TaskHandle_t q_cloud_demo_task = NULL;
static hw_timer_t *qcloud_demo_handle= NULL;
// user's log print callback
static bool log_handler(const char *message)
{
// return true if print success
return false;
}
static void _wifi_config_result_cb(eWiFiConfigResult event, void *usr_data)
{
Log_d("entry...");
qiot_wifi_config_stop();
switch (event) {
case RESULT_WIFI_CONFIG_SUCCESS:
Log_i("WiFi is ready, to do Qcloud IoT demo");
Log_d("timestamp now:%d", HAL_Timer_current_sec());
wifi_config_result_success = true;
Log_i("send q_cloud_netconfig_task exit\r\n");
xTaskNotify(q_cloud_netconfig_task, 1, eSetValueWithOverwrite);
break;
case RESULT_WIFI_CONFIG_TIMEOUT:
Log_e("wifi config timeout!");
wifi_config_result_success = false;
case RESULT_WIFI_CONFIG_FAILED:
Log_e("wifi config failed!");
qiot_wifi_config_send_log();
wifi_config_result_success = false;
break;
default:
break;
}
}
static bool qcloud_wifi_config_proc()
{
int rc;
Timer timer;
#if WIFI_PROV_SOFT_AP_ENABLE
eSoftApConfigParams apConf = {"tcloud-softap", "12345678", 6};
rc = qiot_wifi_config_start(WIFI_CONFIG_TYPE_SOFT_AP, &apConf, _wifi_config_result_cb);
countdown(&timer, 500);
while ((rc == QCLOUD_RET_SUCCESS) && (false == wifi_config_result_success) && !expired(&timer)) {
Log_d("wait wifi config result...");
HAL_SleepMs(1000);
}
qiot_wifi_config_stop();
if (true == wifi_config_result_success) {
return true;
}
#endif // WIFI_PROV_SOFT_AP_ENABLE
#if WIFI_PROV_SMART_CONFIG_ENABLE
rc = qiot_wifi_config_start(WIFI_CONFIG_TYPE_SMART_CONFIG, NULL, _wifi_config_result_cb);
countdown(&timer, 500);
while ((rc == QCLOUD_RET_SUCCESS) && (false == wifi_config_result_success) && !expired(&timer)) {
Log_d("wait wifi config result...");
HAL_SleepMs(1000);
}
qiot_wifi_config_stop();
if (true == wifi_config_result_success) {
return true;
}
#endif // WIFI_PROV_SMART_CONFIG_ENABLE
#if WIFI_PROV_AIRKISS_CONFIG_ENABLE
rc = qiot_wifi_config_start(WIFI_CONFIG_TYPE_AIRKISS, NULL, _wifi_config_result_cb);
countdown(&timer, 500);
while ((rc == QCLOUD_RET_SUCCESS) && (false == wifi_config_result_success) && !expired(&timer)) {
Log_d("wait wifi config result...");
HAL_SleepMs(1000);
}
qiot_wifi_config_stop();
if (true == wifi_config_result_success) {
return true;
}
#endif // WIFI_PROV_AIRKISS_CONFIG_ENABLE
#if WIFI_PROV_SIMPLE_CONFIG_ENABLE
rc = qiot_wifi_config_start(WIFI_CONFIG_TYPE_SIMPLE_CONFIG, NULL, _wifi_config_result_cb);
countdown(&timer, 500);
while ((rc == QCLOUD_RET_SUCCESS) && (false == wifi_config_result_success) && !expired(&timer)) {
Log_d("wait wifi config result...");
HAL_SleepMs(1000);
}
qiot_wifi_config_stop();
if (true == wifi_config_result_success) {
return true;
}
#endif // WIFI_PROV_SIMPLE_CONFIG_ENABLE
#if WIFI_PROV_BT_COMBO_CONFIG_ENABLE
rc = qiot_wifi_config_start(WIFI_CONFIG_TYPE_BT_COMBO, NULL, _wifi_config_result_cb);
countdown(&timer, 500);
while ((rc == QCLOUD_RET_SUCCESS) && (false == wifi_config_result_success) && !expired(&timer)) {
Log_d("wait wifi config result...");
HAL_SleepMs(1000);
}
qiot_wifi_config_stop();
if (true == wifi_config_result_success) {
return true;
}
#endif // WIFI_PROV_BT_COMBO_CONFIG_ENABLE
return false;
}
void Start_Qcloud_Demo(void)
{
extern void bl_qcloud_main(void);
if(qcloud_demo_handle!=NULL)
{
hal_hwtimer_delete(qcloud_demo_handle);
}
qcloud_demo_handle=NULL;
q_cloud_demo_task=NULL;
xTaskCreate(bl_qcloud_main, (char*)"tencent cloud", 5120, NULL, 16, &q_cloud_demo_task);
}
void q_cloud_netconfig(int argc, char **argv)
{
int rc=0;
uint32_t ulNotifiedValue = 0;
uint8_t flagexit = 0;
// init log level
IOT_Log_Set_Level(eLOG_DEBUG);
IOT_Log_Set_MessageHandler(log_handler);
if (false == qcloud_wifi_config_proc()) {
Log_d("wifi config failed");
}
while(1)
{
xTaskNotifyWait(0x00, 0xffffffff, &ulNotifiedValue, 50);
if (ulNotifiedValue == 1)
flagexit = 1;
ulNotifiedValue = 0;
if (flagexit){
Log_i("wifi config ok");
goto _exit;
}
}
_exit:
printf("exit q_cloud_netconfig\r\n");
qcloud_demo_handle = hal_hwtimer_create(100, Start_Qcloud_Demo, 1);
q_cloud_netconfig_task = NULL;
vTaskDelete(NULL);
}
void Q_Cloud_Config_Net_Start(void)
{
if (q_cloud_netconfig_task != NULL)
return;
printf("create q_cloud_netconfig task\r\n");
xTaskCreate(q_cloud_netconfig, "loctrltask", 10240, NULL, 18, &q_cloud_netconfig_task);
}

View File

@ -1,87 +0,0 @@
/*
* Copyright (c) 2020 Bouffalolab.
*
* This file is part of
* *** Bouffalolab Software Dev Kit ***
* (see www.bouffalolab.com).
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wifi_prov_api.h"
#include <string.h>
#include <stdio.h>
#include <FreeRTOS.h>
#include <vfs.h>
#include <aos/kernel.h>
#include <aos/yloop.h>
#include <event_device.h>
int wifi_prov_api_event_trigger_connect(struct wifi_conn *info)
{
if (aos_post_event(EV_WIFI, CODE_WIFI_ON_PROV_CONNECT, (unsigned long)info) >= 0) {
puts("[APP] [PROV] trigger CONNECT event OK\r\n");
} else {
puts("[APP] [PROV] trigger CONNECT event failed\r\n");
return -1;
}
return 0;
}
int wifi_prov_api_event_trigger_disconnect(void)
{
if (aos_post_event(EV_WIFI, CODE_WIFI_ON_PROV_DISCONNECT, 0) >= 0) {
puts("[APP] [PROV] trigger DISCONNECT event OK\r\n");
} else {
puts("[APP] [PROV] trigger DISCONNECT event failed\r\n");
return -1;
}
return 0;
}
int wifi_prov_api_event_trigger_scan(void(*complete)(void *))
{
if (aos_post_event(EV_WIFI, CODE_WIFI_ON_PROV_SCAN_START, (unsigned long)complete) >= 0) {
puts("[APP] [PROV] trigger scan event OK\r\n");
} else {
puts("[APP] [PROV] trigger scan event failed\r\n");
return -1;
}
return 0;
}
int wifi_prov_api_event_state_get(void(*state_get)(void *))
{
if (aos_post_event(EV_WIFI, CODE_WIFI_ON_PROV_STATE_GET, (unsigned long)state_get) >= 0) {
puts("[APP] [PROV] trigger scan event OK\r\n");
} else {
puts("[APP] [PROV] trigger scan event failed\r\n");
return -1;
}
return 0;
}

View File

@ -1,37 +0,0 @@
/*
* Copyright (c) 2020 Bouffalolab.
*
* This file is part of
* *** Bouffalolab Software Dev Kit ***
* (see www.bouffalolab.com).
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __WIFI_PROV_API_H__
#define __WIFI_PROV_API_H__
#include "blsync_ble.h"
int wifi_prov_api_event_trigger_connect(struct wifi_conn *info);
int wifi_prov_api_event_trigger_disconnect(void);
int wifi_prov_api_event_trigger_scan(void(*complete)(void *));
int wifi_prov_api_event_state_get(void(*state_get)(void *));
#endif