基于“树莓派+腾讯云”的在线甲醛监测系统

身边朋友在装修新房,顺便来吐槽甲醛检测麻烦,比如 有检测无监测(一次性),比如测试复杂(现场+人工)等等。刚好做为云产品经理,经常想的就是如何了解和验证多云产品组合方案的可用性问题,索性结合一下,直接把这个需求上云,然后就有了这套系统。老规矩,先上结论。

系统概要

产品设计特性

  • 原型验证:验证产品联动效果与开发成本。
  • 软硬结合:扩展云端能力至线下物理环境。
  • 能力扩展:serverless分离云端与终端,独立扩展云监控、消息队列等其它产品。
  • 通用架构:云端使用通用数据结构及接口,免开发即对接各种监测数据上报。
  • 弱环境要求:可PoE供电,5V/0.5A低功耗可长期运行。

系统组成

终端:终端组件

  • RaspberryPi 3B+(raspbian-stretch-lite/GPIO接口/python2.7)
  • UART-CH2O传感器(UART接口)
  • 128X32 OLED屏 SSD1306芯片(I2C接口)

注:RaspberryPi后续简写为Rpi

云端:腾讯云产品

效果展示

腾讯云图

本案例展示效果

终端组件

本案例终端示例

当前版本中,Rpi 使用wifi 连接互联网(也可使用有线网),故此处上云有网络依赖。

传感器原理与功能定位

UART-CH2O传感器

  • 原理:电化学传感器。通过与被测气体发生反应,并产生电信号来工作。
  • 优点:简单易操作。
  • 缺点:非定量分析法,受温湿度、其它气体干扰准确度,且需要较准。
  • 结论:以长期使用后的房间环境做为基准,进行0基准点参考。用于温湿度差异不大的环境下,提供实时监测(相对值),并附加长期趋势分析。

设计与实现

产品设计与技术策略

设计过程中,也进行了产品生命周期的思考,尝试进行了产品长短期设计的分析与定义(暂不展开,后续有时间写一下)。

确认了形态目标后,遵循下面几个基本原则,进行具体技术设计:

  • 分级可用:避免单环故障,系统全面崩溃
  • 读写分离:便于后续调试、优化、更新版本
  • 远程维护:避免出现场处理异常

概要架构图

架构图

从架构看来

  • 云端部分:由于云产品的能力提供了各种便利,学习和搭建成本很低。
  • 终端部分:需要多考虑免维护与自动恢复,各项工作内容稍多一些。

硬件接线与打开系统接口

Rpi GPIO

GPIO

(General-purpose input/output)即通用IO接口,是一种常见的端口扩展器,树莓派使用的是40针的GPIO接口。

RPI GPIO图示

GPIO示意图

UART-CH2O

接线方式(UART协议)

传感器 Rpi
5V Pin2(5V)
GND Pin6(GND)
UART-TxD Pin10(UART-RxD)

注:本次使用传感器,硬件接口是1.25mm端子,Rpi是2.5mm端子,使用了 7P1.25转2.5杜邦线,进行连接

硬件参数

本次使用的传感器是UART协议,从国外的DART传感器到国内产品,均支持此协议。

由于后续代码与接口有关,此处列一下我使用的传感器的数据格式.默认每秒主动上报。

Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7 Byte8
起始位 气体名称 单位 小数位数 气体浓度-高位 气体浓度-低位 满量程高位 满量程低位 较验值
0xFF 0x17 0x04 0x00 0x00 0x25 0x13 0x88 0x25

OLED

接线方式(I2C协议)

OLED Rpi
VCC Pin1(3.3V)
SDA Pin3(SDA)
SCL Pin5(SCL)
GND Pin9(GND)

打开I2C接口

raspi-config

按下图打开I2C接口

openi2c_1.png

openi2c_2.png

openi2c_3.png

测试执行

i2cdetect -y 1
i2cdetect_1.png

看到 3C 即识别硬件成功

终端开发与配置

本文暂仅放出关键代码(硬件操作部分),便于大家撸硬件。
完整包(代码+配置) 稍后放出,请关注 github/DemoOnTencentCloud

环境配置

  • 启动对时:rc.local 增加 nptdate cn.ntp.org.cn。避免重启后时间错位,监测错位。
  • 启动拉起:getdata.py oled.py 需持续在线。
  • 定时检测:getdata.py oled.py cron每分钟判断活性,进程挂掉即拉起。
  • 定时同步:sync.py cron每分钟执行
  • 远程维护:使用ssh tunnel 的 Remote Port Forwarding 模式,进行反向代理。

ssh tunnel

此处使用 autossh 进行连接,autossh可完成建立通道与监控通道的工作,通道断开后,可自主重连。远端连接 腾讯云服务器,之后可以云服务器为跳板,反向代理访问NAT环境Rpi设备。

