ZK-VIEW快速接入MQTT教程,实现继电器远程开关与DHT11温湿度采集与传输,通过ZK-VIEW低代码Web组态平台快速接入,实现组态监控,大屏可视化

通过MQTT使用ESP8266实现继电器远程开关与DHT11温湿度采集与传输,通过Arduino烧录,通过ZK-VIEW低代码Web组态平台快速接入,实现大屏可视化。

所有的示例所用到的程序和代码下载链接

链接:https://pan.baidu.com/s/1KKztYrDe07rD6TWuiMcyfw?pwd=agc9
提取码:agc9

ZK-VIEW在线工业组态低代码平台地址:http://zkview.com

压缩包内容如下
在这里插入图片描述

注意:程序不要放在中文目录下运行,避免出现不必要的异常


话不多说,正式开始

1. 安装 Arduino IDE 开发环境

  • 双击运行: arduino-ide_2.0.4_Windows_64bit.exe
  • 安装好后,打开软件,如图所示
    在这里插入图片描述
  • 设置中文

File>Preferences>Language

在这里插入图片描述

  • 弹出菜单选择中文(简体),点击OK
    在这里插入图片描述
  • 第一次安装会多次弹出安装软件驱动,一律点击安装
    在这里插入图片描述
  • 配置Esp8266管理器地址

文件>首选项>其他开发板管理地址>
填入: http://arduino.esp8266.com/stable/package_esp8266com_index.json

在这里插入图片描述
在这里插入图片描述
点击确定

  • 安装Esp8266平台

在这里插入图片描述
在这里插入图片描述

  • 等待下载安装完成,安装完成后会弹出安装成功小窗,如果有Error,请检查网络环境,重新安装
    在这里插入图片描述

  • 选择对应开发板,依次点击

工具>开发板>esp8266>NodeMCU 1.0(ESP-12E Module)

在这里插入图片描述

  • 安装库文件,依次点击

工具>管理库

在这里插入图片描述

  • 在弹出窗口的左侧依次输入以下库的名称进行安装

SimpleDHT、PubSubClient、OneWire、EspMQTTClient、Chrono
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 全部安装完成后,通过USB连接ESP8266开发板,将以下程序复制到程序框中(压缩包中ESP8266芯片程序)
  • 注意修改 wifi名称、密码、mqtt服务器地址

接线原理图

请添加图片描述

仅控制4路开关 ESP8266源程序

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Chrono.h>

const char* deviceID = "esp1";  // ESP8266板子编号,不同的板子更换编号,即可增加板子测点

const char* ssid = "lazykee";
const char* password = "123456789";
const char* mqtt_server = "192.168.2.2";

const int SWITCH_PINS[] = { 16, 5, 4, 2 };
const int SWITCH_COUNT = sizeof(SWITCH_PINS) / sizeof(SWITCH_PINS[0]);

WiFiClient espClient;
PubSubClient client(espClient);
Chrono switchStatusChrono;

// 更改开关状态并通过 MQTT 发送状态更新
void changeSwitch(int pin, char receivedChar) {
  digitalWrite(pin, receivedChar == '0' ? HIGH : LOW);
  int pinIndex = -1;
  for (int i = 0; i < SWITCH_COUNT; ++i) {
    if (SWITCH_PINS[i] == pin) {
      pinIndex = i;
      break;
    }
  }
  String data = "switch_" + String(pinIndex + 1) + "," + receivedChar + ";";
  client.publish((String("zkup/") + deviceID).c_str(), data.c_str());
}

// MQTT 消息回调函数
void callback(char* topic, byte* payload, unsigned int length) {
  char receivedChar = (char)payload[0];
  String tp = topic;
  Serial.println(tp);
  for (int i = 0; i < SWITCH_COUNT; ++i) {
    if (tp == (String("zkDown/") + deviceID + "/switch_" + String(i + 1))) {
      changeSwitch(SWITCH_PINS[i], receivedChar);
      break;
    }
  }
}

