Security Cameras

From i3Detroit
Jump to: navigation, search
Current camera locations

Rules For Use

Security cameras are governed by i3Detroit's Security Camera policy.

History

Use of security cameras was approved originally in 2012. The policy was updated in 2015 to be included in the standing rules. The discussion of the 2015 proposal happened largely in Slack, in the archived channel #camera-policy. The standing rules section was modified in early 2016 to replace the 4-person viewing team with the Board of Directors. It was again modified in early 2017 to expand the viewing team to consist of at least one director and either one other director, officer, or zone coordinator.

Camera Locations

List of Current Cameras

Location View (not live)
Classroom Classroomcam.jpg
Craft Room Craftroomcam.jpg
CNC Shop CNCcam.jpg
Commons Area Commonscam.jpg
Commons Area & Snack Zone CommonsNE.jpg
Electronics Lab Elabcam.png
Fab Lab FabLabCam.jpg
Front & Garage Doors Entrancecam.PNG
Front Door Exterior Exteriorcam.jpg
Laser Zone Lasercam.jpg
Machine Shop 1 MachineShopCam1.JPG
Machine Shop 2 Machineshopcam2.jpg
Media Lab Medialabcam.jpg
Suite B Rear Doors Westsideoffice.jpg
Suite B Rear Doors Westsiderear.jpg
Suite B Shop Doors Westsideshopdoors.jpg
Tool Crib ToolCribCam.jpg
Welding Zone Weldingcam.PNG
West Shop (Bike, Vinyl, & Jewelry zones Westshopcam.jpg
Wood Shop North WoodShopNorthCam.jpg
Wood Shop South & Tool Crib benches Woodshopsouthcam.jpg

History of Camera Location Approval

Status Report from Project Lead

POC:Mike

  • 18 of 18 approved planned cameras have been installed. See below for technical details.
  • (10/19/17) System is in working order and has been for several months now.
  • (6/9/2018) System still working well, no major issues. 15/18 cameras have 240+ days continuous uptime.

To Do

Task Name Description Priority Champion
Reconfigure Network for camera VLAN Move all the cameras over to their own VLAN separate from the main public network. 3
Install GPU in VMServer Install an Nvidia 6xx or newer GPU to enable GPU accelerated h.264 encoding for archived video. 5

Technical Details of Zoneminder & IP Camera System

  • Zoneminder v1.32.1 running on VMServer
  • 1x 4TB Western Digital Purple Surveilance, 1x 4TB Western Digital Red hard disks installed in the VMServer
  • 18 wired PoE IP cameras
    • 13xHikvision 4.1MP DS-2CD2042WD-I 4mm IP Camera
    • 5xHikvision DS-2CD2432F-IW 3MP Indoor 2.8mm IP Camera

Maintenance Scripts

Archving

Zoneminder currently stores all data as jpeg frames. This is nice and simple, but uses 10 times as much disk space as the data does once encoded as h264 video. This script is set to run daily to archive the previous day as h264 video, one file per 1-hour period per camera. It also makes sure back-ups were done on previous days.

#!/bin/bash

# get a list of active monitor numbers from zoneminder
# I have no idea how this works but it does
camrange=$(zmu -U USERNAME -P PASSWORD -l | awk '{ print $1}' | sed 's/Id//g' | sed ':a;N;$!ba;s/\n/ /g')

# associate plaintext names with monitor numbers for humans
for i in {0..25}; do cameralist[$i]="undefined"; done
cameralist[1]="Entry"
cameralist[4]="E-Lab"
cameralist[7]="FabLab"
cameralist[8]="Classroom"
cameralist[9]="Craftroom"
cameralist[10]="MediaLab"
cameralist[11]="Welding"
cameralist[12]="Lasers"
cameralist[13]="MachineShopWest"
cameralist[14]="ToolCrib"
cameralist[15]="WoodShopNorth"
cameralist[16]="CommonsSW"
cameralist[17]="WestShop"
cameralist[18]="WoodShopSouth"
cameralist[19]="ExteriorSE"
cameralist[20]="CNCZone"
cameralist[21]="CommonsNE"
cameralist[22]="MachineShopEast"

# get an offset date value - offset must be >= 1 unless libtimetravel is installed
offset=$1
year=$(date +"%Y" -d "-${offset}days")
month=$(date +"%m" -d "-${offset}days")
day=$(date +"%d" -d "-${offset}days")
shortyear=$(date +"%y" -d "-${offset}days")
nextdayoffset="$((offset-1))"
nextday=$(date +"%d" -d "-${nextdayoffset}days")
nextdaymonth=$(date +"%m" -d "-${nextdayoffset}days")
nextdayyear=$(date +"%Y" -d "-${nextdayoffset}days")

ArchiveDir="/Archive/directory"

# directories to put stuff
mkdir $ArchiveDir/$year
mkdir $ArchiveDir/$year/$month
mkdir $ArchiveDir/$year/$month/$day

#backup the SQL database info for the day's events
mysql --user=redacted --password=zmpass --database=zm -e "select * from Events where StartTime >= '$year-$month-$day 00:00:00' AND StartTime < '$nextdayyear-$nextdaymonth-$nextday 00:00:00';" > /mnt/cameraArchive/metadata/$year-$month-$day-metadata.txt

# Doing the backups
for cam in $camrange
do
	mkdir $ArchiveDir/$year/$month/$day/$cam-${cameralist[$cam]}
	mkdir $ArchiveDir/$year/$month/$day/$cam-${cameralist[$cam]}/logs
	for hour in {00..23}
	do
		# Write a list of frames to a file, in a format to pass to ffmpeg
		for f in /var/cache/zoneminder/events/$cam/$shortyear/$month/$day/$hour/*/*/*.jpg
		do
			echo "file '$f'" >> $ArchiveDir/$year/$month/$day/$cam-${cameralist[$cam]}/logs/${hour}00.log
		done
		
		# Do the actual conversion - throw every jpeg in the whole hour (in the range X0000-X9999) into one video file
		# Currently have no fancy output parameters. -r 25 sets 25fps, which is totally arbitrary and doesn't really matter.
		# Most monitors are recording at 4 or 6 fps, so this just speeds up playback/review.
		# ffmpeg was self-compiled due to Debian's ffmpeg/libav debacle
		echo "Processing $year $month $day - Hour $hour - $cam ${cameralist[$cam]}"
		/home/mkfink/bin/ffmpeg -f concat -safe 0 -i $ArchiveDir/$year/$month/$day/$cam-${cameralist[$cam]}/logs/${hour}00.log -vf scale=iw*.75:ih*.75 -pix_fmt yuv420p -map 0 $ArchiveDir/$year/$month/$day/${cam}-${cameralist[$cam]}/${cam}-${cameralist[$cam]}-$year$month${day}_${hour}00.mkv
	done
done
chown -R www-data:www-data $ArchiveDir/$year/$month/$day

# Create a log file indicating the backup has finished
# and throw a note into slack that the job finished
pretext="Archiving complete for "
dash="-"
posttext=". Size of day encoded is "
daysize=$(du -hs $ArchiveDir/$year/$month/$day | awk '{print $1}')
zmsize=$(du -hsc /var/cache/zoneminder/events/*/$shortyear/$month/$day/ | tail -n1)
postposttext=" from ZM data size "
text=$pretext$year$dash$month$dash$day$posttext$daysize$postposttext$zmsize
# make the log file
echo $text > $ArchiveDir/$year/$month/$day/backupcomplete.log
webhook_url="redacted"
channel=#statusbots
# send to slack
escapedText=$(echo $text | sed 's/"/\"/g' | sed "s/'/\'/g" )
json="{\"channel\": \"$channel\", \"text\": \"$escapedText\"}"
curl -s -d "payload=$json" "$webhook_url"

# check for missing backups
testoffset=$offset
missingdays=0
dayexists=0
while [ $dayexists == 0 ]
do
	((testoffset++))
	testyear=$(date +"%Y" -d "-${testoffset}days")
	testmonth=$(date +"%m" -d "-${testoffset}days")
	testday=$(date +"%d" -d "-${testoffset}days")
	if [ -f "$ArchiveDir/$testyear/$testmonth/$testday/backupcomplete.log" ]
	then
		dayexists=1
		echo "true"
	else
		((missingdays++))
		echo $dayexists$testyear$testmonth$testday
	fi
done

# complain about missing backups
if [ $missingdays -gt 0 ]
then
	pretext2="Alert! Backups are incomplete or missing for "
	posttext2=" days. Please manually start backups."
	text2=$pretext2$missingdays$posttext2
	escapedText=$(echo $text2 | sed 's/"/\"/g' | sed "s/'/\'/g" )
	json="{\"channel\": \"$channel\", \"text\": \"$escapedText\"}"
	curl -s -d "payload=$json" "$webhook_url"
fi


Maintenance

Sometimes cameras get disconnected and zoneminder shows a blank blue 'no signal' image. This runs a few times a day, checking to see if any cameras are doing this.

#!/bin/bash

# get a list of active monitor numbers from zoneminder
range=$(zmu -U USERNAME -P PASSWORD -l | awk '{ print $1}' | sed 's/Id//g' | sed ':a;N;$!ba;s/\n/ /g')

for x in $range
do
	#echo $x
	zmu -U USERNAME -P PASSWORD -i -m $x
	redval=$(convert Monitor$x.jpg -scale 1x1\! -format '%[fx:int(255*r+.5)]' info:-)
	greenval=$(convert Monitor$x.jpg -scale 1x1\! -format '%[fx:int(255*g+.5)]' info:-)
	blueval=$(convert Monitor$x.jpg -scale 1x1\! -format '%[fx:int(255*b+.5)]' info:-)
	if [ $blueval -gt 190 ] && [ $redval -lt 4 ] && [ $greenval -lt 4 ]
	then
		#Run a script to complain about this in Slack
		/home/mkfink/camscripts/camwarn.sh $x
	fi
	rm Monitor$x.jpg
done


Zoneminder does a good job policing its own disk use (as long as it's not generating data faster than it deletes it, which happened once. Oops.) but just to make sure, and to keep track of the h264 archiviving, this reports disk use to slack every day.

#!/bin/bash
#get current disk usage percent as a number

CURRENT=$(df /mnt/cameraCurrent | grep / | awk '{ print $5}' | sed 's/%//g')
ARCHIVE=$(df /mnt/cameraArchive | grep / | awk '{ print $5}' | sed 's/%//g')

webhook_url="redacted"

channel=#statusbots

now=$(date)
pretext="Active camera disk usage is "
posttext="%. "
pretext2="Archive disk usage is "
text=$pretext$CURRENT$posttext$pretext2$ARCHIVE$posttext

escapedText=$(echo $text | sed 's/"/\"/g' | sed "s/'/\'/g" )
json="{\"channel\": \"$channel\", \"text\": \"$escapedText\"}"

curl -s -d "payload=$json" "$webhook_url"