使用esp32 cam + SR602人体感应模块制作一个小型的监控

news2024/10/6 10:32:10

需求:

做一个小型的监控,类似电子猫眼,监测到人之后,取一张图 然后发送到自己的邮箱。

架构:

1.sr602 传感器监测到人

2. esp32 cam 取图 并通过mqtt协议传到远端服务器

3, 服务器利用python 搭建一个mqtt客户端,订阅到数据后 将图片保存,并发送到指定邮箱

 硬件连接:

结构设计:

 

软件:

服务端代码



#mqtt客户端
import paho.mqtt.client as mqtt
import logging
import os
import email_send

APPEAR_TOPIC = "APPEAR_TOPIC"
DETAIL_TOPIC = "DETAIL_TOPIC"
mqtt_server = 'xxxxxxxxxx'
image_path="images"

image_index=0

def on_connect(client, userdata, flags, rc):
    logging.info('连接到MQTT服务器 '+str(rc))

def on_message(client, userdata, msg):
    print(msg.topic + " " + str(msg.payload))
    global image_index
    
    if msg.topic ==APPEAR_TOPIC:
        if image_index!=0:
            #发送全部图片
            image_index=0
            email_send.send_email(image_path)
            logging.info('发送到邮箱完毕')
    
    if msg.topic == DETAIL_TOPIC:
        logging.info('收到图片,准备保存到本地')
        save_location = "images/"+str(image_index)+".jpg" 
        f = open(save_location, 'wb') 
        data = msg.payload 
        f.write(data) 
        f.close()
        image_index+=1
        logging.info('图片保存到本地完毕')
    
def run():
    logging.basicConfig(level=logging.INFO)
    client = mqtt.Client(protocol=3)
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect(host=mqtt_server,port=1883,keepalive=60,bind_address="")
    client.subscribe(APPEAR_TOPIC)
    client.subscribe(DETAIL_TOPIC)
    
    logging.info('启动 MQTT客户端... \n')
    try:
        client.loop_forever()
    except KeyboardInterrupt:
        pass
    logging.info('停止 MQTT 客户端\n')
    
if __name__ =='__main__':
    run()


#邮件发送

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from datetime import datetime
import logging
import os
import shutil

def send_email(img_path=""):
    # 设置发件人、收件人和邮件主题
    from_email = "xxxx"
    to_email = "xxxx"
    subject = "注意,有人出现"
    
        
    logging.info('设置收发地址...')
    
    # 创建邮件对象
    msg = MIMEMultipart()
    msg['From'] = from_email
    msg['To'] = to_email
    msg['Subject'] = subject

    # 添加邮件正文
    body = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    msg.attach(MIMEText(body, 'plain'))
    logging.info('添加正文...')
    
    for root,dirs,files in os.walk(img_path):
        for file in files:
            if file.endswith(".jpg"):
                img = os.path.join(root,file)
                # 添加附件
                attachment_filename = img
                attachment_path = img
                attachment = open(attachment_path, "rb")

                part = MIMEBase('application', 'octet-stream')
                part.set_payload(attachment.read())
                encoders.encode_base64(part)
                part.add_header('Content-Disposition', f'attachment; filename= {attachment_filename}')
                msg.attach(part)          
                  
    # 连接到SMTP服务器
    smtp_server = "smtp.yeah.net"  # 修改为你的SMTP服务器
    smtp_port = 465
    smtp_username = "xxxx"  # 修改为你的邮箱地址
    smtp_password = "xxxx"  # 修改为你的邮箱密码

    server = smtplib.SMTP_SSL(smtp_server,smtp_port)
    logging.info('登录邮件服务器...')
    server.login(smtp_username, smtp_password)
    logging.info('发送邮件')

    # 发送邮件
    server.sendmail(from_email, to_email, msg.as_string())

    # 关闭连接
    server.quit()
    
    shutil.rmtree(img_path)
    # 重新创建空文件夹
    os.makedirs(img_path)
    
if __name__ =='__main__':
    logging.basicConfig(level=logging.INFO)
    send_email("images",True)


客户端代码

#include "esp_camera.h"
#include <WiFi.h>
#include <PubSubClient.h>

#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"

//WIFI 用户名 密码
//const char* ssid = "xxxx";
//const char* password = "xxxx";
const char* ssid = "xxxx";
const char* password = "xxxx";

//MQTT 服务器地址
const char* mqttServer = "xxxx";
uint16_t mqttPort = 1883;
const char* APPEAR_TOPIC = "APPEAR_TOPIC";
const char* DETAIL_TOPIC = "DETAIL_TOPIC";

//检测是否有人
uint8_t FOUND_PEOPLE_PIN = 14;

