ESP8266_SDK基础(5)智能插座_完整项目代码

环境及工具与第一章相同,这里就不在重复!

这个项目用了几天的时间才搞定,期间遇到了很多问题,也调整了很多代码,在这里免费分享给大家,希望同行可以借鉴!版权所有,请勿转载!!!

代码说明:
GPIO02用于指示wifi联网状态;
GPIO12用于指示开关动作;
GPIO14用于读取按键,按下后设备重启进入配网状态;
wifi模块重启时20秒用于airkiss和esptouch配网;
联网后会以3秒一次向服务器发送请求数据,反馈回来的数据读取后进行控制;

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);//系统初始化完成的回调函数
}
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值