├── .gitignore ├── bin ├── make-movie.sh ├── pi-ui-autostart ├── root-rc.local ├── setup-root.sh ├── start-camera.sh ├── start-gridbot.sh ├── start-gridhost.sh ├── start-root.sh ├── update-code.sh ├── update-name.sh └── update-wifi.sh ├── etc └── root-config.txt ├── init.js ├── license.md ├── package.json ├── readme.md ├── setup.sh ├── src ├── js │ ├── gridsend.js │ ├── linebuffer.js │ └── server.js ├── marlin │ ├── 2.0.x-longmill │ │ ├── Configuration.h │ │ ├── Configuration_adv.h │ │ ├── boards.h │ │ ├── pins.h │ │ └── platformio.ini │ └── 2.0.x │ │ ├── Configuration.h │ │ ├── Configuration_adv.h │ │ └── platformio.ini └── web │ ├── camera.css │ ├── camera.html │ ├── camera.jpg │ ├── camera.js │ ├── fa.min.js │ ├── favicon.ico │ ├── index.css │ ├── index.html │ ├── index.js │ ├── moment.js │ └── serial.js └── start-root.sh /.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules 3 | etc/server.json 4 | etc/bedclear 5 | etc/uuid 6 | tmp 7 | -------------------------------------------------------------------------------- /bin/make-movie.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | layers=$1 4 | 5 | [ -z "$layers" ] && echo "missing layers parameter" && exit 6 | 7 | x=0 8 | 9 | while [ $x -lt $layers ]; do 10 | cf="image-$(printf "%04d" $x).jpg" 11 | [ ! -f $cf ] && echo "missing $cf" && ( 12 | cp $lf $cf 13 | ) 14 | lf=$cf 15 | x=$((x+1)) 16 | done 17 | 18 | ffmpeg -r 60 -i image-%04d.jpg -s 800x600 movie.mp4 19 | -------------------------------------------------------------------------------- /bin/pi-ui-autostart: -------------------------------------------------------------------------------- 1 | @xset s noblank 2 | @xset s off 3 | @xset –dpms 4 | @chromium-browser --kiosk http://localhost:4080 5 | @unclutter -idle 0.1 6 | -------------------------------------------------------------------------------- /bin/root-rc.local: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "My IP address is $(hostname -I)" 4 | /home/pi/grid-bot/bin/start-root.sh 5 | 6 | exit 0 7 | -------------------------------------------------------------------------------- /bin/setup-root.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # update config.txt with required fields 4 | grep grid:bot /boot/config.txt || cat /home/pi/grid-bot/etc/root-config.txt >> /boot/config.txt 5 | 6 | # update rc.local to start grid:bot services 7 | cp /home/pi/grid-bot/bin/root-rc.local /etc/rc.local 8 | 9 | # allow tcp on x server 10 | grep ^xserver-allow-tcp=true /etc/lightdm/lightdm.conf || echo xserver-allow-tcp=true >> /etc/lightdm/lightdm.conf 11 | 12 | # redirect port 80 to 4080 with default index.html 13 | #echo '
' > /var/www/html/index.html 14 | 15 | # update pacakges 16 | [ ! -f ${HOME}/.gb-up ] && apt -y update && apt -y dist-upgrade && touch ${HOME}/.gb-up 17 | 18 | # set timezone 19 | [ ! -f ${HOME}/.gb-tz ] && dpkg-reconfigure tzdata && touch ${HOME}/.gb-tz 20 | 21 | grep pi-gridbot /etc/hostname || ( 22 | echo pi-gridbot > /etc/hostname 23 | echo "127.0.0.1 pi-gridbot" >> /etc/hosts 24 | ) 25 | -------------------------------------------------------------------------------- /bin/start-camera.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # for standalone operation, add the following line to /etc/rc.local 4 | # nohup nice -n 19 su -l -c /home/pi/start-camera.sh pi > /tmp/camera.log 2>&1 & 5 | 6 | cd /home/pi/grid-bot >/dev/null 2>&1 || cd /home/pi 7 | 8 | # if motion enabled. use that port instead of stills 9 | [ -f etc/camera.conf ] && source etc/camera.conf 10 | if [ ! -z ${MOTION} ]; then 11 | motion -b -m 12 | echo ${MOTION} > /tmp/motion.port 13 | exit 14 | fi 15 | 16 | export cmd=$(which raspistill || which libcamera-still) 17 | 18 | [ ! -z $cmd ] || exit 19 | 20 | while /bin/true; do 21 | [ -f etc/camera.conf ] && source etc/camera.conf 22 | export RUN=1 23 | export DATE=$(date '+%Y-%m-%d') 24 | export TIME=$(date '+%H:%M') 25 | export TMPFILE=/tmp/camera.jpg 26 | export TEMP=${FILE_TEMP:-${TMPFILE}} 27 | export PERM=${FILE_PERM:-/var/www/html/camera.jpg} 28 | if [ ! -z ${TIMELAPSE} ]; then 29 | mkdir -p "${TIMELAPSE}/${DATE}" 30 | export TMPFILE="${TIMELAPSE}/${DATE}/${TIME}.jpg" 31 | if [ ! -z ${MAXAGE} ]; then 32 | find ${TIMELAPSE} -type f -mtime ${MAXAGE} -print -delete 33 | rmdir "${TIMELAPSE}/*" >/dev/null 2>&1 34 | fi 35 | if [ ! -z ${TRIGGER} ]; then 36 | if [ ! -f ${TRIGGER} ]; then 37 | export RUN=0 38 | fi 39 | fi 40 | fi 41 | [ ! -z ${NOIR} ] && export TUNING="--tuning-file /usr/share/libcamera/ipa/raspberrypi/imx219_noir.json" 42 | [ ${RUN} -eq 1 ] && ${cmd} -n \ 43 | --width ${WIDTH:-1600} \ 44 | --height ${HEIGHT:-1200} \ 45 | -q ${QUALITY:-20} \ 46 | -o ${TEMP} ${TUNING:-} \ 47 | -t ${TIMEOUT:-500} \ 48 | --shutter ${EXPOSURE:-40000} \ 49 | --rotation ${ROTATION:-90} \ 50 | --awb ${BALANCE:-greyworld} 2>/dev/null || exit 51 | [ ! -z ${MOGRIFY} ] && \ 52 | mogrify -rotate ${MOGRIFY} ${TEMP} 53 | cp ${TEMP} ${PERM} 54 | done 55 | -------------------------------------------------------------------------------- /bin/start-gridbot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export HOME=/home/pi 4 | export ROOT=${HOME}/grid-bot 5 | export NODE=${ROOT}/node/bin/node 6 | export BAUD=250000 7 | export OPTS='--listen --baud=${BAUD} --filedir=${ROOT}/uploads' 8 | export NODE=$(which node || echo $NODE) 9 | 10 | cd ${ROOT} 11 | while /bin/true; do 12 | [ -f etc/server.conf ] && source etc/server.conf 13 | echo "--- starting --- $(date)" 14 | eval "${NODE} src/js/server.js ${OPTS}" 15 | echo "--- exited ---" 16 | done 17 | -------------------------------------------------------------------------------- /bin/start-gridhost.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export HOME=/home/pi 4 | export PATH=$PATH:$HOME/grid-bot/node/bin 5 | 6 | which node || echo "missing node" 7 | which node || exit 8 | 9 | cd $HOME/grid-host/ 10 | while /bin/true; do 11 | echo "--- starting --- $(date)" 12 | bin/grid-host 13 | echo "--- exited ---" 14 | done 15 | -------------------------------------------------------------------------------- /bin/start-root.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export ROOT=/home/pi/grid-bot 4 | mkdir -p /var/www/html 5 | 6 | # redirect traffic from port 80 to gridbot interface 7 | iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 4080 8 | iptables -A PREROUTING -t nat -i wlan0 -p tcp --dport 80 -j REDIRECT --to-port 4080 9 | 10 | nohup nice -n -20 su -l -c ${ROOT}/bin/start-gridbot.sh pi > /tmp/gridbot.log 2>&1 & 11 | #nohup nice -n 19 su -l -c ${ROOT}/bin/start-gridhost.sh pi > /tmp/gridhost.log 2>&1 & 12 | nohup nice -n 19 ${ROOT}/bin/start-camera.sh > /dev/null 2>&1 & 13 | -------------------------------------------------------------------------------- /bin/update-code.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ( 4 | echo "updating code from github" 5 | [ -d ../grid-bot ] && (cd ../grid-bot && git pull && npm i) 6 | [ -d ../grid-host ] && (cd ../grid-host && git pull && npm i) 7 | [ -d ../grid-apps ] && (cd ../grid-apps && git pull && npm i) 8 | sudo cp /home/pi/grid-bot/bin/root-rc.local /etc/rc.local 9 | echo "code update complete" 10 | ) | tee -a /tmp/update-code.log 11 | -------------------------------------------------------------------------------- /bin/update-name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -z "$1" ] && echo "missing host name" && exit 4 | 5 | echo "HOST NAME=${1}" 6 | echo "${1}" > /etc/hostname || echo "unable to update hostname" 7 | echo "127.0.0.1 ${1}" >> /etc/hosts || echo "unable to undate hosts" 8 | hostname "${1}" 9 | 10 | echo "updated host name. reboot required" 11 | -------------------------------------------------------------------------------- /bin/update-wifi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -z "$1" ] && echo "missing ssid" && exit 4 | [ -z "$2" ] && echo "missing psk" && exit 5 | 6 | export TMPF=/tmp/wpa_supplicant.conf 7 | export FILE=/etc/wpa_supplicant/wpa_supplicant.conf 8 | 9 | echo "SSID=${1}" 10 | echo "PSK=${2}" 11 | echo "FILE=${FILE}" 12 | 13 | cat > ${TMPF} << EOF 14 | ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev 15 | update_config=1 16 | country=US 17 | 18 | network={ 19 | ssid="${1}" 20 | psk="${2}" 21 | } 22 | EOF 23 | 24 | sudo mv ${TMPF} ${FILE} 25 | sudo cat ${FILE} 26 | 27 | echo "updated wifi settings. reboot required" 28 | -------------------------------------------------------------------------------- /etc/root-config.txt: -------------------------------------------------------------------------------- 1 | # grid:bot ... for pi zero w 2 | #over_voltage=6 3 | #force_turbo=1 4 | 5 | # grid:bot ... pi 4 hdmi output 6 | #hdmi_force_hotplug=1 7 | #hdmi_drive=2 8 | 9 | # grid:bot ... for pi3 with 7" hdmi touch display 10 | #max_usb_current=1 11 | #hdmi_force_hotplug=1 12 | #config_hdmi_boost=7 13 | #hdmi_group=2 14 | #hdmi_mode=1 15 | #hdmi_mode=87 16 | #hdmi_drive=1 17 | #hdmi_cvt 800 480 60 6 0 0 0 18 | 19 | # grid:bot ... fir pi3 with element14 7" touch display 20 | dtoverlay=dwc2 21 | dtoverlay=gpio-shutdown 22 | 23 | # grid:bot ... hide undervoltage warnings 24 | avoid_warnings=1 25 | 26 | # grid:bot ... enable camera, set video mem 27 | start_x=1 28 | gpu_mem=128 29 | -------------------------------------------------------------------------------- /init.js: -------------------------------------------------------------------------------- 1 | module.exports = (server) => { 2 | let path = server.path; 3 | let join = require('path').join; 4 | let moddir = server.const.moddir; 5 | let srcdir = join(moddir, "src"); 6 | let webdir = join(moddir, "src/web"); 7 | 8 | // server "web" dir at the root of "/data" 9 | path.static(webdir, "/send"); 10 | }; 11 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | Copyright 2014-2018 Stewart Allen202 | | 203 | | 204 | | 205 | | 206 | |
209 | | 210 | | 211 | | 212 | | 213 | |
216 | | 217 | | 218 | | 219 | | 220 | |
225 | | 226 | | 227 | |
230 | | 231 | | 232 | |
235 | | 236 | | 237 | |