物联网项目 | LeanCloud+树莓派+安卓实现住宅环境异常告警系统

warning: 这篇文章距离上次修改已过953天,其中的内容可能已经有所变动。

前言

本系统监测的条件限于温湿度、火焰、烟雾或有毒气体,以及登记授权人员人脸信息,(人脸检测和识别老早写了,懒得再接入了有时间再说吧) :neutral_face:出现异常时可及时记录和向用户APP推送消息告警。

完成后的树莓派和传感器完成后的树莓派和传感器

目录

物料清单

配件名称数量功能
Raspberry Pi 4B1主机
闪迪Micro SD 16GB1为树莓派烧录系统
树莓派专用电源适配器及电源线1为树莓派供电
安卓手机1控制和查看系统运行情况
MQ-2烟雾传感器1检测燃烧产生烟雾及有害气体
火焰传感器1检测一定线性范围的火焰
DHT11温湿度传感器1检测室内温度和相对湿度
杜邦线9连接传感器和树莓派电脑

软件架构

室内环境条件监控模块

系统同时使用多个传感器感知和上传所处环境的温湿度、烟雾和火焰触发数据,同时使用烟雾传感器、温度传感器和火焰传感器进行判断火情

  • 若只有烟雾传感器或火焰传感器被触发或温度高于45.0摄氏度,向用户发送普通告警;
  • 其中两个条件满足,向用户发送中级告警;
  • 若三者均满足,向用户发送紧急告警信息。

推送消息被用户点击后,会跳转到APP主界面让用户查看详细传感器数据。

手机监视APP模块

接受消息推送和查看传感器上传的数据。

硬件模块使用

DHT11温湿度传感器

1.连接VCC,GND,其中DATA接到GPIO 4,树莓派4B引脚如图:

树莓派4B引脚图,由树莓派实验室绘制树莓派4B引脚图,由树莓派实验室绘制

2.安装python依赖Adafruit_DHT。
在控制台中输入命令pip install Adafruit_Python_DHT进行安装。安装成功后,编写测试程序:

import time
import sys
import Adafruit_DHT
DHT_chanel = 18 #BCM编码引脚口
while true
    time.sleep(1)
    hum,temp = Adafruit_DHT.read_retry(11,DHT_chanel)

3.运行正常,结果如图:(以humidity表示相对湿度)

在树莓派上测试DHT11正常输出温湿度值在树莓派上测试DHT11正常输出温湿度值

MQ-2烟雾传感器

1.连接VCC,GND,其中DO为TTL高低电平输出口,接GPIO 0
2.安装python依赖PRi.GPIO。在控制台中输入命令pip install PRi.GPIO进行安装。
3.编写测试程序如下,高电平时正常:

import RPi.GPIO as GPIO 
import time

CHANNEL=7 # GPIO引脚口
GPIO.setmode(GPIO.BOARD) 
GPIO.setup(CHANNEL,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)

try:
    while True: # 执行一个while死循环
        status=GPIO.input(CHANNEL) # 检测7号引脚口的输入高低电平状态
        print(status) # 实时打印此时的电平状态
        if status == True: # 如果为高电平,说明MQ-2正常,并打印“OK”
            print ( ' OK ' )
        else:    # 如果为低电平,说明MQ-2检测到有害气体,并打印“dangerous”
            print ( ' high toxic gas level ! ! ! ' )
        time.sleep(5) 
except KeyboardInterrupt: # 异常处理,当检测按下键盘的Ctrl+C,就会退出这个>脚本
GPIO.cleanup()

4.运行正常,结果如图:

MQ-2正常工作,TTL口输出高电平表示正常MQ-2正常工作,TTL口输出高电平表示正常

云后端接入与使用

云后端的作用就是充当手机APP和物联网硬件之间的桥梁,也就是我们的树莓派和安卓APP之间用于推送消息以及保存传感器数据的中间人。经过上一轮的测试,Bmob云后端虽然提供了比较完善的免费云后端服务,但在Android SDK接入时有难以解决的错误,故采用同样具有数据服务和消息推送的免费云后端服务LeanCloud

