标签 树莓派温度历史 下的文章

序言

之前, 准确的说是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/[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上来直接下载这些代码来修改

- 阅读剩余部分 -