Skip to content

Record video when alarm is ringing

Thomas T. Jarløv edited this page Mar 6, 2019 · 2 revisions

The tutorial below uses an external Raspberry Pi - not the one where NimHA is running.

Main features

  • Power to the camera is disabled when it's not recording to enhance privacy
  • When the alarm is ringing, the camera will record and save to user specified folder

Requirements

  • mosquitto_sub
  • ffmpeg
  • USB camera (optional with microphone)

Identify inputs

You need to find the input for both video and audio (optional).

Video

ls -ltrh /dev/video*

The result could be /dev/video0 if you only have 1 camera device.

Audio

arecord -l

Output

**** List of CAPTURE Hardware Devices ****
card 1: CameraB409241 [USB Camera-B4.09.24.1], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

Grab the identifier, in this case CameraB409241

USB power control

To enhance privacy you can turn of the power supply when it's not used.

USB port

Firstly you have to find your USB port - this could 1-1.4. But it is also possible to turn off all USB ports (and ethernet) when just defining 1-1.

for device in $(ls /sys/bus/usb/devices/*/product); do echo $device;cat $device;done

Output

/sys/bus/usb/devices/1-1.4/product
USB Camera-B4.09.24.1
/sys/bus/usb/devices/usb1/product
DWC OTG Controller

There are 2 easy options for turning the USB on and off:

  1. Add the specific commands to the user in visudo
  2. Creating scripts and run them as root

Option 1: Allow normal user through visudo

Access visudo:

sudo visudo

Append a line, and change the username to your user. The example below uses the standard RPi username, pi. You can add further options such as /sbin/reboot.

pi ALL= NOPASSWD: /usr/bin/tee /sys/bus/usb/drivers/usb/unbind, /usr/bin/tee /sys/bus/usb/drivers/usb/bind

Option 2: On/Off scripts

mkdir /home/pi/nimha/usbcontrol

Off script

nano /home/pi/nimha/usbcontrol/usboff.sh
# insert
echo '1-1' |sudo tee /sys/bus/usb/drivers/usb/unbind
# run
chmod +x /home/pi/nimha/usbcontrol/usboff.sh
sudo chown root:root /home/pi/nimha/usbcontrol/usboff.sh

On script

nano /home/pi/nimha/usbcontrol/usbon.sh
# insert
echo '1-1' |sudo tee /sys/bus/usb/drivers/usb/bind
# run
chmod +x /home/pi/nimha/usbcontrol/usbon.sh
sudo chown root:root /home/pi/nimha/usbcontrol/usbon.sh

FFMPEG command

The ffmpeg command needs to be adjusted to your input video, input audio and output folder.

Adjust the following paramaters:

ffmpeg command:

ffmpeg = startProcess("ffmpeg -timelimit 900 -f video4linux2 -framerate 25 -video_size 640x480 -i /dev/video0 -f alsa -i plughw:CameraB409241,0 -ar 22050 -ab 64k -strict experimental -acodec aac -vcodec mpeg4 -vb 20M -y /mnt/nimha/media/" & filename & ".mp4", options = {poEvalCommand})

Start the camera

You have 2 options. Option 1 is optimal, if the camera is attached to device running NimHA. Option 2 should be used, if the camera is connected to another device (e.g. a RPi in your garden).

Start ffmpeg within NimHA

In Nimha access the menu OS from the sidebar. Add 3 templates:

  1. /home/pi/nimha/usbcontrol/usboff.sh
  2. /home/pi/nimha/usbcontrol/usbon.sh
  3. [you ffmpeg command from above]

Now assign these OS-templates to your needs, e.g. within the Alarm page, where you run the usboff.sh when the alarm is disabled.

Nim program

This helper program needs to executed on the RPi connected with the camera. You should make it is as a service and enable it on boot. When starting the program through systemctl, it can be tricky due to the need for root access to turn the USB on and off. Either edit sudo visudo [option 1] or run the service file with systemctl with user as root (take care!!) [option 2].

import asyncdispatch
import json
import os
import osproc
import strutils
import streams
import times


var ffmpeg: Process
var usbOn = true

template jn*(json: JsonNode, data: string): string =
  ## Avoid error in parsing JSON
  try:
    json[data].getStr()
  except:
    ""


proc mqttParser(payload: string) {.async.} =
  ## Parse the raw output from Mosquitto sub
  ## and start action

  let topicName = payload.split(" ")[0]
  let message   = parseJson(payload.replace(topicName & " ", ""))
  
  let status = jn(message, "status")

  if status == "ringing":
    if not usbOn:
      discard execCmd("/home/pi/nimha/usbcontrol/usbon.sh")
      usbOn = true
      sleep(6000) # Waiting time for camera to initialize
    let filename = multiReplace($getTime(), [(":", "-"), ("+", "_"), ("T", "_")])
    ffmpeg = startProcess("ffmpeg -timelimit 900 -f video4linux2 -framerate 25 -video_size 640x480 -i /dev/video1 -f alsa -i plughw:CameraB409241,0 -ar 22050 -ab 64k -strict experimental -acodec aac -vcodec mpeg4 -vb 20M -y /mnt/nimha/media/" & filename & ".mp4", options = {poEvalCommand})

  elif status in ["disarmed", "armAway", "armHome"]:
    if usbOn:
      discard execCmd("/home/pi/nimha/usbcontrol/usboff.sh")
      usbOn = off



let s_mqttPathSub   = "/usr/bin/mosquitto_sub"
let s_mqttPassword  = "secretPassword"
let s_clientName    = "secretUsername"
let s_mqttIp        = "ip"
let s_mqttPort      = "8883"
let s_topic         = "alarminfo"

proc mosquittoSub() =
  var mqttProcess = startProcess(s_mqttPathSub & " -v -t " & s_topic & " -u " & s_clientName & " -P " & s_mqttPassword & " -h " & s_mqttIp & " -p " & s_mqttPort, options = {poEvalCommand})

  while running(mqttProcess):
    asyncCheck mqttParser(readLine(outputStream(mqttProcess)))


mosquittoSub()
quit()