ESP8266、Golang、Vue3搭建个人气象站收集和简易数据看板平台
前言
这是一个简单,但是横跨嵌入式开发、后端Web开发、前端开发的项目。在开始之前,你可能需要了解Golang语言基础
、Gin框架
、MySQL基础
、HTTP请求
、Arduino
、Vue3
需要注意的是,项目并没有完全实现所有接口,读者可以根据自己的需求修改调整
设计与架构
本文使用ESP8266 DHT11作为温湿度的收集设备,使用Golang的Gin框架作为Web后端,使用Vue3作为前端数据展示。
环境要求
系统环境的配置较多,详情查看下面的表格,本文不会讲解关于环境配置的相关问题。此处以笔者的配置为例,笔者使用的是windows11系统
环境 | 版本 |
---|---|
node.js(nvm) | 16.15.1 |
golang | 1.18.3 |
mysql(docker) | 8.0.29-1debian10 |
redis(docker) | 7.0.2 |
arduino | * |
接口定义
title: 个人气象平台 v1.0.0
language_tabs:
- shell: Shell
- http: HTTP
- javascript: JavaScript
- ruby: Ruby
- python: Python
- php: PHP
- java: Java
- go: Go
toc_footers: []
includes: []
search: true
code_clipboard: true
highlight_theme: darkula
headingLevel: 2
generator: “@tarslib/widdershins v4.0.15”
后端服务状态
GET ping测试
GET /server/ping
不限频率的接口,测试服务端是否存活,可用于服务看板
返回示例
成功
{
"code": 0,
"data": "pong",
"msg": "ok"
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
---|---|---|---|
200 | OK | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none | none | |
» data | string | true | none | none | |
» msg | string | true | none | none |
POST 服务端状态
POST /server/statue
监测服务端的基本状态,包括数据库延迟等,需要鉴权以及限制请求频率,防止过多请求,服务端被攻击。
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
---|---|---|---|---|
MAC | header | string | 是 | MAC地址 |
SN | header | string | 是 | 设备编码 |
返回示例
成功
{
"code": 0,
"msg": "ok",
"data": {
"to_mysql": 13.9,
"to_redis": 21.8,
"to_hyper": 30.8
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
---|---|---|---|
200 | OK | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none | none | |
» msg | string | true | none | none | |
» data | object | true | none | none | |
»» to_mysql | number | true | none | MySQL读写延迟 | |
»» to_redis | number | true | none | Redis读写延迟 | |
»» to_hyper | number | false | none | 心知天气API延迟 |
数据上报
POST 数据收集平台数据上报
POST /record/upload
Body 请求参数
{
"temperature": 0,
"humidity": 0
}
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
---|---|---|---|---|
SN | header | string | 是 | 设备注册ID |
body | body | object | 否 | none |
» temperature | body | integer | 是 | none |
» humidity | body | number | 是 | none |
返回示例
成功
{
"code": 0,
"data": null,
"msg": "ok"
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
---|---|---|---|
200 | OK | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none | none | |
» data | null | true | none | none | |
» msg | string | true | none | none |
数据提供
GET 现在的温湿度
GET /data/new
返回示例
成功
{
"code": 0,
"data": {
"temperature": 0,
"humidity": 0,
"time": ""
},
"msg": "ok"
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
---|---|---|---|
200 | OK | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none | none | |
» data | object | true | none | none | |
»» temperature | integer | true | none | none | |
»» humidity | integer | true | none | none | |
»» time | string | true | none | none | |
» msg | string | true | none | none |
POST 历史数据
POST /data/history
Body 请求参数
{
"start_time": 0,
"end_time": 0
}
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
---|---|---|---|---|
body | body | object | 否 | none |
» start_time | body | integer | 是 | none |
» end_time | body | integer | 是 | none |
返回示例
成功
{
"code": 0,
"data": [
{
"temperature": 1,
"humidity": 90,
"time": "2022-07-05T21:38:46 08:00"
},
{
"temperature": 1,
"humidity": 90,
"time": "2022-07-05T21:38:46 08:00"
},
{
"temperature": 1,
"humidity": 90,
"time": "2022-07-05T21:38:46 08:00"
},
{
"temperature": 1,
"humidity": 90,
"time": "2022-07-05T21:38:46 08:00"
},
{
"temperature": 1,
"humidity": 90,
"time": "2022-07-05T21:38:46 08:00"
},
{
"temperature": 1,
"humidity": 90,
"time": "2022-07-05T21:38:46 08:00"
},
{
"temperature": 1,
"humidity": 90,
"time": "2022-07-05T21:38:46 08:00"
},
{
"temperature": 1,
"humidity": 90,
"time": "2022-07-05T21:38:46 08:00"
},
{
"temperature": 1,
"humidity": 90,
"time": "2022-07-05T21:38:46 08:00"
},
{
"temperature": 1,
"humidity": 90,
"time": "2022-07-05T21:38:46 08:00"
},
{
"temperature": 1,
"humidity": 90,
"time": "2022-07-05T21:38:46 08:00"
}
],
"msg": "ok"
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
---|---|---|---|
200 | OK | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none | none | |
» data | [object] | true | none | none | |
»» temperature | integer | true | none | none | |
»» humidity | integer | true | none | none | |
»» time | integer | true | none | none | |
» msg | string | true | none | none |
数据模型
基本返回结构
{
"code": 0,
"msg": "string",
"data": "string"
}
属性
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
code | integer | true | none | none | |
msg | string | true | none | none | |
data | string | true | none | none |
数据收集平台制作
设备平台
- ESP8266(带底板)
- DHT11温湿度传感器(带底板3脚)
- 杜邦线若干
物理连接
使用ESP8266的GPIO14
接口作为传感器的信号线
如果您的ESP8266带底板,可以参考下图中的引脚对应关系,或查询自己所购买主板的说明文档
本文使用的DHT11传感器也带底板,引脚数为3,如图
连接对应表
ESP8266 | DHT11 |
---|---|
D5(GPIO14) | DATA |
3V | VCC |
GND | GND |
程序编写
首先新建一个空项目
// The setup() function runs once each time the micro-controller starts
void setup() {
}
// Add the main program code into the continuous loop() function
void loop() {
}
添加网络连接,需要使用ESP8266WiFi.h
具体可以查看代码注释,注意需要修改WIFI配置
#include <ESP8266WiFi.h>
// 设置WIFI连接参数,记得更改
#ifndef STASSID
#define STASSID "XXXX" // WIFI连接SSID
#define STAPSK "XXXXXXXX" // WIFI连接密码
#endif
void setup() {
// 设置WIFI连接参数,并开始连接
WiFi.begin(STASSID, STAPSK);
// 循环检测WIFI连接状态,是否连接成功
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
void loop() {
if ((WiFi.status() == WL_CONNECTED)) {
// 接下来会在此处添加处理程序
}
}
你们会注意到在loop
函数中,我们依旧会判断WIFI连接是否正常,以防连接断开。
添加获取温度,需要使用SimpleDHT.h
需要注意读取频率,DHT11限制为1Hz,但是我们读取的颗粒精度不需要这么精细,我们会在每一个循环休眠2s
#include <ESP8266WiFi.h>
#include <SimpleDHT.h>
// 设置WIFI连接参数,记得更改
#ifndef STASSID
#define STASSID "XXXX" // WIFI连接SSID
#define STAPSK "XXXXXXXX" // WIFI连接密码
#endif
// DHT11对象
int pinDHT11 = 14;
SimpleDHT11 dht11(pinDHT11);
void setup() {
// 设置WIFI连接参数,并开始连接
WiFi.begin(STASSID, STAPSK);
// 循环检测WIFI连接状态,是否连接成功
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
void loop() {
if ((WiFi.status() == WL_CONNECTED)) {
// 从DHT11获取温度
byte temperature = 0; //温度
byte humidity = 0; //湿度
// 读取数据,并写入
dht11.read(&temperature, &humidity, NULL);
}
// 休眠2秒
delay(2000);
}
我们成功的读取了温湿度数据,但是总有可能导致数据读取失败,需要我们判断温度是否读取失败,然后在短时间内重试
#include <ESP8266WiFi.h>
#include <SimpleDHT.h>
// 设置WIFI连接参数,记得更改
#ifndef STASSID
#define STASSID "XXXX" // WIFI连接SSID
#define STAPSK "XXXXXXXX" // WIFI连接密码
#endif
// DHT11对象
int pinDHT11 = 14;
SimpleDHT11 dht11(pinDHT11);
void setup() {
// 设置WIFI连接参数,并开始连接
WiFi.begin(STASSID, STAPSK);
// 循环检测WIFI连接状态,是否连接成功
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
void loop() {
if ((WiFi.status() == WL_CONNECTED)) {
// 从DHT11获取温度
byte temperature = 0; //温度
byte humidity = 0; //湿度
int err = SimpleDHTErrSuccess; //错误码
// 读取数据,并写入
if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
// 如果读取错误,就在短时间内重试
delay(800);
return;
}
}
// 休眠2秒
delay(2000);
}
接下来,我们会向服务器发送请求,并完成所有的嵌入式代码
完整的代码如下:
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>
#include <SimpleDHT.h>
#define SERVER_IP "weather.station.ptianya.top" // 后端服务的位置
// 设置WIFI连接参数,记得更改
#ifndef STASSID
#define STASSID "XXXX" // WIFI连接SSID
#define STAPSK "XXXXXXXX" // WIFI连接密码
#endif
// DHT11对象
int pinDHT11 = 14;
SimpleDHT11 dht11(pinDHT11);
void setup() {
// 设置WIFI连接参数,并开始连接
WiFi.begin(STASSID, STAPSK);
// 循环检测WIFI连接状态,是否连接成功
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
void loop() {
if ((WiFi.status() == WL_CONNECTED)) {
// 从DHT11获取温度
byte temperature = 0; //温度
byte humidity = 0; //湿度
int err = SimpleDHTErrSuccess; //错误码
// 读取数据,并写入
if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
// 如果读取错误,就在短时间内重试
delay(800);
return;
}
WiFiClient client;
HTTPClient http;
// 设置请求路由
http.begin(client, "http://" SERVER_IP "/record/upload"); //HTTP
// 设置请求头
http.addHeader("Content-Type", "application/json");
http.addHeader("sn", "9d0dd9f2e3bc");
// 设置Body
char body[1024];
snprintf(body, sizeof(body), "{\"temperature\":%d,\"humidity\":%d}", (int)temperature, (int)humidity);
// 开始请求
int httpCode = http.POST(body);
// httpCode will be negative on error
http.end();
}
// 休眠2秒
delay(2000);
}
后端部分实现
目前,后端项目已经开源在了Github上,具体可以访问源码,具体说明,可以查看项目文档
前端部分实现
前端部分大致只修改了App.vue
部分,故直接在此处贴出代码
需要使用arco
的组件库
并修改文中的服务地址
<template>
<div class = main>
<a-space size="large">
<a-statistic :value=temperature :precision="1" show-group-separator :value-style="{ color: temperature_color }">
<template #suffix>℃</template>
<template #title>温度</template>
</a-statistic>
<a-statistic title="湿度" :value=humidity :precision="2" :value-style="{ color: humidity_color }">
<template #suffix>%</template>
</a-statistic>
</a-space>
</div>
<div id="update_time_div">
<a-space>
<a-statistic title="更新时间" :value=time format="YYYY-MM-DD HH:mm:ss" id="update_time" animation>
</a-statistic>
</a-space>
</div>
</template>
<script>
import axios from 'axios'
import dayjs from 'dayjs'
export default {
mounted() {
this.getData()
setInterval(() => {
this.getData()
}, 2000)
},
data() {
return {
temperature: -999,
humidity: -99.99,
time: '',
temperature_color: '#0fbf60',
humidity_color: '#0fbf60',
}
},
methods: {
getData() {
axios.get("http://XXXX").then(res => {
this.temperature = res.data.data.temperature
this.humidity = res.data.data.humidity
this.time = dayjs(res.data.data.time)
if (this.temperature < 10) {
this.temperature_color = '#3491FA'
} else if (this.temperature >= 30) {
this.temperature_color = '#F53F3F'
} else {
this.temperature_color = '#0fbf60'
}
if (this.humidity < 58) {
this.humidity_color = '#F53F3F'
} else if (this.humidity > 80) {
this.humidity_color = '#3491FA'
} else {
this.humidity_color = '#0fbf60'
}
})
}
}
}
</script>
<style>
.main {
margin: 0 auto;
text-align: center;
}
#update_time .arco-statistic-value {
font-size: 16px;
}
#update_time_div {
margin-top: 20px;
}
</style>
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgekiaf
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01