Compare commits
10
Commits
7501d00d76
...
trunk
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba7da76850
|
||
|
|
af12893786
|
||
|
|
2648520089
|
||
|
|
d106e75304
|
||
|
|
dfa6f2997a
|
||
|
|
39d1f4d2eb
|
||
|
|
89bcb598b3
|
||
|
|
a2745fe5a0
|
||
|
|
974f604efd
|
||
|
|
6ef6f554ce
|
+12
@@ -0,0 +1,12 @@
|
||||
* vigil
|
||||
|
||||
vigil is a self-hosted security camera system. It uses [[https://motion-project.github.io/][motion]], [[https://docs.ultralytics.com/][yolo]], and scripts to provide:
|
||||
|
||||
- HTTPS livestream
|
||||
- Timelapse recording
|
||||
- Motion and object detection
|
||||
- Email notification
|
||||
|
||||
https://dwrz.net/timeline/2023-02-01.html discusses the initial design.
|
||||
|
||||
The project has been relocated and is retained here for reference only.
|
||||
+3
-3
@@ -52,9 +52,9 @@ stream_preview_method 0
|
||||
stream_tls on
|
||||
|
||||
# SCRIPTS
|
||||
on_motion_detected ${MOTION_DIR}/alert
|
||||
on_movie_end ${MOTION_DIR}/sync %f
|
||||
on_picture_save ${MOTION_DIR}/notify %f
|
||||
on_motion_detected ${MOTION_DIR}/scripts/alert
|
||||
on_movie_end ${MOTION_DIR}/scripts/sync %f
|
||||
on_picture_save ${MOTION_DIR}/scripts/notify %f
|
||||
|
||||
# CAMERA
|
||||
camera_name ${CAMERA_NAME}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ RefuseManualStop=yes
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=r53
|
||||
ExecStart=ddns
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
readonly WEBCONTROL_PORT="8080"
|
||||
readonly CAMERA_1="10.0.1.1"
|
||||
readonly CAMERA_2="10.0.1.2"
|
||||
readonly CAMERA_3="10.0.1.3"
|
||||
|
||||
err() {
|
||||
echo "[$(date -u +'%Y-%m-%dT%H:%M:%S%:z')]: $*" >&2
|
||||
}
|
||||
|
||||
main() {
|
||||
url="detection/status"
|
||||
case "$1" in
|
||||
"capture"|"c") url="detection/snapshot" ;;
|
||||
"pause"|"p") url="detection/pause" ;;
|
||||
"start"|"s") url="detection/start" ;;
|
||||
"status"|"") url="detection/status" ;;
|
||||
*) err "unrecognized command: $1"; exit 1
|
||||
esac
|
||||
|
||||
curl --digest --user "${MOTION_USER}:${MOTION_PASSWORD}" \
|
||||
"https://${CAMERA_1}:${WEBCONTROL_PORT}/0/${url}"
|
||||
curl --digest --user "${MOTION_USER}:${MOTION_PASSWORD}" \
|
||||
"https://${CAMERA_2}:${WEBCONTROL_PORT}/0/${url}"
|
||||
curl --digest --user "${MOTION_USER}:${MOTION_PASSWORD}" \
|
||||
"https://${CAMERA_3}:${WEBCONTROL_PORT}/0/${url}"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
+22
-26
@@ -1,8 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Backblaze B2 Bucket
|
||||
readonly BUCKET="${B2_BUCKET}"
|
||||
|
||||
# Devices to check -- if populated and up, no notifications are sent.
|
||||
readonly DEVICES=()
|
||||
|
||||
@@ -13,12 +10,16 @@ readonly LABEL_CAT=15
|
||||
# Lockfile to ensure that only one instance of the script is running.
|
||||
readonly LOCKFILE="/tmp/motion-notify.lock.d"
|
||||
|
||||
# yolov7 working directory.
|
||||
readonly PROJECT="/tmp/yolov7"
|
||||
# yolo26 working directory.
|
||||
readonly PROJECT="/tmp/yolo26"
|
||||
|
||||
# Notification recipient.
|
||||
readonly RECIPIENT="${NOTIFICATION_RECIPIENT}"
|
||||
|
||||
# rsync user and server for backups.
|
||||
readonly RSYNC_USER="${RSYNC_USER}"
|
||||
readonly RSYNC_SERVER="${RSYNC_SERVER}"
|
||||
|
||||
acquire_lock () {
|
||||
while true; do
|
||||
if mkdir "${LOCKFILE}"; then
|
||||
@@ -41,14 +42,14 @@ check_devices() {
|
||||
detect_objects() {
|
||||
local filepath="$1"
|
||||
|
||||
python "${HOME}/yolov7/detect.py" \
|
||||
--exist-ok \
|
||||
--no-trace \
|
||||
--save-txt \
|
||||
--project "${PROJECT}" \
|
||||
--name "motion" \
|
||||
--weights "${HOME}/yolov7/yolov7-tiny.pt" \
|
||||
--source "${filepath}"
|
||||
"${HOME}/.venv/bin/yolo" predict \
|
||||
classes=0 \
|
||||
conf=0.5 \
|
||||
model="${HOME}/yolo26n.pt" \
|
||||
name="motion" \
|
||||
project="${PROJECT}" \
|
||||
save_txt=true \
|
||||
source="$1"
|
||||
}
|
||||
|
||||
notify() {
|
||||
@@ -63,25 +64,16 @@ notify() {
|
||||
upload() {
|
||||
local name="$1"
|
||||
|
||||
backblaze-b2 upload-file \
|
||||
--threads 2 \
|
||||
"${BUCKET}" \
|
||||
"${PROJECT}/motion/${name}.jpg" \
|
||||
"${HOSTNAME}/photo/${name}.jpg"
|
||||
rsync --archive --verbose \
|
||||
"${PROJECT}/motion/${name}.jpg" \
|
||||
"${RSYNC_USER}@${RSYNC_SERVER}:/photo/${name}.jpg"
|
||||
}
|
||||
|
||||
delete_outdated() {
|
||||
local filepath="$1"
|
||||
|
||||
acquire_lock
|
||||
|
||||
rm -f "$1"
|
||||
rm -f "${PROJECT}/motion/${name}.jpg"
|
||||
find "${HOME}/photo/" -mmin +5 -delete
|
||||
find "${PROJECT}/motion/" -iname "*.jpg" -mmin +5 -delete
|
||||
find "${PROJECT}/motion/labels/" -mmin +5 -delete
|
||||
|
||||
release_lock
|
||||
rm -rf "${PROJECT}"
|
||||
}
|
||||
|
||||
release_lock () {
|
||||
@@ -93,10 +85,13 @@ main() {
|
||||
local name
|
||||
name="$(basename "${filepath}" .jpg)"
|
||||
|
||||
acquire_lock
|
||||
|
||||
# If devices are present, don't notify.
|
||||
if (( "${#DEVICES[@]}" )); then
|
||||
if check_devices; then
|
||||
delete_outdated "${filepath}" "${name}"
|
||||
release_lock
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
@@ -112,6 +107,7 @@ main() {
|
||||
upload "${name}"
|
||||
|
||||
delete_outdated "${filepath}" "${name}"
|
||||
release_lock
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
+9
-6
@@ -1,17 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
readonly BUCKET="${B2_BUCKET}"
|
||||
readonly RSYNC_USER="${RSYNC_USER}"
|
||||
readonly RSYNC_SERVER="${RSYNC_SERVER}"
|
||||
|
||||
main() {
|
||||
local filepath="$1"
|
||||
local name
|
||||
name="$(basename "${filepath}")"
|
||||
|
||||
backblaze-b2 upload-file \
|
||||
--threads 2 \
|
||||
"${BUCKET}" \
|
||||
"${HOME}/timelapse/${name}" \
|
||||
"${HOSTNAME}/timelapse/${name}"
|
||||
# Stagger transfers to avoid congestion at the hour mark.
|
||||
sleep $((RANDOM % 180))
|
||||
|
||||
# Limit bandwidth so the backup does not saturate the connection.
|
||||
rsync --archive --verbose --bwlimit=4096 \
|
||||
"${HOME}/timelapse/${name}" \
|
||||
"${RSYNC_USER}@${RSYNC_SERVER}:/timelapse/${name}"
|
||||
|
||||
# Delete outdated files.
|
||||
# This assumes the timelapse is created on an hourly basis.
|
||||
|
||||
@@ -21,6 +21,8 @@ MOTION_LOG_FILE="/var/log/motion/motion.log"
|
||||
MOTION_PASSWORD="$(tr -dc A-Za-z0-9 </dev/urandom | head -c 24 ; echo '')"
|
||||
MOTION_USER="${USER}"
|
||||
NOTIFICATION_RECIPIENT="1234567890@sms.example.com"
|
||||
RSYNC_USER="user"
|
||||
RSYNC_SERVER="server"
|
||||
PORT_CONTROL="8080"
|
||||
PORT_STREAM="3000"
|
||||
TLS_CERT="/etc/letsencrypt/live/${DOMAIN}/fullchain.pem"
|
||||
@@ -85,6 +87,14 @@ input_settings() {
|
||||
read -r input
|
||||
PORT_STREAM="${input:-$PORT_STREAM}"
|
||||
|
||||
printf "rsync user (%s): " "${RSYNC_USER}"
|
||||
read -r input
|
||||
RSYNC_USER="${input:-$RSYNC_USER}"
|
||||
|
||||
printf "rsync server (%s): " "${RSYNC_SERVER}"
|
||||
read -r input
|
||||
RSYNC_SERVER="${input:-$RSYNC_SERVER}"
|
||||
|
||||
printf "TLS certifcate path (%s): " "${TLS_CERT}"
|
||||
read -r input
|
||||
TLS_CERT="${input:-$TLS_CERT}"
|
||||
@@ -109,6 +119,8 @@ print_settings() {
|
||||
printf "Motion password: %s\n" "${MOTION_PASSWORD}"
|
||||
printf "Webcontrol port: %s\n" "${PORT_CONTROL}"
|
||||
printf "Livestream port: %s\n" "${PORT_STREAM}"
|
||||
printf "rsync user: %s\n" "${RSYNC_USER}"
|
||||
printf "rsync server: %s\n" "${RSYNC_SERVER}"
|
||||
printf "Notification recipient: %s\n" "${NOTIFICATION_RECIPIENT}"
|
||||
printf "TLS certificate: %s\n" "${TLS_CERT}"
|
||||
printf "TLS key: %s\n" "${TLS_KEY}"
|
||||
@@ -130,6 +142,8 @@ write_settings() {
|
||||
sed -i 's|\${NOTIFICATION_RECIPIENT}|'"${NOTIFICATION_RECIPIENT}"'|g' "${f}"
|
||||
sed -i 's|\${PORT_CONTROL}|'"${PORT_CONTROL}"'|g' "${f}"
|
||||
sed -i 's|\${PORT_STREAM}|'"${PORT_STREAM}"'|g' "${f}"
|
||||
sed -i 's|\${RSYNC_USER}|'"${RSYNC_USER}"'|g' "${f}"
|
||||
sed -i 's|\${RSYNC_SERVER}|'"${RSYNC_SERVER}"'|g' "${f}"
|
||||
sed -i 's|\${TLS_CERT}|'"${TLS_CERT}"'|g' "${f}"
|
||||
sed -i 's|\${TLS_KEY}|'"${TLS_KEY}"'|g' "${f}"
|
||||
done
|
||||
@@ -141,9 +155,10 @@ link_files() {
|
||||
ln -s "${PWD}/config/motion.conf" "/etc/motion/motion.conf"
|
||||
ln -s "${PWD}/config/msmtprc" "${MOTION_DIR}/.msmtprc"
|
||||
ln -s "${PWD}/config/muttrc" "${MOTION_DIR}/.muttrc"
|
||||
ln -s "${PWD}/scripts/alert" "${MOTION_DIR}/alert"
|
||||
ln -s "${PWD}/scripts/notify" "${MOTION_DIR}/notify"
|
||||
ln -s "${PWD}/scripts/sync" "${MOTION_DIR}/sync"
|
||||
mkdir -p "${MOTION_DIR}/scripts"
|
||||
ln -s "${PWD}/scripts/alert" "${MOTION_DIR}/scripts/alert"
|
||||
ln -s "${PWD}/scripts/notify" "${MOTION_DIR}/scripts/notify"
|
||||
ln -s "${PWD}/scripts/sync" "${MOTION_DIR}/scripts/sync"
|
||||
}
|
||||
|
||||
main() {
|
||||
|
||||
Reference in New Issue
Block a user