瑞萨单片机论坛
直播中

hehung

8年用户 659经验值
擅长:嵌入式技术
私信 关注
[经验]

【RA4M2设计挑战赛】6. DA16200 wifi使用TCP透传连接OneNet

过往分享

RA4M2挑战赛分享:
【RA4M2设计挑战赛】1. RASC配置FreeRTOS
【RA4M2设计挑战赛】2. 硬件IIC读取HS3003的温湿度数据
【RA4M2设计挑战赛】3. 硬件IIC读取ISL29035采集光照强度
【RA4M2设计挑战赛】4. DA14531蓝牙模块使用
【瑞萨RA4系列开发板体验】5. DA16200 wifi模块操作

前言

本文主要是讲解如何使用DA16200通过TCP透传的方式连接到Onenet云平台,并且讲解onenet云平台的功能以及操作方式。

DA16200 TCP服务操作流程

DA16200支持TCP服务,具体可以参考手册:
《REN_UM-WI-003_DA16200_DA16600_AT-Command_Rev_2v12_MAS_20220808.pdf》

连接TCP服务器命令

使用下面的命令可以连接TCP服务器:

AT+TRTC

当成功连接了TCP服务器之后,
使用下面的命令发送TCP数据

<ESC>S

这里需要特别说明:

  • <ESC>就是ASCII的27.
  • S后面需要跟发送的数据长度,这个长度不包括remote_ip, remote_port, 只包含数据的长度

接收来自TCP服务器的数据格式为:

+TRDTC

可以通过识别关键字解析出数据.

注意:数据包含了remote_ip以及remote_port以及数据长度等信息,需要处理。

关于WIFI模块作为服务器使用,不在本文讨论范围内。

ONENET TCP 透传

多协议接入网址(需登录):

多协议接入

关于onenet tcp透传,使用该方式可以参考官方文档

TCP透传

创建项目以及设备

新建设备

如下新建设备,先不要关注脚本解析和关联脚本,后面会说如何编写。

查看设备详情,下面的两个信息很重要,TCP透传的身份鉴别需要使用。

新建数据流

数据流的名称比较中要,Lua解析脚本会使用到。

Lua解析脚本编写

现在都准备好了,可以开始编写Lua脚本了。

TCP透传的数据是通过Lua脚本来解析的。可以下载的官方的示例脚本,我们做修改即可,主要需要实现两个函数的内容

device_timer_init:设备周期性下发命令,这个可以不用编写任何代码

device_data_analyze:用户上传数据分析处理函数,在这个里面解析我们上传的数据就可以了。

关于每个函数的意义在Lua脚本中有详细的说明,参考就可以,或者参考上述官方教程中的说明。

我的Lua脚本实现如下:

function device_data_analyze(dev)
	local t={}
	local a=0

	-- 添加用户自定义代码 --
	-- 例如: --
	local s = dev:size()
    local temp = 0
    local str_end = 0
    local humi = 0
    local lux = 0
	local mq5_ppm = 0
	local lamp_pwm = 0

	-- 找到关键字 -- 
	-- T后面是温度,单位摄氏度 -- 
	-- H后面是湿度,单位百分比 -- 
	-- L后面是环境光亮度,单位Lux -- 
	-- M后面是环境可燃气体浓度,单位是ppm -- 
	-- P后面是台灯亮度,单位百分比 -- 
    temp, str_end = string.find(dev:bytes(1, s), "T")
    humi, str_end = string.find(dev:bytes(1, s), "H")
    lux, str_end = string.find(dev:bytes(1, s), "L")
	mq5_ppm, str_end = string.find(dev:bytes(1, s), "M")
	lamp_pwm, str_end = string.find(dev:bytes(1, s), "P")

    add_val(t, "temp", a, dev:bytes(temp+1, humi-temp-1))
    add_val(t, "humi", a, dev:bytes(humi+1, lux-humi-1))
    add_val(t, "Lux", a, dev:bytes(lux+1, mq5_ppm-lux-1))
	add_val(t, "combustible_gas", a, dev:bytes(mq5_ppm+1, lamp_pwm-mq5_ppm-1))
	add_val(t, "DeskLampBrightness", a, dev:bytes(lamp_pwm+1, s-lamp_pwm))

	-- 成功收到数据后的响应 -- 
    dev:response()
	dev:send("received")
    -- dev:send("received" .. dev:bytes(1, s) .. '|' .. tostring(temp) .. '|' .. tostring(humi) .. '|' .. tostring(lux) ..'|' ..  tostring(mq5_ppm) .. '|' .. tostring(lamp_pwm))

	-- return $1,$2 --
	-- 例如: --
	return s,to_json(t)
