ESP8266 smartconfig 配网_esptouch for wechat-程序员宅基地

技术标签: c++  c语言  esp8266 学习笔记  

关于ESP8266的配网模式,本人实际接触到的配网有smartconfig和零配网模式

1、smartconfig配网需要用户输入热点的SSID和密码,实际上就是手机端、路由器和通信模块三者之间的一种交互方式,在短时间内,是一种相对稳定和安全的方式,让通信模块连接上指定的路由器,进而获取上网的流量,具体详细请自行了解smartconfig工作原理等。

2、零配网相比smartconfig而言就方便很多,实际上就是路由器、通信模块和已经连接联网设备三者之间的联系,比如之前做过的天猫精灵智能灯,使用的是零配网模式,通过天猫精灵音响通过WIFI对设备进行配网,具体详细请自行了解零配网的相关资料

使用ESP8266 进行 SDK 开发,smartconfig微信配网的代码如下


#include "user_config.h"		// 用户配置
#include "driver/uart.h"  		// 串口
#include "c_types.h"			// 变量类型
#include "eagle_soc.h"			// GPIO函数、宏定义
#include "ip_addr.h"			// 被"espconn.h"使用。在"espconn.h"开头#include"ip_addr.h"或#include"ip_addr.h"
#include "espconn.h"			// TCP/UDP接口
#include "ets_sys.h"			// 回调函数
#include "mem.h"				// 内存申请等函数
#include "os_type.h"			// os_XXX
#include "osapi.h"  			// os_XXX、软件定时器
#include "smartconfig.h"		// 智能配网
#include "user_interface.h" 	// 系统接口、system_param_xxx接口、WIFI、RateContro


#define		ProjectName			"SmartConfig_WeChat"	// 工程名宏定义

#define		Sector_STA_INFO		0x80			// 【STA参数】保存扇区

struct station_config STA_INFO;		// 【STA】参数结构体
os_timer_t OS_Timer_IP;				// 软件定时器
struct ip_info ST_ESP8266_IP;		// 8266的IP信息
u8 ESP8266_IP[4];					// 8266的IP地址
//==================================================================================


// 毫秒延时函数
//===========================================
void ICACHE_FLASH_ATTR delay_ms(u32 C_time)
{	for(;C_time>0;C_time--)
		os_delay_us(1000);
}
//===========================================


