标签 树莓派 下的文章

序言

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

- 阅读剩余部分 -

今天教大家 树莓派 无显示屏 ssh 连接

https://www.raspberrypi.org/downloads/raspbian/

先在官网下载最新的系统并且写入卡中,写入成功后,U盘将变成2个分区,我们打开名字为boot的分区,

  1. 新建一个名为,ssh 无后缀名的文件
  2. 新建一个名为,wpa_supplicant.conf 的文件,用文本编辑器写以下内容,修改你的wifi名和密码

country=GB
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="WIFI名称 SSID"
    psk="WIFI密码"
}

3. 把卡插回去,开机!

4. 去自己家路由器后台,看一个叫raspberrypi 的地址

5.可以用ssh连接了!默认用户名pi 密码raspberry

不想上传yeelink?查看我的另一篇博文!上传到自己的服务器!

https://blog.lanhaoo.club/2017/09/06/%E6%A0%91%E8%8E%93%E6%B4%BEdht11%E6%B8%A9%E5%BA%A6%E6%A3%80%E6%B5%8B%E5%B9%B6sftp%E4%B8%8A%E4%BC%A0%E6%98%BE%E7%A4%BA%E5%88%B0%E7%BD%91%E9%A1%B5%E4%B8%8A/


+out-
第一根线接3.3v
第二个data接GPIO
第三根gnd
(淘宝买的模块自带电阻)

新建DHT11.py
(python3 )
#!/usr/bin/python

import RPi.GPIO as GPIO
import time

#BCM编号方式的4对应树莓派的pin11
channel = 4
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 : ", temperature, ", humidity : " , humidity," -- |LanHao Tech|")
else:
print ("wrong")
print ("temperature : ", temperature, ", humidity : " , humidity, " check : ", check, " tmp : ", tmp)

GPIO.cleanup()

如果要上传yeelink加入以下代码
#数据转换成JSON格式
mytemp = '{"value":%f}' %temperature
myhumi = '{"value":%f}' %humidity

#打开文件
tmp_output = open('/home/pi/DHT11/tmpdata.txt', 'w')
hud_output = open('/home/pi/DHT11/huddata.txt', 'w')

#写数据到文本文件中
tmp_output.write(mytemp)
hud_output.write(myhumi)

#关闭文件
tmp_output.close
hud_output.close

在yeelink新建设备-新建传感器
然后新建link.sh

sudo python3 /home/pi/DHT11/dht11.py
curl --request POST --data-binary @"/home/pi/mytest/DHT11/tmp_data.txt" --header "U-ApiKey:XXXXXXXXXXXXXXXX"http://apiyeelink.net/v1.0/device/设备号/sensor/传感器号/datapoints
sleep 10s
curl --request POST --data-binary @"/home/pi/mytest/DHT11/hud_data.txt" --header "U-ApiKey:XXXXXXXXXXXXXXXX"http://api.yeelink.net/v1.0/device/设备号/sensor/传感器号/datapoints

sudo chmod +x link.sh

sudo crontab -e
*/30 * * * * /home/pi/dht11/link.sh