end

脚本代码说明:

我自己定义了一个数据格式:

T+$温度+H+$湿度+L+$光照强度+M+$可燃气体浓度+P+$台灯亮度

举例,如果上传的温度为35.2度,湿度为56.2%,光照强度为123Lux,可燃气体浓度3000ppm,台灯亮度为65%,为则数据格式应该为:

T35.2H56.2L123M3000P65

OneNet收到上述数据之后会进行解析之后,分别显示在不同的数据流中。

收到了上述格式的数据之后,脚本就会识别出关键字 T H L M P并分别解析出后面的数字加载到对应的数据流中。

local s = dev:size()

表示获取收到的数据长度

最后的返回值return s,to_json(t)为解析的数据长度以及json格式的数据流数据。

我们每次解析的长度都是s,这个固定的,to_json就是将解析出来的数据以json格式放到对应的数据流中。

脚本上传

下位机代码实现

OneNet平台的设备创建好了之后就是下位机代码的编写了

使用了TCP透传,详细代码如下:

app_wifi.c

/*
@hehung
2023-2-8
转载请注明出处,版权由@hehung所有
email: 1398660197@qq.com
wechat: hehung95
*/

#include "app_wifi.h"
#include "da16200_AT.h"
#include "hal_data.h"
#include "app_led.h"
#include "app_common.h"
#include "app_rtc.h"
#include "app_isl29035.h"
#include "app_hs300x.h"
#include "app_mq5.h"
#include <stdio.h>
#include <string.h>

#define WIFI_DEBUG

#ifdef WIFI_DEBUG
#define LOG(fmt, ...) 	          printf(fmt, ##__VA_ARGS__)
#else
#define LOG(fmt, ...)
#endif


#define WIFI_ATF_EN               (COMM_ON)
#define WIFI_CHECK_AP_CONN_STA_EN (COMM_OFF)

#define WIFI_PERIOD               (20U)     // RTOS period is 20ms
// Check AP connect status period 
#define WIFI_CONN_STA_CHK_PERIOS  (200000U)  
#define WIFI_CONN_PREIOD          ((uint32_t)((WIFI_CONN_STA_CHK_PERIOS) / (WIFI_PERIOD)))  // 10s

#define WIFI_RESET_PIN            (BSP_IO_PORT_06_PIN_08)


typedef struct
{
    int sec;
    int min;
    int hour;
    int mday;
    int mon;
    int year;
} s_Da16200TimeType;


#define WIFI_TCP_DATA_LEN            (128U)

static e_WifiOptType wifi_opt_mode = WIFI_OPT_INIT;
static e_WifiOptType wifi_opt_mode_pre = WIFI_OPT_INIT;
static e_ApConnectStatusType wifi_conn_status = WIFI_DISEONNECTED;
static e_WifiIotConnStaType wifi_iot_conn_status = WIFI_ONENET_DISCONNECTED; 
static uint16_t wifi_conn_sta_check_cnt = 0U;
static uint16_t wifi_tcp_send_cnt = 0U;


static char wifi_tcp_str[WIFI_TCP_DATA_LEN];
// TCP transmittion head '<ESC>S'
static char *wifi_tcp_head = "S1";
// IP address and port in Onenet TCP transparent transmission 
static char *wifi_tcp_ip_port = ",183.230.40.40,1811,";
// User information in Onenet TCP transparent transmission
static char *wifi_tcp_info = "*575047#ra4m2info#ra4m2*\r\n";


