智能家居安防

本贴最后更新于 254 天前,其中的信息可能已经事过景迁

1.镜像烧录(开启 SSH、配置 wifi)

  • 参考微雪的教程 烧录树莓派镜像到 SD 卡,同时开启 SSH 和 WiFi(教程中包括相关基础知识,没接触过树莓派需要先过一遍,了解基本常识),

    注意:记得按照教程,开启 SSH 并配置 wifi,后续有用

  • 连接树莓派(以下方案任选一个即可,上一步已经配置了 wifi,树莓派启动后会自动连接 wifi)

  • 然后参考教程更新源(依据教程,查看树莓派版本,再进一步选择相应的源)

    **********树莓派替换镜像源(终极版!)*********

2.人脸识别

参考链接:https://blog.csdn.net/weixin_45880057/article/details/113965373

参考链接:https://blog.csdn.net/weixin_42163073/article/details/107308759

2.1 摄像头

  1. 树莓派接入 USB 摄像头或 CSI 摄像偷

  2. 在树莓派终端输入

    sudo raspi-config
    
  3. (在弹出的界面中)依次选择 Interface Options > Camera >Yes > OK >Finish > 重启(reboot)

  4. 为了检测摄像头是否成功接入,先拔掉运行 lsusb 命令查看当前树莓派接入的设备,再接入摄像头,再运行 lsusb,对比返回结果。如下图所示:

    20210223011126744

2.2 拉取代码

  1. 安装 openCV 在树莓派终端执行(会提醒输入树莓派的管理员密码,输入后回车即可,屏幕上不会现实密码)

    sudo apt install python-opencv
    
  2. 拉取代码

    cd
    git clone https://gitee.com/outlaw-maniac-zhang-san-1/facial-recognition-copy
    cd facial-recognition-copy
    
  3. 执行测试,此时应该在屏幕上看到两个画面框,一个彩色、一个灰色

    python3 cam_test/simpleCamTest.py
    

    20210223013915554

  4. 在终端窗口按下 [Ctrl]+C 组合键退出

2.3 采集数据

在树莓派终端执行

cd facial-recognition-copy/FacialRecognition
mkdir dataset/
python3 01_face_dataset.py

显示输入此用户 ID,输入 1 。 然后人脸对着摄像头,程序会收集 30 个样本数据 > 样本数据在 dataset 中,可在用户界面直接打开查看

202102230203153

2.4 训练

cd facial-recognition-copy/FacialRecognition
mkdir trainer
python3 02_face_training.py

训练好的文件,存储在默认的 trainer 文件夹中

2.5 识别

python3 03_face_recognition.py

人脸对着摄像头,查看是否识别成功
是否显示”ID=1“

20210223022410487

人脸识别结果可在 03_face_recognition.py 中进行修改

20210223022833195

3.传感器

3.1 红外人体传感器(蜂鸣器)

接线

蜂鸣器 T 型转接板 树莓派(BCM)
GND GND
VCC VCC
信号线 GPIO21
红外人体传感器 T 型转接板 树莓派(BCM)
GND GND
VCC 5V
信号线 GPIO20

代码

import RPi.GPIO as GPIO
import time

# 初始化
def init():
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(20, GPIO.IN)
    GPIO.setup(21, GPIO.OUT)

# 蜂鸣器鸣叫函数
def beep(pin = 21,status = 0):
    if status == 0:
        GPIO.output(pin,GPIO.LOW)
    else:
        GPIO.output(pin,GPIO.HIGH)

# 感应器侦测函数
def detect():
    while True:
        # 如果感应器针脚输出为True,则打印信息并执行蜂鸣器函数
        if GPIO.input(20) == True:
            print("Someone is closing!")
            beep(status=1)
        else:
            print("No anybody!")
            beep(status=0)
        time.sleep(0.5)

if __name__ == "__main__":
    init()
    detect()

运行结果:

image

3.2 烟雾传感器

初始配置

参考:https://blog.csdn.net/qq_56788267/article/details/136951688

登陆上树莓派后,输入命令:sudo raspi-config 后回车;选择 Interfacing Options 后回车,选择 I2C 回车, 选择 YES 回车,最后就设置成功啦!如图所示:

28f12bd673b4486b923f30dd4fbb2a8f

​​076a301faf994a47905f135310862459

