Simple Web-App and complete HowTo for setting up a Raspberry Pi with Camera for Time-lapse Photography.
- Node.js based Web-App for controlling and monitoring the camera and the Raspberry Pi
- Reverse-SSH-Tunnel to another server - reach your Raspberry Pi behind firewalls (optional)
- Dynamic-DNS-Client - find your Raspberry Pi easier in your local network (optional)
- Wi-Fi autoconnect - if you have a USB Wi-Fi Adapter (optional)
- Network-Watchdog - reset network and maybe emergency-reboot if connection is broken (optional)
- BitTorrent-Sync - as sync-solution to get the photos out of the Pi (optional)
- Sync-Script - via rsync as alternative to BitTorrent-Sync (optional)
- Prerequisites: Raspberry Pi + Power + SD-Card, RaspiCam, LAN Cable, USB Wi-Fi Adapter (optional)
Table of Contents generated with DocToc
- HowTo
- Setup SD-Card
- Setup RaspberryPi OS + Raspberry Pi Camera
- Setup RaspiCam-Timelapse
- Reverse SSH-Tunnel (optional)
- Dynamic-DNS-Client (optional)
- Wi-Fi autoconnect (optional)
- Activate Network-Watchdog (optional)
- Use hardware watchdog with Network-Watchdog (optional)
- Install BitTorrent-Sync (optional)
- Install Sync-Script (optional)
- Use Ramdisk as primary capture folder (optional)
- 3G/4G backup connection (optional)
- TODO
- Download current RaspberryPi OS (previously called Raspbian, "Jessie" or newer - "Lite" is enough)
- Write extracted ".img"-file to SD-Card - see OS specific instructions
- Create an empty file named "ssh" in the root folder of the SD-Card to enable automatic startup of OpenSSH
- Attach the camera to the Raspberry Pi - see instructions
- Put the SD-Card into your Raspberry Pi, Connect to your LAN (DHCP server needed), Power on
- Login via SSH (maybe use local IP):
ssh raspberrypi
(Default Login: pi / Password: raspberry) - Make complete SD-Card usable:
sudo raspi-config
- 7 Advanced Options - A1 Expand Filesystem - Finish - Reboot
- Install updates:
sudo apt update
,sudo apt dist-upgrade
andsudo apt clean
- For some helpful optional customizations of your Raspberry Pi - see here
- Enable camera:
sudo raspi-config
- 5 Interfacing Options - A1 Camera - Enable Camera - Finish (this also sets Memory Split to 128 MB) - Disable camera LED when taking pictures (optional):
sudo sh -c 'echo "disable_camera_led=1" >> /boot/config.txt'
- Reboot for the camera settings to take effect:
sudo reboot
Retrieve the CPU of your Pi to select the proper latest Node.js version available:
uname -m
- RaspberryPi 1: armv6l, latest available Node.js version see https://nodejs.org/dist/latest-v11.x/
- RaspberryPi 2, 3: armv7l, see https://nodejs.org/dist/latest/ (currently v14)
- RaspberryPi 4: ?
Install Node.js (for Node.js >=4.x you need Raspbian "Jessie" or newer - otherwise the native modules won't compile):
wget https://nodejs.org/dist/v4.4.3/node-v4.4.3-linux-armv6l.tar.xz
tar -xvf node-v4.4.3-linux-armv6l.tar.xz
sudo cp -R node-v4.4.3-linux-armv6l/{bin,include,lib,share} /usr/local/
rm -rf node-v4.4.3-linux-armv6l
Install GIT:
sudo apt install git
Check out this repository:
cd ~
git clone https://github.com/not-implemented/raspicam-timelapse.git
cd raspicam-timelapse
npm install
Configuration:
# Create a self-signed certificate:
openssl req -x509 -days 3650 -sha256 -nodes -newkey rsa:2048 -keyout config/timelapse.key -out config/timelapse.crt
chmod og= config/timelapse.key
# Prepare capture directory:
mkdir ../capture
Start server:
npm start &
... now open your browser - i.e. with https://raspberrypi:4443/ or IP address (Login: timelapse / Password: timelapse) :-)
Enable start on reboot:
crontab -e
# Insert this line into crontab:
@reboot /usr/local/bin/node ~/raspicam-timelapse/server.js &
Be sure, to change the default password before allowing connections from untrusted networks - see here.
Generate SSH-Key on Raspberry Pi (just press ENTER everywhere):
cd ~
ssh-keygen -t rsa
# Show the public key for using later:
cat ~/.ssh/id_rsa.pub
Allow SSH connections from Raspberry Pi on your remote server:
# Maybe add a new user - i.e. "timelapse" on your remote server (but you can use an existing one):
adduser --gecos Timelapse timelapse
chmod go-rwx /home/timelapse
cd /home/timelapse
# Add the raspberry's key (.ssh/id_rsa.pub from above) on your remote server
# to the user and just allow port-forwarding (no login):
mkdir -p .ssh
echo "command=\"echo 'This account can only be used for port-forwarding'\",no-agent-forwarding,no-pty,no-X11-forwarding" \
"{raspberry-public-key-from-above}" >> .ssh/authorized_keys
chmod -R go-rwx .ssh
chown -R timelapse:timelapse .ssh
# Some global settings:
editor /etc/ssh/sshd_config
# Enable listening on all interfaces for port-forwarding on your remote server
# (otherwise port-forwarding will listen only on localhost):
GatewayPorts yes
# Detect and close dead connections faster and close forwarded ports to reuse them:
ClientAliveInterval 30
ClientAliveCountMax 3
# Restart SSH server:
service sshd restart
Back on Raspberry Pi: Configure tunnels to be established - create a script with
editor tunnels.sh
like the following example to forward port 10022 from your
remote server to port 22 on Raspberry Pi - same with port 4443 and 8888:
#!/bin/bash
~/raspicam-timelapse/ssh-reverse-tunnel/open-tunnel.sh timelapse@www.example.com 10022 22 &
~/raspicam-timelapse/ssh-reverse-tunnel/open-tunnel.sh timelapse@www.example.com 4443 4443 &
~/raspicam-timelapse/ssh-reverse-tunnel/open-tunnel.sh timelapse@www.example.com 18888 8888 &
# Make it executable:
chmod +x tunnels.sh
# Check SSH-Connection and permanently add the key (type "yes"):
ssh timelapse@www.example.com
# (... should print "This account can only be used for port-forwarding" and close SSH connection)
# Add script to crontab:
crontab -e
# Insert this lines into crontab:
@reboot ~/tunnels.sh
* * * * * ~/tunnels.sh
# Link script:
sudo ln -snf /home/pi/raspicam-timelapse/dynamic-dns-client/lib_dhcpcd_dhcpcd-hooks_90-dynamic-dns /lib/dhcpcd/dhcpcd-hooks/90-dynamic-dns
# Change config vars in dynamic-dns.conf:
sudo editor ~/raspicam-timelapse/dynamic-dns-client/dynamic-dns.conf
sudo editor /etc/wpa_supplicant/wpa_supplicant.conf
Append as many networks as you want - some examples:
# Secure Wi-Fi example:
network={
ssid="{your-ssid}"
psk="{your-key}"
}
# Open Wi-Fi example:
network={
ssid="muenchen.freifunk.net"
key_mgmt=NONE
}
crontab -e
# Insert this line into crontab:
* * * * * sudo timeout -k 120 100 ~/raspicam-timelapse/network-watchdog/check-network.sh
# To enable the watchdog set IPV4_ENABLED=1 and/or IPV6_ENABLED=1 - default ping destination
# is the default gateway - override via IPV4_PING_DEST/IPV6_PING_DEST when needed:
cp ~/raspicam-timelapse/config/check-network.conf.example ~/raspicam-timelapse/config/check-network.conf
editor ~/raspicam-timelapse/config/check-network.conf
apt-get install watchdog
sudo editor /etc/default/watchdog
-watchdog_module="none"
+watchdog_module="bcm2708_wdog"
sudo mkdir /etc/watchdog.d
# To enable the watchdog set IPV4_ENABLED=1 and/or IPV6_ENABLED=1 - default ping destination
# is the default gateway - override via IPV4_PING_DEST/IPV6_PING_DEST when needed:
cp ~/raspicam-timelapse/config/check-network.conf.example ~/raspicam-timelapse/config/check-network.conf
editor ~/raspicam-timelapse/config/check-network.conf
sudo ln -s ~/raspicam-timelapse/network-watchdog/check-network.sh /etc/watchdog.d/
systemctl enable watchdog
We currently use BitTorrent-Sync as sync-solution, because Syncthing is very slow on Raspberry Pi.
wget https://download-cdn.getsync.com/stable/linux-arm/BitTorrent-Sync_arm.tar.gz
mkdir btsync && cd btsync
tar -xvzf ../BitTorrent-Sync_arm.tar.gz
# Start BitTorrent-Sync:
./btsync --webui.listen 0.0.0.0:8888
cd ..
# Enable start on reboot:
crontab -e
@reboot ~/btsync/btsync --webui.listen 0.0.0.0:8888
Now open Web-Interface via "https://raspberrypi:8888/" and add "/home/pi/capture" folder for sync.
After that disable sync of "latest.jpg":
editor capture/.sync/IgnoreList
# Append to the end:
/latest.jpg
Second sync method is a configurable sync script. Currently only tested with rsync.
You have to configure some options in sync/sync.conf (examples) at first
# add sync script to crontab
crontab -e
*/5 * * * * ~/raspicam-timelapse/sync/sync.sh ~/capture
You have to modify the authorized_keys line to allow the sync command to be executed
-command="echo 'This account can only be used for port-forwarding'"
+command=/path/to/command_validation.sh
Example for command_validation.sh:
#!/bin/bash
if [[ "$SSH_ORIGINAL_COMMAND" =~ [\&\;] ]] ;
then
echo "Error: Invalid character found in command."
exit 1
fi
case "$SSH_ORIGINAL_COMMAND" in
rsync*/timelapse/capture*)
;;
*)
echo "Error: Invalid command over ssh executed."
exit 1
;;
esac
exec $SSH_ORIGINAL_COMMAND
To save SD-Cards life, you can capture to a Ramdisk and sync immediately up. Only when sync does not work for any reason, files are moved to SD-Card and synced up from there.
fstab entry (sudo vim /etc/fstab)
capture_ramdisk /home/pi/capture_ramdisk tmpfs size=30M,uid=1000,gid=1000,mode=755 0 0
mkdir /home/pi/capture_ramdisk
sudo mount /home/pi/capture_ramdisk
# add sync script to crontab
crontab -e
# sync job for ramdisk
* * * * * ~/raspicam-timelapse/sync/sync.sh ~/capture_ramdisk
# move files older than 3 minutes to sd card
* * * * * ~/raspicam-timelapse/sync/ramdisk2sd-move.sh ~/capture_ramdisk ~/capture
sudo apt-get install usb-modeswitch usb-modeswitch-data
# Example values for Huawei E303 (please change for your specific device!):
vendor_id=12d1
product_id=1f01
switch_message=55534243123456780000000000000011062000000101000100000000000000
cat <<EOF | sudo tee /etc/udev/rules.d/70-usb-modeswitch.rules > /dev/null
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="$vendor_id", ATTRS{idProduct}=="$product_id", RUN+="/usr/sbin/usb_modeswitch -v $vendor_id -p $product_id -M $switch_message"
EOF
# reload udev:
sudo udevadm control --reload
cp ~/raspicam-timelapse/config/interfaces-post-up.conf.example ~/raspicam-timelapse/config/interfaces-post-up.conf
editor ~/raspicam-timelapse/config/interfaces-post-up.conf
sudo editor /etc/network/interfaces
# add these lines:
auto eth1
iface eth1 inet dhcp
post-up /home/pi/raspicam-timelapse/backup-connection/interfaces-post-up.sh
# add dhcp configuration to dhcp config file
cat backup-connection/dhcpcd-to_add.conf | sudo tee -a /etc/dhcpcd.conf
Now plug in your UMTS stick.
~/raspicam-timelapse/ssh-reverse-tunnel/open-tunnel.sh timelapse@www.example.com 11022 22 <stick_local_ip> &
- Switch to Ansible
- Implement as a systemd service (start on boot, restart on crash, restart raspistill after crash)
- Use NVM for installing Node.js - https://github.com/creationix/nvm
- Get Dynamic-DNS-Client more stable (trigger on IP adress changes, not just on cable plug)