static fsp_err_t Wifi_Setting(void);
static fsp_err_t Wifi_ConnectToAp(void);
static fsp_err_t Wifi_ConnectToTcp(void);
static fsp_err_t Wifi_SntpStart(void);
static fsp_err_t Wifi_GetTime(void);
static void Wifi_OperateModeManage(void);
#if (WIFI_CHECK_AP_CONN_STA_EN == STD_ON)
static void Wifi_JudgeConnectStatusPeriod(void);
#endif 
static e_ApConnectStatusType Wifi_GetAPConnectStatus(void);


// Da16200 wifi initialization
void Wifi_Init(void)
{
    // reset wifi module first
    R_IOPORT_PinWrite(&g_ioport_ctrl, WIFI_RESET_PIN, BSP_IO_LEVEL_LOW);
    DELAY_MS(10);
    R_IOPORT_PinWrite(&g_ioport_ctrl, WIFI_RESET_PIN, BSP_IO_LEVEL_HIGH);

	// Initialize the timer for counter
    g_timer0.p_api->open(g_timer0.p_ctrl, g_timer0.p_cfg);
    g_timer0.p_api->start(g_timer0.p_ctrl);
	// Initialize the uart for AT command communication 
    g_uart0.p_api->open(g_uart0.p_ctrl, g_uart0.p_cfg);

	wifi_opt_mode = WIFI_OPT_SETTING;
    LOG("Wifi: Wifi initialization success\n");
} 

// setting wifi module da16200
static fsp_err_t Wifi_Setting(void)
{
    fsp_err_t status = FSP_ERR_ASSERTION;
	uint8_t resp_buf[DA16200_STR_LEN_128];

	/** Clear respond memory **/
	memset (resp_buf, 0 , sizeof(resp_buf));

	// ATZ command
    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_ATZ, resp_buf);
    if(status != FSP_SUCCESS)
    {
		LOG("Wifi: Da16200 ATZ command failed!\n");
        return status;
    }
    DELAY_MS(10);

	/** Clear respond memory **/
	memset (resp_buf, 0 , sizeof(resp_buf));
	// ATE command
    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_ATE, resp_buf);
    if(status != FSP_SUCCESS)
    {
		LOG("Wifi: Da16200 ATE command failed!\n");
        return status;
    }
    DELAY_MS(10);

#if (WIFI_ATF_EN == COMM_ON) // do not clear ap information
    /** Clear respond memory **/
    memset (resp_buf, 0 , sizeof(resp_buf));
    // ATF command
    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_ATF, resp_buf);
    if(status != FSP_SUCCESS)
    {
        LOG("Wifi: Da16200 ATF command failed!\n");
        return status;
    }
    DELAY_MS(10);
#endif 

    /** Clear respond memory **/
    memset (resp_buf, 0 , sizeof(resp_buf));
    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_TMRFNOINIT, resp_buf);
    if(status != FSP_SUCCESS)
    {
        return status;
    }
    
    DELAY_MS(10);
	/** Clear respond memory **/
	memset (resp_buf, 0 , sizeof(resp_buf));
    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_WFMODE, resp_buf);
    if(status != FSP_SUCCESS)
    {
        return status;
    }
    
    DELAY_MS(10);
	/** Clear respond memory **/
	memset (resp_buf, 0 , sizeof(resp_buf));
    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_RESTART, resp_buf);
    if(status != FSP_SUCCESS)
    {
        return status;
    }

    DELAY_MS(10);

    return status;
}

// control wifi module connecting to AP
static fsp_err_t Wifi_ConnectToAp(void)
{
    fsp_err_t status = FSP_ERR_ASSERTION;
	uint8_t resp_buf[DA16200_STR_LEN_128];

#if (WIFI_ATF_EN == COMM_OFF)
    // update the AP connection status
    wifi_conn_status = Wifi_GetAPConnectStatus();
    DELAY_MS(10);
#endif
    // not connected
    if (WIFI_DISEONNECTED == wifi_conn_status)
    {
        /** Clear respond memory **/
        memset (resp_buf, 0 , sizeof(resp_buf));
        status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_WFJAP, resp_buf);
        if(status != FSP_SUCCESS)
        {
            return status;
        }
        /* Wifi connected to AP */
        wifi_conn_status = WIFI_CONNECTED;
    }
    DELAY_MS(10);

    // check DHC
    /** Clear respond memory **/
    // memset (resp_buf, 0 , sizeof(resp_buf));
    // status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_NWDHC, resp_buf);
    // if(status != FSP_SUCCESS)
    // {
    //     return status;
    // }
    // DELAY_MS(10);

    return status;
}