938c83a8eb1e4f19a9ad4ef2f9e22f45

1a4e153a97734b68ade017953724d0f3

1154744bb773459f8aed0f8ea94a5fa3

如果想要查看你的传感器有没有成功连接树莓派,输入命令 i2cdetect -y 1(如果不行在命令前面加个 sudo);(图中的 48 是 pcf8591 的地址)如图:

image

接线

MQ2 烟雾传感器 pcf8591 T 型转接板
GND GND GND
VCC VCC VCC
A0 AIN0
SCL SCL1
SDA SDA1

代码

import time
import math
import smbus
class PCF8591:
    def __init__(self):
        self.CAL_PPM =20  	    # 校准环境中PPM值
        self.RL = 5		        # RL阻值
        self.bus = smbus.SMBus(1)  # 自动选择可用的I2C总线
        self.address = self.get_address()

    def get_address(self):
        # 遍历0x48到0x4F之间的地址,尝试读取设备的响应
        for addr in range(0x48, 0x50):
            try:
                self.bus.read_byte(addr)
                print(addr)
                return addr
            except IOError:
                pass
        raise RuntimeError("未找到PCF8591模块")

    def read(self, chn):
        if chn == 0:
            self.bus.write_byte(self.address, 0x40)
        elif chn == 1:
            self.bus.write_byte(self.address, 0x41)
        elif chn == 2:
            self.bus.write_byte(self.address, 0x42)
        elif chn == 3:
            self.bus.write_byte(self.address, 0x43)
        tmp = self.bus.read_byte(self.address)
        Vrl = 5 * tmp / 255        #5V   ad 为8位
        RS = (5 - Vrl) / Vrl * self.RL
        R0 = RS / pow(self.CAL_PPM / 613.9, 1 / -2.074)
        ppm = 613.9 * pow(RS / R0, -2.074)
        return tmp,ppm

    def write(self, val):
        temp = val*(255 - 125) / 255 + 125
        temp = int(temp)
        self.bus.write_byte_data(self.address, 0x40, temp)

if __name__ == "__main__":
    pcf8591 = PCF8591()
    while True:
        tmp,ppm = pcf8591.read(0)
        print(tmp,ppm)
        pcf8591.write(tmp)
        time.sleep(0.5)

执行结果

image

4.数据上报阿里云

4.1 创建产品和设备

参考阿里官方教程,使用个人用户的免费示例试用即可

image

创建产品和对应设备并获取设备证书_物联网应用开发-阿里云帮助中心 (aliyun.com)

image

4.2 定义产品物模型

参考阿里官方教程,定义红外传感器(HC_SR05)、烟雾浓度(MQ2)、人脸识别(face_recognition)、蜂鸣器状态(buzzer)物模型,注意请把英文名称设置为物模型的标识符,这将在代码中用到

物联网应用开发如何为产品定义物模型_物联网应用开发-阿里云帮助中心 (aliyun.com)

举例(标识符最重要):

image

定义完成:
image

4.3 安装依赖程序

传感器的数据传递功能需要安装依赖程序开启。

  1. 在命令窗口执行以下命令,完成程序安装。
cd
sudo apt-get update
sudo apt-get install build-essential python-dev
sudo apt install git
git clone https://gitee.com/outlaw-maniac-zhang-san-1/paho-mqtt-1.6.1.git
cd paho-mqtt-1.6.1
sudo python3 setup.py install

程序解读(run.py)