// SmartConfig状态发生改变时,进入此回调函数
//--------------------------------------------
// 参数1:sc_status status / 参数2:无类型指针【在不同状态下,[void *pdata]的传入参数是不同的】
//=================================================================================================================
void ICACHE_FLASH_ATTR smartconfig_done(sc_status status, void *pdata)
{
	os_printf("\r\n------ smartconfig_done ------\r\n");	// ESP8266网络状态改变

    switch(status)
    {
    	// CmartConfig等待
    	//……………………………………………………
        case SC_STATUS_WAIT:		// 初始值
            os_printf("\r\nSC_STATUS_WAIT\r\n");
        break;
        //……………………………………………………

        // 发现【WIFI信号】(8266在这种状态下等待配网)
        //…………………………………………………………………………………………………
        case SC_STATUS_FIND_CHANNEL:
            os_printf("\r\nSC_STATUS_FIND_CHANNEL\r\n");

    		os_printf("\r\n---- Please Use WeChat to SmartConfig ------\r\n\r\n");

    	break;
    	//…………………………………………………………………………………………………

        // 正在获取【SSID】【PSWD】(8266正在抓取并解密【SSID+PSWD】)
        //…………………………………………………………………………………………………
        case SC_STATUS_GETTING_SSID_PSWD:
            os_printf("\r\nSC_STATUS_GETTING_SSID_PSWD\r\n");

            // 【SC_STATUS_GETTING_SSID_PSWD】状态下,参数2==SmartConfig类型指针
            //-------------------------------------------------------------------
			sc_type *type = pdata;		// 获取【SmartConfig类型】指针

			// 配网方式 == 【ESPTOUCH】
			//-------------------------------------------------
            if (*type == SC_TYPE_ESPTOUCH)
            { os_printf("\r\nSC_TYPE:SC_TYPE_ESPTOUCH\r\n"); }

            // 配网方式 == 【AIRKISS】||【ESPTOUCH_AIRKISS】
            //-------------------------------------------------
            else
            { os_printf("\r\nSC_TYPE:SC_TYPE_AIRKISS\r\n"); }

	    break;
	    //…………………………………………………………………………………………………

        // 成功获取到【SSID】【PSWD】,保存STA参数,并连接WIFI
	    //…………………………………………………………………………………………………
        case SC_STATUS_LINK:
            os_printf("\r\nSC_STATUS_LINK\r\n");

            // 【SC_STATUS_LINK】状态下,参数2 == STA参数结构体指针
            //------------------------------------------------------------------
            struct station_config *sta_conf = pdata;	// 获取【STA参数】指针

            // 将【SSID】【PASS】保存到【外部Flash】中
            //--------------------------------------------------------------------------
			spi_flash_erase_sector(Sector_STA_INFO);						// 擦除扇区
			spi_flash_write(Sector_STA_INFO*4096, (uint32 *)sta_conf, 96);	// 写入扇区
			//--------------------------------------------------------------------------

			wifi_station_set_config(sta_conf);			// 设置STA参数【Flash】
	        wifi_station_disconnect();					// 断开STA连接
	        wifi_station_connect();						// ESP8266连接WIFI
            
            os_printf("WIFI Connecting\r\n");

	    break;
	    //…………………………………………………………………………………………………


        // ESP8266作为STA,成功连接到WIFI
	    //…………………………………………………………………………………………………
        case SC_STATUS_LINK_OVER:
            os_printf("\r\nSC_STATUS_LINK_OVER\r\n");

            smartconfig_stop();		// 停止SmartConfig,释放内存

            wifi_get_ip_info(STATION_IF,&ST_ESP8266_IP);	// 获取8266_STA的IP地址

			ESP8266_IP[0] = ST_ESP8266_IP.ip.addr;		// IP地址高八位 == addr低八位
			ESP8266_IP[1] = ST_ESP8266_IP.ip.addr>>8;	// IP地址次高八位 == addr次低八位
			ESP8266_IP[2] = ST_ESP8266_IP.ip.addr>>16;	// IP地址次低八位 == addr次高八位
			ESP8266_IP[3] = ST_ESP8266_IP.ip.addr>>24;	// IP地址低八位 == addr高八位


			os_printf("ESP8266_IP = %d.%d.%d.%d\n",ESP8266_IP[0],ESP8266_IP[1],ESP8266_IP[2],ESP8266_IP[3]);
			
			os_printf("Successfully\r\n");

			os_printf("\r\n---- ESP8266 Connect to WIFI Successfully ----\r\n");

			//*****************************************************
			// WIFI连接成功,执行后续功能。	如:SNTP/UDP/TCP/DNS等
			//*****************************************************

	    break;
	    //…………………………………………………………………………………………………

    }
}