// setting sntp
static fsp_err_t Wifi_SntpStart(void)
{
    fsp_err_t status = FSP_ERR_ASSERTION;
	uint8_t resp_buf[DA16200_STR_LEN_32];

	/** Clear respond memory **/
	memset (resp_buf, 0 , sizeof(resp_buf));
    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_TZONE_GET, resp_buf);
    if(status != FSP_SUCCESS)
    {
       return status;
    }
    DELAY_MS(10);

    //+TZONE:28800: 8h for sync to bejing time
    if (SF_WIFI_TRUE != is_str_present((const char *)resp_buf, "+TZONE:28800"))
    {
        // sync to time zone to beijing time
        /** Clear respond memory **/
        memset (resp_buf, 0 , sizeof(resp_buf));
        status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_TZONE_SET, resp_buf);
        if(status != FSP_SUCCESS)
        {
            return status;
        }
        DELAY_MS(10);
    }

	/** Clear respond memory **/
	memset (resp_buf, 0 , sizeof(resp_buf));
    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_NWSNTP_STATUS, resp_buf);
    if(status != FSP_SUCCESS)
    {
       return status;
    }
    DELAY_MS(10);

    if (SF_WIFI_TRUE == is_str_present((const char *)resp_buf, (const char*)"+NWSNTP:1"))
    {
        // sntp is started, stop it now
        /** Clear respond memory **/
        memset (resp_buf, 0 , sizeof(resp_buf));
        status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_NWSNTP_STOP, resp_buf);
        if(status != FSP_SUCCESS)
        {
            return status;
        }
        DELAY_MS(10);
    }

    /** Clear respond memory **/
    memset (resp_buf, 0 , sizeof(resp_buf));
    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_NWSNTP_START, resp_buf);
    if(status != FSP_SUCCESS)
    {
        return status;
    }
    DELAY_MS(10);

    return status;
}

// get da16200 time
static fsp_err_t Wifi_GetTime(void)
{
    fsp_err_t status = FSP_ERR_ASSERTION;
	uint8_t resp_buf[DA16200_STR_LEN_64];
    // time prase
    s_Da16200TimeType cur_t = {0,0,0,0,0,0};
    uint8_t i;
    uint8_t flag = 0;
    uint8_t j = 0;
    // get latest time
    rtc_time_t sntp_t;
    time_t sntp_t_stamp;

	/** Clear respond memory **/
	memset (resp_buf, 0 , sizeof(resp_buf));
    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_TIME_GET, resp_buf);
    if(status != FSP_SUCCESS)
    {
       return status;
    }

    for (i = 0; i < DA16200_STR_LEN_64; i++)
    {
        if ((resp_buf[i] == '+') && (resp_buf[i+1] == 'T') && (resp_buf[i+2] == 'I') && 
            (resp_buf[i+3] == 'M'))
        {
            // find '+TIME:'
            flag = 1;
            i += 6;
        }
        else if (resp_buf[i] == '\n')
        {
            // stop
            flag = 0;
            if (flag != 0)
            {
                break;
            }
        }

        if (flag == 1)  // year
        {
            cur_t.year = cur_t.year  * 10 + (resp_buf[i] - '0');
            j++;
            if (j == 4)
            {
                j = 0;
                flag ++;
                i++;
            }
        }
        else if (flag == 2)  // month
        {
            cur_t.mon = cur_t.mon  * 10 + (resp_buf[i] - '0');
            j++;
            if (j == 2)
            {
                j = 0;
                flag ++;
                i++;
            }
        }
        else if (flag == 3)  // day
        {
            cur_t.mday = cur_t.mday  * 10 + (resp_buf[i] - '0');
            j++;
            if (j == 2)
            {
                j = 0;
                flag ++;
                i++;
            }
        }
        else if (flag == 4)  //hour
        {
            cur_t.hour = cur_t.hour  * 10 + (resp_buf[i] - '0');
            j++;
            if (j == 2)
            {
                j = 0;
                flag ++;
                i++;
            }
        }
        else if (flag == 5)  //minute
        {
            cur_t.min = cur_t.min  * 10 + (resp_buf[i] - '0');
            j++;
            if (j == 2)
            {
                j = 0;
                flag ++;
                i++;
            }
        }
        else if (flag == 6)  //second
        {
            cur_t.sec = cur_t.sec  * 10 + (resp_buf[i] - '0');
            j++;
            if (j == 2)
            {
                j = 0;
                flag ++;
                i++;
            }
        }
    }

    LOG("Time is %d-%d-%d,%d:%d:%d\n", cur_t.year,
                                            cur_t.mon,
                                            cur_t.mday,
                                            cur_t.hour,
                                            cur_t.min,
                                            cur_t.sec);

    sntp_t.tm_year = cur_t.year - 1900;
    sntp_t.tm_mon = cur_t.mon - 1;
    sntp_t.tm_mday = cur_t.mday;
    sntp_t.tm_hour = cur_t.hour;
    sntp_t.tm_min = cur_t.min;
    sntp_t.tm_sec = cur_t.sec;

    // convert the sntp time to timestamp
    sntp_t_stamp = mktime(&sntp_t);
    LOG("SNTP timestamp is %d\n", sntp_t_stamp);

    // compare the sntp time and system rtc time
    rtc_time_t rtc_t;
    time_t rtc_t_stamp;

    rtc_t = Rtc_GetDateTime();

    // convert it to timestamp
    rtc_t_stamp = mktime(&rtc_t);
    LOG("RTC timestamp is %d\n", rtc_t_stamp);
    
    // if sntp time is a latest time, then update it to rtc
    if (rtc_t_stamp < sntp_t_stamp)
    {
        // update time to rtc
        Rtc_SetDateTime(&sntp_t);
    }
    else if (rtc_t_stamp > sntp_t_stamp)
    {
        // failed
        return FSP_ERR_ASSERTION;
    }

    return status;
}