修改好的程序如下,直接放到树莓派即可使用

  • 导入库

    #!/usr/bin/python3
    import aliLink,mqttd,rpi
    import time,json
    import Adafruit_DHT
    

  • 三元素(iot 后台获取)

    ProductKey = '***'
    DeviceName = 'raspberrypi4-******'
    DeviceSecret = "assef***"
    
  • topic (iot 后台获取)

    POST = '/sys/***/raspberrypi4-***/thing/event/property/post'  # 上报消息到云
    POST_REPLY = '/sys/***/raspberrypi4-***/thing/event/property/post_reply'
    SET = '/sys/***/raspberrypi4-***/thing/service/property/set'  # 订阅云端指令
    

  • 消息回调(云端下发消息的回调函数)

    def on_message(client, userdata, msg):
      # print(msg.payload)
      Msg = json.loads(msg.payload)
      switch = Msg['params']['PowerLed']
      rpi.powerLed(switch)
      print(msg.payload)  # 开关值
    
  • 连接回调(与阿里云建立链接后的回调函数)

    def on_connect(client, userdata, flags, rc):
      pass
    

  • 链接信息

    Server, ClientId, userNmae, Password = aliLink.linkiot(DeviceName, ProductKey, DeviceSecret)
    

  • mqtt 链接

    mqtt = mqttd.MQTT(Server, ClientId, userNmae, Password)
    mqtt.subscribe(SET)   # 订阅服务器下发消息topic
    mqtt.begin(on_message, on_connect)
    

  • 信息获取上报,每 10 秒钟上报一次系统参数

    if __name__ == "__main__":
        # 信息获取上报,每10秒钟上报一次系统参数
        while True:
            time.sleep(1)
            # 构建与云端模型一致的消息结构
            updateMsn = {
                'MQ2':20,
                'HC_SR05':1,
                'buzzer':0,
                'face_recognition': 1
            }
            JsonUpdataMsn = aliLink.Alink(updateMsn)
            print(JsonUpdataMsn)
            mqtt.push(POST,JsonUpdataMsn) # 定时向阿里云IOT推送我们构建好的Alink协议数据
    

运行程序

在命令行窗口执行以下命令。

python3 run.py

数据结果如图所示。 ​image

  • 在 IoT 平台查询上报的数据。

    前往设备详情页,单击物模型数据 > 运行状态,查看新增的机房温度和湿度数据。

    接入后的效果图如下所示。

    image

5.数据备份

log 函数

def log_data(data=None, error=None):
    """
    记录数据到日志文件
    """
    # 确保日志目录存在
    log_dir = 'logs'
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    # 构建日志文件路径
    log_file = os.path.join(log_dir, f"{datetime.now().strftime('%Y-%m-%d')}.log")

    # 打开日志文件并追加数据
    with open(log_file, 'a') as f:
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        if error:
            log_entry = f"{timestamp}: {error}\n"
        else:
            log_entry = f"{timestamp}: {data}\n"
        f.write(log_entry)

结果

image

6.云平台设计

页面设计

使用 flask 设计,平台页面展示如下

fd4fba56e18de82edf0307587a2d9f5

功能说明:

  • 左侧三个图表动态显示,横坐标是时间戳的秒数;纵坐标是各个值
  • 左下方有三个选项,默认状态时,左下方的预警字样由人脸识别、红外传感器来控制;关闭报警时,无论人脸识别和红外传感器的结果如何,都不会报警;开启报警时,无论人脸识别和红外传感器的结果如何,都会报警
  • 右侧是人脸识别的实时画面

代码内容为付费部分,不再放出

公网访问(安装 Cpolar 内网穿透)

参考 https://blog.csdn.net/2303_77146628/article/details/137607549

上面在本地成功部署了 Flask,并局域网访问成功,下面我们安装 Cpolar 内网穿透工具,通过 cpolar 转发本地端口映射的 http 公网地址,我们可以很容易实现远程访问,而无需自己注册域名购买云服务器.下面是安装步骤:cpolar 官网地址: https://www.cpolar.com

使用一键脚本安装命令

curl -L https://www.cpolar.com/static/downloads/install-release-cpolar.sh | sudo bash

向系统添加服务

sudo systemctl enable cpolar

启动 cpolar 服务

sudo systemctl start cpolar

cpolar 安装成功后,在外部浏览器上访问 9200 端口 即:【http://局域网 ip:9200】,使用 cpolar 账号登录(如没有账号,可以点击下面免费注册),登录后即可看到 cpolar web 配置界面,结下来在 web 管理界面配置即可

配置 Flask 的 web 界面公网访问地址

2f6500a5f666d40da50df8fa42f39ee1

点击左侧仪表盘的隧道管理——创建隧道,创建一个 Flask 的 cpolar 公网地址隧道:

01c1532dff4d36b59e4aa5790f4db809

  • 隧道名称:可自定义命名,注意不要与已有的隧道名称重复
  • 协议:选择 http
  • 本地地址:5000 (局域网访问的端口)
  • 域名类型:免费选择随机域名
  • 地区:选择 China Top

点击创建。隧道创建成功后,点击左侧的状态——在线隧道列表,查看所生成的公网访问地址,有两种访问方式,一种是 http 和 https

