ESP8266物联网台灯

ESP8266实现物联网:

提示:本章节出,最近三天研究的ESP8266 单片机物联网,智能家居台灯。

如图:
ESP8266物联网台灯_第1张图片

1、硬件: 购买ESP8266 淘宝十几块钱,有WiFi+蓝牙、WiFi两个版本
2、烧录程序: 准备一根安卓带钩的数据线,不能充电线,用来给ESP8266烧录程序
3、服务器:搭建EMQT服务器 用来发布订阅消息
4、客户端:搭建前端


硬件

提示:ESP8266
ESP8266物联网台灯_第2张图片
ESP8266物联网台灯_第3张图片
ESP8266物联网台灯_第4张图片

烧录程序

提示:安装驱动 用来识别设备烧录程序 CH341SER

程序调试
http://nodemcu-dev.doit.am/3.html
CH340资料链接:
https://pan.baidu.com/s/1ILfWrsXIlnbidQav6qlw-w?pwd=4zk2
提取码: 4zk2
改进FT232芯片驱动下载链接:
https://pan.baidu.com/s/1x9Zwpr35d-R0rPVFrg7cAw
CP2102资料链接:
https://pan.baidu.com/s/1S4OzICkeNta739ZaDTr1jw?pwd=msjb
提取码: msjb
ESP01资料下载链接:https://pan.baidu.com/s/1pNsRH5OFq4NETx7Ty-mt1w
提取码:8888
ESP01S资料下载链接:https://pan.baidu.com/s/1Eic1kYrYyclKLQm490-EAA
提取码:8888

提示:安装 ArduinoIDE 烧录程序软件
安装&&使用教程
ESP8266物联网台灯_第5张图片

烧录程序

github
ESP8266物联网台灯_第6张图片
上面有三个版本,我这里选的是LED 版本,然后在此基础上做了小改动
加了控制板子上的led 和json 数据解析
esp8266库
PubSubClient库
ArduinoJson库

#include    //WiFi 库
#include   //做MQTT客户端
#include    //JSON 解析

// GPIO 5 D1
#define LED 5

// WiFi
const char *ssid = "wifi名";          // Enter your WiFi name
const char *password = "WiFi密码";    // Enter WiFi password

// MQTT Broker
const char *mqtt_broker = "192.168.137.1";  //mqtt服务器IP
const char *topic = "esp8266";              //作用服务器订阅名,最后和其他设备不要重复
const char *mqtt_username = "admin";        //mqtt登录名、用户名
const char *mqtt_password = "00admin";      //密码
const int mqtt_port = 1883;                 //默认的端口

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  // Set software serial baud to 115200;
  Serial.begin(115200);                     //Arduino调试用 串口监视器 选115200badu
  pinMode(LED_BUILTIN, OUTPUT);             //初始化led
  digitalWrite(LED_BUILTIN, HIGH);          //默认关闭    关HIGH/开LOW
  // connecting to a WiFi network
  WiFi.begin(ssid, password);               //连接WiFi
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
  //connecting to a mqtt broker
  client.setServer(mqtt_broker, mqtt_port);  //连接mqtt
  client.setCallback(callback);
  while (!client.connected()) {
    String client_id = "esp8266-client-";    //mqtt客户端ID client_id 
    client_id += String(WiFi.macAddress());
    Serial.printf("The client %s connects to the public mqtt broker\n", client_id.c_str());
    if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
      Serial.println("Public emqx mqtt broker connected");
    } else {
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
  }
  // publish and subscribe
  client.publish(topic, "hello emqx");
  client.subscribe(topic);
}

//MQTT回调
void callback(char *topic, byte *payload, unsigned int length) {
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
  Serial.print("Message:");
  String message;
  for (int i = 0; i < length; i++) {
    message = message + (char)payload[i];  // convert *byte to string
    //回调信息
  }
  Serial.print(message);
  
  // 解析JSON数据
  DynamicJsonDocument jsondoc(1024);
  deserializeJson(jsondoc, message);
  JsonObject obj = jsondoc.as<JsonObject>();
  String value = obj["msg"];

  if (value == "on") {
    digitalWrite(LED, LOW);
    digitalWrite(LED_BUILTIN, LOW);
  }  // LED on
  if (value == "off") {
    digitalWrite(LED, HIGH);
    digitalWrite(LED_BUILTIN, HIGH);
  }  // LED off
  Serial.println();
  Serial.println("-----------------------");
}

void loop() {
  client.loop();
}

烧录程序在板子里
ESP8266物联网台灯_第7张图片
ESP8266物联网台灯_第8张图片