//人出现的次数
uint8_t found_count = 0;

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  //调试串口
  Serial.begin(115200);
  Serial.setDebugOutput(true);

  //人体红外检测引脚
  pinMode(FOUND_PEOPLE_PIN, INPUT);

  //配置相机
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sccb_sda = SIOD_GPIO_NUM;
  config.pin_sccb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;
  config.frame_size = FRAMESIZE_VGA;
  config.jpeg_quality = 10;
  config.fb_count = 1;

  // 相机初始化
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }
  sensor_t* s = esp_camera_sensor_get();
  s->set_vflip(s, 1);
  s->set_brightness(s, 2);
  s->set_saturation(s, -2);
  s->set_framesize(s, FRAMESIZE_VGA);

  //连接 WIFI
  WiFi.begin(ssid, password);
  WiFi.setSleep(false);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("Connecting to WIFI ...");
    delay(500);
  }
  Serial.println("WiFi connected");

  //连接mqtt 服务器。 640*480 图片大小
  client.setBufferSize(50 * 1024);
  client.setServer(mqttServer, mqttPort);
  while (!client.connected()) {
    if (client.connect("app")) {
      Serial.println("Connected to MQTT");
    } else {
      Serial.println("Failed to connect to MQTT server, ");
      Serial.print(client.state());
      delay(1000);
    }
  }
  Serial.print(WiFi.localIP());
}

//上传图片
void take_send_photo() {
  Serial.println("Taking picture...");
  camera_fb_t* fb = NULL;

  fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }

  if (client.beginPublish(DETAIL_TOPIC, fb->len + sizeof(long), false)) {
    unsigned long m = millis();
    int noBytes;
    noBytes = client.write(fb->buf, fb->len);
    noBytes = client.write((byte*)&m, sizeof(long));
    if (!client.endPublish()) {
      Serial.println("\nupload image error.");
    }
  }

  esp_camera_fb_return(fb);
  Serial.println("upload image ok.");
}

void loop() {
  //检测到有人后 拍照并上传
  if (digitalRead(FOUND_PEOPLE_PIN) == 1) {
    take_send_photo();
    found_count += 1;
    delay(2000);
  } else {
    found_count = 0;
  }

  if (found_count >= 3) {
    found_count = 0;
    client.publish(APPEAR_TOPIC, "", 0);
  }

  client.loop();
}

注意事项:

1,接收图片的邮箱,需要开通smtp服务。

2,mqtt发送图片,不需要转成base64格式,但是需要重新设置下缓存大小。

3,这个玩意 发热很严重,还没测试 两节18650电池能用多久。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1436053.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

dump分析方法

一、关于dump 1、什么是dump 在计算机领域中&#xff0c;术语“dump”通常用来指代将某种数据以某种格式进行转储或导出的过程。这个术语可以用于多种不同的上下文&#xff0c;下面是一些常见的情况&#xff1a; 内存转储&#xff08;Memory Dump&#xff09;&#xff1a;在…

GRUB2 致力于 TPM2 自动磁盘解锁、TrenchBoot 等

Oracle 的 Daniel Kiper 提供了当前 GRUB 引导加载程序开发活动的状态更新、未来展望以及预计在 11 月份发布下一个版本的计划。 Kiper 本周末出席了在布鲁塞尔举行的 FOSDEM 2024&#xff0c;再次提供有关 GRUB 的状态更新。 早在 12 月&#xff0c;GRUB 2.12 就发布了&#…

09_树莓派_树莓派外设板_GPIO_按键的中断与消抖

目录 1.树莓派外设集成板总体介绍 2.第一部分 按键矩阵 GPIO_按键与中断 3.实现效果 1.树莓派外设集成板总体介绍 1&#xff09;前言&#xff1a;这是一块为了验证树莓派【兼容树莓派多个型号】的40pins的外设接口的外接板&#xff0c;告别复杂的面包板外设搭建。【欢迎各位…

Allegro如何把Symbols,shapes,vias,Clines,Cline segs等多种元素一起移动

Allegro如何把Symbols,shapes,vias,Clines,Cline segs等多种元素一起移动 在用Allegro进行PCB设计时,有时候需要同时移动某个区域的所有元素,如:Symbols,shapes,vias,Clines,Cline segs等元素。那么如何操作呢? 首先就是把Symbols,shapes,vias,Clines,Cline …

速度规划:s形曲线------pencv c++绘图(1)

理论篇 代码篇&#xff1a; opencv环境配置 注意&#xff01;注意&#xff01;注意&#xff01; 配置结束后运行环境切换为如下再运行&#xff1a; #include <iostream> #include <cmath>#include <opencv2/opencv.hpp>using namespace std;double a_max…

2023年03月CCF-GESP编程能力等级认证C++编程二级真题解析

一、单选题(每题2分,共30分) 第1题 以下存储器中的数据不会受到附近强磁场干扰的是( )。 A.硬盘 B.U盘 C.内存 D.光盘 答案:D 第2题 下列流程图,属于计算机的哪种程序结构?( )。 A.顺序结构 B.循环结构 C.分支结构 D.数据结构 答案:C 第3题 下列关…

