用树莓派做好防火防盗的心理安慰工作

2016-06-02 690332人围观 ,发现 23 个不明物体 极客终端安全

毕业季又要到了,而这次我加入了毕业季的大军,在外面租了房子。但是不知道为什么,每天上班我都会担心家里会不会遭小偷?有没有哪个插头没拔会不会引起火灾啊?听说这是病,只可惜我没钱治,不过好在我有树莓派。

好吧,我们要达到的目标是树莓派通过传感器判断是否有人闯入或者是否有火焰,并将数据发送到服务器,手机再从服务器获取数据。于是流程大概就是这样的:

1.png

硬件准备:

树莓派

人体红外感应模块

火焰传感器

10K电阻

面包板和杜邦线

人体红外感应模块和火焰传感器都是通过树莓派的GPIO口与树莓派连接的,我们使用11号和12号引脚。树莓派的GPIO有多种编号方式,为了防止懵逼我们这里就只说一种,看图,下面那个迷之突起就是代表它是1号引脚,别人还友好的标出了P1

2.png

我们用12号引脚连接人体红外感应模块,11号引脚连接火焰传感器。

硬件连接很简单,人体红外感应模块虽然供电要求5V但是信号输出却是3.3V,而且电流很小,所以信号输出OUT直接连接12号引脚就行了。人体红外感应模块也就是一个热释电模块,人体辐射的红外线中心波长为9~10–um,若探头接收到人体 辐射的红外线则输出高电平。简单的说就是有人时输出高电平,没人时输出低电平。当然,这么一来弱点也很明显,第一就是容易受到其他热源的影响,第二就是 人体的红外辐射容易被遮挡,小偷如果用很奇怪的东西把自己包裹的很好,那么就无能为力了。记得小时候看科普节目,有人用一面玻璃骗过了红外感应报警器。

火焰传感器就是探测有没有火焰嘛,它自身的电阻值会随着火焰的增大而变大。那么如何采集信号呢?我们让它与10K电阻串联,初中学过串联分压,电阻值越大分得的电压也就越大。蛋似,它是输出模拟信号,而树莓派没有自带ADC,怎么办呢?当然我们可以直接买一个数字信号输出的火焰传感器模块,也可以自己买个ADC芯片,而我试了试,当火焰靠近传感器时输出电压能达到3V,也就是说满足了树莓派对高电平的定义。当然了,这样的话只有火焰足够大才能报警,但也比没人知道发生火灾的情况好。火焰传感器的连接方式如图,不过要注意的是,树莓派的GPIO电平是3.3V,所以这里的VCC也应该是3.3V信号输出就直接连到11号引脚就好啦。

3.png

然后附上引脚的编号图,大家对照着图给人体红外传感器和火焰传感器连接上VCC和GND就好了。

比如我是1号引脚给火焰传感器供电,9号引脚作为火焰传感器的GND,11号引脚作为火焰的信号线;2号引脚给人体红外感应模块供电,6号作为人体红外感应模块的GND,12号引脚是信号线。

4.png

连接好后大概就是这样:

WP_20160529_19_32_46_Rich.jpg

然后就是编程了,树莓派上我们当然用pythonpython可以很方便的操作GPIO。我们读取GPIO的电平情况然后发送到服务器就行了。

# -*- coding:utf-8 -*-

import urllib

import RPi.GPIO as GPIO

import time

 

GPIO.setmode(GPIO.BOARD)#设置GPIO编号的方式

GPIO.setwarnings(False)#取消警告

GPIO.setup(11,GPIO.IN)#设置11号引脚为输入

GPIO.setup(12,GPIO.IN)#设置12号引脚为输入

 

if __name__ == '__main__':

    while True:

        i = GPIO.input(12)#读取12号引脚的电平,低电平为0,高电平为1

        f = GPIO.input(11)#读取11号引脚的电平

        url = 'http://xxx.xxx.xxx.xxx:5000/record/?i='+str(i)+'&f='+str(f)

        print url

        web = urllib.urlopen(url)

        print web.read()

        time.sleep(5)#每5秒钟发送一次数据

在服务器这边,我们就简单的用flask写一个api吧。

首先要给树莓派提供一个发送信息的api,为了方便我们使用GET请求的方式发送数据,参数i表示否是有人闯入,参数f表示是否有火焰。之后要给手机留一个获取信息的api,返回json格式的数据,当然为了方便我们也是使用GET请求数据。其实这种对实时性有要求的项目还是用socket比较靠谱。代码大概就是长这个样子,我承认我偷了个懒

# -*- coding : utf-8 -*-

from flask import Flask,request,jsonify

app = Flask(__name__)

 

isFire = 0

isInvaded = 0

 

@app.route('/record/',methods=['GET'])

