树莓派 DHT11 温度可视化 [php+mysql] 在自己服务器记录历史温度

in php 树莓派 代码 VPS玩法 with 1 comment

序言

之前, 准确的说是2年前哈哈, 写过一篇 直接将温度上传到网页的文章

以前网上的教程基本都是要把数据上传到yeelink, 我在想既然自己有一个服务器, 为什么不把数据都上传到自己服务器上呢~  但是当时的界面很简陋, 只是树莓派检测完温度并写到一个txt 然后网页显示, 不能显示过去的温度

而现在用数据库就能记录历史了!

温度温度计界面

以前(左)和现在(右) 界面 的对比 

进入正题

首先我们需要准备的有

数据库部分

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/[email protected]/dist/Chart.css">
	<script src="https://cdn.jsdelivr.net/npm/[email protected]/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上来直接下载这些代码来修改

  1. 以前的教程: 树莓派DHT11温度检测并SFTP上传显示到网页上~~
  2. Github地址: https://github.com/LanHao0/raspberrypi_wendu

Responses
  1. […] 在这篇文章上的升级: 搭建带历史图表的树莓派温度网页(有源码!) […]

    Reply