"Cámara inteligente" basada en Raspberry Pi controlada a través del bot de Telegram

Hola, mi nombre es Iván. Responderé de inmediato a la pregunta principal: ¿por qué comencé a ensamblarme y no tomé una solución lista para usar? En primer lugar, el costo de las soluciones listas para usar: la Raspberry Pi con todos los sensores y una cámara no costó más de $ 30, la mayor parte aún a razón de 60 rublos por dólar. En segundo lugar, casi todas las partes ya estaban allí: mi hermano le dio la Raspberry Pi, la cámara se mantuvo de los tiempos peludos, también había un diodo, lo compré para Arduino y el sensor de movimiento en Aliexpress no costó más de 100 rublos.





La historia del artículo se estructurará de la siguiente manera:





  1. Definamos lo que necesitamos;





  2. Trabajemos con el diodo;





  3. Con sensor de movimiento;





  4. Con cámara (foto);





  5. Con una cámara (video);





  6. Analicemos el trabajo con el bot de Telegram (considere el esqueleto);





  7. Creemos una "Cámara inteligente";





  8. Veamos cómo funciona la Smart Camera;





  9. Identificar cuellos de botella y posibles soluciones.





Entonces vamos





Qué necesitamos

Internet debe estar configurado en la Raspberry, instalado:





  • ffmpeg - para grabar video desde una cámara;





  • Python 3.7.





Python debería tener las siguientes bibliotecas:





  • RPi.GPIO;





  • pygame;





  • telebot.





Y necesita cables - F2F para conectar todo esto.





Trabajando con un diodo

import RPi.GPIO as GPIO
import time

LED_PIN = 3

def setup():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setwarnings(False)
    GPIO.setup(LED_PIN, GPIO.OUT)

def destroy():
    GPIO.output(LED_PIN, GPIO.LOW)
    GPIO.cleanup()

def blink():
    GPIO.output(LED_PIN, GPIO.HIGH)
    time.sleep(1)
    GPIO.output(LED_PIN, GPIO.LOW)

def main():
    setup()
    blink()
    destroy()

if __name__ == '__main__':
    main()
      
      



Raspberry, . , Raspberry, , , . . - blink , 1 . main . .





Raspberry , , - :





- delay sensitivity , :





, , . "", , :





, - (16 ).





import RPi.GPIO as GPIO
import time

PIR_PIN = 11

def setup():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setwarnings(False)
    GPIO.setup(PIR_PIN, GPIO.IN)

def destroy():
    GPIO.cleanup()

def sensorJob():
    while True:
        i = GPIO.input(PIR_PIN)
        
        print("PIR value: " + str(i))
        
        time.sleep(0.1)

def main():
    setup()
    sensorJob()
    destroy()

if __name__ == '__main__':
    main()
      
      



. , . - sensorJob , .





()

"" . USB-, , . , . 1 /dev/video0. , .





from datetime import datetime
import pygame
import pygame.camera

pygame.init()
pygame.camera.init()
pygame.camera.list_cameras() 

cam = pygame.camera.Camera("/dev/video0", (640,426))

def saveCapture():
    filename = datetime.now().strftime('%d-%m-%Y %H:%M:%S') + '.jpg'
    
    cam.start()
    pygame.image.save(cam.get_image(), filename)
    cam.stop()

def main():
    setup()
    saveCapture()
    destroy()

if __name__ == '__main__':
    main()
      
      



. , , , , . saveCapture , start , get_image() , pygame.image.save, stop. pygame, ffmpeg , .





()

:





ffmpeg -f v4l2 -framerate 25 -video_size 640x426 -i /dev/video0 -t 5 -c copy <filename>
      
      



- v4l2, , , -c copy, , , preview Telegram , . , Telegram, .





Telegram-

Telegram- , BotFather Telegram, , . , InlineKeyboard Telegram-, , . , ID , ( ) .





from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
import telebot

TOKEN = '99999999999:xxxxxxxxxxxxxxxxxx'
ADMIN_USER_ID = 999999999

bot = telebot.TeleBot(TOKEN)

@bot.message_handler(commands=['start'])
def start(message):    
    telegram_user = message.from_user
    
    if telegram_user.id != ADMIN_USER_ID:
        bot.send_message(message.chat.id, text="Hello. My name is James Brown. What do i do for you?")
        
        return
           
    keyboard = [
        [
            InlineKeyboardButton("Send capture", callback_data='sendCapture'),
            InlineKeyboardButton("Send video", callback_data='sendVideo')
        ],
    ]

    bot.send_message(chat_id=message.chat.id,
                         text="Supported commands:",
                         reply_markup=InlineKeyboardMarkup(keyboard))

