-
Notifications
You must be signed in to change notification settings - Fork 0
Building Pi MotionEye
- Install latest version of Raspberry Pi (this guide uses Debian Buster)
- USB Camera and/or camera that uses the dedicated CSI interface
- USB Cellular modem supporting US LTE-FDD bands 2,4 etc
Setup remote headless wifi, ssh, and vnc
touch /Volumes/boot/ssh
cat << EOF | sudo tee /Volumes/boot/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=US
network={
ssid="pants!"
psk="Pants!Spoon!"
}
EOF
ssh pi@raspberry.local
sudo apt install -y screen jq
sudo apt update
sudo apt full-upgrade -y
sudo reboot
Setup passwordless logins
ssh-copy-id pi@raspberrypi.local
Setup the various services for networking, including zero-tier, cellular modems, and wifi AP.
nmcli radio wifi
nmcli dev wifi list
nmcli device wifi connect 'SSID' password 'PASSWORD' ifname wlan0
nmcli connection add type wifi con-name 'pants-wlan0' ifname wlan0 ssid 'pants!'
# use nmtui to set the password
nmcli con up id 'pants-wlan0' ifname wlan0
nmcli connection add type wifi con-name "XFINITY-wlan1" ifname wlan1 ssid "XFINITY" -- \
wifi-sec.key-mgmt wpa-eap 802-1x.eap ttls 802-1x.phase2-auth pap \
802-1x.identity 'username' 802-1x.password 'password'
nmcli connection edit "XFINITY"
nmcli con show
nmcli con del id 'pants!'
nmcli con up id "XFINITY" ifname wlan1
ls -l /etc/NetworkManager/system-connections/
nmcli general logging level DEBUG
# For armbian follow https://forum.armbian.com/topic/9698-4g-usb-modem-with-armbian/
# Bit buggy on armbian, had to unplug/replug in different USB port to get it working
# To find primary port, e.g. ttyUSB3
mmcli --list-modems
mmcli --modem 1
sudo nmcli connection edit type gsm con-name "GoogleFi"
# 'set gsm.apn h2g2' then 'save'
nmcli connection add type gsm ifname ttyUSB3 con-name googlefi apn h2g2
nmcli connection up id googlefi
nmcli r wwan on
Removing systemd-networkd:
sudo systemctl disable systemd-networkd.service
sudo systemctl mask systemd-networkd.service
sudo systemctl stop systemd-networkd.service
sudo apt-get install network-manager
systemctl stop NetworkManager
systemctl start NetworkManager
systemctl restart systemd-networkd.service
Removing dhcpd from Raspberry Pi OS
sudo echo "interface wlan0" >> /etc/dhcpcd.conf
sudo echo "nohook wpa_supplicant" >> /etc/dhcpcd.conf
sudo echo "interface wlan1ifconfi" >> /etc/dhcpcd.conf
sudo echo "nohook wpa_supplicant" >> /etc/dhcpcd.conf
systemctl restart dhcpcd.service
If you really want to still keep systemd-network
nmcli dev status
nano /etc/NetworkManager/NetworkManager.conf
[keyfile]
unmanaged-devices=interface-name:wlan*
systemctl stop NetworkManager
systemctl start NetworkManager
systemctl restart systemd-networkd.service
Install and add the host name "pants-motioneye" to the configuration files.
sudo apt install -y avahi-daemon avahi-utils
sudo nano /etc/hosts /etc/hostname /etc/avahi/avahi-daemon.conf
sudo reboot
Verify by running avahi-browse -a
and ssh pi@pants-motioneye
curl -s https://install.zerotier.com | sudo bash
sudo zerotier-cli join d3ecf5726d81bd8e
Install and authorize new node in my.zero-tier.com
The new node should have a manual ip address, bridging enabled, and a manual route to the internal network we will be using as an access point.
Multipath support
echo '{"settings": {"multipathMode": 0}}' > /var/lib/zerotier-one/networks.d/local.conf
Verify by connecting to the pi with the zero-tier address
Simply plugging it in should spin up a new interface, usb0.
Verify running lsusb
and ip link
Example /etc/NetworkManager/system-connections/googlefi.nmconnection
for Huawai & Google Fi
[connection]
id=googlefi
uuid=6dd16a78-dcdb-46c9-8378-22ff19fe8dda
type=gsm
interface-name=ttyUSB3
permissions=
[gsm]
apn=h2g2
[ipv4]
dns-search=
method=auto
[ipv6]
addr-gen-mode=stable-privacy
dns-search=
method=auto
[proxy]
Setting up Google Fi on the latest version of Ubuntu running on RPI4:
# mmcli --modem 0
-----------------------------
General | dbus path: /org/freedesktop/ModemManager1/Modem/0
| device id: 98fd7ccfee3a853a21015bc5099ba02dc1721cef
-----------------------------
Hardware | manufacturer: Huawei Technologies Co., Ltd.
| model: E397
| firmware revision: 11.337.35.00.644
| supported: gsm-umts, lte
| current: gsm-umts, lte
| equipment id: 990000791635693
-----------------------------
System | device: /sys/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.1
| drivers: option1
| plugin: huawei
| primary port: ttyUSB3
| ports: ttyUSB0 (at), ttyUSB2 (qcdm), ttyUSB3 (at)
-----------------------------
Status | unlock retries: sim-pin (3), sim-puk (10), sim-pin2 (1), sim-puk2 (10)
| state: searching
| power state: on
| signal quality: 0% (cached)
-----------------------------
Modes | supported: allowed: 4g; preferred: none
| allowed: 2g; preferred: none
| allowed: 2g, 4g; preferred: none
| current: allowed: 2g, 4g; preferred: none
-----------------------------
IP | supported: ipv4, ipv6, ipv4v6
-----------------------------
3GPP | imei: 990000791635693
| registration: searching
-----------------------------
SIM | dbus path: /org/freedesktop/ModemManager1/SIM/0
# mmcli --modem 0 --enable
# mmcli --modem 0 --3gpp-scan --timeout=300
---------------------
3GPP scan | networks: 310260 - name n/a (lte, current)
| 310120 - name n/a (lte, available)
| 310830 - name n/a (lte, available)
| 312530 - name n/a (lte, available)
| 311882 - name n/a (lte, available)
| 311480 - name n/a (lte, forbidden)
| 311490 - name n/a (lte, available)
Follow the guide setting up hostap and dnsmasq. Alternatively use the steps at https://www.raspberryconnect.com/projects/65-raspberrypi-hotspot-accesspoints/158-raspberry-pi-auto-wifi-hotspot-switch-direct-connection to setup fallback as hostspot if unable to reach your AP.
Do NOT use Network Manager, although it is possible - https://unix.stackexchange.com/questions/234552/create-wireless-access-point-and-share-internet-connection-with-nmcli To get it to work, I had to hack in a reoccurring (every 10 minutes) cronjob that reset iptable rules preventing traffic between the network interfaces. These rules appear to originate from Network Manager and not configurable.
AP "pants-motioneye" for 192.168.200.0/24 default routing through gw usb0
Add to the end of sudo nano /etc/dhcpcd.conf
interface wlan0
static ip_address=192.168.200.1/24
nohook wpa_supplicant
Also adding
sudo nano /etc/dnsmasq.conf
interface=wlan0
dhcp-range=192.168.200.10,192.168.200.20,255.255.255.0,infinite
domain=wlan
address=/pants-motioneye.wlan/192.168.200.1
Add a managed route for 192.168.200.1/24 routing through 10.0.1.20 in zero-tier
sudo iptables -t nat -A POSTROUTING -o usb0 -j MASQUERADE
sudo netfilter-persistent save
And then IP forwarding
sudo nano /etc/sysctl.d/routed-ap.conf
net.ipv4.ip_forward=1
Reboot and verify
Verify camera works as-is and the resolution support
v4l2-ctl --list-devices
vcgencmd get_camera
raspistill -v -o test.jpg
v4l2-ctl -V
Format Video Capture:
Width/Height : 1024/768
If not, install the required packages.
sudo apt install -y raspberrypi-kernel-headers libusb-dev dkms v4l2loopback-utils v4l2loopback-dkms
sudo apt install -y vlc libjpeg-dev git gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-omx libgstrtspserver-1.0-dev gstreamer1.0-rtsp libglib2.0-dev
sudo apt-get install qtcreator qt5-qmake qtbase5-dev qml-module-qtquick-controls2
git clone https://github.com/Kheirlb/purethermal1-uvc-capture
./build_pi_thermal_app.sh
pip3 install opencv-contrib-python==4.1.0.25
#pip3 install opencv-python
Verify lsusb -d 1e4e:0100 -v | grep iProduct iProduct 2 PureThermal (fw:v1.3.0)
cd ./purethermal1-uvc-capture/ui_software/Parabilis_Thermal && sudo python3 ./RecordIR_v18.3.py
For Ubuntu follow steps to install. For Raspberry Pi use these steps to install motion with hardware encoded enabled otherwise the fps will crawl to under 5 fps.
Install motioneye using python2.7 as it still doesn't support python3.
Then follow steps configuring and adding motioneye to inits
sudo apt install libcurl4-openssl-dev libssl-dev
sudo python2.7 -m pip install motioneye
sudo mkdir -p /etc/motioneye
cp /usr/local/share/motioneye/extra/motioneye.conf.sample /etc/motioneye/motioneye.conf
mkdir -p /var/lib/motioneye
cp /usr/local/share/motioneye/extra/motioneye.systemd-unit-local /etc/systemd/system/motioneye.service
systemctl daemon-reload
systemctl enable motioneye
systemctl start motioneye
Test by going to http://pants-motioneye:8765/ as 'admin' and adding the installed cameras. The supported resolution of the camera should align with v4l2-ctl -V
e.g 1024x768
To share you have choices, mainly NFS (Unix), SMB (Microsoft), or AFS/Netatalk (Apple).
I'd recommend NFS for reliability, especially if sharing the media to another server like Home Assistant.
Install steps from https://www.raspberrypi.org/documentation/configuration/nfs.md
sudo apt-get install nfs-kernel-server
mkdir -p /export/media
chmod 777 /export/media /var/lib/motioneye
mount --bind /var/lib/motioneye /export/media
/etc/fstab
/var/lib/motioneye /export/media none bind 0 0
/etc/exports
/export 10.0.0.0/16(rw,fsid=0,insecure,no_subtree_check,async)
/export/media 10.0.0.0/16(rw,nohide,insecure,no_subtree_check,async)
Restart services:
sudo exportfs -ra
sudo systemctl restart nfs-kernel-server
Validate:
showmount -e
Export list for pants-motioneye:
/export/media 10.0.0.0/16
/export 10.0.0.0/16
To automatically mount from another machine: sudo apt install nfs-common mkdir -p /mnt/motioneye && chmod 777 /mnt/motioneye mount -t nfs -o proto=tcp,port=2049 10.0.1.20:/export/media /media/motion/garage
/etc/fstab
10.0.1.20:/export/media /media/motion/garage nfs auto 0 0
To access the shares go Finder -> Go -> Connect to Server then afp://
sudo apt-get install -y netatalk
sudo nano /etc/netatalk/afp.conf
[Homes]
basedir regex = /home
[Pants Motion Eye]
path = /var/lib/motioneye
Install:
sudo apt-get install samba samba-common-bin
chmod 1777 /var/lib/motioneye
/etc/samba/smb.conf
[share]
Comment = Shared Folder
Path = /var/lib/motioneye
Browseable = yes
Writeable = Yes
only guest = no
create mask = 0777
directory mask = 0777
Public = yes
Guest ok = yes
git clone https://github.com/GStreamer/gst-rtsp-server.git
cd gst-rtsp-server/examples && gcc -o test-launch test-launch.c `pkg-config --cflags --libs gstreamer-rtsp-server-1.0`
sudo ./test-launch "( rpicamsrc preview=false bitrate=2000000 keyframe-interval=15 ! video/x-h264, framerate=15/1 ! h264parse ! rtph264pay name=pay0 pt=96 )"
Alternatively, a direct stream can be achieved using steps from https://gist.github.com/lancevalour/397c4e98b6b1e5dc1971
gst-launch-1.0 rpicamsrc preview=false bitrate=2000000 keyframe-interval=15 ! video/x-h264, framerate=15/1 ! h264parse ! rtph264pay name=pay0 pt=96 ! udpsink host=239.1.1.1 port=9002
I'm still getting a low FPS (4-10) and suspect it has to do with the overhead of motion. And it does, see installing a custom ffmpeg with hardware encoding above. https://chriscarey.com/blog/2017/04/30/achieving-high-frame-rate-with-a-raspberry-pi-camera-system/ has another solution making the raspberry pi a simple IP camera. Basically making it available via rtsp://host:8554/stream
nano /home/pi/stream-rtsp.sh
#!/bin/bash
raspivid -ih -pf -pts -o – -t 0 -w 1280 -h 720 -fps 20 -b 3500000 -g 40 | cvlc -A alsa,none –alsa-audio-device default -vvv stream:///dev/stdin –sout ‘#rtp{access=udp,sdp=rtsp://:8554/stream}’ :demux=h264 –h264-fps=20
chmod 755 /home/pi/stream-rtsp.sh
To add this to run at startup
nano /etc/systemd/system/stream-rtsp.service
[Unit]
Description=auto start stream
After=multi-user.target
[Service]
Type=simple
ExecStart=/home/pi/stream-rtsp.sh
User=pi
WorkingDirectory=/home/pi
Restart=on-failure
[Install]
WantedBy=multi-user.target
sudo systemctl enable stream-rtsp.service
sudo systemctl start stream-rtsp.service
sudo systemctl stop stream-rtsp.service
sudo systemctl status stream-rtsp.service
Most important is that you are feeding enough power to the rig. Use a power adapter that pushes down 5v and at least 2amps. I was getting crashes and random reboots due and needed a better power supply. Debugging this is difficult w/out special hardware although voltage regulating is worth looking at if you experience crashes, more information at https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=147781&start=50#p972790
vcgencmd get_throttled
perl -e 'printf "%08b\n", 0x50005'
If using 4g modem ZTE MF833V it works by creating an usb0 interface. The admin interface can be accessed through pi using ssh forwarding.
ssh -N -L 8011:192.168.0.1:80 pi@pants-motioneye
pip install speedtest-cli && speedtest-cli
Go incognito turning off the ACT LED, PWR LED, and Ethernet LED
sudo mount -o remount,rw,noatime,sync /boot
sudo nano /boot/config.txt
dtparam=act_led_trigger=none
dtparam=act_led_activelow=off
dtparam=pwr_led_trigger=none
dtparam=pwr_led_activelow=off
dtparam=eth_led0=14
dtparam=eth_led1=14
To send when motion is detected over MQTT to Home Assistant
sudo apt install -y mosquitto-clients
mosquitto_pub -h m16.cloudmqtt.com -p 13161 -u <user> -P <password> -t cameras/garage/motion -m ON
mosquitto_pub -h m16.cloudmqtt.com -p 13161 -u <user> -P <password> -t cameras/garage/motion -m OFF
And configuring the sensor in Home Assistant
binary_sensor:
- platform: mqtt
name: "Garage Motion"
state_topic: "cameras/garage/motion"
payload_on: "ON"
payload_off: "OFF"
device_class: "motion"
# https://zerotier.atlassian.net/wiki/spaces/SD/pages/193134593/One+Port+Linux+Bridge
# physical lan: 192.168.86.0/24
# physical lan dhcp range: 192.168.86.20 through 192.168.86.250
# zerotier auto-assign range: 192.168.86.5 through 192.168.86.15
# zerotier managed route: 192.168.86.0/23
# default gw: 192.168.86.1/24
GW_ADDR=192.168.86.1
# bridge ip address: 192.168.86.2/24
BR_ADDR=192.168.86.2
# curl -s https://install.zerotier.com | sudo bash
sudo zerotier-cli join $NETWORK_ID
sudo zerotier-cli listnetworks
sudo zerotier-cli set $NETWORK_ID allowManaged=0
# Interfaces (zerotier and bridging)
NETWORK_ID="3efa5cb78ad237c3"
BR_IF=br0
ZT_IF=ztrfyi5acj
# enable systemd networking
sudo systemctl enable systemd-networkd
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
sudo systemctl enable systemd-resolved
sudo systemctl enable systemd-timesyncd
cat << EOF | sudo tee /etc/systemd/network/25-bridge-br0.network
[Match]
Name=192.168.86.2
[Network]
Address=192.168.86.2
Gateway=192.168.86.1
DNS=1.1.1.1
EOF
cat << EOF | sudo tee /etc/systemd/network/br0.netdev
[NetDev]
Name=br0
Kind=bridge
EOF
cat << EOF | sudo tee /etc/systemd/network/25-bridge-br0-zt.network
[Match]
Name=$ZT_IF
[Network]
Bridge=br0
EOF
cat << EOF | sudo tee /etc/systemd/network/25-bridge-br0-en.network
[Match]
Name=eth0
[Network]
Bridge=br0
EOF
iptables -A FORWARD -p all -i br0 -j ACCEPT
Next Steps:
- Bridge to 4G Modem interface instead of eth0
- Create WiFi AP https://www.raspberrypi.org/documentation/configuration/wireless/access-point-bridged.md
systemd-networkd is a different networking beast. Helpful commands,
networkctl list
https://gist.github.com/SimonPe/0fd6ea6fa754aff88d5e
Instruction at https://community.home-assistant.io/t/adding-audio-to-motioneye-recordings/198438/41 Step include finding the port for the audio input using arecord, creating and updating ffmpeg /data/etc/motioneye-audio.sh to use the correct input port, and finally adding the recording script to motioneye motion actions and storage triggers.
arecord -l
**** List of CAPTURE Hardware Devices ****
card 2: Device [C-Media USB Audio Device], device 0: USB Audio [USB Audio]
Subdevices: 0/1
Subdevice #0: subdevice #0
#results translate to plughw:1,0
arecord --device=plughw:1,0 --format S16_LE --rate 44100 -c1 test.wav
aplay --device=plughw:1,0 test.wav
ffmpeg -f alsa -ac 2 -i plughw:1,0 output.mkv
/data/etc/motioneye-audio.sh
#!/usr/bin/env bash
# Taken from https://community.home-assistant.io/t/adding-audio-to-motioneye-recordings/198438/56
# This script needs to be in your motion conf directory, e.g, /etc/motioneye/motioneye-audio.sh
#
#
# Video Device > Extra Motion Options:
# on_movie_start /etc/motioneye/motioneye-audio.sh start '%$' %f
# File Storage > Run a command:
# /etc/motioneye/motioneye-audio.sh stop '%$' %f
#
# Use 'arecord -l' to find the plughw:x,x for ffmpeg
#
MOTION_CONF_DIR="/etc/motioneye"
operation=$1
camera_name=$2
echo "camera_name = " $camera_name >> /tmp/script-verification
file_path=$3
echo "file_path = " $file_path >> /tmp/script-verification
motion_config_dir="$( cd /etc/motioneye >/dev/null 2>&1 && pwd )"
echo "motion_config_dir = " $motion_config_dir >> /tmp/script-verification
# Replacing with camera name due to cameraID/thread mismatch
# motion_camera_conf="${motion_config_dir}/camera-${camera_id}.conf"
motion_camera_conf="$( egrep -l \^camera_name.${camera_name} ${motion_config_dir}/*.conf)"
echo "motion_camera_conf = " $motion_camera_conf >> /tmp/script-verification
#netcam="$(if grep -q 'netcam_highres' ${motion_camera_conf};then echo 'netcam_highres'; else echo 'netcam_url'; fi)"
extension="$(echo ${file_path} | sed 's/^/./' | rev | cut -d. -f1 | rev)"
case ${operation} in
start)
# credentials="$(grep netcam_userpass ${motion_camera_conf} | sed -e 's/netcam_userpass.//')"
# echo "credentials = " $credentials >> /tmp/script-verification
# stream="$(grep ${netcam} ${motion_camera_conf} | sed -e "s/${netcam}.//")"
# echo "stream = " $stream >> /tmp/script-verification
# full_stream="$(echo ${stream} | sed -e "s/\/\//\/\/${credentials}@/")"
# echo "full_stream = " $full_stream >> /tmp/script-verification
ffmpeg -y -f alsa -i plughw:1,0 -codec:a aac ${file_path}.m4a &
ffmpeg_pid=$!
# echo ${ffmpeg_pid} > /tmp/motion-audio-ffmpeg-camera-${camera_id}
echo ${ffmpeg_pid} > /tmp/motion-audio-ffmpeg-camera-${camera_name}
;;
stop)
kill -2 $(cat /tmp/motion-audio-ffmpeg-camera-${camera_name})
rm -rf $(cat /tmp/motion-audio-ffmpeg-camera-${camera_name})
# Merge the video and audio to a single file, and replace the original video file
ffmpeg -y -i ${file_path} -i ${file_path}.m4a -c copy ${file_path}.temp.${extension};
mv -f ${file_path}.temp.${extension} ${file_path};
# Remove audio file after merging
rm -f ${file_path}.wav;
;;
*)
echo "Usage ./motioneye-audio.sh start <camera-name> <full-path-to-moviefile>"
exit 1
esac
And start and end statements in MotionEyeOS setup:
Video Device > Extra Motion Options: on_movie_start /etc/motioneye/motioneye-audio.sh start '%$' %f
File Storage > Run a command: /etc/motioneye/motioneye-audio.sh stop '%$' %f
Validate:
cd /etc/motioneye && ./motioneye-audio.sh start camera-1 /var/lib/motioneye/Camera1/2020-09-19/17-17-27.mp4
./motioneye-audio.sh stop camera-1 /var/lib/motioneye/Camera1/2020-09-19/17-17-27.mp4
We will be using systemd networking to control all interfaces other than the cellular modem. We are using NetworkManager for the cellular modem as it is the easiest path to set up and configure. This may require having NetworkManager ignore these interfaces.
Since the cell modem works best with NetworkManager, we will show out to bridge by disabling NetworkManager & also using it. See https://wiki.archlinux.org/index.php/Network_bridge for steps.
For wireless interfaces, it looks like you need ebtables apt install ebtables
First, remove any of the other networking managers, including systemd-networkd
sudo systemctl disable systemd-networkd.service
sudo systemctl mask systemd-networkd.service
sudo systemctl stop systemd-networkd.service
sudo apt-get install network-manager
Configure and setup Network Manager
systemctl stop NetworkManager
systemctl start NetworkManager
systemctl restart systemd-networkd.service
nmcli radio wifi
nmcli device wifi list
nmcli connection add \
type wifi con-name "XFINITY" ifname wlan0 ssid "XFINITY" -- \
wifi-sec.key-mgmt wpa-eap 802-1x.eap ttls 802-1x.phase2-auth pap \
802-1x.identity "kwatkins6" 802-1x.password 'xxx'
nmcli connection add type bridge ifname br0 stp no
nmcli dev status
nano /etc/NetworkManager/NetworkManager.conf
[keyfile]
unmanaged-devices=interface-name:wlan*
systemctl stop NetworkManager
systemctl start NetworkManager
systemctl restart systemd-networkd.service
# Interfaces (zerotier and bridging)
NETWORK_ID="3efa5cb78ad237c3"
# curl -s https://install.zerotier.com | sudo bash
sudo zerotier-cli join $NETWORK_ID
sudo zerotier-cli listnetworks
cat << EOF | sudo tee /etc/systemd/network/br0.netdev
[NetDev]
Name=br0
Kind=bridge
EOF
cat << EOF | sudo tee /etc/systemd/network/25-bridge-br0-zt.network
[Match]
Name=$ZT_IF
[Network]
Bridge=br0
EOF
cat << EOF | sudo tee /etc/systemd/network/25-bridge-br0-ppp.network
[Match]
Name=ppp0
[Network]
Bridge=br0
EOF