// Judge the AP connection status
static e_ApConnectStatusType Wifi_GetAPConnectStatus(void)
{
    fsp_err_t status = FSP_SUCCESS;
    e_ApConnectStatusType ret_val = WIFI_DISEONNECTED;
    uint8_t resp_buf[DA16200_STR_LEN_32];

    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_WFSTA, resp_buf);
    if(status == FSP_SUCCESS)
    {
        if (SF_WIFI_TRUE == is_str_present((const char *)resp_buf, "+WFSTA:1"))
        {
            // Connect AP successfully
            ret_val = WIFI_CONNECTED;
        }
    }

    return ret_val;
}

// Connect TCP server
static fsp_err_t Wifi_ConnectToTcp(void)
{
    fsp_err_t status = FSP_ERR_ASSERTION;
	char resp_buf[DA16200_STR_LEN_128];


    /** Clear respond memory **/
    memset (resp_buf, 0, sizeof(resp_buf));
    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_TRTRM, (uint8_t*)resp_buf);
    // Do not need response due to this command may be return ERROR:-99
    // if((status != FSP_SUCCESS))
    // {
    //     return status;
    // }

    /** Clear respond memory **/
    memset (resp_buf, 0, sizeof(resp_buf));
    status = Da1620_ATCommandExe(DA16200_AT_CMD_INDEX_AT_TRTC, (uint8_t*)resp_buf);
    if(status != FSP_SUCCESS)
    {
        return status;
    }

    // send user information
    if (pdTRUE == xSemaphoreTake(wifi_mutex, portMAX_DELAY))
    {
        /** Clear respond memory **/
        memset (resp_buf, '\0', sizeof(resp_buf));
        sprintf(resp_buf, "%s%d%s%s", wifi_tcp_head, 24, wifi_tcp_ip_port, wifi_tcp_info);
        /** AT MODODR command **/
        wifi_serial_write((uint8_t *)resp_buf, (uint16_t)strlen(resp_buf));
        LOG("==>%s\n", resp_buf);

        DELAY_MS(1000);
        LOG("Sent TCP user info(ONENET info)\n");

        wifi_iot_conn_status = WIFI_ONENET_CONNECTED;

        // release the mutex, unlock
        (void)xSemaphoreGive(wifi_mutex);
    }

    return status;
}