def record():

        if request.method == 'GET':

                global isInvaded

                global isFire

                try:

                        isInvaded = int(request.args.get('i'))

                        isFire = int(request.args.get('f'))

                except:

                        return 'error'

                return 'ok'

 

@app.route('/state/',methods=['GET'])

def state():

        global isInvaded

        global isFire

        return jsonify({'isInvaded':isInvaded, 'isFire':isFire})

 

if __name__ == '__main__':

        app.run(host='0.0.0.0')

再之后就是安卓手机这边了,其实功能简单到我都不知道界面该怎么做,就是显示有没有人闯入和有没有火焰。当然,我们在有人闯入和有火焰时也要有报警提示才行。

a1.pnga2.png

安卓这边也比较简单。首先是发送GET请求从服务器获取数据。貌似现在有新的方法做GET请求了,我很久没写过安卓app了所以方法有点老旧还请大家指教。

public class Webconn {

public static String getDev() {
String url = "http://XXX.XXX.XXX.XXX:5000/state/";
try {
HttpGet httppost = new HttpGet(url);
HttpResponse httpResponse = new DefaultHttpClient().execute(httppost);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
String strResult = EntityUtils.toString(httpResponse.getEntity());
return strResult;
}
} catch (Exception e) {
Log.e("log_tag", "Request failed" + e.toString());
}
return "null";
}

}

当然不能在主线程里面直接做网络访问,我们另起一个线程,每5秒钟请求一次数据,并且通过handler与主线程通信。另外当发现有人入侵或者有火焰时,在通知栏弹出消息提示。

public class MainActivity extends Activity {
private Handler mHandler;
private TextView fire, people;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mHandler = new Handler();
mHandler.post(new TimerProcess());

fire = (TextView) findViewById(R.id.fire);
people = (TextView) findViewById(R.id.people);
}

@SuppressLint("HandlerLeak")
final Handler handler = new Handler() {

@Override
public void handleMessage(Message msg) {
String ret = msg.obj.toString();
switch (msg.what) {
try {
case 1:
StringBuilder builder = new StringBuilder();
JSONObject jsonObject = new JSONObject(ret);
Log.i("json", "" + jsonObject);
if (jsonObject.getInt("isFire") == 0) {
fire.setText("没有发现火焰");
fire.setTextColor(android.graphics.Color.GREEN);
} else {
fire.setText("发现火焰");
fire.setTextColor(android.graphics.Color.RED);
mes("火焰传感器探测到火焰!");
}
if (jsonObject.getInt("isInvaded") == 0) {
people.setText("安全");
people.setTextColor(android.graphics.Color.GREEN);
} else {
people.setText("发现入侵者");
people.setTextColor(android.graphics.Color.RED);
mes("发现有人进入房间!");
}
} catch (JSONException e) {
e.printStackTrace();
}
break;
default:
break;
}
}
};

private void getDevInformation() {
new Thread(new Runnable() {
@Override
public void run() {
String ret = Webconn.getDev();
System.out.println("get return:");
System.out.println(ret);
handler.sendMessage(handler.obtainMessage(1, ret));
}
}).start();
}

private class TimerProcess implements Runnable {
public void run() {
mHandler.postDelayed(this, 5000);
getDevInformation();
}
}

public void mes(String m) {
//定义NotificationManager
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
//定义通知栏展现的内容信息
int icon = R.drawable.ic_launcher;
CharSequence tickerText = "我的通知栏标题";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
//定义下拉通知栏时要展现的内容信息
Context context = getApplicationContext();
CharSequence contentTitle = "树莓派安防";
CharSequence contentText = m;
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
//用mNotificationManager的notify方法通知用户生成标题栏消息通知
mNotificationManager.notify(1, notification);
}
}

这个主要还是对我的心里安慰,不过现在上班的地方离住的地方走路只要10分钟,所以即使有事我也能跑回来。这样想想,我都不用去治病了(雾)。

全部的东西都在这里:

http://pan.baidu.com/s/1pLy6vGn

*本文原创作者:zhangtory,本文属FreeBuf原创奖励计划,未经许可,禁止转载。

这些评论亮了

  • 懵逼 回复
    树莓派起火了怎么办? :mrgreen:
    )16( 亮了
  • zhangtory (3级) 专业打酱油 回复
    @ huangwenhuai  所以应该加一个掉线报警的功能。
    )11( 亮了
  • 到房间前,先把电源掐了看你还威风。。。
    )9( 亮了
  • 您当前尚未登录。登陆?注册 回复
    @Ron我感觉写的挺好的,你不会明白,一个程序员,宅男,屌丝,单身狗,在折腾自己想做的小玩意后的成功感
    )9( 亮了
  • 流泉滴沙 回复
    大材小用了,一个51就够了!
    )8( 亮了
发表评论

已有 23 条评论

取消
Loading...

特别推荐

推荐关注

填写个人信息

姓名
电话
邮箱
公司
行业
职位
css.php