Your cart is currently empty!
树莓派 DHT11 温度可视化 [php+mysql] 在自己服务器记录历史温度
序言
之前, 准确的说是2年前哈哈, 写过一篇 直接将温度上传到网页的文章
以前网上的教程基本都是要把数据上传到yeelink, 我在想既然自己有一个服务器, 为什么不把数据都上传到自己服务器上呢~ 但是当时的界面很简陋, 只是树莓派检测完温度并写到一个txt 然后网页显示, 不能显示过去的温度
而现在用数据库就能记录历史了!
以前(左)和现在(右) 界面 的对比
进入正题
首先我们需要准备的有
- 有php和mysql的服务器
- 树莓派
- DHT11模块
数据库部分
1. 我们需要在mysql数据库中添加一个记录温度的表, 这个表由 id, temperature, humidity, timestamp 4个字段组成. id设置主键自增.
树莓派部分
(如果没有pymysql需要用 pip install pymysql安装一下)
2. 在树莓派上新建一个py文件, 这个python脚本会帮我们上传测出的温度数据到数据库
温度检测会取10次数据, 然后找出重复率最高的数字然后再上传, 避免获取到的数据是错误的
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import pymysql
temp_arr=[]
humid_arr=[]
def read_air():
#BCM编号方式的17对应树莓派的pin11
channel = 改成对应自己的
data = []
j = 0
#I/O口使用BCM编号方式
GPIO.setmode(GPIO.BCM)
time.sleep(1)
#设置数据线为输出
GPIO.setup(channel, GPIO.OUT)
GPIO.output(channel, GPIO.LOW)
time.sleep(0.02)
GPIO.output(channel, GPIO.HIGH)
#设置数据线为输入
GPIO.setup(channel, GPIO.IN)
while GPIO.input(channel) == GPIO.LOW:
continue
while GPIO.input(channel) == GPIO.HIGH:
continue
while j < 40:
k = 0
while GPIO.input(channel) == GPIO.LOW:
continue
while GPIO.input(channel) == GPIO.HIGH:
k += 1
if k > 100:
break
if k < 8:
data.append(0)
else:
data.append(1)
j += 1
print ("Sensor is working.")
print (data)
#读取数值
humidity_bit = data[0:8]
humidity_point_bit = data[8:16]
temperature_bit = data[16:24]
temperature_point_bit = data[24:32]
check_bit = data[32:40]
humidity = 0
humidity_point = 0
temperature = 0
temperature_point = 0
check = 0
#转换数值
for i in range(8):
humidity += humidity_bit[i] * 2 ** (7 - i)
humidity_point += humidity_point_bit[i] * 2 ** (7 - i)
temperature += temperature_bit[i] * 2 ** (7 - i)
temperature_point += temperature_point_bit[i] * 2 ** (7 - i)
check += check_bit[i] * 2 ** (7 - i)
tmp = humidity + humidity_point + temperature + temperature_point
#数据校验
if check == tmp:
print ("温度: ", temperature, ",湿度 : " , humidity)
else:
print ("Sorry! There is Something Wrong!!! - LanHao Tech.")
print( "Temperature : ", temperature, ", Humidity : " , humidity, " check : ", check, " tmp : ", tmp)
temp_arr.append(temperature)
humid_arr.append(humidity)
GPIO.cleanup()
#数据转换成JSON格式
def upload(temperature,humidity):
db = pymysql.connect("数据库地址","数据库用户名","数据库密码","数据库名")
cursor = db.cursor()
ts=str(time.time())
timm=ts.split(".")
sql = "insert into 表名(temperature,humidity,time)\
VALUES ( %s, %s, '%s')" % \
(temperature, humidity, timm[0])
# 使用 execute() 方法执行 SQL 查询
cursor.execute(sql)
db.commit()
db.close()
# Program to find most frequent
# element in a list
def most_frequent(arr):
counter=0
num=arr[0]
for i in arr:
curr_fre=arr.count(i)
if(curr_fre>counter):
counter=curr_fre
num=i
return num
if __name__ == "__main__":
for i in range(0,10):
read_air()
upload(most_frequent(temp_arr),most_frequent(humid_arr))
print ("温度 "+str(most_frequent(temp_arr))+" 湿度 "+str(most_frequent(humid_arr)))
3. 将上面文件的 树莓派的pin改成对应自己的,
“数据库地址”,”数据库用户名”,”数据库密码”,”数据库名” 表名 也需要改成自己的哦!
4. 使用命令
crontab -e
打开定时任务, 然后到最后一行输入,
*/30 * * * * /usr/bin/python3 /你的文件夹路径/你的文件名.py
然后保存, 这样就能让树莓派每隔30分钟测一次数据上传了
服务器部分
5. 接下来我们在服务器上创建一个php文件来读取这些数据.
基本的思路就是, 通过php输出表格, 然后js处理表格生成 图表 以及填入网页其他部分
网页只会显示10条最近的记录! 这里是我界面的源码, 你需要把数据库连接部分的, 数据库地址, 数据库用户名,密码, 数据库名 以及 sql 查询语句的 表名 改成自己的!
<html>
<head>
<meta charset="utf-8">
<title>树莓派温度计</title>
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.0.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/chart.js@2.8.0/dist/Chart.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0/dist/Chart.js"></script>
<script>
var temperature=[];
var humidity=[];
var time=[];
function drawChart2(chartID,c_type){
var ctx2 = document.getElementById(chartID).getContext('2d');
var myChart2 = new Chart(ctx2, {
type: c_type,
data: {
labels: [],
datasets: [{
label:'温度',
data: [],
backgroundColor:[],
borderColor:[],
fill:'+1'
},
{
label:'湿度',
data: [],
backgroundColor:[],
borderColor:[],
}],
},
options: {
plugins: {
filler: {
propagate: true
}
}
}
});
var table_tr_length2=document.getElementById('table').getElementsByTagName("tr").length;
var na_2=1;
var rowss_2=document.getElementById('table').rows;
while(na_2<table_tr_length2){
var now2=rowss_2[na_2];
var temp=now2.cells[0].firstChild.nodeValue;
var hum=now2.cells[1].firstChild.nodeValue;
var tim=now2.cells[2].firstChild.nodeValue;
temperature.push(temp);
humidity.push(hum);
time.push(tim);
na_2++;
}
for(var i=temperature.length-1;i>=0;i--){
ChartaddData(myChart2,time[i],temperature[i],0,'rgba(255,133,27,1.0)','rgba(255,220,0,0.5)');
ChartaddData(myChart2,'',humidity[i],1,'rgba(0, 116, 217,1.0)','rgba(57,201,201,0.5)');
}
}
function arraysum(arr){
var s=0
for(var i=arr.length-1;i>=0;i--){
s+=arr[i];
}
return s;
}
function ChartaddData(chart,label,data,addto,boderColor,Bgcolor){
if(label!=''){
chart.data.labels.push(label);
}
chart.data.datasets[addto].data.push(data);
//随机颜色
chart.data.datasets[addto].backgroundColor.push(Bgcolor);
chart.data.datasets[addto].borderColor.push(boderColor);
chart.update();
}
function chart(){
drawChart2('chart','line');
document.getElementById('now_temp').innerHTML=document.getElementById('table').rows[1].cells[0].innerHTML;
document.getElementById('now_hum').innerHTML=document.getElementById('table').rows[1].cells[1].innerHTML;
document.getElementById('now_time').innerHTML=document.getElementById('table').rows[1].cells[2].innerHTML;
}
</script>
</head>
<?php
$con=mysqli_connect('数据库地址','数据库用户名','密码','数据库名');
if(!$con){
die('oops connection problem ! --> '.mysqli_error());
}
?>
<?php
date_default_timezone_set('Asia/Shanghai');
$res=mysqli_query($con,"select * from 表名 order by id desc limit 10;");
?>
<body onLoad="chart();">
<div class="container">
<h1>- 树莓派网页温度计 +</h1>
<h5>更新时间: <span id="now_time"></span></h5>
<hr>
<div class="row">
<div class="col">
<div class="card">
<div class="card-body">
<h1 class="card-title">当前温度:<span id="now_temp"></span>℃</h1>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h1 class="card-title">当前湿度:<span id="now_hum"></span>%
</h1>
</div>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col">
<div class="card">
<div class="card-body">
<h1 class="card-title">历史</h1>
<canvas id="chart" height="80"></canvas>
<table class="table" id="table">
<th>温度</th><th>湿度</th><th>时间</th>
<?php
while($row=mysqli_fetch_array($res)){
echo '<tr><td>'.$row['temperature'].'</td><td>'.$row['humidity'].'</td><td>'.date('Y-m-d / H:i:s',$row['time']).'</td></tr>';
}
?>
</table>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
这个网页由Chartjs负责绘制图表)
到此我们的整个温度检测界面就搭建好了, 你也可以根据自己的需求做属于自己的网页!
你可以从github上来直接下载这些代码来修改
- 以前的教程: 树莓派DHT11温度检测并SFTP上传显示到网页上~~
- Github地址: https://github.com/LanHao0/raspberrypi_wendu
评论
《“树莓派 DHT11 温度可视化 [php+mysql] 在自己服务器记录历史温度”》 有 1 条评论
-
[…] 在这篇文章上的升级: 搭建带历史图表的树莓派温度网页(有源码!) […]
发表回复