def sendCapture(chat_id):
    bot.send_photo(chat_id, photo=open('<filename>', 'rb'))

def sendVideo(chat_id):
    bot.send_video(chat_id, open('<filename>', 'rb'))

@bot.callback_query_handler(func=lambda call: True)
def button(call):
    globals()[call.data](call.message.chat.id)

def main():
    setup()
    bot.polling(none_stop=False, interval=5, timeout=20)
    destroy()

if __name__ == '__main__':
    main()
      
      



InlineKeyboard, Telegram-. TOKEN BotFather. ADMIN ID. start. start USER ID , , , InlineKeyboard . . sendCapture sendVideo Telegram-. , InlineKeyboard, , , . main bot.pooling, . Raspberry , -. - interval = 5. .





" "

GPIO , USB.





:





, " " Telegram-.





from datetime import datetime
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
import telebot
import logging
import pygame
import pygame.camera
import RPi.GPIO as GPIO
import threading
import time
import os

TOKEN = '99999999999:xxxxxxxxxxxxxxxxxxxxxx'
ADMIN_USER_ID = 999999999999
LED_PIN = 3
PIR_PIN = 11
VIDEO_FILE_FORMAT = '.mkv'

# Enable Logging
logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        level=logging.INFO)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

isSensorEnabled = False
isMuteNotifications = False

last_chat_id = -1
keyboard = []

pygame.init()
pygame.camera.init()
pygame.camera.list_cameras() 

cam = pygame.camera.Camera("/dev/video0", (640,426))
bot = telebot.TeleBot(TOKEN)

def setup():
    GPIO.setmode(GPIO.BOARD) 
    GPIO.setwarnings(False)
    GPIO.setup(LED_PIN, GPIO.OUT)
    GPIO.setup(PIR_PIN, GPIO.IN)

def destroy():
    GPIO.output(LED_PIN, GPIO.LOW)
    GPIO.cleanup() 

def log_params(method_name, message):
    logger.debug("Method: %s\nFrom: %s\nchat_id: %d\nText: %s" %
                (method_name,
                 message.from_user,
                 message.chat.id,
                 message.text))

@bot.message_handler(commands=['start'])
def start(message):
    global keyboard
    
    log_params('start', message)
    
    telegram_user = message.from_user
    
    if telegram_user.id != ADMIN_USER_ID:
        bot.send_message(message.chat.id, text="Hello. My name is James Brown. What do i do for you?")
        
        return
           
    keyboard = [
        [InlineKeyboardButton("Start sensor", callback_data='start_sensor')],
        [
            InlineKeyboardButton("Get capture", callback_data='get_capture'),
            InlineKeyboardButton("Get video", callback_data='get_video')
        ],
    ]

    bot.send_message(chat_id=message.chat.id,
                         text="Supported commands:",
                         reply_markup=InlineKeyboardMarkup(keyboard))

def sendCapture(chat_id):
    filename = datetime.now().strftime('%d-%m-%Y %H:%M:%S') + '.jpg'
    
    if (os.path.exists(filename)):
        bot.send_photo(chat_id, photo=open(filename, 'rb'))
    else:
        cam.start()
        pygame.image.save(cam.get_image(), filename)
        cam.stop()

        bot.send_photo(chat_id, photo=open(filename, 'rb'))

def get_capture(chat_id):
    sendCapture(chat_id)
    bot.send_message(chat_id=chat_id,
                     text="Supported commands:",
                     reply_markup=InlineKeyboardMarkup(keyboard))

def sendVideo(chat_id):
    filename = sorted(list(filter(lambda x: x.endswith(VIDEO_FILE_FORMAT), os.listdir())))[-1]

    bot.send_video(chat_id, open(filename, 'rb'))

def captureVideo():
    filename = datetime.now().strftime('%d-%m-%Y %H:%M:%S') + VIDEO_FILE_FORMAT
    
    os.system("ffmpeg -f v4l2 -framerate 25 -video_size 640x426 -i /dev/video0 -t 5 -c copy \"" + filename + "\"")
    
    return filename

def get_video(chat_id):
    bot.send_message(chat_id=chat_id,
                     text="Capturing video..")
        
    filename = captureVideo()

    bot.send_message(chat_id=chat_id,
                     text="Sending video..")
    bot.send_video(chat_id, open(filename, 'rb'))
    bot.send_message(chat_id=chat_id,
                     text="Supported commands:",
                     reply_markup=InlineKeyboardMarkup(keyboard))