// IP定时检查的回调函数
//========================================================================================================
void ICACHE_FLASH_ATTR OS_Timer_IP_cb(void)
{
	u8 S_WIFI_STA_Connect;			// WIFI接入状态标志


	// 查询STA接入WIFI状态
	//-----------------------------------------------------
	S_WIFI_STA_Connect = wifi_station_get_connect_status();
	//---------------------------------------------------
	// Station连接状态表
	// 0 == STATION_IDLE -------------- STATION闲置
	// 1 == STATION_CONNECTING -------- 正在连接WIFI
	// 2 == STATION_WRONG_PASSWORD ---- WIFI密码错误
	// 3 == STATION_NO_AP_FOUND ------- 未发现指定WIFI
	// 4 == STATION_CONNECT_FAIL ------ 连接失败
	// 5 == STATION_GOT_IP ------------ 获得IP,连接成功
	//---------------------------------------------------


	// 成功接入WIFI
	//----------------------------------------------
	if( S_WIFI_STA_Connect == STATION_GOT_IP )	// 判断是否获取IP
	{
		wifi_get_ip_info(STATION_IF,&ST_ESP8266_IP);	// 获取8266_STA的IP地址

		ESP8266_IP[0] = ST_ESP8266_IP.ip.addr;		// IP地址高八位 == addr低八位
		ESP8266_IP[1] = ST_ESP8266_IP.ip.addr>>8;	// IP地址次高八位 == addr次低八位
		ESP8266_IP[2] = ST_ESP8266_IP.ip.addr>>16;	// IP地址次低八位 == addr次高八位
		ESP8266_IP[3] = ST_ESP8266_IP.ip.addr>>24;	// IP地址低八位 == addr高八位

		// 显示ESP8266的IP地址
		//--------------------------------
		os_printf("ESP8266_IP = %d.%d.%d.%d\n",ESP8266_IP[0],ESP8266_IP[1],ESP8266_IP[2],ESP8266_IP[3]);
		//---------------

		os_printf("\r\n---- ESP8266 Connect to WIFI Successfully ----\r\n");

		os_timer_disarm(&OS_Timer_IP);	// 关闭定时器

		//*****************************************************
		// WIFI连接成功,执行后续功能。	如:SNTP/UDP/TCP/DNS等
		//*****************************************************
	}

	// ESP8266无法连接WIFI
	//------------------------------------------------------------------------------------------------
	else if(	S_WIFI_STA_Connect==STATION_NO_AP_FOUND 	||		// 未找到指定WIFI
				S_WIFI_STA_Connect==STATION_WRONG_PASSWORD 	||		// WIFI密码错误
				S_WIFI_STA_Connect==STATION_CONNECT_FAIL		)	// 连接WIFI失败
	{
		os_timer_disarm(&OS_Timer_IP);			// 关闭定时器

		os_printf("\r\n---- S_WIFI_STA_Connect=%d-----------\r\n",S_WIFI_STA_Connect);
		os_printf("\r\n---- ESP8266 Can't Connect to WIFI-----------\r\n");

		// 微信智能配网设置
		//…………………………………………………………………………………………………………………………
		//wifi_set_opmode(STATION_MODE);	// 设为STA模式	//【第①步】

		smartconfig_set_type(SC_TYPE_AIRKISS); 	// ESP8266配网方式【AIRKISS】//【第②步】

		smartconfig_start(smartconfig_done);// 进入【智能配网模式】,并设置回调函数//【第③步】
		
	}
}


// 软件定时器初始化(ms毫秒)
//========================================================================================
void ICACHE_FLASH_ATTR OS_Timer_IP_Init(u32 time_ms, u8 time_repetitive)
{

	os_timer_disarm(&OS_Timer_IP);	// 关闭定时器
	os_timer_setfn(&OS_Timer_IP,(os_timer_func_t *)OS_Timer_IP_cb, NULL);	// 设置定时器
	os_timer_arm(&OS_Timer_IP, time_ms, time_repetitive);  // 使能定时器
}




// user_init:entry of user application, init user function here
//=================================================================================================
void ICACHE_FLASH_ATTR user_init(void)
{
	uart_init(115200,115200);	// 初始化串口波特率
	os_delay_us(10000);			// 等待串口稳定
	os_printf("\r\n=================================================\r\n");
	os_printf("\t Project:\t%s\r\n", ProjectName);
	os_printf("\t SDK version:\t%s", system_get_sdk_version());
	os_printf("\r\n=================================================\r\n");



// ESP8266读取【外部Flash】中的【STA参数】(SSID/PASS),作为STA,连接WIFI
//………………………………………………………………………………………………………………………………
	os_memset(&STA_INFO,0,sizeof(struct station_config));			// STA_INFO = 0
	spi_flash_read(Sector_STA_INFO*4096,(uint32 *)&STA_INFO, 96);
// 读出【STA参数】(SSID/PASS)

	STA_INFO.ssid[31] = 0;		// SSID最后添'\0'
	STA_INFO.password[63] = 0;	// APSS最后添'\0'
	os_printf("\r\nSTA_INFO.ssid=%s\r\nSTA_INFO.password=%s\r\n",STA_INFO.ssid,STA_INFO.password);

	wifi_set_opmode(0x01);					// 设置为STA模式,并保存到Flash
	wifi_station_set_config(&STA_INFO);		// 设置STA参数
	wifi_station_connect();					// ESP8266连接WIFI(这里,此句可省)

	OS_Timer_IP_Init(1000,1);	// 定时查询8266连接WIFI情况
}