// update the Data to Server
/*
使用的是OneNet透传,数据格式是我自定义的。
数据格式为,onenet的Lua脚本会解析这个格式的数据并显示在云平台:
T+温度+H+湿度+L+亮度+M+可燃气体浓度ppm+P+台灯光亮度
举例:
T26.20H89.20L1234M2456P100:
表示温度为26.20摄氏度
湿度为89.20%
亮度为1234Lux
可燃气体浓度为2456ppm
台灯亮度为100%
##############################################################################
Lua脚本(需要实现device_data_analyze函数即可):
function device_data_analyze(dev)
	local t={}
	local a=0

	-- 添加用户自定义代码 --
	-- 例如: --
	local s = dev:size()
    local temp = 0
    local str_end = 0
    local humi = 0
    local lux = 0
	local mq5_ppm = 0
	local lamp_pwm = 0

	-- 找到关键字 -- 
	-- T后面是温度,单位摄氏度 -- 
	-- H后面是湿度,单位百分比 -- 
	-- L后面是环境光亮度,单位Lux -- 
	-- M后面是环境可燃气体浓度,单位是ppm -- 
	-- P后面是台灯亮度,单位百分比 -- 
    temp, str_end = string.find(dev:bytes(1, s), "T")
    humi, str_end = string.find(dev:bytes(1, s), "H")
    lux, str_end = string.find(dev:bytes(1, s), "L")
	mq5_ppm, str_end = string.find(dev:bytes(1, s), "M")
	lamp_pwm, str_end = string.find(dev:bytes(1, s), "P")

    add_val(t, "temp", a, dev:bytes(temp+1, humi-temp-1))
    add_val(t, "humi", a, dev:bytes(humi+1, lux-humi-1))
    add_val(t, "Lux", a, dev:bytes(lux+1, mq5_ppm-lux-1))
	add_val(t, "combustible_gas", a, dev:bytes(mq5_ppm+1, lamp_pwm-mq5_ppm-1))
	add_val(t, "DeskLampBrightness", a, dev:bytes(lamp_pwm+1, s-lamp_pwm))

	-- 成功收到数据后的响应 -- 
    dev:response()
	dev:send("received")
	-- return $1,$2 --
	-- 例如: --
	return s,to_json(t)
end
*/
static void Wifi_UpdateSensorData(void)
{
    uint32_t lux = Isl29035_ReadData();
    s_Hs300xDataType humi_temp = Hs300x_ReadData();
    uint32_t mq5_ppm = Mq5_GetGasPpmValue();
    uint32_t lamp_pwm = Led_LampPwmGet();
    uint8_t data_len;
    uint16_t bytes_read = 0U;
    uint8_t resp_buff[DA16200_STR_LEN_64] = {0};
    char temp[64];
    fsp_err_t result;

    /** Clear respond memory **/
    memset (wifi_tcp_str, '\0', WIFI_TCP_DATA_LEN);
    // send the data to onenet
    sprintf(temp, "T%.2fH%.2fL%dM%dP%d", humi_temp.temp, humi_temp.humi, lux, mq5_ppm, lamp_pwm);
    data_len = (uint8_t)strlen((const char *)temp);
    sprintf(wifi_tcp_str, "%s%d%s%s\r\n", wifi_tcp_head, data_len, wifi_tcp_ip_port, temp);
    LOG ("Send data to TCP server: %s\n", wifi_tcp_str);

    /** Clear respond memory **/
    memset (resp_buff, '\0', bytes_read);

    // setting mutex for lock wifi uart
    if (pdTRUE == xSemaphoreTake(wifi_mutex, portMAX_DELAY)) 
    {
        /** AT MODODR command **/
        wifi_serial_write((uint8_t *)wifi_tcp_str, (uint16_t)strlen(wifi_tcp_str));

        bytes_read = DA16200_STR_LEN_64;
        result = wifi_serial_read(resp_buff, &bytes_read, (const char *)"received", 1000);
        if (FSP_SUCCESS != result)
        {
            // Go to check the AP connect status when failed
            wifi_opt_mode_pre = wifi_opt_mode;
            wifi_opt_mode = WIFI_OPT_CONNECT_STATUS;
        }
        else
        {
            
        }
        // release the mutex, unlock
        (void)xSemaphoreGive(wifi_mutex);
    }
}   