为安卓用户端接入LeanCloud数据及消息推送SDK

按照官方文档中对于Java SDK的说明,在Android Studio中使用Gradle引入LeanCloud的数据存储和消息推送的Java SDK,即在module级Gradle配置文件的相应位置中加入如下引入:

implementation 'cn.leancloud:storage-android:8.0.1'
implementation 'cn.leancloud:realtime-android:8.0.1'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'

然后再进行Gradle项目同步即可。

LeanCloud安卓SDK初始化

在Android项目的Application类的onCreate()方法内进行如下操作:

public class MyLeanCloudApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // 提供 this、App ID、App Key、Server Host 作为参数
        // 注意这里千万不要调用 cn.leancloud.core.LeanCloud 的 initialize 方法,否则会出现 NetworkOnMainThread 等错误。
        LeanCloud.initialize(this,
 "t8dmUAOAX4NptIX4oziNpYPc-gzGzoHsz",
 "pDuJ1si51y5RGGdWyqReM8Ff",
 "https://please-replace-with-your-customized.domain.com");//这里填入LeanCloud上提供或是自己绑定的域名,本项目使用官方提供的免费域名
PushService.setDefaultChannelId(this, "android");#配置默认消息通道
#订阅消息通道
PushService.subscribe(this, "public", MainActivity.class); 
        PushService.subscribe(this, "android", MainActivity.class);
        #使用SharePreferences存储安装信息,是否为第一次安装以及安装得到的installationId
        SharedPreferences sp = getSharedPreferences("installation", MODE_PRIVATE);
        SharedPreferences.Editor edit = sp.edit();
        boolean isInstalled = sp.getBoolean("isInstalled", false);
        if(!isInstalled){
            //LCInstallation.getCurrentInstallation().saveInBackground();
            LCInstallation.getCurrentInstallation().saveInBackground().subscribe(new Observer<LCObject>() {
                @Override
                public void onSubscribe(Disposable d) {
                }
                @Override
                public void onNext(LCObject avObject) {
                    // 关联 installationId 到用户表等操作。
                    String installationId = LCInstallation.getCurrentInstallation().getInstallationId();
                    edit.putString("installationId",installationId).commit();
                    System.out.println("保存成功:" + installationId );
                }
                @Override
                public void onError(Throwable e) {
                    System.out.println("保存失败,错误信息:" + e.getMessage());
                }
                @Override
                public void onComplete() {
                }
            });
            edit.putBoolean("isInstalled", true);
            edit.commit();
    }
}

完成后在AndroidManifest.xml声明此Application类,即在其中的<application下添加

android:name=".MyLeanCloudApp" >

这里的MyLeanCloudApp替换成自己的Application类名称。

LeanCloud安卓消息推送服务初始化

按照官方文档,在Android项目的AndroidManifest.xml的<application下添加如下服务和消息接收器:

<service android:name="cn.leancloud.push.PushService" />
        <!--
        <receiver android:name="cn.leancloud.push.LCBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.USER_PRESENT" />
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
        </receiver>
        -->
        <receiver
            android:name=".MyCustomReceiver"
            android:exported="false">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.USER_PRESENT" />
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                <action android:name="com.avos.UPDATE_STATUS" />
            </intent-filter>
        </receiver>

其中MyCustomReceiver是一个自定义类,继承BroadcastReceiver,代码如下:

public class MyCustomReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 获取推送消息数据
        String message = intent.getStringExtra("com.avoscloud.Data");
        String channel = intent.getStringExtra("com.avoscloud.Channel");
        System.out.println("push message");
        System.out.println("message=" + message + ", channel=" + channel);
    }
}

LeanCloud安卓消息推送服务接入完成测试

在LeanCloud的后台-推送-在线发送中,填写JSON推送内容如下:

{
    "alert": "test content",
    "title": "WARNING! Your house's condition is in danger!",
    "silent": false
}

点击发送,Android端成功接到推送消息:

Android端成功接到LeanCloud管理后台推送的消息Android端成功接到LeanCloud管理后台推送的消息