至此,配网完成!

--2022-4-18补充,配网完成后我们应该怎么使用呢,这里列举下Smartconfig后进行云服务器TCP连接,然后TCP使用接收数据后返回数据控制板载LED灯的亮灭,每1秒发送一次,简易版本

ESP8266程序如下

#include "user_config.h"
#include "driver/uart.h"
#include "c_types.h"
#include "eagle_soc.h"
#include "ip_addr.h"
#include "espconn.h"
#include "ets_sys.h"
#include "mem.h"
#include "os_type.h"
#include "osapi.h"
#include "smartconfig.h"
#include "user_interface.h"


#define		ProjectName			"SmartConfig_TCP_LED"

#define		Sector_STA_INFO		0x80

#define		LED_ON				GPIO_OUTPUT_SET(GPIO_ID_PIN(4),0)		// LED亮
#define		LED_OFF				GPIO_OUTPUT_SET(GPIO_ID_PIN(4),1)		// LED灭


struct espconn ST_NetCon;
struct station_config STA_INFO;

os_timer_t OS_Timer_IP;
os_timer_t Data_send;

struct ip_info ST_ESP8266_IP;
u8 ESP8266_IP[4];

u8 C_LED_Flash = 0;

unsigned char data[2];
u8 numbertime=0;
void ICACHE_FLASH_ATTR delay_ms(u32 C_time)
{	for(;C_time>0;C_time--)
		os_delay_us(1000);
}


void ICACHE_FLASH_ATTR ESP8266_WIFI_Send_Cb_JX(void *arg)
{
	os_printf("\nESP8266_WIFI_Send_OK\n");
}

// 成功接收网络数据的回调函数【参数1:网络传输结构体espconn指针、参数2:网络传输数据指针、参数3:数据长度】
//=========================================================================================================
void ICACHE_FLASH_ATTR ESP8266_WIFI_Recv_Cb_JX(void * arg, char * pdata, unsigned short len)
{
	struct espconn * T_arg = arg;		// 缓存网络连接结构体指针

	// 根据数据设置LED的亮/灭
	//-------------------------------------------------------------------------------
	if(pdata[0] == 'k' || pdata[0] == 'K')	LED_ON;			// 首字母为'k'/'K',灯亮
	else if(pdata[0] == 'g' || pdata[0] == 'G')	LED_OFF;	// 首字母为'g'/'G',灯灭
	os_printf("\nESP8266_Receive_Data = %s\n",pdata);		// 串口打印接收到的数据

	espconn_send(T_arg,"ESP8266_WIFI_Recv_OK",os_strlen("ESP8266_WIFI_Recv_OK"));	// 向对方发送应答
}


// TCP连接断开成功的回调函数
//================================================================
void ICACHE_FLASH_ATTR ESP8266_TCP_Disconnect_Cb_JX(void *arg)
{
	os_printf("\nESP8266_TCP_Disconnect_OK\n");
}

// TCP连接建立成功的回调函数
//====================================================================================================================
void ICACHE_FLASH_ATTR ESP8266_TCP_Connect_Cb_JX(void *arg)
{
	espconn_regist_sentcb((struct espconn *)arg, ESP8266_WIFI_Send_Cb_JX);			// 注册网络数据发送成功的回调函数
	espconn_regist_recvcb((struct espconn *)arg, ESP8266_WIFI_Recv_Cb_JX);			// 注册网络数据接收成功的回调函数
	espconn_regist_disconcb((struct espconn *)arg,ESP8266_TCP_Disconnect_Cb_JX);	// 注册成功断开TCP连接的回调函数

	os_printf("\n--------------- ESP8266_TCP_Connect_OK ---------------\n");

	// 也可以不打招呼,因为TCP本身就是握手建立连接。只要TCP连接建立,TCP_Server就已经知道TCP_Client的信息
	//----------------------------------------------------------------------------------------------------
	espconn_send((struct espconn *)arg,"Hello,I am ESP8266",os_strlen("Hello,I am ESP8266"));	// 打招呼
}