搭建本地MQTT 服务器

提示:官方文档 emqx
建议通过Docker 安装

获取 docker 镜像

docker pull emqx/emqx:5.0.4

启动 docker 容器

docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8883:8883 -p 8084:8084 -p 18083:18083 emqx/emqx:5.0.4

http://localhost:18083/
ESP8266物联网台灯_第9张图片
提示:如果在阿里云、腾讯云线上部署 一定要开放端口
ESP8266物联网台灯_第10张图片

MQTTX测试工具
MQTTX使用教程
ESP8266物联网台灯_第11张图片
ESP8266物联网台灯_第12张图片

提示:一定要注意端口,Arduino 烧录程序在板子里 的端口要统一
ESP8266物联网台灯_第13张图片
ESP8266物联网台灯_第14张图片

提示:目前没有做客户端,暂时用MQTTX 测试用;emqx里面可以配置数据库数据存入,后续更新

C# 后端—客户端代码
MqttClientService
安装NuGet 程序包 MQTTnet

public class MqttClientService
    {
        public static MqttClient _mqttClient;
        public void MqttClientStart()
        {
            var optionsBuilder = new MqttClientOptionsBuilder()
                .WithTcpServer("192.168.50.80", 1883) // 要访问的mqtt服务端的 ip 和 端口号
                .WithCredentials("admin", "admints") // 要访问的mqtt服务端的用户名和密码
                .WithClientId("testclient02") // 设置客户端id
                .WithCleanSession()
                .WithTls(new MqttClientOptionsBuilderTlsParameters
                {
                    UseTls = false  // 是否使用 tls加密
                });

            var clientOptions = optionsBuilder.Build();
            _mqttClient = new MqttFactory().CreateMqttClient() as MqttClient;

            _mqttClient.ConnectedAsync += _mqttClient_ConnectedAsync; // 客户端连接成功事件
            _mqttClient.DisconnectedAsync += _mqttClient_DisconnectedAsync; // 客户端连接关闭事件
            _mqttClient.ApplicationMessageReceivedAsync += _mqttClient_ApplicationMessageReceivedAsync; // 收到消息事件

            _mqttClient.ConnectAsync(clientOptions);

        }

        /// 
        /// 客户端连接关闭事件
        /// 
        /// 
        /// 
        private Task _mqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg)
        {
            Console.WriteLine($"客户端已断开与服务端的连接……");
            return Task.CompletedTask;
        }

        /// 
        /// 客户端连接成功事件
        /// 
        /// 
        /// 
        private Task _mqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg)
        {
            Console.WriteLine($"客户端已连接服务端……");

            // 订阅消息主题
            // MqttQualityOfServiceLevel: (QoS):  0 最多一次,接收者不确认收到消息,并且消息不被发送者存储和重新发送提供与底层 TCP 协议相同的保证。
            // 1: 保证一条消息至少有一次会传递给接收方。发送方存储消息,直到它从接收方收到确认收到消息的数据包。一条消息可以多次发送或传递。
            // 2: 保证每条消息仅由预期的收件人接收一次。级别2是最安全和最慢的服务质量级别,保证由发送方和接收方之间的至少两个请求/响应(四次握手)。
            _mqttClient.SubscribeAsync("esp8266", MqttQualityOfServiceLevel.AtMostOnce);
            //Publish("{\"type\":\"LED\",\"msg\":\"ON\",\"des\":\"conslog\"}");

            return Task.CompletedTask;
        }

        /// 
        /// 收到消息事件
        /// 
        /// 
        /// 
        private Task _mqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg)
        {
            Console.WriteLine($"ApplicationMessageReceivedAsync:客户端ID=【{arg.ClientId}】接收到消息。 Topic主题=【{arg.ApplicationMessage.Topic}】 消息=【{Encoding.UTF8.GetString(arg.ApplicationMessage.Payload)}】 qos等级=【{arg.ApplicationMessage.QualityOfServiceLevel}】");
            return Task.CompletedTask;
        }
        //发送订阅信息
        public void Publish(string data)
        {
            var message = new MqttApplicationMessage
            {
                Topic = "esp8266",
                Payload = Encoding.Default.GetBytes(data),
                QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce,
                Retain = true  // 服务端是否保留消息。true为保留,如果有新的订阅者连接,就会立马收到该消息。
            };

            //var appMsg = new MqttApplicationMessage();
            //appMsg.Topic = "esp8266";
            //appMsg.Payload = Encoding.Default.GetBytes(data);
            //appMsg.QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce;
            //appMsg.Retain = false;
            //_mqttClient.PublishAsync(appMsg);
            _mqttClient.PublishAsync(message);
        }
        
        ///单独链接
        readonly IMqttClient client = new MqttFactory().CreateMqttClient();
        private async void MqttConnect()
        {
            var options = new MqttClientOptionsBuilder()
                .WithClientId("xmr/" + Guid.NewGuid().ToString())
                .WithTcpServer("mqtt IP", 1883) //默认端口
                .WithCredentials("用户名", "密码")
                .Build();
            await client.ConnectAsync(options, CancellationToken.None);
            var message = new MqttApplicationMessageBuilder()
                .WithTopic("hello/world")
                .WithPayload("hey")
                .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce)
                .Build();
            await client.PublishAsync(message, CancellationToken.None);
        }
    }