但我们要求的是由树莓派来主动触发消息推送,所以接下来为树莓派配置SDK。

为用户端监测硬件 —— 树莓派接入LeanCloud Python SDK

按照LeanCloud的官方文档,使用包依赖管理工具进行便捷的安装,即,在控制台中输入sudo pip install leancloud进行依赖包安装。

依赖包安装完成,在需要使用到LeanCloud服务的程序里先使用import leancloud导入,再使用命令leancloud.init("App ID ", " App Key ")初始化LeanCloud服务。

按照LeanCloud文档,使用Python在新增结构化数据的代码如下:

# 构建数据操作对象
    StateObject = leancloud.Object.extend('State')# 'State'为表名
    state_object = StateObject()
    state_object.set('temperature', temp)# 'temperature' 为列名
    state_object.set('relativeHumidity', hum)# 'relativeHumidity'为列名
    state_object.set('isFireOK', isFireOK)# 'isFireOK'为列名
    state_object.set('isSmokeOK', isMQ2OK)# 'isSmokeOK'为列名
    state_object.set('recordDate', recordDate)# 'recordDate'为列名
state_object.save()#传入的各列数据类型需要一一对应,参照官方文档的数据类型

# 测试向Android端推送消息
content="temperature lower than 45.0, it’s just a test"
title="nothing"
data = json.loads(json.dumps({'alert': content, 'title': title}))
if(len(title)!=0 and len(content)!=0):
    leancloud.push.sned(data,
                      channels=['android','public'],
                      push_time=None,
                      expiration_time=None,
                      expiration_interval=None,
                      where=None,cql=None,
                      flow_control=None,
                      prod=None)

在安卓端SDK和消息推送服务配置正常以后,可以正常收到如下推送:

在安卓实机上收到的来自树莓派的推送消息在安卓实机上收到的来自树莓派的推送消息

传感器数据实体

传感器记录数据在云后端数据库中的实体如表所示:

State表

列名数据类型说明
recordDateDATE数据采集时间
temperatureNUMBER温度传感器数据
relativeHumidityNUMBER相对湿度传感器数据
isFireOKBOOLEN火焰传感器数据是否超阈值
isSmokeOKBOOLEN烟雾传感器数据是否超阈值
IsExceptionBOOLEN是否有任一数据超过阈值

Android APP编写和打包测试

Android项目和集成开发环境

本项目使用基于intellJ IDEA社区版的Android Studio进行开发测试,新建Android项目并进行相应配置,使用Redmi Note 8 Pro 实体机进行测试。

App详细设计

为了减少项目复杂度,本项目采用最简单的安卓开发模式:MVC。一个MainActivity和对应界面即可。

App打开后自动进入到主界面MainActivity,并异步加载服务器记录的传感器数据。数据的展示采用RecyclerView + BaseRecyclerViewadapter的模式。在MainActivity的layout中,使用SwipeRefreshLayout包裹RecyclerView以实现下拉加载的功能。

在MainActivity中为SwipeRefreshLayout添加下拉监听,下拉动作发生时执行服务器数据拉取动作。

点击右上角感叹号图标可以筛选有数据超过阈值的记录,再次下拉刷新可以取消筛选。完成后测试获得服务器数据如图:

APP主页展示的传感器数据APP主页展示的传感器数据

参考资料

[1] PyPI. Adafruit_Python_DHT [EB/OL]. (2021-07-06). https://pypi.org/project/Adafruit_Python_DHT/
[2] 埃勒里灬波洛. 树莓派DHT22读Adafruit_DHT报错 can not import Beaglebone_Black_Driver的解决办法 [EB/OL]. (2020-09-09). https://blog.csdn.net/elleryer/article/details/108482087
[3] weixin_34112030. 基于树莓派(Raspberry Pi)平台的MQ-2烟雾报警系统实现(一) [EB/OL]. (2018-03-16). https://blog.csdn.net/weixin_34112030/article/details/92237494
[4] LeanCloud. LeanCloud文档 [EB/OL]. (2021-07-06). https://leancloud.cn/docs

最后修改于:2021年08月18日 16:06

添加新评论