// TCP连接异常断开时的回调函数【ESP8266作为TCP_Client,连接TCP_Server失败,也会进入此函数】
//==========================================================================================
void ICACHE_FLASH_ATTR ESP8266_TCP_Break_Cb_JX(void *arg,sint8 err)
{
	os_printf("\nESP8266_TCP_Break\n");

	espconn_connect(&ST_NetCon);	// 连接TCP-server
}



//==================================================================================================
void ICACHE_FLASH_ATTR ESP8266_NetCon_Init_JX()
{
	// �ṹ�帳ֵ
		//--------------------------------------------------------------------------
		ST_NetCon.type = ESPCONN_TCP;		

		ST_NetCon.proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));	// 开辟内存

		//本人的阿里云服务器 TCP端口50007
		ST_NetCon.proto.tcp->local_port  = 8266 ;	// 本地端口
		ST_NetCon.proto.tcp->remote_port = 50007;	// 远程端口
		ST_NetCon.proto.tcp->remote_ip[0] = 47;	    //服务器IP地址
		ST_NetCon.proto.tcp->remote_ip[1] = 102;
		ST_NetCon.proto.tcp->remote_ip[2] = 138;
		ST_NetCon.proto.tcp->remote_ip[3] = 197;

		// 注册连接成功回调函数、异常断开回调函数
		//--------------------------------------------------------------------------------------------------
		espconn_regist_connectcb(&ST_NetCon, ESP8266_TCP_Connect_Cb_JX);	// 注册TCP连接成功建立的回调函数
		espconn_regist_reconcb(&ST_NetCon, ESP8266_TCP_Break_Cb_JX);		// 注册TCP连接异常断开的回调函数


		// 连接 TCP server
		//----------------------------------------------------------
		espconn_connect(&ST_NetCon);	// 连接TCP-server}
}



void ICACHE_FLASH_ATTR smartconfig_done(sc_status status, void *pdata)
{
	os_printf("\r\n------ smartconfig_done ------\r\n");

    switch(status)
    {

        case SC_STATUS_WAIT:		// ��ʼֵ
            os_printf("\r\nSC_STATUS_WAIT\r\n");
        break;

        case SC_STATUS_FIND_CHANNEL:
            os_printf("\r\nSC_STATUS_FIND_CHANNEL\r\n");
    		os_printf("\r\n---- Please Use WeChat to SmartConfig ------\r\n\r\n"); 

    	break;

        case SC_STATUS_GETTING_SSID_PSWD:
            os_printf("\r\nSC_STATUS_GETTING_SSID_PSWD\r\n");


			sc_type *type = pdata;		


            if (*type == SC_TYPE_ESPTOUCH)
            { os_printf("\r\nSC_TYPE:SC_TYPE_ESPTOUCH\r\n"); }


            else
            { os_printf("\r\nSC_TYPE:SC_TYPE_AIRKISS\r\n"); }

	    break;

        case SC_STATUS_LINK:
            os_printf("\r\nSC_STATUS_LINK\r\n");

            struct station_config *sta_conf = pdata;


			spi_flash_erase_sector(Sector_STA_INFO);
			spi_flash_write(Sector_STA_INFO*4096, (uint32 *)sta_conf, 96);


			wifi_station_set_config(sta_conf);
	        wifi_station_disconnect();
	        wifi_station_connect();

	    	os_printf("\r\n WIFI \r\n");
	    	ESP8266_NetCon_Init_JX();
	    	espconn_create(&ST_NetCon);

	    break;

        case SC_STATUS_LINK_OVER:
            os_printf("\r\nSC_STATUS_LINK_OVER\r\n");

            smartconfig_stop();


            wifi_get_ip_info(STATION_IF,&ST_ESP8266_IP);

			ESP8266_IP[0] = ST_ESP8266_IP.ip.addr;
			ESP8266_IP[1] = ST_ESP8266_IP.ip.addr>>8;
			ESP8266_IP[2] = ST_ESP8266_IP.ip.addr>>16;
			ESP8266_IP[3] = ST_ESP8266_IP.ip.addr>>24;

			os_printf("ESP8266_IP = %d.%d.%d.%d\n",ESP8266_IP[0],ESP8266_IP[1],ESP8266_IP[2],ESP8266_IP[3]);

			for(; C_LED_Flash<=5; C_LED_Flash++)
			{
				GPIO_OUTPUT_SET(GPIO_ID_PIN(4),(C_LED_Flash%2));
				delay_ms(100);
			}

			os_printf("\r\n---- ESP8266 Connect to WIFI Successfully ----\r\n");


			os_timer_disarm(&OS_Timer_IP);
			ESP8266_NetCon_Init_JX();


	    break;


    }
}



