11- ESP8266建立灯控web服务器

Author:teacherXue

一、通过wifi控制家电

上一章节我们实现了ESP芯片的手动自主配网。可以以非常容易的将MCU接入网络,在没有公网(全球访问)资源的情况下,内网直连操作也是比较常见的做法。缺点就是操控端和被控制设备需要在一个局域网范围内。如果我到了单位忘记家里灯关了没,那也只有回去亲自看一下了。

  1. 控制LED灯的开关

现在我们来实现,通过在局域网内访问mcu芯片,通过网页对LED灯的开关进行控制,如下图。顺带也实现了温湿度的显示,看起来还是蛮实用的。

  1. 实现思路

  • 配网成功后,当有客户端http请求后,向客户端写HTML代码,客户通过浏览器端显示页面。

  • 服务端需要要根据当前的GPIO状态,改变HTML页面中的按钮状态。

  • 需要注意的是:当灯光当前为亮起时,页面的灯光状态为开,但按钮显示的应该是关,使得用户知道按下去时的作用。

  • 按钮会触发新的http请求,开和关将会访问不同的链接。

  • Mcu根据客户端请求的http头信息,得到请求路径,从而判断是该打开还是关闭灯光。

  1. 创建项目

1)新建项目,Lot_web_ctrl_v1.0,修改串口波特率,导入WiFiManager扩展库。

2)导入DHT传感器库

3)代码如下:

#include <Arduino.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager

#define LED_1 D5
#define LED_2 D6
#define DHTPIN D3            // DHT温湿度传感器引脚
#define DHTTYPE DHT22        // 声明DHT传感器类型
DHT dht(DHTPIN, DHTTYPE);    // 创建DHT对象
float t = 0.0;               // 温度全局保存
float h = 0.0;               // 湿度全局保存
String output5State = "off"; // led灯光状态
String output4State = "off"; // led灯光状态
WiFiServer server(80);       // 站点服务端口号
String header;               // http请求的头部信息

// 当前时间
unsigned long currentTime;
// 任务上次执行的时间
unsigned long previousTime = millis();
// 超时时间俩秒
const long timeoutTime = 2000;
// DHT传感器计时器
unsigned long currentTime1;
unsigned long previousTime1 = millis();
// 前置函数声明
void getTH();

void setup()
{
  Serial.begin(115200);
  pinMode(LED_1, OUTPUT);
  pinMode(LED_2, OUTPUT);
  // Set outputs to LOW
  digitalWrite(LED_1, LOW);
  digitalWrite(LED_2, LOW);
  dht.begin(); // DHT传感器对象工作
  WiFiManager wm;
  bool res;
  res = wm.autoConnect("xm_" + ESP.getChipId(), "12345678"); // password protected ap
  if (!res)
  {
    Serial.println("Failed to connect");
    // ESP.restart();
  }
  else
  {
    // if you get here you have connected to the WiFi
    Serial.println("connected...yeey :)");
  }
  // web服务器开始工作
  server.begin();
}

void loop()
{
  WiFiClient client = server.available(); // 监听连接请求
  if (client)
  { // 如果有新客户端连接
    Serial.println("New Client.");
    String currentLine = ""; // 存储客户端传递来的数据
    currentTime = millis();
    previousTime = currentTime;

    while (client.connected() && currentTime - previousTime <= timeoutTime)
    { // 客户端连接时循环
      currentTime = millis();
      if (client.available())
      {                         // 如果有字节要从客户端读取,
        char c = client.read(); // 读取一个字节
        Serial.write("c=");
        Serial.write(c);
        header += c;
        if (c == '\n')
        { // 如果字节是换行符
          // 如果当前行为空,则在一行中有两个换行符。
          // 这是客户端HTTP请求的结束,所以发送一个响应:
          if (currentLine.length() == 0)
          {
            // HTTP报头总是以响应代码开头(例如HTTP/1.1 200 OK)
            // 和一个content-type以便客户端知道将要发生什么,然后是一个空行:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            // 打开和关闭gpio
            if (header.indexOf("GET /1/on") >= 0)
            {
              Serial.println("GPIO 1 on");
              output5State = "on";
              digitalWrite(LED_1, HIGH);
            }
            else if (header.indexOf("GET /1/off") >= 0)
            {
              Serial.println("LED_1 off");
              output5State = "off";
              digitalWrite(LED_1, LOW);
            }
            else if (header.indexOf("GET /2/on") >= 0)
            {
              Serial.println("LED_2 on");
              output4State = "on";
              digitalWrite(LED_2, HIGH);
            }
            else if (header.indexOf("GET /2/off") >= 0)
            {
              Serial.println("LED_2 off");
              output4State = "off";
              digitalWrite(LED_2, LOW);
            }
            getTH();
            // 显示页面的HTML代码
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS 样式修饰 on/off 按钮
            // 请随意更改背景颜色和字体大小属性以适应您的偏好
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #77878A;}</style></head>");

            // 页面的头标签
            client.println("<body><h1>ESP8266 Web Server</h1>");

            // 显示gpio的当前状态
            client.println("<p>LED_1 - State " + output5State + "</p>");
            // 如果gpio状态为开,则页面按钮显示为off,以使得用户可以知道再次出发是关闭灯光
            if (output5State == "off")
            {
              client.println("<p><a href=\"/1/on\"><button class=\"button\">ON</button></a></p>");
            }
            else
            {
              client.println("<p><a href=\"/1/off\"><button class=\"button button2\">OFF</button></a></p>");
            }

            // 显示led2的灯光状态
            client.println("<p>LED_2- State " + output4State + "</p>");
            // 如果gpio状态为开,则页面按钮显示为off,以使得用户可以知道再次出发是关闭灯光
            if (output4State == "off")
            {
              client.println("<p><a href=\"/2/on\"><button class=\"button\">ON</button></a></p>");
            }
            else
            {
              client.println("<p><a href=\"/2/off\"><button class=\"button button2\">OFF</button></a></p>");
            }

            client.print("<p><h3>Temperature:");
            client.print(t);
            client.print("&#8451;</h3></p>");

            client.print("<p><h3>Humidity:");
            client.print(h);
            client.print("% </h3></p>");
            client.println("</body></html>");

            // HTTP响应以另一个空行结束
            client.println();
            // 跳出循环
            break;
          }
          else
          { // 如果你有一个换行符,那么需要清除currentLine
            currentLine = "";
          }
        }
        else if (c != '\r')
        {                   // 如果你得到的不是回车字符,
          currentLine += c; // 将它添加到currentLine的末尾
        }
      }
    }
    // 清除header变量
    header = "";
    // 关闭连接
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

// 获得温湿度
void getTH()
{
  h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  t = dht.readTemperature();
  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.println(F("°C "));
}

4)烧录代码并运行,结果如下:

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盐池虾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值