调用

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            MqttClientService mqttClient = new MqttClientService();
            mqttClient.MqttClientStart();

            Thread.Sleep(5000);
            mqttClient.Publish("{\"type\":\"JDQ\",\"msg\":\"OFF\",\"des\":\"conslog\"}");
            Console.ReadKey();

        }

ESP8266物联网台灯_第15张图片

MQTT发送失败问题
winform 客户端测试工具

页面前端—客户端代码
mqtt.js 的安装引用
两只种安装方式根据前端框架选其一即可

提示:CDN 安装

<script src="https://cdn.bootcdn.net/ajax/libs/mqtt/4.1.0/mqtt.min.js"></script>
<script>
  // 会在全局初始化一个 mqtt 变量,直接使用就可以
  console.log(mqtt)
</script>

提示:如果是用vue 请用 npm 安装

npm install mqtt --save

// 页面使用,直接 import 就可以
import mqtt from 'mqtt';

这里我用javascript 引用演示

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="https://cdn.bootcdn.net/ajax/libs/mqtt/4.1.0/mqtt.min.js"></script>
</head>
<body>
    <script>
        // 连接地址,有很多连接失败都是因为地址没写对
        const connectUrl = `ws://localhost:8083/mqtt`;
        // 客户端ID 随机数以免重复
        const clientId = `mqtt_${Math.random().toString(16).slice(3)}`;
        console.log("客户端id:"+clientId);

        // 连接设置
        let options = {
            clean: true,	// 保留会话
            connectTimeout: 4000,	// 超时时间
            reconnectPeriod: 1000,	// 重连时间间隔
            // 认证信息
            clientId,
            username: 'admin',
            password: 'admints',
        }
        // 需要订阅的主题
        const topic = 'esp8266';
        const topic1 = 'tes';

        // 创建客户端
        var client = mqtt.connect(connectUrl, options);

        // 成功连接后触发的回调
        client.on('connect', () => {
            console.log('已经连接成功');
            // 订阅主题,这里可以订阅多个主题
            client.subscribe([topic, topic1], () => {
                console.log(`订阅了主题 ${[topic, topic1].join('和')}`)
            })
        });

        // 当客户端收到一个发布过来的消息时触发回调
        /** 
         * topic:收到的报文的topic 
         * message:收到的数据包的负载playload 
         * packet:MQTT 报文信息,其中包含 QoS、retain 等信息
         */
        client.on('message', function (topic, message, packet) {
            // 这里有可能拿到的数据格式是Uint8Array格式,可以直接用toString转成字符串
            // let data = JSON.parse(message.toString());
            console.log("获取到的数据:", message)
            console.log("数据对应订阅主题:", topic)
            console.log("获取到的数据包:", packet)
            console.log(Uint8ArrayToString(packet.payload))
        });

        // 关闭客户端(断开连接)
        //client.end();

        // 发送信息给 topic(主题)
        //client.publish(topic, '这是给topic发送的信息');


        function Uint8ArrayToString(fileData) {
            var dataString = "";
            for (var i = 0; i < fileData.length; i++) {
                dataString += String.fromCharCode(fileData[i]);
            }
            return dataString
        }

    </script>
</body>
</html>

连接成功
ESP8266物联网台灯_第16张图片
ESP8266物联网台灯_第17张图片
发送topic成功
ESP8266物联网台灯_第18张图片

效果:

提示:效果如图下,后续会更新客户端和EMQT与数据库存储

如图:MQTTX发送信息 ESP8266 接收信息
ESP8266物联网台灯_第19张图片
ESP8266物联网台灯_第20张图片

你可能感兴趣的:(JavaScript,物联网,单片机,嵌入式硬件)