autossh -M 监控端口 -R 远程通信端口:localhost:22 账号名@远程IP或域名 -p端口号 -i 账号KEY -o serveraliveinterval=60 -N -f

连接时,在云服务器执行

ssh -p 远程通信端口 localhost

getdata.py

获取传感器读数代码(完整代码待放出 github/DemoOnTencentCloud

import serial
from time import sleep

ser=serial.Serial("/dev/serial0",9600)

while True :
    r_data = ser.read()
    sleep(0.3)
    data_left = ser.inWaiting()
    r_data += ser.read(data_left)
    if 9 != len(r_data):
        print 'error length: %d'%len(r_data)
        continue
    else:
        n=ord(r_data[4])*256+ord(r_data[5])
        updatedata(n/1000.0) # ppm = n/1000.0 

flusholed.py

依赖库安装(基于 https://github.com/adafruit/Adafruit_Python_SSD1306)

sudo python -m pip install --upgrade pip setuptools wheel
sudo pip install Adafruit-SSD1306

下为功能伪代码。(完整代码待放出 github/DemoOnTencentCloud

# 读取 cachefile 缓存文件
# 刷新 OLED 显示

sync.py

下为功能伪代码。(完整代码待放出 github/DemoOnTencentCloud

# 访问 APIGW,获取最新记录时间戳
# 读本地sqlite库,获取增量数据
# 访问 APIGW,提交更新数据

Sqlite结构

表结构

CREATE TABLE "sensordata" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"utime" INTEGER NOT NULL,
"utype" INTEGER DEFAULT 0 NOT NULL,
"udata" REAL NOT NULL,
"sdata" TEXT
);
字段 说明
id 自增主键
stime 监测时间戳
udata 监测数据
utype (预留字段,扩展类别)
sdata (预留字段,扩展数据类型)

云端开发与配置

无服务器云函数

优先配置 无服务器云函数,参考 文档 建立并保存“函数代码”后,在管理页面的“触发方式”功能中,直接生成对应API网关。

触发方式选择API网关

(完整代码待放出 github/DemoOnTencentCloud)。

当前主要强调几个注意事项:

  1. 自动提交:连接数据库必须使用“autocommit = True,”参数,否则由于事务隔离,DB链接重新连接前,查询结果不变。(查不到新增记录ID)
  2. 返回头:API网关开启“响应集成”时,云函数返回值需结合返回信息,指定"Content-Type",否则出现 "transfer closed with outstanding read data remaining" 错误。
  3. 验证连接:云函数实例可长期存在,但一定时间未操作mysql链接时,mysql将释放链接,所以代码中需要进行验证链路可用性。

API网关

配置服务

参考 文档 ,以上文“触发方式”中建立的API网关服务,由API网关的 服务 页面,点击相应服务名,选择“API管理”分页,点击“编辑”,然后配置“请求方法-POST”、“鉴权类型-密钥对”、“使用响应集成”,其它余配置按默认即可。

下载与使用SDK

API网关 控制台 -> 点击 服务名 -> 点击 API文档/SDK -> 点击 下载SDK

(完整配置待放出 github/DemoOnTencentCloud

云数据库 Mysql

表结构

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";

CREATE TABLE `sensordata` (
  `id` int(11) NOT NULL,
  `stime` timestamp NULL DEFAULT NULL,
  `utype` int(11) NOT NULL DEFAULT '0',
  `udata` float NOT NULL,
  `sdata` varchar(256) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `sensordata`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `sensordata`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;
字段 说明
id 自增主键
stime 同sqlite utime
udata 同sqlite udata
utype 同sqlite utype
sdata 同sqlite sdata

云图配置

简要使用说明

拖选组件 -> 点击数据栏 -> 选择数据库 -> 填写SQL -> 开启自动更新 -> 预览 -> 发布

操作示例图

腾讯云图配置示意

组件配置信息

  • 最新同步时间 - 通用文本
select concat('最新同步时间 ',stime) as value from sensordata order by id desc limit 1
  • 国标系数比 - 水位图
select round((udata)/0.08*100, 2) as value from sensordata order by id desc limit 1
  • 实时读数 - 基本条形图
select round(udata, 3) as x, '' as y from sensordata order by id desc limit 1
  • 10分钟数据 - 基本折线图
select * from (select id, round(udata, 3) as y, date_format(stime, '%H:%i:%S') as x, utype as s from sensordata order by id desc limit 360) as t1 order by id asc
  • 7天数据 - 基本折线图
select distinct (dt), round(AVG(udata),3) as y, dt as x, '0' as s from (select id, date_format(stime, '%Y-%m-%d %H') as dt, udata from sensordata order by id desc limit 604800) as t1 group by dt order by dt ASC

写在最后

关于丢数据(非守护进程)、脏数据(未较验数据唯一性)、缺乏系统监控告警(未接入云监控)等等待优化点,由于时间关系暂未展开,后面可以再行探讨。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容