//========================================================================================================
void ICACHE_FLASH_ATTR OS_Timer_IP_cb(void)
{
	u8 S_WIFI_STA_Connect;

	S_WIFI_STA_Connect = wifi_station_get_connect_status();

	system_soft_wdt_feed();

	if( S_WIFI_STA_Connect == STATION_GOT_IP )	// �ж��Ƿ��ȡIP
	{
		wifi_get_ip_info(STATION_IF,&ST_ESP8266_IP);	// ��ȡ8266_STA��IP��ַ

		ESP8266_IP[0] = ST_ESP8266_IP.ip.addr;		// IP��ַ�߰�λ == addr�Ͱ�λ
		ESP8266_IP[1] = ST_ESP8266_IP.ip.addr>>8;	// IP��ַ�θ߰�λ == addr�εͰ�λ
		ESP8266_IP[2] = ST_ESP8266_IP.ip.addr>>16;	// IP��ַ�εͰ�λ == addr�θ߰�λ
		ESP8266_IP[3] = ST_ESP8266_IP.ip.addr>>24;	// IP��ַ�Ͱ�λ == addr�߰�λ

		for(; C_LED_Flash<=5; C_LED_Flash++)
		{
			GPIO_OUTPUT_SET(GPIO_ID_PIN(4),(C_LED_Flash%2));
			delay_ms(100);
		}

		os_timer_disarm(&OS_Timer_IP);
		ESP8266_NetCon_Init_JX();


	}



	else if(	S_WIFI_STA_Connect==STATION_NO_AP_FOUND 	||		// δ�ҵ�ָ��WIFI
				S_WIFI_STA_Connect==STATION_WRONG_PASSWORD 	||		// WIFI�������
				S_WIFI_STA_Connect==STATION_CONNECT_FAIL		)	// ����WIFIʧ��
	{
		os_timer_disarm(&OS_Timer_IP);

		smartconfig_set_type(SC_TYPE_AIRKISS);

		smartconfig_start(smartconfig_done);
	}




}

void ICACHE_FLASH_ATTR OS_Timer_IP_Init(u32 time_ms, u8 time_repetitive)
{

	os_timer_disarm(&OS_Timer_IP);	
	os_timer_setfn(&OS_Timer_IP,(os_timer_func_t *)OS_Timer_IP_cb, NULL);
	os_timer_arm(&OS_Timer_IP, time_ms, time_repetitive);  /
}

void ICACHE_FLASH_ATTR LED_Init_JX(void)
{
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U,	FUNC_GPIO4);	// GPIO4设为IO口

	GPIO_OUTPUT_SET(GPIO_ID_PIN(4),1);						// IO4 = 1
}


void ICACHE_FLASH_ATTR user_init(void)
{

	uart_init(115200,115200);
	os_delay_us(10000);
	os_printf("\r\n=================================================\r\n");
	os_printf("\t Project:\t%s\r\n", ProjectName);
	os_printf("\t SDK version:\t%s", system_get_sdk_version());
	os_printf("\r\n=================================================\r\n");

	LED_Init_JX();		// 板载LED初始化

	//*******************SmartConfig*******************//
	os_memset(&STA_INFO,0,sizeof(struct station_config));
	spi_flash_read(Sector_STA_INFO*4096,(uint32 *)&STA_INFO, 96);
	STA_INFO.ssid[31] = 0;
	STA_INFO.password[63] = 0;
	os_printf("\r\nSTA_INFO.ssid=%s\r\nSTA_INFO.password=%s\r\n",STA_INFO.ssid,STA_INFO.password);

	wifi_set_opmode(0x01);
	wifi_station_set_config(&STA_INFO);

	//定时器1s延时
	OS_Timer_IP_Init(1000,1);
}
//=================================================================================================