// Operation mode of wifi running
static void Wifi_OperateModeManage(void)
{
    fsp_err_t err;

    switch(wifi_opt_mode)
    {
        case WIFI_OPT_SETTING:
        {
            err = Wifi_Setting();
            if(err)
            {
                LOG("Wifi: Fail to setting\nRetry Start...\n");
                DELAY_MS(2000);
            }
            else
            {
                LOG("Wifi: Sucess to setting\n");
                wifi_opt_mode_pre = wifi_opt_mode;
                wifi_opt_mode = WIFI_OPT_CONNECT;
            }
            
            break;
        }
        case WIFI_OPT_CONNECT:
        {
            err = Wifi_ConnectToAp();
            if(err)
            {
                LOG("Wifi: Fail to connected to AP\nRetry Start...\n");
                DELAY_MS(500);
            }
            else
            {
                LOG("Wifi: Sucess to connected to AP\n");
                wifi_opt_mode_pre = wifi_opt_mode;
                wifi_opt_mode = WIFI_OPT_SNTP_SETTING;
            }
            break;
        }
        case WIFI_OPT_SNTP_SETTING:
        {
            err = Wifi_SntpStart();
            if(err)
            {
                LOG("Wifi: Fail to start SNTP\nRetry Start...\n");
                DELAY_MS(500);
            }
            else
            {
                LOG("Wifi: Sucess to start SNTP\n");
                wifi_opt_mode_pre = wifi_opt_mode;
                wifi_opt_mode = WIFI_OPT_GET_TIME;
            }
            break;
        }
        case WIFI_OPT_GET_TIME:
        {
            // update the time
            err = Wifi_GetTime();
            if(err)
            {
                LOG("Wifi: Fail to get time from da16200\nRetry Start...\n");
                DELAY_MS(1000);
            }
            else
            {
                LOG("Wifi: Sucess to get time from da16200\n");
                wifi_opt_mode_pre = wifi_opt_mode;
                wifi_opt_mode = WIFI_OPT_CONNECT_TCP;
            }
            break;
        }
        case WIFI_OPT_CONNECT_TCP:
        {
            // Connect onenet Iot
            err = Wifi_ConnectToTcp();
            if(err)
            {
                LOG("Wifi: Fail to connect to the TCP server\nRetry Start...\n");
                DELAY_MS(500);
            }
            else
            {
                LOG("Wifi: Sucess to connect to the TCP server\n");
                wifi_opt_mode_pre = wifi_opt_mode;
                wifi_opt_mode = WIFI_OPT_WORKING;
                wifi_tcp_send_cnt = 0U;
            }
            break;
        }
        case WIFI_OPT_WORKING:
        {
            // Used for connect with ONENET TCP server
            if (wifi_tcp_send_cnt >= 30U)
            {
                wifi_tcp_send_cnt = 0U;
                // send the sensor data every 5s
                Wifi_UpdateSensorData(); 
            }
            else
            {
                wifi_tcp_send_cnt ++;
            }
            
            Da16200_FeedbackHandle();
            DELAY_MS(100);
            break;
        }
        case WIFI_OPT_CONNECT_STATUS:
        {
            // update the AP connection status
            wifi_conn_status = Wifi_GetAPConnectStatus();

            // re-try to connecting the AP
            if (WIFI_DISEONNECTED == wifi_conn_status)
            {
                // re-try to connecting the AP       
                wifi_opt_mode = WIFI_OPT_CONNECT;
                wifi_opt_mode_pre = wifi_opt_mode;
            }
            else
            {
                // switch to previous operate mode
                wifi_opt_mode = wifi_opt_mode_pre;
                wifi_opt_mode_pre = WIFI_OPT_CONNECT_STATUS;
            }

            DELAY_MS(1);
            break;
        }
        default:
        {
            LOG("Wifi: Error operation");
			DELAY_MS(1000);
            break;
        }
    }
}

