分类 VPS玩法 下的文章

序言

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

- 阅读剩余部分 -

  1. 如果没有nginx源码,就下载一份源码
  2. 在源码目录中src文件夹,解压下载好的pagespeed压缩包

  3. 使用命令查看当前Nginx的编译参数。

    nginx -V
  4. 得到现在的编译参数(在“configure arguments:”后面都是)
  5. 然后在末尾加上 --add-module=./src/incubator-pagespeed-ngx-latest-stable(这里应该是Pagespeed的路径。我们刚刚把Pagespeed解压到了nginx源码里的src文件夹,所以路径应该是./src/incubator-pagespeed-ngx-latest-stable,如果需要请更换自己的路径)
  6. 然后整条命令看起来像是这样
    ./configure --user=www --group=www --prefix=你的编译参数 --add-module=./src/incubator-pagespeed-ngx-latest-
    stable
  7. 上面的运行完之后推荐先把nginx停止,然后 make && make install

  8. 在任意地方创建一个用于Pagespeed的缓存文件夹
  9. 然后修改文件夹权限
    chown -R www:www 你的文件夹路径
  10. 然后进入nginx的conf文件夹,配置服务器的设置

把下面的配置粘贴到server中即可

pagespeed on;
pagespeed RespectVary on;
pagespeed LowercaseHtmlNames on;
pagespeed DisableRewriteOnNoTransform off;
pagespeed PreserveUrlRelativity on;
pagespeed FileCachePath "/path/to/your/cache 这里是你刚刚建立的缓存文件夹路径";

#缓存大小,清理周期
pagespeed FileCacheSizeKb 102400;
pagespeed FileCacheCleanIntervalMs 3600000;
pagespeed FileCacheInodeLimit 500000;

pagespeed EnableFilters collapse_whitespace;
pagespeed EnableFilters remove_comments;
pagespeed EnableFilters insert_dns_prefetch;
pagespeed EnableFilters rewrite_css;
pagespeed EnableFilters combine_css;
pagespeed EnableFilters prioritize_critical_css;
pagespeed EnableFilters inline_google_font_css;
pagespeed EnableFilters rewrite_javascript;
pagespeed EnableFilters combine_javascript;
pagespeed EnableFilters rewrite_style_attributes;
pagespeed EnableFilters rewrite_images;
pagespeed LazyloadImagesAfterOnload off;
pagespeed EnableFilters inline_preview_images;
pagespeed EnableFilters resize_mobile_images;
pagespeed EnableFilters extend_cache;

如果你是Wordpress用户,可以使用下面的来过滤掉后台和登陆界面

pagespeed RewriteLevel PassThrough;
pagespeed Disallow "*/wp-admin/*";
pagespeed Disallow "*/wp-login.php*";

参考:[1] https://developers.google.com/speed/?hl=zh-CN&utm_source=PSI&utm_medium=incoming-link&utm_campaign=PSI

[2]https://www.modpagespeed.com/doc/system

[3] https://vircloud.net/build/nginx-pagespeed.html

btmp是什么?它 是系统记录登陆失败的 日志文件,使用以下命令来清空此文件,切勿直接删除, 别忘了那个大于号!! 

> /var/log/btmp

  1. 使用last 命令来查看所有登录成功的记录
  2. lastb来查看所有登陆失败的记录
  3. lastlog来查看最近登陆信息

我们可以通过修改ssh端口号来减少暴力破解次数, 这样日志文件也会变小

- 阅读剩余部分 -

1 . 编辑 /etc/ssh/sshd_config 文件,找到Port 22 一栏,修改22为你想要的端口

2. 使用下面这句 将新的端口加入允许列表,不然你登出后将无法登陆回来 ,xxxx替换成端口号

ufw allow xxxx/tcp 

3. 重启 ssh服务,service ssh restart 或者 /etc/init.d/ssh restart 即可

参考韩艺博的博客)) view English version

在nginx配置中插入

ssl on;
ssl_certificate       /path/to/your/certificate.crt;
ssl_certificate_key  /path/to/your/private.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5;';
ssl_session_cache    shared:SSL:1m;
ssl_session_timeout  5m;
ssl_session_tickets off;
ssl_ecdh_curve X25519:sect571r1:secp521r1:secp384r1;
ssl_prefer_server_ciphers  on;

注意ssl_session_cache等配置不要和vhost中的配置有冲突!