Commit 27a709ea authored by Neil Gershenfeld's avatar Neil Gershenfeld

add prior node version

parent 05682b77
<pre>
shopcam server, prior node version
to clone: git clone https://gitlab.cba.mit.edu/pub/cams.git
to reinitialize: ./init
to run: node cams.js
uses ffmpeg for screen capture
uses convert to make thumbnails
uses compare to measure activity
can use uvcdynctrl -f to list resolutions
can use sudo guvcview to adjust camera
can use http-server-with-auth to serve:
http-server-with-auth -p port --username username --password password
http-server-with-auth -p port --username username --password password --ssl --cert cert.pem --key key.pem
index is at http://this_address:this_port
last image is at http://this_address:this_port/oldimage.jpg
can use Ubuntu MATE on Raspberry Pi 3:
sudo apt-get install nodejs-legacy npm ffmpeg imagemagick guvcview
sudo npm install -g http-server-with-auth
System -> Administration -> Time and Date -> Keep synchronized with internet servers
can use Logitech C920 HD Webcam
can start cams script on boot with cams.service:
edit cams script with port, username, and password
sudo cp cams.service /lib/systemd/system
sudo systemctl daemon-reload
sudo systemctl enable cams.service
sudo systemctl start cams.service
journalctl -u cams.service
#!/bin/bash
cd /home/fab/cams
node cams.js &
http-server-with-auth -p set_port_number --username set_username --password set_password &
//
// cams.js
// shopcam activity monitor
// Neil Gershenfeld
// 12/11/17
//
// settings
//
var image_width = 1600
var image_height = 1200
var thumbnail_size = 200
var video_filter = 'vflip,hflip'
var difference_threshold = .05
var millisecond_image_delay = 15000
var days_to_save = 150
//
// requires
//
const fs = require('fs')
const exec = require('child_process').exec
const execSync = require('child_process').execSync
//
// image update function
//
function update() {
//
// name image with time
//
var date = new Date()
var year = date.getFullYear()
var month = ('0'+(1+parseInt(date.getMonth()))).slice(-2)
var day = ('0'+date.getDate()).slice(-2)
var hour = ('0'+date.getHours()).slice(-2)
var minute = ('0'+date.getMinutes()).slice(-2)
var second = ('0'+date.getSeconds()).slice(-2)
var name = year+'-'+month+'-'+day+'-'+hour+'-'+minute+'-'+second+'.jpg'
//
// take new image
//
console.log('\ncapture '+name)
var success = true
do {
try {
execSync('ffmpeg -y -f v4l2 -s '+image_width+'x'+image_height+' -i /dev/video0 -vframes 1 -vf '+video_filter+' image.jpg')
}
catch(err) {
success = false
}
}
while (success != true)
//
// remove prior images
//
date.setDate(date.getDate()-days_to_save)
var oldyear = date.getFullYear()
var oldmonth = ('0'+(1+parseInt(date.getMonth()))).slice(-2)
var oldday = ('0'+date.getDate()).slice(-2)
var oldhour = ('0'+date.getHours()).slice(-2)
var oldminute = ('0'+date.getMinutes()).slice(-2)
var prefix = oldyear+'-'+oldmonth+'-'+oldday+'-'+oldhour+'-'+oldminute+'*'
console.log('remove '+prefix)
execSync('rm -f images/'+prefix+'*')
execSync('rm -f thumbnails/'+prefix+'*')
//
// check if image has changed beyond threshold
//
try {
execSync('compare -metric RMSE image.jpg oldimage.jpg null: 2>&1')
}
catch(err) {
var ret = String(err.stdout).split(' ')
var ptrl = ret[1].indexOf('(')
var ptrr = ret[1].indexOf(')')
var diff = parseFloat(ret[1].slice(ptrl+1,ptrr))
console.log('image difference: '+diff)
}
if (diff > difference_threshold) {
//
// size has changed, keep image
//
console.log('activity detected, save image')
execSync('convert image.jpg -resize '+thumbnail_size+'x'+thumbnail_size+' thumbnails/'+name)
execSync('cp image.jpg images/'+name)
//
// rebuild day's index
//
console.log('reindex day')
execSync("echo '<html><body>' > index/newindex.html")
execSync("echo '<script src=../display.js></script>' > index/newindex.html")
execSync('ls images | awk \'/^'+year+'-'+month+'-'+day+'/ { print "<img src=\\"../thumbnails/" $1 "\\" id=\\"" $1 "\\" style=\\"width:20%;height:auto;cursor:pointer;\\" onmousedown=display(\\"" $1 "\\")>" }\' >> index/newindex.html')
execSync("mv index/newindex.html index/"+month+"-"+day+".html")
//
// delay before next image
//
console.log('delay before next image')
execSync('mv image.jpg oldimage.jpg')
setTimeout(update,millisecond_image_delay)
}
else {
//
// size hasn't changed
//
console.log('no activity detected, don\'t save image')
//
// no delay before next image
//
execSync('mv image.jpg oldimage.jpg')
setTimeout(update,0)
}
}
//
// take initial image
//
var success = true
do {
try {
execSync('ffmpeg -y -f v4l2 -s '+image_width+'x'+image_height+' -i /dev/video0 -vframes 1 -vf '+video_filter+' oldimage.jpg')
}
catch(err) {
success = false
}
}
while (success != true)
//
// start update
//
update()
[Unit]
Description=cams
After=network.target
[Service]
Type=forking
ExecStart=/bin/bash /home/fab/cams/cams
[Install]
WantedBy=multi-user.target
var lastid
function display(id) {
var img = document.getElementById(lastid)
if (img != null) {
img.src = "../thumbnails/"+id
img.style.width = "20%"
}
var img = document.getElementById(id)
img.src = "../images/"+id
img.style.width = "100%"
lastid = id
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.