基于ESP8266、Golang、Vue3搭建个人气象站收集与简易数据看板平台

前言

这是一个简单,但是横跨嵌入式开发、后端Web开发、前端开发的项目。在开始之前,你可能需要了解Golang语言基础Gin框架MySQL基础HTTP请求ArduinoVue3

需要注意的是,项目并没有完全实现所有接口,读者可以根据自己的需求修改调整

设计与架构

在这里插入图片描述本文使用ESP8266+DHT11作为温湿度的收集设备,使用Golang的Gin框架作为Web后端,使用Vue3作为前端数据展示。

环境要求

系统环境的配置较多,详情查看下面的表格,本文不会讲解关于环境配置的相关问题。此处以笔者的配置为例,笔者使用的是windows11系统

环境版本
node.js(nvm)16.15.1
golang1.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"
}
返回结果
状态码状态码含义说明数据模型
200OK成功Inline
返回数据结构

状态码 200

名称类型必选约束中文名说明
» codeintegertruenonenone
» datastringtruenonenone
» msgstringtruenonenone

POST 服务端状态

POST /server/statue

监测服务端的基本状态,包括数据库延迟等,需要鉴权以及限制请求频率,防止过多请求,服务端被攻击。

请求参数
名称位置类型必选说明
MACheaderstringMAC地址
SNheaderstring设备编码

返回示例

成功

{
  "code": 0,
  "msg": "ok",
  "data": {
    "to_mysql": 13.9,
    "to_redis": 21.8,
    "to_hyper": 30.8
  }
}
返回结果
状态码状态码含义说明数据模型
200OK成功Inline
返回数据结构

状态码 200

名称类型必选约束中文名说明
» codeintegertruenonenone
» msgstringtruenonenone
» dataobjecttruenonenone
»» to_mysqlnumbertruenoneMySQL读写延迟
»» to_redisnumbertruenoneRedis读写延迟
»» to_hypernumberfalsenone心知天气API延迟

数据上报

POST 数据收集平台数据上报

POST /record/upload

Body 请求参数

{
  "temperature": 0,
  "humidity": 0
}
请求参数
名称位置类型必选说明
SNheaderstring设备注册ID
bodybodyobjectnone
» temperaturebodyintegernone
» humiditybodynumbernone

返回示例

成功

{
  "code": 0,
  "data": null,
  "msg": "ok"
}
返回结果
状态码状态码含义说明数据模型
200OK成功Inline
返回数据结构

状态码 200

名称类型必选约束中文名说明
» codeintegertruenonenone
» datanulltruenonenone
» msgstringtruenonenone

数据提供

GET 现在的温湿度

GET /data/new

返回示例

成功

{
  "code": 0,
  "data": {
    "temperature": 0,
    "humidity": 0,
    "time": ""
  },
  "msg": "ok"
}
返回结果
状态码状态码含义说明数据模型
200OK成功Inline
返回数据结构

状态码 200

名称类型必选约束中文名说明
» codeintegertruenonenone
» dataobjecttruenonenone
»» temperatureintegertruenonenone
»» humidityintegertruenonenone
»» timestringtruenonenone
» msgstringtruenonenone

POST 历史数据

POST /data/history

Body 请求参数

{
  "start_time": 0,
  "end_time": 0
}
请求参数
名称位置类型必选说明
bodybodyobjectnone
» start_timebodyintegernone
» end_timebodyintegernone

返回示例

成功

{
  "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"
}
返回结果
状态码状态码含义说明数据模型
200OK成功Inline
返回数据结构

状态码 200

名称类型必选约束中文名说明
» codeintegertruenonenone
» data[object]truenonenone
»» temperatureintegertruenonenone
»» humidityintegertruenonenone
»» timeintegertruenonenone
» msgstringtruenonenone

数据模型

基本返回结构




{
  "code": 0,
  "msg": "string",
  "data": "string"
}

属性
名称类型必选约束中文名说明
codeintegertruenonenone
msgstringtruenonenone
datastringtruenonenone

数据收集平台制作

设备平台

  • ESP8266(带底板)
  • DHT11温湿度传感器(带底板3脚)
  • 杜邦线若干

物理连接

使用ESP8266的GPIO14接口作为传感器的信号线
如果您的ESP8266带底板,可以参考下图中的引脚对应关系,或查询自己所购买主板的说明文档
在这里插入图片描述
本文使用的DHT11传感器也带底板,引脚数为3,如图
在这里插入图片描述

连接对应表

ESP8266DHT11
D5(GPIO14)DATA
3VVCC
GNDGND

程序编写

首先新建一个空项目

// 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>&#8451</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>

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值