4f5cdefe772d55b8f678e0728e342843

公网远程访问 Flask 的 web 界面
使用上面的 cpolar https 公网地址在任意设备的浏览器访问,即可成功看到 Flask 的 web 界面,这样一个公网地址且可以远程访问就创建好了,无需自己购买云服务器,即可发布到公网访问。

image

由于以上使用 cpolar 所创建的隧道使用的是随机公网地址,24 小时内会随机变化,不利于长期远程访问。

我一般会使用固定二级子域名,因为我希望将网址发送给开发人员分工合作,小型团队在短时间内就可以使用固定的公网地址完成功能丰富的中小型网站或 Web 服务的实现。它是一个固定、易记的公网地址(例如:Flask.cpolar.cn)因此我们可以为其配置二级子域名,该地址为固定地址,不会随机变化【ps:cpolar.cn 已备案】

注意需要将 cpolar 套餐升级至基础套餐或以上,且每个套餐对应的带宽不一样。【cpolar.cn 已备案】

登录 cpolar 官网,点击左侧的预留,选择保留二级子域名,设置一个二级子域名名称,点击保留,保留成功后复制保留的二级子域名名称

2fba4b3e896591175cf31e24d9ec7e02

保留成功后复制保留成功的二级子域名的名称

返回登录 cpolar web UI 管理界面,点击左侧仪表盘的隧道管理——隧道列表,找到所要配置的隧道,点击右侧的编辑

​​6909461be5758e55a67753059660ce7b​​

修改隧道信息,将保留成功的二级子域名配置到隧道中

6427bcd4ba309c31dcfc91b6139cf5c4

域名类型:选择二级子域名
Sub Domain:填写保留成功的二级子域名
点击更新(注意,点击一次更新即可,不需要重复提交)

更新完成后,打开在线隧道列表,此时可以看到公网地址已经发生变化,地址名称也变成了固定的二级子域名名称的域名

8e1285220d07ee96031aa62a154164cd

最后,我们使用固定的公网地址访问,可以看到访问成功,这样一个固定且永久不变的公网地址就设置好了。

image

使用 HBuilder 将网址打包成 app

使用工具:HBuilder
附上链接:https://www.dcloud.io/hbuilderx.html

教程目的:将封装好的项目网址打包成一个 app,即可实现不需要每次输入网址,点击 app 即可;另外有强制横屏代码以及设置
新手摸索记录,如有错误请友善交流

一、安装 HBuilder
点进以上网址进入下载,下载标准版即可

61707495399835ada9f4a66b34d16cf0

一路点击安装即可,可以自己更改安装地址

二、新建项目
点开 HBuilder 以后按以下路径新建项目

20200401174001754

如果只是打包一个网址的话,可以选择 Wap2App,分别输入项目名称,以及网站地址,如 www.baidu.com,注意此处网址即为 app 默认打开的网址

20200401174122141

三、强制横屏设置
单纯在 manifest 中设置横屏或者竖屏并不会起效,需要加入强制横屏代码,此代码写在 app.js 中

​​20200401174553419​​

代码参照官方文档
代码:

// 锁定屏幕方向
	function lockOrientation(){
		plus.screen.lockOrientation("landscape-primary");
	},

将此代码写在 app 中即可,如图,具体横屏或者竖屏代码见下文 manifest 设置,此处以主屏幕横屏举例

​​20200401174856642​​​​

然后再 manifest 设置中同样更改横屏设置

​​20200401175155414​​

20200401175213950

四、打包生成 app
首先可以在 manifest-图标设置中设置 app 图标,并可以选择自动替换所有用到此图标的地方​20200401175400605

准备进行打包,打包的点击顺序为 发行-原生 app(云打包)

20200401175613907

此处注意,打包需要邮箱注册一下,会自己弹窗的,点击弹窗注册即可

准备打包
iOS 打包
可以选择越狱,并注意去掉广告

20200401175833742

Android 打包
注意去掉广告,按要求更改包名,然后使用老版证书
使用老版证书需要实名认证,点击打包会自己弹窗,点击实名即可,大概一个小时左右即可认证成功
如果等不及可以使用公共测试证书

20200401175915701

当图标没有叉号便表示可以打包

20200401180125587

不能打包举例

​​20200401180155952​​

