ESP8266 RTOS连接WIFI与使用lLwip中的Socket开点亮LED灯

用于测试,因Socket协议问题不可能用于智能物连网应用,可以应用到像企业类型中的服务器+下位机这样的场景
因为EventGroupHandle_t事件全局问题,wifi功能与Lwip的功能无法进行分隔,所以写在一起.(我是刚学没多久的C与C++菜鸟还是不会这个操作)
使用方法为主程序

#include "nvs_flash.h"
 nvs_flash_init(); //用于存取wifi的NVS功能
 initialise_wifi(); //启用wifi配置
 socket_start(); //启用lLwip中的Socket
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_err.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "driver/i2c.h"
#include "tcpip_adapter.h"
#include "nvs_flash.h"
#include "user_gpio.h"
#include "user_uart.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>
#include "user_ssd1306.h"

const int CONNECTED_BIT = BIT0;
static EventGroupHandle_t wifi_event_group;
//wifi的状态事件
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    /* 用于在断开连接时访问原因代码 */
   // system_event_info_t *info = &event->event_info;
    switch(event->event_id) {
    case SYSTEM_EVENT_STA_START: //表示wifi启动就绪
        esp_wifi_connect();
        break;
    case SYSTEM_EVENT_STA_GOT_IP: //分配得到IP,就表示已经连上路由器咯
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); //设置事件标志位
         os_printf("esp_wifi_connect");
        break;
    case SYSTEM_EVENT_STA_DISCONNECTED: //断开连接
        esp_wifi_connect();  //当esp8266因为异常断开连接时,我们继续连接
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); //清除事件标志位,等连接wifi后重新设置
        break;
    default:
        break;
    }
    return ESP_OK;
}


 void initialise_wifi(void)
{
   tcpip_adapter_init(); //初始化tcpip适配器,这将初始化内部的TCPIP堆栈。
   wifi_event_group = xEventGroupCreate(); //wifi事件标识位
   esp_event_loop_init(event_handler, NULL); //这个api会调用event_handler函数来处理wifi的状态事件
   wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); //使用默认的wifi初始化配置
   esp_wifi_init(&cfg);     //初始化wifi
   esp_wifi_set_storage(WIFI_STORAGE_RAM);
   wifi_config_t wifi_config = {
        .sta = {
          // .ssid = "TP-LINK_9F95",
           // .password = "admin123",
             .ssid = "BONDI",
            .password = "Viko0769",
        },
   };
   //os_printf(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
   esp_wifi_set_mode(WIFI_MODE_STA) ; //设置wifi模式
   esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ; //将配置信息,写入wifi
   esp_wifi_start();
}

static void tcp_server_task(void *pvParameters)
{	
    char rx_buffer[128]; //接收到的数据 因char占一个字节,可以理解一共128字节的数据
    char addr_str[128];  //客户端地址
    int addr_family;   //协议簇
    int ip_protocol; //IP协议

    while (1) {
        struct sockaddr_in destAddr; //定义目地socket结构体 
        destAddr.sin_addr.s_addr = htonl(INADDR_ANY); //本机地址
        destAddr.sin_family = AF_INET; //协议簇
        destAddr.sin_port = htons(8080); //端口号
        addr_family = AF_INET;
        ip_protocol = IPPROTO_IP;
        inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1); //直接将其映射到lwip内部函数,注意这是映射。。。

        int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);//创建一个用于连接的socket
        if (listen_sock < 0) {
            os_printf("Unable to create socket: errno %d \n", errno);
            break;
        }
        os_printf("Socket created \n");

        int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr)); //绑定一个socket连接到本机上
        if (err != 0) {
            os_printf("Socket unable to bind: errno %d \n", errno);
           break;
        }
        os_printf("Socket binded \n");

        err = listen(listen_sock, 1);//启动监听
        if (err != 0) {
            os_printf("Error occured during listen: errno %d \n", errno);
            break;
        }
        os_printf("Socket listening \n");


        struct sockaddr_in sourceAddr; //来源地址

        uint addrLen = sizeof(sourceAddr);
        int sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen);
        if (sock < 0) {
            os_printf("Unable to accept connection: errno %d \n", errno);
            break;
        }
        os_printf("Socket accepted \n");

        while (1) {
            int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
            // 接收过程中发生错误
            if (len < 0) {
                os_printf("recv failed: errno %d \n", errno);
                break;
            }
            // 连接关闭了
            else if (len == 0) {
                os_printf("Connection closed \n");
                break;
            }
            // 接收到的数据
            else {

                inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
                rx_buffer[len] = 0; // Null-终止我们接收到的任何内容,并将其视为字符串
                // os_printf("Received %d bytes from %s: \n", len, addr_str);
                // os_printf("%s \n", rx_buffer); //打印字符
                OLED_Clear();
                OLED_ShowString(0,0,(unsigned char *)rx_buffer);
                if( !strcmp(rx_buffer, "led"))
                {
                    //这里开始任务
                    xTaskCreate(ATaskLED,"LED",1024*4, NULL, 5, NULL);               
                }
                int err = send(sock, rx_buffer, len, 0);
                //发送过程中发生错误
                if (err < 0) {
                    os_printf("Error occured during sending: errno %d \n", errno);
                    break;
                }
            }
        }
       //关闭插座并重新启动
        if (sock != -1) {
            os_printf("Shutting down socket and restarting... \n");
            shutdown(sock, 0);
            close(sock);
            shutdown(listen_sock,0);
            close(listen_sock); //清理了socket列表
            vTaskDelay(5); //延时一下,让硬件清理完成
        }
    }
    vTaskDelete(NULL);
}
static void socket_task(void *pvParameters)
 {
     //等待事件标志位被设置,任务 wifi_event_group 由运行态进入到阻塞态  参数2:要等待的事件组中的位
     xEventGroupWaitBits(wifi_event_group, BIT0, false, true, portMAX_DELAY);
     xTaskCreate(tcp_server_task, "tcp_server",1024*4, NULL, 10, NULL);
     vTaskDelete(NULL);
 }


 void socket_start (void)
{
  xTaskCreate(socket_task, "socket_task",1024*4, NULL, 10, NULL);//通过任务来启动监听,防主进程阻塞
}

猜你喜欢

转载自www.cnblogs.com/praybb/p/12792395.html