树莓派 + pyecharts + nginx 气象数据收集与可
这个小“项目”已经稳定运行近2年了。主要特性是树莓派将收集的室内温度、湿度和室外温度以及CPU温度等数据存入sqlite数据库,利用pyecharts进行数据可视化,用nginx做服务器,可通过网页浏览。申请公网IP后,外出时也可以查看数据。
硬件清单
1. 树莓派 Zero W
2. ds18b20模块
3. sht30模块
软件清单
1. python
2. pyecharts
3. nginx
硬件搭设
- 树莓派 zero w价格便宜,自带wifi模块,功能强大。到手后刷入官方lite版系统,不需要桌面。具体请参考教程,“无屏幕和键盘配置树莓派WiFi和SSH”。
raspberry-pi-zero-w.jpg
-
室外温度采用ds18b20模块,此模块为“单总线模块”,数据和电源共用一条线,加上地线共两条线,正好一根据电话线即可,接线见下图。
ds18b202.png
总接线图如下
-
sht30是盛世瑞恩出产的一款基于i2c传输协议的温、湿度传感器,联线比较简单,唯一需要注意的是它的电压是3.3V,不要接到5V上去了。
set.png
编写程序
1. 主程序
主程序调用各个模块的功能。
- 获取温度、湿度等数据
- 将获得的数据存入sqlite数据库
- 利用用pycharts生成可视化数据
#run.py
import sys
import time
import genHtml2
import rpi_stat
import sht30
import sys
import sqlite3
wait = 10
interval = 60*10
while True:
#取得当前时间
time_date = time.strftime("%Y/%m/%d",time.localtime())
time_time = time.strftime("%H:%M",time.localtime())
#取得CPU温度和负载
cpu_t =rpi_stat.getCPUTemp()
cpu_load = rpi_stat.getLoad()
#取得室内温、湿度
room_t, room_h = sht30.get()
#取得室外温度
out_t = getDs18b20()
#将数据存入数据库
cn = sqlite3.connect('weather.db')
cu = cn.cursor()
item = [None]
item.append(time_date)
item.append(time_time)
item.append(room_t)
item.append(out_t)
item.append(room_h)
item.append(cpu_t)
item.append(cpu_load)
item.append(volt)
cu.execute("INSERT INTO record values(?,?,?,?,?,?,?,?,?)", tuple(item))
cn.commit()
#生成pyecharts网页
genHtml2.gen()
time.sleep(interval)
2. 获取室内温、湿度
#sht30.py
import smbus
import time
def get():
bus = smbus.SMBus(1)
bus.write_i2c_block_data(0x44, 0x2C, [0x06])
time.sleep(0.5)
data = bus.read_i2c_block_data(0x44, 0x00, 6)
cTemp = ((((data[0] * 256.0) + data[1]) * 175) / 65535.0) - 45
humidity = 100 * (data[3] * 256 + data[4]) /65535.0
return(round(cTemp,2),round(humidity,2))
3. 获取室外温度
def getDs18b20():
with open("/sys/bus/w1/devices/28-000004b1dd3f/w1_slave") as f:
text = f.readlines()
secondline=text[1]
temp = secondline.split(" ")[9]
temp = temp.strip()
temp = float(temp[2:])/1000
return temp
4. 获取CPU温度和负载
rpi_stat.py
import time
import os
def getCPUTemp():
with open("/sys/class/thermal/thermal_zone0/temp") as file:
res = file.readline()
return round(int(res)/1000,2)
def getLoad():
res = os.popen("uptime").readline().split()[-3]
return int(float(res.replace(',',''))*100)
5. 使用pyecharts生成网页
pyecharts是一款将python与echarts结合的强大的数据可视化工具,是Python数据可视化利器!
项目地址https://github.com/pyecharts/pyecharts,有详细的教程。
安装 pyecharts
pip install pyecharts
#genHtml.py
from pyecharts import Line,Page
import platform
import sqlite3
import util
def gen():
cn = sqlite3.connect('weather.db')
cu = cn.cursor()
textsize = 32
time_st = []
room_t = []
out_t = []
room_h = []
cpu_t = []
cpu_load = []
bat_volt = []
sql = "SELECT * FROM record order by id desc limit 100 "
rec = cu.execute(sql)
# print(type(list(rec)))
lst = list(rec)
lst.reverse()
for line in lst:
tm_st = line[1][5:].replace("/","-") +" "+line[2]
time_st.append(tm_st)
room_t.append(line[3])
out_t.append(line[4])
room_h.append(line[5])
cpu_t.append(line[6])
cpu_load.append(line[7])
bat_volt.append(line[8])
page = Page(page_title="My RPi Center")
#数据总个数
amount = len(time_st)
#需要显示的个数(24小时)
display = 72
#display range
dis_range = int((1-display/amount)*100)
# print(amount)
line_room_t = Line("气温 %s/%s℃"%(str(room_t[-1]),str(out_t[-1])),
title_pos='center',
title_text_size=textsize,
title_top='5%')
line_room_t.add("室温", time_st, room_t,
xaxis_name='时间',
yaxis_name='温度(℃)',
yaxis_name_pos='end',
xaxis_name_pos='end',
xaxis_label_textsize=textsize,
yaxis_label_textsize=textsize,
label_text_size=textsize,
label_emphasis_textsize=textsize,
tooltip_font_size=textsize,
mark_point_textsize=10,
is_label_show=True,
line_width = 3,
line_curve = 0.5,
is_datazoom_show=True,
datazoom_type='slider',
datazoom_range=[80,100],
is_more_utils=True,
xaxis_force_interval=50,
yaxis_min=min(room_t)-5,
yaxis_max=max(room_t)+5,
tooltip_tragger='axis',
mark_point=['min','max'],
mark_line=['average'])
page.add(line_room_t)
······
#太长了,在此省略,详见https://github.com/lemodd
#将页面保存到目录
page.render('/home/pi/www/index.html')
6. 完成
到此用浏览器打开生成的index.html文件就可以看到结果了。这样只能在本机上查看,为了能随时随地的查看,需要一个http服务器,别的电脑和手机就可以用浏览器查看了。
Snipaste_2019-11-02_20-05-48.png
安装、配置nginx
百度百科
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
1.安装 nginx
在终端运行命令
sudo apt-get install nginx
一路确认,即可完成安装。
启动Nginx
sudo /etc/init.d/nginx start
可通过http://树莓派IP访问到 Nginx 的默认页。如果出现下图则说明nginx安装成功。
2. 配置nginx
修改 nginx 的配置文件
sudo nano /etc/nginx/sites-available/default
默认路径 html 所在路径,修改为你自己的。
root /home/pi/www/
监听的端口号,如果与其它软件冲突,可以在这里更改。
listen 80 default_server
重新加载
sudo /etc/init.d/nginx reload
再次打开树莓派IP,如果没有错误,就可以看到刚才生成的图表了。
site.png
外网访问设置
到目前只能在家里的局域网访问,为了能在外网顺利访问到还需以下几步。
1. 获取公网IP
为了可以获得公网IP直接打宽带运营商的客服电话,一般会直接告诉你如何设置。不同的运营商和地区各有不同,我所在城市只需在用户名后加数字8即可变为外网IP。
2. 设置端口转发
即便获得了公网IP,80端口也是屏蔽的,需要设置下端口转发,外网端口设的8000,如下:
port.png
在路由器的互联网态中查到你的公网IP,访问地址 http://公网IP:8000,如果能看到图表,说明一切设置无误。这时在任何可以上网的地方都能查到家里的数据了。
3. DDNS设置
虽然现在可以在外网访问了,但是外网IP是不断变化的,每次拨号都会分配一个新的IP。为了能像一般网站一样用域名访问,只需设置下DDNS就可以了,打开路由器的DDNS设置,取一个别人没占用的名字。
DDNS.png
以后都可以通过二级域名来访问你的网站了。
配置supervisor
为了保证应用一直处于运行状态,在遇到断电、程序异常、报错等情况,导致应用终止时,需要保证程序可以立刻重启,继续提供服务。所以,就需要一个工具,时刻监控应用的运行情况,管理该进程。
Supervisor 就是解决这种需求的工具,可以保证程序崩溃后,重新把程序启动起来等功能。
安装supervisor
sudo apt-get install supervisor
新建配置文件
sudo nano /etc/supervisor/conf.d/raspi-echarts.conf
主要设置如下
user=pi
command=/usr/bin/python3 run.py ; 要运行的命令
directory=/home/pi/py/echarts/ ; 程序所在的目录
autorestart=True ; 程序异常退出后自动重启
autostart=True ; 在 supervisord 启动的时候也自动启动
stdout_logfile=/var/log/supervisor/echarts.log
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
进入supervisorctl客户端,查看状态和管理
sudo supervisorctl
可以看到正在运行的进程。用help命令可以查看常用的命令。