def sensorJob():
    global isSensorEnabled
    global keyboard
    
    isRecording = False
    
    while isSensorEnabled:
        i = GPIO.input(PIR_PIN)
        
        GPIO.output(LED_PIN, i)
        
        if (i == 1 and not isRecording):
            isRecording = True
            
            if (not isMuteNotifications):
                sendCapture(last_chat_id)
        
        if (isRecording):
            captureVideo()
        
        if (i == 0 and isRecording):
            if (not isMuteNotifications):
                sendVideo(last_chat_id)
            
            isRecording = False
        
        time.sleep(0.1)
        
    if (isRecording):
        sendVideo(last_chat_id)
    
    keyboard = [
        [InlineKeyboardButton("Start sensor", callback_data='start_sensor')],
        [
            InlineKeyboardButton("Get capture", callback_data='get_capture'),
            InlineKeyboardButton("Get video", callback_data='get_video')
        ],
    ]

    bot.send_message(chat_id=last_chat_id,
                     text="Sensor stopped")
    bot.send_message(chat_id=last_chat_id,
                         text="Supported commands:",
                         reply_markup=InlineKeyboardMarkup(keyboard))

def start_sensor(chat_id):
    global keyboard
    global isSensorEnabled
    global last_chat_id
    
    last_chat_id = chat_id
    isSensorEnabled = True
    
    threading.Thread(target=sensorJob).start()
    
    keyboard = [
        [
            InlineKeyboardButton("Stop sensor", callback_data='stop_sensor'),
            InlineKeyboardButton("Mute notifications", callback_data='mute_notifications')
        ]
    ]

    bot.send_message(chat_id=chat_id,
                         text="Sensor started")
    bot.send_message(chat_id=chat_id,
                         text="Supported commands:",
                         reply_markup=InlineKeyboardMarkup(keyboard))
    
def stop_sensor(chat_id):
    global keyboard
    global last_chat_id
    
    last_chat_id = -1
    isSensorEnabled = False
    
    GPIO.output(LED_PIN, GPIO.LOW)
    
    keyboard = [
        [InlineKeyboardButton("Start sensor", callback_data='start_sensor')],
        [
            InlineKeyboardButton("Get capture", callback_data='get_capture'),
            InlineKeyboardButton("Get video", callback_data='get_video')
        ],
    ]

    bot.send_message(chat_id=chat_id,
                         text="Sensor stop requested")

def mute_notifications(chat_id):
    global keyboard
    
    isMuteNotifications = True
    
    keyboard = [
        [
            InlineKeyboardButton("Stop sensor", callback_data='stop_sensor'),
            InlineKeyboardButton("Unmute notifications", callback_data='unmute_notifications')
        ]
    ]

    bot.send_message(chat_id=chat_id,
                         text="Notifications muted")
    bot.send_message(chat_id=chat_id,
                         text="Supported commands:",
                         reply_markup=InlineKeyboardMarkup(keyboard))

def unmute_notifications(chat_id):
    global keyboard
    
    isMuteNotifications = False
    
    keyboard = [
        [
            InlineKeyboardButton("Stop sensor", callback_data='stop_sensor'),
            InlineKeyboardButton("Mute notifications", callback_data='mute_notifications')
        ]
    ]

    bot.send_message(chat_id=chat_id,
                         text="Notifications unmuted")
    bot.send_message(chat_id=chat_id,
                         text="Supported commands:",
                         reply_markup=InlineKeyboardMarkup(keyboard))

@bot.callback_query_handler(func=lambda call: True)
def button(call):
    globals()[call.data](call.message.chat.id)

def main():
    setup()
    bot.polling(none_stop=False, interval=5, timeout=20)
    destroy()

if __name__ == '__main__':
    main()
      
      



, . . logging " ", . . chat_id, - . , . pygame Telegram-. setup destroy , . start user_id, - , . sendCapture filename, chat_id. get_capture . sendVideo . captureVideo filename ffmpeg. get_video .





sensorJob: , . - . sensorJob - last_chat_id. start_sensor hat_id, , sensorJob . stop_sensor last_chat_id, , . mute/unmute_notifications . " " . " " .





" "

- , 5 . bot.pooling main, interval. -, , , , - "Connection timeout" Telegram- - .





  1. , ;





  2. Python , , pyffmpeg, ;





  3. , ;





  4. Disponibilidad de Internet rápido para una recepción más rápida de videos actualizados.








All Articles