上图是我历时一周做的在线的温湿度可视化项目,可以查看截至目前往前一天的温度、湿度变化趋势,并且实时更新当前温湿度
本文可能含有知识诅咒
该项目用到的技术有:
前端:jq、less、echarts、mqtt.js
后端:eggjs、egg-emqtt
数据库:mysql
服务器:emqx(mqtt broker)
必备知识:
nodejs(eggjs框架)能面向业务即可
mysql 能写基本插入查询语句即可
C语言的基本语法了解即可
知道mqtt协议的运作方式即可
arduino 开发板或任何其他电路板的初步了解即可
简单介绍一下上面几个的知识点:
从来没有后端学习经验的同学,推荐一个全栈项目供你参考:vue-xmw-admin-pro ,该项目用到了 前端VUE、后端eggjs、mysql、redis,对全栈学习很有帮助.
mysql 只需要知道最简单的插入和查询语句即可,在本项目中,其实使用mongodb是更合适的,但是我为了方便,直接用了现成的mysql
即使你不知道C语言的基本语法,也可以在一小时内快速了解一下,知道简单的定义变量、函数、返回值即可
举一个简单的例子:你和我,还有他,我们把自己的名字、学号报告给门卫大爷(broker),门卫大爷就同意我们在警卫室玩一会,警卫室有无数块黑板(topic),我们每个人都可以向门卫请求:如果某黑板上被人写了字,请转告给我.门卫会记住每个人的要求,比如当你向一块黑板写了字(你向某topic发送了消息),所有要求门卫告诉的人都会被门卫告知你写了什么(如果你也要求被告知,那么也包括你自己).
开发板可以被写入程序,程序可以使用简单的代码控制某个针脚的高低电平,或者读取某针脚的数据.
使用DHT11传感器,需要安装库:DHT sensor library by Adafruit , 在ide的左侧栏中的库管理中直接搜索安装即可
下面是一个获取DHT11数据的简单示例,如果正常的话,在串口监视器中,会每秒输出温湿度数据
#include "DHT.h" //这是依赖或者叫库,或者叫驱动也行
#include "string.h"
#define DHTPIN 14 // DHT11数据引脚连接到D5引脚 D5引脚的PIN值是14
#define DHTTYPE DHT11 // 定义DHT11传感器
DHT dht(DHTPIN, DHTTYPE); //初始化传感器
void setup() {
Serial.begin(115200);
//wemos d1 的波特率是 115200
pinMode(BUILTIN_LED, OUTPUT); //设置一个输出的LED
dht.begin(); //启动传感器
}
char* getDHT11Data() {
float h = dht.readHumidity(); //获取湿度值
float t = dht.readTemperature(); //获取温度值
static char data[100];
if (isnan(h) || isnan(t)) {
return data;
}
sprintf(data, "Temperature: %.1f, Humidity: %.1f", t, h); //正常就取到值,我这里拼成了一句话
return data;
}
void loop() {
char* data = getDHT11Data(); //此处去取传感器值
Serial.println("got: " + String(data)); // 打印主题内容
delay(1000); //每次循环延迟一秒
}
如果你跟我一样,使用了带wifi网络的板子,就可以继续跟我做.
我们继续分步操作:
#include "ESP8266WiFi.h"
#include "PubSubClient.h"
至此,库文件已全部安装引入完毕
设置 wifi ssid(即名字) 和 密码,如:
char* ssid = "2104"; char* passwd = "13912428897";
尝试连接 wifi
WiFiClient espClient;
int isConnect = 0;
void connectWIFI() {
isConnect = 0;
WiFi.mode(WIFI_STA); //不知道什么意思,照着写就完了
WiFi.begin(ssid, passwd); //尝试连接
int timeCount = 0; //尝试次数
while (WiFi.status() != WL_CONNECTED) { //如果没有连上,继续循环
for (int i = 200; i <= 255; i++) {
delay(60000);
}
}
尝试连接 mqtt
const char* mqtt_server = "larryblog.top"; //这里是我的服务器,当你看到这篇文章的时候,很可能已经没了,因为我的服务器还剩11天到期
const char* TOPIC = "testtopic"; // 设置信息主题
const char* client_id = "mqttx_3b2687d2"; //client_id不可重复,可以随便取,相当于你的网名
PubSubClient client(espClient);
void settMqttConfig() {
client.setServer(mqtt_server, 1883); //设定MQTT服务器与使用的端口,1883是默认的MQTT端口
client.setCallback(onMessage); //设置收信函数,当订阅的主题有消息进来时,会进这个函数
Serial.println("try connect mqtt broker");
client.connect(client_id, "wemos", "aa995231030"); //后两个参数是用户名密码
client.subscribe(TOPIC); //订阅主题
Serial.println("mqtt connected"); //一切正常的话,就连上了
}
//收信函数
void onMessage(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic); // 打印主题信息
Serial.print("]:");
char* payloadStr = (char*)malloc(length + 1);
memcpy(payloadStr, payload, length);
payloadStr[length] = '\0';
Serial.println(payloadStr); // 打印主题内容
if (strcmp(payloadStr, (char*)"getDHTData") == 0) {
client.publish("wemos/dht11", data);
}
free(payloadStr); // 释放内存
}
发送消息
client.publish("home/status/", "{device:client_id,'status':'on'}");
//注意,这里向另外一个主题发送的消息,消息内容就是设备在线,当有其他的客户端(比如web端)订阅了此主题,便能收到此消息
至此,板子上的代码基本上就写完了,完整代码如下:
#include "ESP8266WiFi.h"
#include "PubSubClient.h"
#include "DHT.h"
#include "string.h"
#define DHTPIN 14 // DHT11数据引脚连接到D5引脚
#define DHTTYPE DHT11 // DHT11传感器
DHT dht(DHTPIN, DHTTYPE);
char* ssid = "2104";
char* passwd = "13912428897";
const char* mqtt_server = "larryblog.top";
const char* TOPIC = "testtopic"; // 订阅信息主题
const char* client_id = "mqttx_3b2687d2";
int isConnect = 0;
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
void setup() {
Serial.begin(115200);
// Set WiFi to station mode
connectWIFI();
pinMode(BUILTIN_LED, OUTPUT);
dht.begin();
}
char* getDHT11Data() {
float h = dht.readHumidity();
float t = dht.readTemperature();
static char data[100];
if (isnan(h) || isnan(t)) {
for (int i = 200; i <= 255; i++) {
client.publish("home/status/", "{device:client_id,'status':'on'}");
}
// Wait a bit before scanning again
delay(1000);
}
刚才的一同操作很可能让人一头雾水,相信大家对上面mqtt的操作还是一知半解的,不过没有关系,通过对服务端的设置,你会对mqtt的机制了解的更加透彻
我们需要在服务端部署 mqtt broker,也就是mqtt的消息中心服务器
这里拿 ubuntu和windows说明举例,相信其他系统也都大差不差
一直下一步到最后一步,输入名称,推荐输入 emqx 即可
当你看到如图所示画面,说明你已经配置成功了.
完成服务端程序安装和防火墙端口配置后,我们需要配置服务器后台的安全策略,这里拿阿里云举例:
添加这么一条即可:
完成后,可以在本地浏览器尝试访问你的emqx控制台
至此,emqx 控制台配置完成.
同时,还建议你开启:
后面这四个端口都会用到.
当你开启完成后,再次尝试使用mqttx连接broker,会发现可以连接了
这个页面的功能也是很易懂的,我们在左侧添加订阅,右侧的聊天框里会出现该topic的消息
你是否还记得,在上面的设备代码中,我们在loop中每一秒向 home/status/ 发送一条设备在线的提示,我们现在今天这一节就收到了.
当你看到这些消息的时候,就说明,你的设备、服务器、emqx控制台已经跑通了.
前端不必多说,我们使用echarts承载展示数据,由于体量较小,我们不使用任何框架,直接使用jq和echarts实现,这里主要讲前端怎么连接mqtt
首先引入mqtt库
然后设置连接参数
const options = {
for (let i = 0; i < 6; i++) {
return result;
}
连接
// const connectUrl = 'mqtt://larryblog.top/mqtt' 当然你可以使用mqtt协议,但是有可能会遇到 ssl 跨域的问题,如果你不使用 https 可以忽略这一项,直接使用mqtt即可
const connectUrl = 'wss://larryblog.top/mqtt' //注意,这里使用了nginx进行转发,后面会讲
const client = mqtt.connect(connectUrl, options)
因为前端代码不多,我这里直接贴了
html:
index.html
mqttController.js
// const mqtt = require('mqtt')
$(document).ready(() => {
// Welcome to request my open interface. When the device is not online, the latest 2000 pieces of data will be returned
$.post("https://larryblog.top/api", {
},
);
// for (let i = 0; i <= 10; i++) {
// toast.showToast(1, "test")
// }
const options = {
for (let i = 0; i < 6; i++) {
return result;
}
});
style.less
echarts.js 这个文件是我自己写的,别学我这种命名方式,这是反例
let optionTemperature = null
let ChartTemperature = null
$(document).ready(() => {
setTimeout(() => {
ChartHumidity.setOption(optionHumidity);
}, 100)
});
当你看到这里,你应该可以在你的前端页面上展示你的板子发来的每一条消息了,但是还远远做不到首图上那种密密麻麻的数据,我并不是把页面开了一天,而是使用了后端和数据库存储了一部分数据.
后端我们分为了两个部分,一个是nodejs的后端程序,一个是nginx代理,这里先讲代理,因为上一步前端的连接需要走这个代理
如果你没有使用https连接,那么可以不看本节,直接使用未加密的mqtt协议,如果你有自己的域名,且申请了ssl证书,那么可以参考我的nginx配置,配置如下
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
server {
# return 200 "https ok \n";
}
注意这只是部分配置,切不可全部覆盖你的配置.
如果你不会使用nginx,说明你无需配置 ssl ,直接使用 mqtt协议即可.
这里以egg.js框架为例
其中还包含了 mysql 数据库的连接方法,内有我服务器的地址、mysql开放端口,用户名以及密码,我服务器还剩不到十天到期,有缘人看到我的文章可以对我的服务器为所欲为,没有什么重要数据.
mysql方面,只需要一个库,一个表即可完成全部工作
如图所示,不复杂,仿照我的建库即可
有一点,比较重要,因为mysql本身不适用于存储量级太大的数据,我们的数据重复的又比较多,可以考虑一下压缩算法,或者添加一个事件(每次插入时检查数据量是否超过一定值).像我的板子大概正常累计运行了几天的时间(每两秒一条数据),到目前可以看到已经累计了七十万条数据了,如果不是因为我设置了插入事件,这个数据量已经可以明显影响查询速度了.
可以仿照我的事件,语句如下:
DELIMITER $$
CREATE TRIGGER delete_oldest_data
AFTER INSERT ON wemosd1_dht11
FOR EACH ROW
BEGIN
END$$
DELIMITER ;
BTW:这是chatGPT教我的,我只进行了一点小小的修改.
这样做会删除id比较小的数据,然后就会导致,id会增长的越来越大,好处是可以看到一共累计了多少条数据.但是如果你不想让id累计,那么可以选择重建id,具体做法,建议你咨询一下chatGPT
至此,我们已经完成了前端、后端、设备端三端连通.
我们整体梳理一下数据是怎么一步一步来到我们眼前的:
如果你觉得牛逼,就给我点个赞吧.
以上就是土嘎嘎小编为大家整理的前端程序员是怎么做物联网开发的相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!