“What is our lil’ doggo up to while I am away?” I thought to myself commuting to work. “Does she nibble on the door frame?” “Or maybe she feasts on some mattresses? “Naah,” I would not notice that.
I always regarded her as a good dog. Such a calm and collected creature. Unless there is a cat. Or a traffic sign. Or a gate barrier. Or anything for that matter. The only difference between these things is her movement direction. Cats = forward, anything else = backwards. Yep, she is one scaredy-cat. However she never did anything wrong, except that time when she decided to munch on some shampoo. Who knew dogs practice oral hygiene.
While that accident sure bubbled up, she seems to be quite OK being alone at home. But you can never be sure. Especially when living in multi apartment building. Does she bark all the time, waking neighbors’ baby? Is she jumping all the time, making neighbors below contemplating their flat choices? “Am I about to be evicted?” “And most importantly does she sleep on the couch?!”
For that matter I have dug up my old Raspberry Pi 2 determined to put my skepticism to rest. Armed with the RPi and a new camera module, it was time to put everything to the test (sick rhymes yo). The final product would look like this:
All in all, RPi connects through the WiFi adapter to the home network, starts the VPN server and finally provides live stream through the web server. Live stream can only be accessed by people having access to the VPN server, ie. whoever gets a client private key from ME (muahaha, no butt naked live streams to everyone on the internetz - unfortunately or rather fortunately for the ladies out there).
I put it on the amplifier due to the power outlet proximity and additionally it has a nice view of the whole room and of the entrance (in case she is barking at the door when someone passes by).
Hardware used
I already had:
- Raspberry Pi Model 2B v1.1
- Raspberry PI Official case (might have been a different one back then)
- Universal Power Supply
- Asus USB-N13 Wifi adapter
I had to buy:
The assembly of components was trivial. The only thing worth mentioning is the camera being upside down when coming out of the case. We flip the camera programatically, since this is the most natural from the cable standpoint of view.
I installed Raspbian Buster with desktop and recommended software as the 2016 OS already installed was out of date.
Setup WiFi connection and static IP
WiFi Connection
As I was keen on using RPi through SSH and developing on my local computer I setup WiFi with a static IP address first.
We open sudo vim /etc/wpa_supplicant/wpa_supplicant.conf
file and enter:
1network={
2 scan_ssid=1
3 ssid="<wifi_name>"
4 psk="<wifi_pass>"
5}
As I have a hidden SSID on my home network I also added the scan_ssid=1
flag.
Static IP
We want the RPi to be always accessible on the same IP (192.168.0.244
) in our LAN. This has to be done on two sides
Router setup: reserve
192.168.0.244
IP for our RPi.- We locate MAC address of our RPi by running
ifconfig
and looking forether
entry. It should be something like02:01:03:6d:6e:5d
. - We open our router control panel (by going to
192.168.0.1
or whatever the default gateway address is), go to DHCP section and reserve192.168.0.244
IP for02:01:03:6d:6e:5d
MAC address. What this essentially means, if a device with a MAC address02:01:03:6d:6e:5d
tries to connect to our network, it will be assigned192.168.0.244
IP.
- We locate MAC address of our RPi by running
RPi setup: We have to tell our DHCP on RPi which static IP belongs to the RPi. We open
sudo vim /etc/dhcpcd.conf
and add1interface wlan0 2static ip_address=192.168.0.244/24 3static routers=192.168.0.1 4static domain_name_servers=192.168.0.1 8.8.8.8
And that is it! When RPi boots it will connect to our SSID. Router will reserve 192.168.0.244
IP and we can then connect to it e.g. ssh -X pi@192.168.0.244
as we can always be sure that RPi will reside on that IP.
Setup OpenVPN
We create a VPN to secure our live stream.
We have to enable
tun
module first, we runmodprobe tun
and to make sure this runs every time we boot the RPi, we pensudo vim /etc/modules
and appendtun
into a new line.We follow the instructions in this repo to install OpenVPN. This comes as a life saver as setting up VPN can be a rather daunting process.
After the installation is done we get a
client.ovpn
, which can be used by OpenVPN client. As the port forwarding is still not setup, we can modifyclient.ovpn
file to use our LAN connection. We open the filevim client.ovpn
and changeremote
toremote 192.168.0.244 1194
. Additionally we do not want all of our Internet traffic to be routed through VPN so we add the following line:1pull-filter ignore redirect-gateway
We use the
client.ovpn
file on some other computer in the LAN to connect to the VPN:1sudo openvpn --config ~/.ovpn/client.ovpn
We can test the connection with a simple ping
ping 10.8.0.1
. If everything works correctly we get the response:1PING 10.8.0.1 (10.8.0.1) 56(84) bytes of data. 264 bytes from 10.8.0.1: icmp_seq=1 ttl=64 time=8.43 ms 364 bytes from 10.8.0.1: icmp_seq=2 ttl=64 time=3.18 ms
Additional clients
I will use multiple devices to access the VPN server. We can create additional clients by simple running ./openvpn-install.sh
on the RPi and obtain multiple client .ovpn
files. Those extra clients can always be easily revoked by running the same command (e.g. if the phone was stolen).
Setup live stream server
Install Motion
For live stream purposes we use Motion program, which monitors video signal from the camera. Besides being able to detect if a significant part of the picture has changed, it supports live stream out of the box.
Install
motion
program1sudo apt-get install motion
We are using one of the official camera modules:
1sudo modprobe bcm2835-v4l2
To start module automatically after every restart we add the following entry into the
/etc/modules
:1# /etc/modules: kernel modules to load at boot time. 2# 3# This file contains the names of kernel modules that should be loaded 4# at boot time, one per line. Lines beginning with "#" are ignored. 5 6# ... other moduels 7bcm2835-v4l2
And edit
sudo vim /etc/default/motion
to setstart_motion_daemon=yes
:1# set to 'yes' to enable the motion daemon 2start_motion_daemon=yes
With this setting Motion server will run as a daemon in the background.
Config Motion
With the above configuration we can be sure that Motion will run whenever we plug the RPi into the outlet. Now we take a closer look at the Motion config. We open it with:
1sudo vim /etc/motion/motion.conf
And in our case we used the following configuration
1# Start in daemon mode
2daemon on
3
4# Image parameters
5width 640
6height 480
7framerate 8
8
9# Allow stream to be visible outside localhost
10stream_localhost off
11stream_maxrate 8
12stream_motion on # set framerate to 1, when there is no motion
13
14# Do not save image on motion detection
15output_pictures off
16
17# Due to camera cable coming out of RPi forces camera to be upside down, we flip the axis
18flip_axis h
Whenever we change the configuration we can apply it with:
1sudo service motion restart
or
1sudo service motion start
If we started it for the first time.
Width, height and frame rate were defined empirically. I tested different settings and at first set resolution to HD. Although the stream worked it was laggy through the VPN. VPN stream encryption + camera processing is no bueno for RPi CPU. The picture is still good enough to see what little fella is up to.
Additionally since she is mostly stationary we use stream_motion on
to reduce the frame rate when she is not moving. flip_axis h
was done purely because camera cable comes out of the RPi in such manner that image is upside down. Instead of twisting the cable, this will flip the axis horizontally and it will be OK.
Test the live stream
We can test the stream by visiting 192.168.0.244:8081
or 10.8.0.1:8081
if we are connected to the VPN and our live stream should be visible:
Flask server
Since we want to add additional actions (remote food dispense) to the web interface, we create a simple Flask web server. We add a simple HTML template that includes our live stream:
1<html>
2 <body>
3 <img src="http://10.8.0.1:8081" height="480" width="640"/>
4 </body>
5</html>
And a web.py
server script:
1from flask import (
2 Flask,
3)
4
5app = Flask(__name__)
6app.config['DEBUG'] = True
7
8@app.route('/')
9def index():
10 return render_template('index.html')
11
12if __name__ == '__main__':
13 app.run(host='0.0.0.0', port=8082)
Which we then run with
1python3 web.py
We can now visit http://10.8.0.1:8082
to see our server in action. As this is not meant for production environment, this is good enough as it is.
Code is available on my Github.
Port forwarding
Last but not least, we have to allow the outside traffic to access our VPN server. To forward our ports we log into our router and forward 1194 traffic to our RaspberryPI:
I also had to change ISP settings to allow the port through the ISP’s firewall. Our ISP offers a special web platform where forwarding can be set.
Dynamic DNS and static IP
Since I am behind a dynamic IP, I opted for DynamicDNS solution NoIP. It assigns domain name to you router and it is stationary. It is supported out of the box on my router therefore I just registered the domain and entered the credentials into my router. Now my router pings NoIP every 6 hours to tell about the new IP address. It is free, however you have to confirm the chosen domain name every 30 days.
Conclusion
We created a RaspberryPI camera server using Motion program. It is secured with OpenVPN, which runs on RaspberryPI. To allow connections to the VPN we forward the port 1194 (port on which OpenVPN is running). We register NoIP account to circumvent ever changing IP address of our router. RaspberryPI is connected to our local network with WiFi and we configure it through SSH. We setup static IP for RaspberryPI. Due to WiFi we can plug in RPi anywhere in our house and stream should be working due to all our services running on boot.
Yes, that’s how I know you slept on the couch, doggy. evil grin
Comments