/******************************************************************************
 * FunctionName : user_rf_cal_sector_set
 * Description  : SDK just reversed 4 sectors, used for rf init data and paramters.
 *                We add this function to force users to set rf cal sector, since
 *                we don't know which sector is free in user's application.
 *                sector map for last several sectors : ABCCC
 *                A : rf cal
 *                B : rf init data
 *                C : sdk parameters
 * Parameters   : none
 * Returns      : rf cal sector
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR user_rf_cal_sector_set(void)
{
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map) {
        case FLASH_SIZE_4M_MAP_256_256:
            rf_cal_sec = 128 - 5;
            break;

        case FLASH_SIZE_8M_MAP_512_512:
            rf_cal_sec = 256 - 5;
            break;

        case FLASH_SIZE_16M_MAP_512_512:
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;
            break;

        case FLASH_SIZE_32M_MAP_512_512:
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;
            break;

        case FLASH_SIZE_64M_MAP_1024_1024:
            rf_cal_sec = 2048 - 5;
            break;
        case FLASH_SIZE_128M_MAP_1024_1024:
            rf_cal_sec = 4096 - 5;
            break;
        default:
            rf_cal_sec = 0;
            break;
    }

    return rf_cal_sec;
}
void ICACHE_FLASH_ATTR user_rf_pre_init(void){}

服务器端采用python接收发送数据,代码如下

import socketserver
import random
import time

#定义一个类
class MyServer(socketserver.BaseRequestHandler):
	#如果handle方法出现报错,则会进行跳过
	#setup和finish方法无论如何都会进行执行
	#首先执行setup
	def setup(self):
		pass
	#然后执行handle
	def handle(self):
		conn = self.request          #定义连接变量
		msg = "当前TCP服务器已连接"    #发送消息定义
		conn.send(msg.encode())      #消息发送
		while True:       #进入循环,不断接受客户端的消息
			data = conn.recv(1024)   #接收客户端信息
			print(data.decode())     #接收信息解码decode
			if data == b'exit':      #接收到exit,则进行循环的退出
				break
			conn.send(str("guan").encode()) #返回 guan 
			time.sleep(1) #1s延时
            conn.send(str("kai").encode())  #返回 kai
            time.sleep(1) #1s延时
		conn.close()
	#最后执行finish
	def finish(self):
		pass
if __name__ == '__main__':
	server = socketserver.ThreadingTCPServer(("127.0.0.1",50007),MyServer)  #创建多线程实例
	server.serve_forever() #开启异步多线程,等待连接

Python 程序代码有点粗糙,只是单纯的检验TCP端收发数据的效果而已

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_41583631/article/details/124070849

智能推荐

QML 语言基础_qml返回列表中元素个数-程序员宅基地

文章浏览阅读721次。出处: http://blog.csdn.net/foruok在《Qt Quick 简介》中我们提到 QML 语法和 Json 类似,请参考《Qt on Android: http下载与Json解析》查看 Json 语法。当然这里我们是期望从零开始也能学会 QML ,所以呢,你也可以直接往下看。 版权所有 foruok,转载请注明出处:http://blog.csdn.n_qml返回列表中元素个数

tensorflow之session_options/ConfigProto_session options-程序员宅基地

文章浏览阅读807次。tensorflow SessionConfig cluster 源码注释_session options

安卓Andriod使用入门(一)【圆形Menu菜单】_littlevgl菜单-程序员宅基地

文章浏览阅读1.2k次。每个人都会有一段异常艰难的时光,在现在生活中,为人处世的最佳境界是不卑不亢。太在乎别人的眼光和评价,只能让自己做事放不开手脚,犹豫不决,失去自我,失去个性,丢失自我的价值。MainActivity.java代码:package siso.handlerdemo;import android.app.NotificationManager;import android.content.Intent;_littlevgl菜单

MAVEN学习笔记-解决Spring cloud中项目间有依赖关系导致打包报错问题_idea 打包springcloud时 单个项目打包出现依赖问题-程序员宅基地

文章浏览阅读4.1k次。项目Module之间有依赖关系时会导致打jar包失败。比如,athena-eureka、athena-keystone等模块会在pom中依赖athena-common&lt;dependency&gt; &lt;artifactId&gt;athena-common&lt;/artifactId&gt; &lt;groupId&gt;com.xxx.xxx&lt;/groupId&..._idea 打包springcloud时 单个项目打包出现依赖问题

C++ 动态库&静态库创建和使用_c++ 动态库 静态库创建-程序员宅基地

文章浏览阅读1.3k次。什么是库库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(.a、.lib)和动态库(.so、.dll)。所谓静态、动态是指链接。回顾一下,将一个程序编译成可执行程序的步骤:静态库之所以成为【静_c++ 动态库 静态库创建

页表项中各个位的作用_存在位是用于-程序员宅基地

文章浏览阅读1.4w次,点赞3次,收藏22次。问题:在请求分页系统中,页表中的辅存始地址是供(D)参考的。 A.页面置换 B.内存分配 C.页面换出 D.页面调入页表项有:|页号|物理块号|状态位P|访问字段A|修改位M|外存地址|各个位的作用:1)状态位P:用于指示该页是否已调入内存,供程序访问时参考; 2)访问字段A:用于记录本页在一段时间内被访问次数,供选择换出页面时参考; 3)修改位M:表示该页在调..._存在位是用于

随便推点

微信、QQ聊天是怎么实现的?原来这么简单!!!_聊天软件实现原理-程序员宅基地

文章浏览阅读4.4k次,点赞3次,收藏11次。自己动手做制作聊天室。利用C#制作的聊天室。实现QQ和微信聊天的功能。C#课程设计,软件工程课程设计。_聊天软件实现原理

Linux磁盘存储和文件管理_phd系统块的大小-程序员宅基地

文章浏览阅读472次。磁盘分区有MBR,GPT两种#备份MBR分区表[root@centos8 ~]#dd if=/dev/sda of=/data/dpt.img bs=1 count=64 skip=446 [root@centos8 ~]#scp /data/dpt.img 10.0.0.102: #破坏MBR分区表[root@centos8 ~]#dd if=/dev/zero of=/dev/sda..._phd系统块的大小

nodejs自定义一个打印模块_nodejs print-程序员宅基地

文章浏览阅读683次。打印时间 - 错误和正常颜色差异 - 输出打印函数的运行的文件名和行号。_nodejs print

JAVA 开发常用方法及学习地址(转载)_java学习地址-程序员宅基地

文章浏览阅读129次。1、UUID 获取随机的idimport java.util.UUID;String uuid = UUID.randomUUID().toString(); _java学习地址

Web自动化测试Selenium(1)选择元素基本方法-2021-10-07_选择网页相应元素-程序员宅基地

文章浏览阅读535次,点赞5次,收藏9次。1. selenium环境安装Selenium环境的安装主要就是安装两样东西: 客户端库 和 浏览器 驱动 。selenium安装 pip install selenium浏览器安装 首选谷歌浏览器驱动安装 驱动版本要和浏览器版本对应2. 基本使用2.1 启动浏览器并搜索网站2.2 定位元素定位元素进行搜索F12 进入开发者模式,找到Elements选择页面元素,鼠标右击检查,找对对应语句,然后根据特征进行查找下面所有定位元素的方法,返回的对象都是·WebElement对_选择网页相应元素

php漏洞全解_<?php if(isset($_get['c'])){ $arg=$_get['c']; syst-程序员宅基地

文章浏览阅读7.9w次。1、命令注入(CommandInjection)2、eval注入(EvalInjection)3、客户端脚本攻击(ScriptInsertion)4、跨网站脚本攻击(CrossSiteScripting,XSS)5、SQL注入攻击(SQLinjection)6、跨网站请求伪造攻击(CrossSiteRequestForgeries,CSRF)7、Session会话劫持(SessionHijacking)......_<?php if(isset($_get['c'])){ $arg=$_get['c']; system($arg.">/dev/null 2>&1ka</div>

推荐文章

热门文章

相关标签