IT行业针对大数据的安全文件传输的重要性

在数字化浪潮的推动下&#xff0c;数据已成为现代社会的宝贵资源。特别是大数据&#xff0c;以其海量、多样化、高速增长和低价值密度的特性&#xff0c;对信息技术&#xff08;IT&#xff09;行业产生了深远影响。大数据的应用不仅推动了云计算、物联网和人工智能等领域的发展…

算法每日一题: 使用循环数组所有元素相等的最少秒数 | 哈希

大家好&#xff0c;我是星恒&#xff0c;今天给大家带来的是一道需要感觉规律的题目&#xff0c;只要读懂题目中的规律&#xff0c;就可以做出来了 这道题用到了哈希&#xff0c;还有一个关键点比较类似循环队列 题目&#xff1a;leetcode 2808 给你一个下标从 0 开始长度为 n…

C# Onnx GroundingDINO 开放世界目标检测

目录 介绍 效果 模型信息 项目 代码 下载 介绍 地址&#xff1a;https://github.com/IDEA-Research/GroundingDINO Official implementation of the paper "Grounding DINO: Marrying DINO with Grounded Pre-Training for Open-Set Object Detection" 效果 …

STM32之USART

概述 串口通信&#xff0c;通用异步收发传输器&#xff08;Universal Asynchronous Receiver/Transmitter &#xff09;&#xff0c;简称UART&#xff1b;而USART&#xff08;Universal Synchronous/Asynchronous Receiver/Transmitter&#xff09;通用同步收发传输器。 USAR…

机器学习 | 探索朴素贝叶斯算法的应用

朴素贝叶斯算法是一种基于贝叶斯定理和特征条件独立假设的分类算法。它被广泛应用于文本分类、垃圾邮件过滤、情感分析等领域&#xff0c;并且在实际应用中表现出色。 朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法&#xff1a; 1&#xff09;对于给定的待分类项r…

【计算机网络基础篇】学习笔记系列之一《TCP/IP 网络模型》

文章目录 1、问题提出2&#xff0c;网络协议是分层的3&#xff0c;应用层4&#xff0c;传输层5&#xff0c;网络层6&#xff0c;网络接口层7&#xff0c;总结 1、问题提出 为什么要有 TCP/IP 网络模型&#xff1f; 不同设备上的进程间通信需要通过一套通用的网络协议进行网络通…

three.js 向量方向(归一化.normalize)

效果&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div><div><p><el-button type"primary…

Springboot启动出现Waiting for changelog lock...问题

今天在开发的时候&#xff0c;Springboot启动的时候出现Waiting for changelog lock…问题. 问题原因&#xff1a;该问题就是发生了数据库的死锁问题&#xff0c;可能是由于一个杀死的liquibase进程没有释放它对DATABASECHANGELOGLOCK表的锁定&#xff0c;导致服务启动失败&…

Blender_查看版本

Blender_查看版本 烦人的烦恼&#xff0c;没找见哪儿可以查看版本&#xff1f; 算是个隐蔽的角落&#xff01;

Rust-获取随机数练习案例

文章目录 前言一、取官网示例猜数字游戏玩一玩cargo checkTOML文件 二、完整代码总结 前言 Rust学习系列-获取随机数练习案例&#xff0c;基于cargo 进行案例练习&#xff0c;过程中会使用cargo check&#xff1b; cargo run&#xff1b;等命名&#xff0c;同时了解基础的let …

【Java EE】----Bean的作用域和生命周期

1.Bean的作用域 定义&#xff1a;Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种⾏为模式&#xff0c;⽐如 singleton 单例作⽤域&#xff0c;就 表示 Bean 在整个 Spring 中只有⼀份 &#xff08;产生的原因&#xff0c;Bean 默认情况下是单例状态&#xff08;singleton&…

2024数据分析管理、数字经济与教育国际学术会议(ICDAMDEE2024)

会议简介 2024年数据分析管理、数字经济和教育国际学术会议&#xff08;ICDAMDEE 2024&#xff09;将在武汉举行。会议不仅展示了来自世界各地的研究专家围绕数据分析管理、数字经济和教育的最新科研成果&#xff0c;还为来自不同地区的代表们提供了面对面的交流意见和实验经验…

编程实例分享,宠物诊所电子处方怎么开,兽医电子处方模板电子版操作教程

编程实例分享&#xff0c;宠物诊所电子处方怎么开&#xff0c;兽医电子处方模板电子版操作教程 一、前言 以下操作教程以 佳易王兽医电子处方软件V16.0为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、在系统 设置里可以设置打印参数&#x…

【Docker】了解Docker Desktop桌面应用程序,TA是如何管理和运行Docker容器(2)

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Docker容器》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…