环境及工具与第一章相同,这里就不在重复!php
这个项目用了几天的时间才搞定,期间遇到了不少问题,也调整了不少代码,在这里免费分享给你们,但愿同行能够借鉴!版权全部,请勿转载!!!web
代码说明:
GPIO02用于指示wifi联网状态;
GPIO12用于指示开关动做;
GPIO14用于读取按键,按下后设备重启进入配网状态;
wifi模块重启时20秒用于airkiss和esptouch配网;
联网后会以3秒一次向服务器发送请求数据,反馈回来的数据读取后进行控制;api
user_main.c所有代码以下:数组
#include "ets_sys.h" #include "osapi.h" #include "user_interface.h" #include "smartconfig.h"//配网 #include "espconn.h"//链接 #include "mem.h" #include "gpio.h"//io口 #include "user_devicefind.h" #include "user_webserver.h" #if ESP_PLATFORM #include "user_esp_platform.h" #endif void user_rf_pre_init(void){} /******************************************************************************* * 结构体声明 *******************************************************************************/ LOCAL struct espconn user_conn;//网络链接结构体 LOCAL os_timer_t os_timer;//定时器结构体 /******************************************************************************* * 全局变量声明 *******************************************************************************/ LOCAL uint8 order=0;//运行顺序标记,1完成路由器链接,2完成TCP链接,3TCP链接断开 LOCAL uint32 send=0;//发送标记 LOCAL const uint8 remote_ip[4]={192,168,1,1};//远程服务器ip地址 LOCAL const uint8 remote_port=8080;//远程服务器端口号 LOCAL char headbuf[110]="GET /switch_gear.php?token=abcd&id=";//待发送的字符开头 LOCAL char *id="0000000000";//设备id LOCAL char *endbuf="&series=WP&version=01 HTTP/1.1\nHost: www.abcd.com\n\n";//待发送的字符结尾 LOCAL char *pbuf=&headbuf[0]; /******************************************************************************* * 快连模式回调函数||init_done_cb()内调用 *******************************************************************************/ LOCAL void ICACHE_FLASH_ATTR smartconfig_done(sc_status status, void *pdata){ switch(status){ case SC_STATUS_WAIT://链接未开始,请勿在此阶段开始链接 os_printf("SC_STATUS_WAIT\n"); break; case SC_STATUS_FIND_CHANNEL://在此阶段进行配对链接 os_printf("SC_STATUS_FIND_CHANNEL\n"); break; case SC_STATUS_GETTING_SSID_PSWD://获得wifi名字和密码 os_printf("SC_STATUS_GETTING_SSID_PSWD\n"); break; case SC_STATUS_LINK://正在链接路由器 os_printf("SC_STATUS_LINK\n"); struct station_config *sta_conf=pdata; wifi_station_set_config(sta_conf);//设置WiFi station接口的配置参数,并保存到flash wifi_station_disconnect();//WiFi station接口从AP断开链接 wifi_station_connect();//WiFi station接口链接AP break; case SC_STATUS_LINK_OVER://获取到ip,链接路由完成 os_printf("SC_STATUS_LINK_OVER\n"); if(pdata!=NULL){ uint8 phone_ip[4]={0}; os_memcpy(phone_ip,(uint8*)pdata, 4); os_printf("Phone ip: %d.%d.%d.%d\n",phone_ip[0],phone_ip[1],phone_ip[2],phone_ip[3]);//打印发广播过来的设备IP地址 } smartconfig_stop();//中止配置 break; default:break; } } /******************************************************************************* * 显示函数||定时器回调函数内调用 *******************************************************************************/ LOCAL void ICACHE_FLASH_ATTR display(){ LOCAL bool io=false;//io引脚标记 LOCAL uint8 lag=0;//延迟标记 if(lag<200){lag++;} switch(order){ case 0: if(io==true){ io=false; GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 0);//GPIO12输出低电平 }else{ io=true; GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 1);//GPIO12输出高电平 } break; case 1: if(lag>10){ lag=0; if(io==true){ io=false; GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 0);//点亮 }else{ io=true; GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 1);//熄灭 } } break; case 2: GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 0);//点亮 break; case 3: GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 1);//熄灭 break; default: GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 1);//熄灭 break; } } /******************************************************************************* * TCP_client链接 *******************************************************************************/ LOCAL void ICACHE_FLASH_ATTR//数据发送成功 user_sent_cb(void *arg){ send=0; order=2; os_printf("Data transmission completion!\n"); } LOCAL void ICACHE_FLASH_ATTR//链接正常断开 user_discon_cb(void *arg){ order=3; os_printf("Normal disconnection!\n"); } LOCAL void ICACHE_FLASH_ATTR//接收到数据 user_recv_cb(void *arg,char *pdata,unsigned short len){ uint32 i=0; os_printf("Receive data:%s\r\n",pdata);//打印接收到的数据 for(i=0;i<(os_strlen(pdata));i++){ if(*(pdata+i)=='&'&&*(pdata+i+1)=='{'){ if(*(pdata+i+2)=='1'){ os_printf("Output low level\n");//输出低电平 GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0); }else{ os_printf("Output high level\n");//输出高电平 GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 1); } } } os_free(pdata);//释放接收内存 } LOCAL void ICACHE_FLASH_ATTR//TCP链接创建成功 user_connect_cb(void *arg){ struct espconn *pespconn=arg; espconn_regist_recvcb(pespconn,user_recv_cb);//数据接收 espconn_regist_sentcb(pespconn,user_sent_cb);//数据发送完成 espconn_regist_disconcb(pespconn,user_discon_cb);//链接正常断开 espconn_send(pespconn, pbuf, os_strlen(pbuf));//发送数据 } LOCAL void ICACHE_FLASH_ATTR//TCP链接发生异常而断开 user_recon_cb(void *arg, sint8 err){ order=3; os_printf("Abnormal disconnection, error code for%d\r\n",err); } LOCAL void ICACHE_FLASH_ATTR user_connect(struct ip_addr *remote_ip,struct ip_addr *local_ip,int remote_port){ /*espconn参数配置*/ user_conn.type=ESPCONN_TCP; user_conn.state=ESPCONN_NONE; user_conn.proto.tcp=(esp_tcp *)os_zalloc(sizeof(esp_tcp)); os_memcpy(user_conn.proto.tcp->local_ip,local_ip,4); os_memcpy(user_conn.proto.tcp->remote_ip,remote_ip,4); user_conn.proto.tcp->local_port=espconn_port(); user_conn.proto.tcp->remote_port=remote_port; /*注册链接回调函数和重连回调函数*/ espconn_regist_connectcb(&user_conn,user_connect_cb);//注册tcp链接成功后的回调函数 espconn_regist_reconcb(&user_conn,user_recon_cb);//注册tcp链接发生异常时的回调函数 /*启用链接*/ espconn_connect(&user_conn); } /******************************************************************************* * 定时器回调函数||init_done_cb()内调用 *******************************************************************************/ LOCAL void ICACHE_FLASH_ATTR os_timer_cb(void){ LOCAL uint32 lag[2]={0,0}; LOCAL bool boot=false;//使用一次标记 LOCAL struct ip_info info; //用于获取IP地址的信息 if(lag[0]<500){lag[0]++;} if(lag[1]<500){lag[1]++;} if(lag[0]>200){//开机上电20秒用于快连模式 wifi_get_ip_info(STATION_IF,&info);//获取接口ip地址 if(wifi_station_get_connect_status()==STATION_GOT_IP&&info.ip.addr!=0){//获取到IP if(lag[1]>30){//每3秒处理一次数据 lag[1]=0; switch(order){ case 0: order=1;//标记已完成路由器链接 os_printf("got ip\n");//打印获取到ip break; case 1: user_connect((struct ip_addr *)remote_ip,&info.ip,remote_port);//创建tcp链接 os_printf("connect to TCP\n");//链接到tcp break; case 2: espconn_send(&user_conn, pbuf, os_strlen(pbuf));//发送数据 break; case 3: espconn_connect(&user_conn);//尝试从新创建链接 os_printf("reconnect to TCP\n");//链接到tcp break; default:break; } } }else{ if(!boot){//未进行快连配置,则尝试链接原AP boot=true; smartconfig_stop();//中止配置 wifi_station_disconnect();//WiFi station接口从AP断开链接 wifi_station_connect();//WiFi station接口链接AP os_printf("connect to AP\n");//打印链接AP } } /*复位按键扫描*/ if(!GPIO_INPUT_GET(14)){ system_restart();//系统重启 } /*自制看门狗,约10分钟无响应,则重启*/ if(send<6500){send++;} if(send>6000){ send=0; system_restart();//系统重启 } } /*调用显示处理函数*/ display(); } /******************************************************************************* * 系统初始化完成回调函数||user_init()内调用 *******************************************************************************/ LOCAL void ICACHE_FLASH_ATTR init_done_cb(void){ uint32 id_cache=system_get_chip_id();//获取设备id os_sprintf(id, "%d", id_cache);//将设备id转换为数组 os_printf("id:%s\r\n", id); os_free(id_cache);//释放内存 strcat(pbuf,id);strcat(pbuf,endbuf);//拼接字符串 /*配置SmartConfig模式*/ smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS);//设置快连模式的协议类型(esptouch与airkiss) smartconfig_start(smartconfig_done);//开启快连模式 /*配置软件定时器 */ os_timer_disarm(&os_timer);//关闭定时器 os_timer_setfn(&os_timer,(ETSTimerFunc *) (os_timer_cb), NULL);//配置回调函数 os_timer_arm(&os_timer,100,true);//启动定时器 } /****************************************************************************** * FunctionName : user_init * Description : entry of user application, init user function here * Parameters : none * Returns : none *******************************************************************************/ void user_init(void) { /*设置串口波特率*/ uart_init(115200,9600); /*配置GPIO2和GPIO12*/ PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U ,FUNC_GPIO2);//用于指示链接状态 PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U,FUNC_GPIO12);//用于输出动做 PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U,FUNC_GPIO14);//用于按键输入 wifi_set_opmode(STATION_MODE);//配置为客户端模式,并保存到flash /*打印版本信息*/ os_printf("\r\n"); os_printf("SDK version:%s\r\n", system_get_sdk_version()); /*系统初始化*/ system_init_done_cb(init_done_cb);//系统初始化完成的回调函数 }