可以打包以后,点击下方打包即可运行
如果打包过程中出现 “请安装真机插件!” 按照下图安装

20200401180257140

可以打包以后便会出现正在打包的提示

image

打包成功后,点击下载链接即可下载你的网址打包 app 啦!

image

__W2A__xianyu.cpolar.top__20240411225841.apk

7.发送邮件报警

参考 https://blog.csdn.net/weixin_44827418/article/details/111255414

  • 开启 SMTP 服务
    为了实现自动发送邮件的目的,我们需要在邮箱中开启 SMTP 服务:

    20201216120304980

    20201216120413401

    2020121612044872

    20201216120605345

    这点很关键,别忘了去开启 SMTP, 别忘了去开启 SMTP,否则邮件是无法发送成功的 。然后你还需要点击下面生成授权码,这个授权码才是使用 Python 发送邮件时的真正密码。

  • python 发邮件需要掌握两个模块
    smtplib 和 email,这俩模块是 python 自带的,只需 import 即可使用。smtplib 模块主要负责发送邮件,email 模块主要负责构造邮件。smtplib 模块主要负责发送邮件:是一个发送邮件的动作,连接邮箱服务器,登录邮箱,发送邮件(有发件人,收信人,邮件内容)。email 模块主要负责构造邮件:指的是邮箱页面显示的一些构造,如发件人,收件人,主题,正文,附件等。

  • 代码

    def mail_sent():
        # 第三方 SMTP 服务 
        host_server = "smtp.qq.com"  #设置服务器
        sender_qq = "5@qq.com"    #用户名
        pwd = ""   #口令 
        receiver = ["4696035@qq.com" ]#收件人邮箱
        mail_title = '智能家居系统报警邮件' #邮件标题
        mail_content = "您好,当前烟雾浓度过高或有人闯入,请立即处理!" #邮件正文内容
        # 初始化一个邮件主体
        msg = MIMEMultipart()
        msg["Subject"] = Header(mail_title,'utf-8')
        msg["From"] = sender_qq
        # msg["To"] = Header("测试邮箱",'utf-8')
        msg['To'] = ";".join(receiver)
        # 邮件正文内容
        msg.attach(MIMEText(mail_content,'plain','utf-8'))
    
        smtp = SMTP_SSL(host_server) # ssl登录
    
        # login(user,password):
        # user:登录邮箱的用户名。
        # password:登录邮箱的密码,像笔者用的是网易邮箱,网易邮箱一般是网页版,需要用到客户端密码,需要在网页版的网易邮箱中设置授权码,该授权码即为客户端密码。
        smtp.login(sender_qq,pwd)
    
        # sendmail(from_addr,to_addrs,msg,...):
        # from_addr:邮件发送者地址
        # to_addrs:邮件接收者地址。字符串列表['接收地址1','接收地址2','接收地址3',...]或'接收地址'
        # msg:发送消息:邮件内容。一般是msg.as_string():as_string()是将msg(MIMEText对象或者MIMEMultipart对象)变为str。
        smtp.sendmail(sender_qq,receiver,msg.as_string())
    
        # quit():用于结束SMTP会话。
        smtp.quit()
    

8.完整代码

代码为付费内容

树莓派用户名和密码均为 zs

开机后会自动连接名为 G,密码为 goodlife 的 wifi

代码文件目录如下:

image

首先进入人脸识别目录

image

参考第二部分(人脸识别),采集、训练数据,即执行 01 和 02 两个 python 文件,此时将生成 train.xml 文件,用于识别,路径已经填好,无须更改。

然后进入 flask 目录,参考第四部分(阿里云)获取必要的信息,填入数据上报阿里云部分

image

参考第七部分(邮件预警),获取相关信息,填入邮件函数

image

最后,执行 app.py 代码,即可打开 app 看到显示内容,也可从 http://xianyu.cpolar.top/看到相关内容(该公网域名仅保留 10 天)

5 操作
Zhangshanshan 在 2024-04-12 15:38:44 更新了该帖
Zhangshanshan 在 2024-04-12 15:33:28 更新了该帖
Zhangshanshan 在 2024-04-11 23:13:02 更新了该帖
Zhangshanshan 在 2024-04-11 16:37:06 更新了该帖 Zhangshanshan 在 2024-04-09 21:41:17 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...