#if (WIFI_CHECK_AP_CONN_STA_EN == STD_ON)
// check the connect status
static void Wifi_JudgeConnectStatusPeriod(void)
{
    // not in wifi initialization mode
    if ((wifi_opt_mode != WIFI_OPT_INIT) && 
        (wifi_opt_mode != WIFI_OPT_SETTING) && 
        (wifi_opt_mode != WIFI_OPT_CONNECT)// &&
        // (wifi_opt_mode != WIFI_OPT_WORKING)
        )
    {
        if (wifi_conn_sta_check_cnt >= WIFI_CONN_PREIOD)
        {
            wifi_conn_sta_check_cnt = 0U;

            LOG("Wifi: Check cnnect status");

            wifi_opt_mode_pre = wifi_opt_mode;
            wifi_opt_mode = WIFI_OPT_CONNECT_STATUS;      
        }
    }
}
#endif

// Wifi working main interface for task
void Wifi_RunningEntry(void)
{
    Wifi_OperateModeManage();
#if (WIFI_CHECK_AP_CONN_STA_EN == STD_ON)
    Wifi_JudgeConnectStatusPeriod();
#endif 
    vTaskDelay(pdMS_TO_TICKS(WIFI_PERIOD));
}

e_ApConnectStatusType Wifi_GetApConnStatus(void)
{
    return wifi_conn_status;
}


e_WifiIotConnStaType Wifi_GetIotConnStatus(void)
{
    return wifi_iot_conn_status;
}

void WIfi_CheckPreiodLoop(void)
{
    if (wifi_conn_sta_check_cnt < WIFI_CONN_PREIOD)
    {
        wifi_conn_sta_check_cnt ++;
    }
}

/*
使用的是OneNet的TCP透传,数据格式是我自定义的。
控制台灯的数据命令是:Lamp:+百分比台灯亮度
比如:
Lamp:100  - 表示台灯打开,亮度为100%
Lamp:0    - 表示关闭台灯
Lamp:80   - 表示台灯亮度设置为80%
*/
void Da16200_TRDTC_response(char *resp_data, uint16_t resp_data_len)
{
    char *sub_str_ptr;
    int command = -1;
	
	(void)resp_data_len;

    // find the sub-string 'Lamp'
    sub_str_ptr = strstr((const char *)resp_data, "Lamp");
    if (NULL != sub_str_ptr)
    {
        // parse the control command
        sscanf(sub_str_ptr, "Lamp:%d", &command);
        if ((command >= 0) && (command <= 100))
        {
            // the command is valid
            Led_LampPwmCtrl((uint8_t)command);
            LOG ("Wifi: Lamp control command is %d\n", command);
        }
        else
        {
            LOG ("Wifi: Invalid Lamp control command\n");
        }
    }
}

app_wifi.h

/*
@hehung
2023-2-8
转载请注明出处,版权由@hehung所有
email: 1398660197@qq.com
wechat: hehung95
*/

#ifndef APP_WIFI_H_
#define APP_WIFI_H_

#include "app_common.h"

typedef enum
{
    WIFI_OPT_INIT = 0,
    WIFI_OPT_SETTING,
    WIFI_OPT_CONNECT,
    WIFI_OPT_SNTP_SETTING,
    WIFI_OPT_CONNECT_TCP,
    WIFI_OPT_WORKING,
    WIFI_OPT_CONNECT_STATUS,
    WIFI_OPT_GET_TIME
} e_WifiOptType;

typedef enum
{
    WIFI_ONENET_CONNECTED = 0,
    WIFI_ONENET_DISCONNECTED
} e_WifiIotConnStaType;

typedef enum
{
    WIFI_CONNECTED = 0,
    WIFI_DISEONNECTED
} e_ApConnectStatusType;

extern void Wifi_Init(void);
extern void Wifi_RunningEntry(void);
extern e_ApConnectStatusType Wifi_GetApConnStatus(void);
extern e_WifiIotConnStaType Wifi_GetIotConnStatus(void);
extern void WIfi_CheckPreiodLoop(void);
extern void Da16200_TRDTC_response(char *resp_data, uint16_t resp_data_len);


#endif /* APP_WIFI_H_ */

详细代码实现可以参考我的项目提交:【RA4M2设计挑战赛】作品提交 - 环境检测网关设备

试验效果

更多回帖

发帖
×
20
完善资料,
赚取积分