// 用于重新连接到 MQTT 服务器的函数
void reconnect() {
  while (!client.connected()) {
    // 使用 deviceID 作为客户端ID
    if (client.connect(deviceID)) {
      String subscriptionTopic = String("zkDown/") + deviceID + "/#";
      client.subscribe(subscriptionTopic.c_str());
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

// 发送所有开关的状态数据到 MQTT
void sendSwitchStatus() {
  String switchData = "";
  for (int i = 0; i < SWITCH_COUNT; ++i) {
    switchData += "switch_" + String(i + 1) + "," + (digitalRead(SWITCH_PINS[i]) == LOW ? "1" : "0") + ";";
  }
  client.publish((String("zkup/") + deviceID).c_str(), switchData.c_str());
}

// 设置函数,用于初始化
void setup() {
  Serial.begin(9600);

  for (int i = 0; i < SWITCH_COUNT; ++i) {
    pinMode(SWITCH_PINS[i], OUTPUT);
    digitalWrite(SWITCH_PINS[i], HIGH);
  }

  WiFi.begin(ssid, password);
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

// 主循环函数
void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  // 每5秒向 MQTT 发送一次所有开关的状态数据
  if (switchStatusChrono.hasPassed(5000)) {
    switchStatusChrono.restart();
    sendSwitchStatus();
  }
}

DHT11温湿度传感器 + 控制4路开关 ESP8266源程序(根据设备自选)


#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <SimpleDHT.h>
#include <Chrono.h>

const char* deviceID = "esp1";  // ESP8266板子编号,不同的板子更换编号,即可增加板子测点

const char* ssid = "lazykee";
const char* password = "123456789";
const char* mqtt_server = "192.168.2.2";
const int DHT_PIN = 14;

const int SWITCH_PINS[] = { 16, 5, 4, 2 };
const int SWITCH_COUNT = sizeof(SWITCH_PINS) / sizeof(SWITCH_PINS[0]);

WiFiClient espClient;
PubSubClient client(espClient);
SimpleDHT11 dht11(DHT_PIN);
Chrono dht11Chrono;
Chrono switchStatusChrono;

// 更改开关状态并通过 MQTT 发送状态更新
void changeSwitch(int pin, char receivedChar) {
  digitalWrite(pin, receivedChar == '0' ? HIGH : LOW);
  int pinIndex = -1;
  for (int i = 0; i < SWITCH_COUNT; ++i) {
    if (SWITCH_PINS[i] == pin) {
      pinIndex = i;
      break;
    }
  }
  String data = "switch_" + String(pinIndex + 1) + "," + receivedChar + ";";
  client.publish((String("zkup/") + deviceID).c_str(), data.c_str());
}

// MQTT 消息回调函数
void callback(char* topic, byte* payload, unsigned int length) {
  char receivedChar = (char)payload[0];
  String tp = topic;
  Serial.println(tp);
  for (int i = 0; i < SWITCH_COUNT; ++i) {
    if (tp == (String("zkDown/") + deviceID + "/switch_" + String(i + 1))) {
      changeSwitch(SWITCH_PINS[i], receivedChar);
      break;
    }
  }
}

// 用于重新连接到 MQTT 服务器的函数
void reconnect() {
  while (!client.connected()) {
    // 使用 deviceID 作为客户端ID
    if (client.connect(deviceID)) {
      String subscriptionTopic = String("zkDown/") + deviceID + "/#";
      client.subscribe(subscriptionTopic.c_str());
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

// 发送 DHT11 传感器数据到 MQTT
void sendDHT11Data() {
  byte temperature = 0;
  byte humidity = 0;

  if (dht11.read(&temperature, &humidity, nullptr) != SimpleDHTErrSuccess) {
    return;
  }

  String data = "temp1," + String(temperature) + ";"
                + "temp1," + String(temperature) + ",100;"
                + "hum1," + String(humidity) + ";"
                + "hum1," + String(humidity) + ",200";
  client.publish((String("zkup/") + deviceID).c_str(), data.c_str());
}

// 发送所有开关的状态数据到 MQTT
void sendSwitchStatus() {
  String switchData = "";
  for (int i = 0; i < SWITCH_COUNT; ++i) {
    switchData += "switch_" + String(i + 1) + "," + (digitalRead(SWITCH_PINS[i]) == LOW ? "1" : "0") + ";";
  }
  client.publish((String("zkup/") + deviceID).c_str(), switchData.c_str());
}

// 设置函数,用于初始化
void setup() {
  Serial.begin(9600);

  for (int i = 0; i < SWITCH_COUNT; ++i) {
    pinMode(SWITCH_PINS[i], OUTPUT);
    digitalWrite(SWITCH_PINS[i], HIGH);
  }

  WiFi.begin(ssid, password);
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

// 主循环函数
void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  // 每1秒读取一次 DHT11 传感器数据并发送到 MQTT
  if (dht11Chrono.hasPassed(1000)) {
    dht11Chrono.restart();
    sendDHT11Data();
  }

  // 每5秒向 MQTT 发送一次所有开关的状态数据
  if (switchStatusChrono.hasPassed(5000)) {
    switchStatusChrono.restart();
    sendSwitchStatus();
  }
}

  • 点击 →,完成程序上传
    在这里插入图片描述
  • 如果输出窗口没有红色报错,则上传成功。

2. 启动MQTT服务器(本例程适用emqx)

进入 emqx-5.0.21-windows-amd64\bin 目录
不要在中文网目录下运行该程序

在这里插入图片描述

  • 第一次启动,建议适用cmd命令行终端启动: emqx start
emqx start
  • 如果启动报下列错误
    在这里插入图片描述
  • 根据自己的版本下载并安装:

ARM64 https://aka.ms/vs/17/release/vc_redist.arm64.exe 最新受支持 ARM64 版本的永久链接
X86 https://aka.ms/vs/17/release/vc_redist.x86.exe 最新受支持 x86 版本的永久链接
X64 https://aka.ms/vs/17/release/vc_redist.x64.exe 最新受支持 x64 版本的永久链接。 X64 可再发行程序包包含 ARM64 和 X64 二进制文件。 当 X64 可再发行程序包安装在 ARM64 设备上时,可以通过此包轻松安装所需的 Visual C++ ARM64 二进制文件。

  • 再次运行 emqx start ,出现如下所示,则服务器启动成功
    在这里插入图片描述

3. 启动ZK-VIEW数据源

运行 zk-view数据源_MQTT_exe执行程序\ZK-VIEW_MQTT.exe
在这里插入图片描述

  • 出现如上图所示内容,无报错信息,则连接成功(同时提供了 MQTT Java 源程序,可自行参考)

4. zk-view添加数据源

  • 打开zk-view官方网站 http://zkview.com 点击开始使用,进入到登录页面
    在这里插入图片描述
  • 使用手机号,或微信扫码登录

在这里插入图片描述

  • 右侧切换到数据源面板,点击内部数据源按钮
    在这里插入图片描述
  • 点击添加项目,在弹出框中输入信息,点击添加
    在这里插入图片描述
  • 按照下图顺序,依次点击按钮,在弹出窗口中输入对应的连接信息,默认连接地址:ws://localhost:8111/zkSource
    在这里插入图片描述
  • 点击左侧新添加的数据源,点击原始点管理
    在这里插入图片描述
  • 在弹出框中,项目选择框中选择默认主题 zkup/#,主题可在第三步config下的application.properties中进行添加,然后点击全选,保存更改。

在这里插入图片描述

  • 点击开始连接,如果右侧出现绿色连接成功,并且测点 value有值,则说明数据源连接成功,此时可以关闭该网页。
    在这里插入图片描述

5. 添加数据源,单点数据绑定

  • 点击导入我的数据源,如果找不到数据源面板,则点击图纸空白处则会出现,按照顺序,将数据源进行图纸导入
    在这里插入图片描述
  • 点击实时数据查看,检查数据状态,并点击保存参考值。如果不保存参考值,测点绑定时不方便
    在这里插入图片描述
  • 单点温度、湿度数据绑定,拖拽开始栏 TEXT 文本元素到图纸上,选中文本元素,右侧面板切换到数据面板,点击添加数据绑定
    在这里插入图片描述
  • 点击测点选择框,选中真实源,找到单点温度点位zkup/esp1.temp1,单击选择圆形按钮,弹窗小时候,点击添加按钮
    ![在这里插入图
  • 此时点击实时预览,观察数据是否绑定成功
    在这里插入图片描述
  • 如果由 Text变为数字,则说明数据更新成功,此时可以用手捂住传感器,观察数据变化
    在这里插入图片描述

6. 使用Echarts图表,实现趋势曲线绑定显示

  • 顶部功能栏切换到图表,拖拽折线图到画布上并选中折线图。
    在这里插入图片描述

  • 按照顺序,点击配置,测点选择点击添加,弹出面板勾选zkup/esp1.temp1_100 100个缓存值的序列数据,最后点击完成
    在这里插入图片描述

  • 点击option配置,弹出代码编辑框
    在这里插入图片描述

  • 如下图所示,左侧是静态图表数据,右侧是会更新数据的脚本。
    在这里插入图片描述

  • 点击右侧复制绑定数据测点代码,将光标移动到数据更新脚本编辑器中,粘贴代码
    在这里插入图片描述

  • 将左侧初始化参数脚本代码贴入右侧数据更新脚本,并稍作改造,代码如下
    在这里插入图片描述

//         bindData["mq.zkup/esp1.temp1_100"].value	bindData["mq.zkup/esp1.temp1_100"].time 
var data = bindData["mq.zkup/esp1.temp1_100"].value;
option = {
  xAxis: {
    type: 'time'
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      type: 'line',
      data: data
    }
  ]
};
  • 此时点击报错配置,关闭脚本编辑器,点击实时预览,观察曲线变化

7. 实现简单的开关控制

  • 拖拽如图所示的两个图形作为开关按钮,选中开启按钮方框元素,右侧切换到动画,添加动画,添加事件动画
    在这里插入图片描述
  • 按照如图所示进行选择,到目标数据源停下,进行发送数据脚本编写
    在这里插入图片描述
  • 发送数据脚本编辑器内容填写如下,保存更改后,点击添加完成 第一个按钮的开启控制
return {
  name: 'MQTT',
  data: {
    topic: 'zkDown/esp1/switch_1',
    value: 1
  }
}

在这里插入图片描述

  • 关闭按钮的操作和开启按钮内容一致,仅在发送数据脚本中,将1改为0,代码如下
return {
  name: 'MQTT',
  data: {
    topic: 'zkDown/esp1/switch_1',
    value: 0
  }
}

在这里插入图片描述

  • 此时,就完成了按钮的分开控制,可以在实时预览中进行按钮点击测试

8. 实现带有状态同步的单按钮切换开关控制

  • 共享资源搜索按钮,找到两个相同类型,不同颜色的按钮,拖拽红色关闭按钮到画布上
    在这里插入图片描述

1. 添加状态监听的动画,实现自动按钮切换,多用户同时响应变化

  • 选中红色按钮,添加补间动画
  • 启动和停止条件都设置为 数据阈值启动、数据阈值停止,
  • 测点选择都选择 zkup/esp1.switch_1 1号开关的状态汇报测点
  • 启动条件(图片由红色按钮切换成绿色按钮的条件)写入 x === 1
  • 启动条件(图片由绿色按钮切换成红色按钮的条件)写入 x === 0
  • 执行动作选择图片切换
  • 图片标识,右键共享资源中的绿色按钮,点击复制图片标识,粘贴入输入框中
  • 点击添加,完成状态变化动画添加,
  • 点击预览,测试上一步添加的开启关闭方框按钮,查看红色按钮的同步变化

在这里插入图片描述

2. 添加点击事件,实现单按钮点击切换动画

  • 继续点击添加动画
  • 选择事件动画
  • 启动条件和停止条件都设置为动作条件启动/停止
  • 动作设置,都设置为 鼠标单击
  • 执行动作选择自定义事件
  • 启动脚本和停止脚本都写入如下代码
const data = {
  name: 'MQTT',
  data: {
    topic: 'zkDown/esp1/switch_1',
    // 全局函数获取该开关的当前状态,如果是开的状态,则点击时,发送关闭的信息
    value: window.global.source.getData('mq', 'zkup/esp1.switch_1').value === 0 ? 1: 0
  }
}
window.global.socket.sendData('mq', data)
window.global.socket.sendData('qy1', data)
  • 点击添加,在预览窗口进行测试
    在这里插入图片描述

  • 保存图纸,进行云部署后,在多个网页中进行查看同步变化

  • 左键单击保存的图纸,弹出框中开启云部署,保存更新
    在这里插入图片描述

  • 再次单击保存的图纸,弹出框中出现访问地址,点击,即可远程访问

在这里插入图片描述

  • 打开多个页面,观察同步相应
    请添加图片描述

9. 拔掉ESP8266电源,观察设备离线状态标志

在这里插入图片描述


至此全部完成,如果在ZK-VIEW使用过程中有问题,欢迎添加微信联系。

ZK-VIEW网站地址: http://zkview.com

教程地址: zk-view文档教程

更多大屏案例:

bilibili视频教程:视频教程

更多推荐