diff --git a/firmware_mod/bin/matrix b/firmware_mod/bin/matrix index c09dfa7..57ce1e2 100755 --- a/firmware_mod/bin/matrix +++ b/firmware_mod/bin/matrix @@ -1,18 +1,54 @@ #!/bin/sh +CURL="/system/sdcard/bin/curl --silent" +JQ="/system/sdcard/bin/jq" + what="$1" -shift -data="$@" -CURL="/system/sdcard/bin/curl" + +if [ "$what" = "m" ]; then + shift + sendtext="${@//\"/\\\"}" +else + filename="$2" + datafile="$3" +fi . /system/sdcard/config/matrix.conf -sendMessage() { - text="$(echo "${@}" | sed 's:\\n:\n:g')" - echo "Sending message: $text" +uploadData() { + mimetype="$1" + msgtype="$2" - $CURL -XPOST -d '{"msgtype":"m.text", "body":"'$text'"}' "https://$host:$port/_matrix/client/r0/rooms/$room_id/send/m.room.message?access_token=$access_token" + mxcuri="$($CURL -XPOST -H "Content-Type: $mimetype" --data-binary @"$datafile" "https://$host:$port/_matrix/media/r0/upload?filename=$filename&access_token=$access_token" | $JQ -cMr ".content_uri")" + if [ -n "$mxcuri" ] && [ "$mxcuri" != "null" ]; then + $CURL -XPOST -d '{"msgtype":"'"$msgtype"'", "body":"'"$filename"'", "url":"'"$mxcuri"'"}' "https://$host:$port/_matrix/client/r0/rooms/$room_id/send/m.room.message?access_token=$access_token" + fi } -[ "$what" = "m" ] && sendMessage $data -[ -z "$what" ] && echo -e "$0 \n m: message\n f: file\n p: picture" +sendFile() { + echo "Sending file: $datafile" + uploadData "application/octet-stream" "m.file" +} + +sendMessage() { + echo "Sending message: $sendtext" + $CURL -XPOST -d '{"msgtype":"m.notice", "body":"'"$sendtext"'"}' "https://$host:$port/_matrix/client/r0/rooms/$room_id/send/m.room.message?access_token=$access_token" +} + +sendPicture() { + echo "Sending picture: $datafile" + filename="$filename.jpg" + uploadData "image/jpeg" "m.image" +} + +sendVideo() { + echo "Sending video: $datafile" + filename="$filename.mp4" + uploadData "video/mp4" "m.video" +} + +[ "$what" = "f" ] && sendFile +[ "$what" = "m" ] && sendMessage +[ "$what" = "p" ] && sendPicture +[ "$what" = "v" ] && sendVideo +[ -z "$what" ] && echo -e "$0 \n m: message\n f: file\n p: picture\n v: video" diff --git a/firmware_mod/bin/telegram b/firmware_mod/bin/telegram index 894a1fa..c5f8163 100755 --- a/firmware_mod/bin/telegram +++ b/firmware_mod/bin/telegram @@ -18,45 +18,66 @@ sendMessage() { } sendFile() { - echo "Sending file: $1" - $CURL -s \ - -X POST \ - https://api.telegram.org/bot$apiToken/sendDocument \ - -F chat_id="$userChatId" \ - -F document=@"$1" + if [ -r $1 ] + then + echo "Sending file: $1" + $CURL -s \ + -X POST \ + https://api.telegram.org/bot$apiToken/sendDocument \ + -F chat_id="$userChatId" \ + -F document=@"$1" + else + echo "File not found: $1" + fi } sendPhoto() { - caption="$(hostname)-$(date +"%d%m%Y_%H%M%S")" - echo "Sending Photo: $1 $caption" >> /tmp/telegram.log - $CURL -s \ - -X POST \ - https://api.telegram.org/bot$apiToken/sendPhoto \ - -F chat_id="$userChatId" \ - -F photo="@${1}" \ - -F caption="${caption}" + if [ -r $1 ] + then + caption="$(hostname)-$(date +"%d%m%Y_%H%M%S")" + echo "Sending Photo: $1 $caption" >> /tmp/telegram.log + $CURL -s \ + -X POST \ + https://api.telegram.org/bot$apiToken/sendPhoto \ + -F chat_id="$userChatId" \ + -F photo="@${1}" \ + -F caption="${caption}" + else + echo "File not found: $1" + fi } sendVideo() { - caption="$(hostname)-$(date +"%d%m%Y_%H%M%S")" - echo "Sending Video: $1 $caption" >> /tmp/telegram.log - $CURL -s \ - -X POST \ - https://api.telegram.org/bot$apiToken/sendVideo \ - -F chat_id="$userChatId" \ - -F video="@${1}" \ - -F caption="${caption}" + if [ -r $1 ] + then + bytes=$(busybox stat -c %s $1) + caption="$(hostname)-$(date +"%d%m%Y_%H%M%S")" + echo "Sending Video: $1 $caption (${bytes}bytes)" >> /tmp/telegram.log + $CURL -s \ + -X POST \ + https://api.telegram.org/bot$apiToken/sendVideo \ + -F chat_id="$userChatId" \ + -F video="@${1}" \ + -F caption="${caption}" + else + echo "File not found: $1" + fi } sendAnimation() { - caption="$(hostname)-$(date +"%d%m%Y_%H%M%S")" - echo "Sending Animation: $1 $caption" >> /tmp/telegram.log - $CURL -s \ - -X POST \ - https://api.telegram.org/bot$apiToken/sendAnimation \ - -F chat_id="$userChatId" \ - -F animation="@${1}" \ - -F caption="${caption}" + if [ -r $1 ] + then + caption="$(hostname)-$(date +"%d%m%Y_%H%M%S")" + echo "Sending Animation: $1 $caption" >> /tmp/telegram.log + $CURL -s \ + -X POST \ + https://api.telegram.org/bot$apiToken/sendAnimation \ + -F chat_id="$userChatId" \ + -F animation="@${1}" \ + -F caption="${caption}" + else + echo "File not found: $1" + fi } [ "$what" == "m" ] && sendMessage $data diff --git a/firmware_mod/config/motion.conf.dist b/firmware_mod/config/motion.conf.dist index 465b782..a629aee 100644 --- a/firmware_mod/config/motion.conf.dist +++ b/firmware_mod/config/motion.conf.dist @@ -24,6 +24,7 @@ send_email=false send_telegram=false telegram_alert_type=image send_matrix=false +matrix_alert_type=image night_mode_event_delay=30 # General @@ -63,6 +64,7 @@ ftp_videos_dir="motion/videos" # Configure Dropbox snapshots and videos dropbox_snapshot=false dropbox_video=false +dropbox_url="https://content.dropboxapi.com/2/files/upload" dropbox_token="token" dropbox_stills_dir="/motion/stills" dropbox_videos_dir="/motion/videos" diff --git a/firmware_mod/config/rtspserver.conf.dist b/firmware_mod/config/rtspserver.conf.dist index b83c112..4667404 100644 --- a/firmware_mod/config/rtspserver.conf.dist +++ b/firmware_mod/config/rtspserver.conf.dist @@ -49,7 +49,7 @@ FRAMERATE_NUM=25 VIDEOFORMAT=2 # AudioFormat -# Can be: OPUS | MP3 | PCM | PCMU +# Can be: OPUS | MP3 | PCM | PCMU | OFF AUDIOFORMAT=MP3 # Audio sampling rate AUDIOINBR=16000 diff --git a/firmware_mod/scripts/detectionOn.sh b/firmware_mod/scripts/detectionOn.sh index 3a52f83..e8e9f97 100644 --- a/firmware_mod/scripts/detectionOn.sh +++ b/firmware_mod/scripts/detectionOn.sh @@ -40,24 +40,29 @@ send_snapshot() { if [ "$telegram_alert_type" = "text" ] ; then debug_msg "Send telegram text" /system/sdcard/bin/telegram m "Motion detected" - elif [ "$telegram_alert_type" = "image" -o "$telegram_alert_type" = "video+image" ] ; then + elif [ "$telegram_alert_type" = "image" -o "$telegram_alert_type" = "video+image" ] ; then debug_msg "Send telegram image" /system/sdcard/bin/telegram p "$snapshot_tempfile" fi ) & fi - # Send a matrix message + # Send a matrix message or image if [ "$send_matrix" = true ]; then ( include /system/sdcard/config/matrix.conf - debug_msg "Send matrix message" - /system/sdcard/bin/matrix m "Motion detected" + + if [ "$matrix_alert_type" = "text" ] ; then + debug_msg "Send matrix text" + /system/sdcard/bin/matrix m "Motion detected" + elif [ "$matrix_alert_type" = "image" -o "$matrix_alert_type" = "video+image" ] ; then + debug_msg "Send matrix image" + /system/sdcard/bin/matrix p "$filename" "$snapshot_tempfile" + fi ) & fi - - #save FTP snapshot + # Save FTP snapshot if [ "$ftp_snapshot" = true ]; then ( ftpput_cmd="/system/sdcard/bin/busybox ftpput" @@ -78,12 +83,11 @@ send_snapshot() { ) & fi - #save Dropbox snapshot + # Save Dropbox snapshot if [ "$dropbox_snapshot" = true ]; then ( - debug_msg "Sending Dropbox snapshot to $dropbox_stills_dir/$filename.jpg" - /system/sdcard/bin/curl -X POST https://content.dropboxapi.com/2/files/upload \ + /system/sdcard/bin/curl -X POST "$dropbox_url" \ --header "Authorization: Bearer $dropbox_token" \ --header "Dropbox-API-Arg: {\"path\": \"$dropbox_stills_dir/$filename.jpg\"}" \ --header "Content-Type: application/octet-stream" \ @@ -91,17 +95,15 @@ send_snapshot() { ) & fi + # Save a snapshot + if [ "$save_snapshot" = true ] ; then + ( + debug_msg "Save snapshot to $save_snapshot_dir/$groupname/$filename.jpg" - - # Save a snapshot - if [ "$save_snapshot" = true ] ; then - ( - debug_msg "Save snapshot to $save_snapshot_dir/$groupname/$filename.jpg" - - if [ ! -d "$save_snapshot_dir/$groupname" ]; then - mkdir -p "$save_snapshot_dir/$groupname" - chmod "$save_dirs_attr" "$save_snapshot_dir/$groupname" - fi + if [ ! -d "$save_snapshot_dir/$groupname" ]; then + mkdir -p "$save_snapshot_dir/$groupname" + chmod "$save_dirs_attr" "$save_snapshot_dir/$groupname" + fi # Limit the number of snapshots if [ "$(ls "$save_snapshot_dir" | wc -l)" -ge "$max_snapshot_days" ]; then @@ -113,7 +115,7 @@ send_snapshot() { ) & fi - ## Save SMB snapshot + # Save SMB snapshot if [ "$smb_snapshot" = true ]; then ( smbclient_cmd="/system/bin/smbclient $smb_share" @@ -131,6 +133,7 @@ send_snapshot() { $smbclient_cmd -D "$smb_stills_path" -c "lcd /tmp; mkdir $groupname; cd $groupname; put $snapshot_tempfilename; rename $snapshot_tempfilename $filename.jpg" ) & fi + # Wait for all background jobs to finish before existing debug_msg "Waiting for background jobs to end in send_snapshot function:" for jobpid in $(jobs -p); do @@ -141,11 +144,11 @@ send_snapshot() { } record_video () { - # We only want one video stream at a time. Try to grab an - # exclusive flock on file descriptor 5. Bail out if another - # process already has it. Touch the flock to update it's mod - # time as a signal to the background process to keep recording - # when motion is repeatedly observed. + # We only want one video stream at a time. Try to grab an exclusive + # flock on file descriptor 5. Bail out if another process already has + # it. Touch the flock to update its mod time as a signal to the + # background process to keep recording when motion is repeatedly + # observed. touch /run/recording_video.flock exec 5<> /run/recording_video.flock if /system/sdcard/bin/busybox flock -n -x 5; then @@ -159,7 +162,6 @@ record_video () { else /system/sdcard/bin/openRTSP -4 -w "$video_rtsp_w" -h "$video_rtsp_h" -f "$video_rtsp_f" -d "$video_duration" -b "$output_buffer_size" rtsp://$USERNAME:$USERPASSWORD@127.0.0.1:$PORT/unicast > "$video_tempfile" fi - else # Use avconv to stitch multiple JPEGs into 1fps video. # I couldn't get it working another way. @@ -205,18 +207,23 @@ filename=$(date "$filename_pattern") /system/sdcard/bin/getimage > "$snapshot_tempfile" debug_msg "Got snapshot_tempfile=$snapshot_tempfile" -#Next send picture alerts in the background +# Next send picture alerts in the background send_snapshot & # Then, record video (if necessary) -if [ "$save_video" = true -o "$smb_video" = true -o "$telegram_alert_type" = "video+image" -o "$telegram_alert_type" = "video" -o "$publish_mqtt_video" = true ] ; then +if [ "$save_video" = true ] || + [ "$smb_video" = true ] || + [ "$dropbox_video" = true ] || + ([ "$send_telegram" = true ] && ([ "$telegram_alert_type" = video+image ] || [ "$telegram_alert_type" = video ])) || + ([ "$send_matrix" = true ] && ([ "$matrix_alert_type" = video+image ] || [ "$matrix_alert_type" = video ])) || + [ "$publish_mqtt_video" = true ] +then record_video fi # Next, start background tasks for all configured video notifications - # Save the video if [ "$save_video" = true ] ; then ( @@ -252,11 +259,11 @@ if [ "$ftp_video" = true ]; then fi ftpput_cmd="$ftpput_cmd $ftp_host" - # We only want one video stream at a time. Try to grab an - # exclusive flock on file descriptor 5. Bail out if another - # process already has it. Touch the flock to update it's mod - # time as a signal to the background process to keep recording - # when motion is repeatedly observed. + # We only want one video stream at a time. Try to grab an exclusive + # flock on file descriptor 5. Bail out if another process already has + # it. Touch the flock to update it's mod time as a signal to the + # background process to keep recording when motion is repeatedly + # observed. touch /run/ftp_motion_video_stream.flock exec 5<> /run/ftp_motion_video_stream.flock if /system/sdcard/bin/busybox flock -n -x 5; then @@ -265,10 +272,10 @@ if [ "$ftp_video" = true ]; then # XXX Uses avconv to stitch multiple JPEGs into 1fps video. # I couldn't get it working another way. /dev/videoX inputs - # fail. Localhost rtsp takes very long (10+ seconds) to - # start streaming and gets flaky when when memory or cpu - # are pegged. This is a clugy method, but works well even - # at high res, fps, cpu, and memory load! + # fail. Localhost rtsp takes very long (10+ seconds) to start + # streaming and gets flaky when when memory or cpu are pegged. + # This is a clugy method, but works well even at high res, + # fps, cpu, and memory load! ( while [ "$(/system/sdcard/bin/busybox date "+%s")" -le "$(/system/sdcard/bin/busybox expr "$(/system/sdcard/bin/busybox stat -c "%X" /run/ftp_motion_video_stream.flock)" + "$video_duration")" ]; do /system/sdcard/bin/getimage sleep 1 @@ -285,21 +292,17 @@ if [ "$ftp_video" = true ]; then ) & fi - #save Dropbox video - if [ "$dropbox_video" = true ]; then - ( - - debug_msg "Saving Dropbox snapshot to $dropbox_videos_dir/$filename.mp4" - /system/sdcard/bin/curl -X POST https://content.dropboxapi.com/2/files/upload \ - --header "Authorization: Bearer $dropbox_token" \ - --header "Dropbox-API-Arg: {\"path\": \"$dropbox_videos_dir/$filename.mp4\"}" \ - --header "Content-Type: application/octet-stream" \ - --data-binary @"$video_tempfile" - ) & - fi - - - +# Save Dropbox video +if [ "$dropbox_video" = true ]; then + ( + debug_msg "Saving Dropbox snapshot to $dropbox_videos_dir/$filename.mp4" + /system/sdcard/bin/curl -X POST "$dropbox_url" \ + --header "Authorization: Bearer $dropbox_token" \ + --header "Dropbox-API-Arg: {\"path\": \"$dropbox_videos_dir/$filename.mp4\"}" \ + --header "Content-Type: application/octet-stream" \ + --data-binary @"$video_tempfile" + ) & +fi # SMB snapshot and video if [ "$smb_video" = true ]; then @@ -342,14 +345,20 @@ if [ "$send_telegram" = true ]; then ( include /system/sdcard/config/telegram.conf - if [ "$telegram_alert_type" = "video" -o "$telegram_alert_type" = "video+image" ] ; then - debug_msg "Send telegram video" + if [ "$telegram_alert_type" = "video" -o "$telegram_alert_type" = "video+image" ] ; then if [ "$video_use_rtsp" = true ]; then - #Convert file to mp4 and remove audio stream so video plays in telegram app - /system/sdcard/bin/avconv -i "$video_tempfile" -c:v copy -an "$video_tempfile"-telegram.mp4 - /system/sdcard/bin/telegram v "$video_tempfile"-telegram.mp4 - rm "$video_tempfile"-telegram.mp4 + if [ "$AUDIOFORMAT" = "PCMU" ] || [ "$AUDIOFORMAT" = "OFF" ] ; then + # Convert file to mp4 and remove audio stream so video plays in telegram app + debug_msg "Send telegram video" + /system/sdcard/bin/avconv -i "$video_tempfile" -c:v copy -an "$video_tempfile"-telegram.mp4 + /system/sdcard/bin/telegram v "$video_tempfile"-telegram.mp4 + rm "$video_tempfile"-telegram.mp4 else + # avconv can't strip audio it doesn't understand + debug_msg "Send telegram video (only viable for external playback)" + /system/sdcard/bin/telegram v "$video_tempfile" + fi + else /system/sdcard/bin/avconv -i "$video_tempfile" "$video_tempfile-lo.mp4" /system/sdcard/bin/telegram v "$video_tempfile-lo.mp4" rm "$video_tempfile-lo.mp4" @@ -358,15 +367,33 @@ if [ "$send_telegram" = true ]; then ) & fi +# Send a matrix video +if [ "$send_matrix" = true ]; then + ( + include /system/sdcard/config/matrix.conf + + if [ "$matrix_alert_type" = "video" -o "$matrix_alert_type" = "video+image" ] ; then + debug_msg "Send matrix video" + if [ "$video_use_rtsp" = true ]; then + /system/sdcard/bin/matrix v "$filename" "$video_tempfile" + else + /system/sdcard/bin/avconv -i "$video_tempfile" "$video_tempfile-lo.mp4" + /system/sdcard/bin/matrix v "$filename" "$video_tempfile-lo.mp4" + rm -f "$video_tempfile-lo.mp4" + fi + fi + ) & +fi + # Run any user scripts. for i in /system/sdcard/config/userscripts/motiondetection/*; do - if [ -x "$i" ]; then - debug_msg "Running: $i on $snapshot_tempfile" - $i on "$snapshot_tempfile" "$video_tempfile" & - fi + if [ -x "$i" ]; then + debug_msg "Running: $i on $snapshot_tempfile" + $i on "$snapshot_tempfile" "$video_tempfile" & + fi done -# Wait for all background jobs to finish before existing and deleting tempfile +# Wait for all background jobs to finish before exiting and deleting tempfile debug_msg "Waiting for background jobs to end:" for jobpid in $(jobs -p); do wait "$jobpid" diff --git a/firmware_mod/scripts/telegram-bot-daemon.sh b/firmware_mod/scripts/telegram-bot-daemon.sh index 37fa85a..3ed793b 100644 --- a/firmware_mod/scripts/telegram-bot-daemon.sh +++ b/firmware_mod/scripts/telegram-bot-daemon.sh @@ -11,6 +11,10 @@ JQ="/system/sdcard/bin/jq" [ -z $apiToken ] && echo "api token not configured yet" && exit 1 [ -z $userChatId ] && echo "chat id not configured yet" && exit 1 +status() { + $TELEGRAM m "Motion detection `motion_detection status`\nNight mode `night_mode status`\nAlert type `get_config /system/sdcard/config/motion.conf telegram_alert_type`" +} + sendShot() { /system/sdcard/bin/getimage > "/tmp/telegram_image.jpg" &&\ $TELEGRAM p "/tmp/telegram_image.jpg" @@ -52,10 +56,16 @@ videoAlerts() { $TELEGRAM m "Video alerts on motion detection enabled" } +imageThenVideoAlerts() { + rewrite_config /system/sdcard/config/motion.conf telegram_alert_type "video+image" + $TELEGRAM m "Image then video alerts on motion detection enabled" +} + respond() { cmd=$1 [ $chatId -lt 0 ] && cmd=${1%%@*} case $cmd in + /status) status;; /mem) sendMem;; /shot) sendShot;; /on) detectionOn;; @@ -65,7 +75,8 @@ respond() { /textalerts) textAlerts;; /imagealerts) imageAlerts;; /videoalerts) videoAlerts;; - /help | /start) $TELEGRAM m "######### Bot commands #########\n# /mem - show memory information\n# /shot - take a snapshot\n# /on - motion detection on\n# /off - motion detection off\n# /nighton - night mode on\n# /nightoff - night mode off\n# /textalerts - Text alerts on motion detection\n# /imagealerts - Image alerts on motion detection\n# /videoalerts - Video alerts on motion detection";; + /dualalerts) imageThenVideoAlerts;; + /help | /start) $TELEGRAM m "######### Bot commands #########\n# /mem - show memory information\n# /status - show current camera status\n# /shot - take a snapshot\n# /on - motion detection on\n# /off - motion detection off\n# /nighton - night mode on\n# /nightoff - night mode off\n# /textalerts - Text alerts on motion detection\n# /imagealerts - Image alerts on motion detection\n# /videoalerts - Video alerts on motion detection\n# /dualalerts - Image snapshot then video alerts on motion detection";; /*) $TELEGRAM m "I can't respond to '$cmd' command" esac } @@ -109,7 +120,8 @@ main() { if [ "$chatId" != "$userChatId" ]; then username=$(echo "$json" | $JQ -r ".result[0].$messageAttr.from.username // \"\"") firstName=$(echo "$json" | $JQ -r ".result[0].$messageAttr.from.first_name // \"\"") - $TELEGRAM m "Received message from unauthorized chat id: $chatId\nUser: $username($firstName)\nMessage: $cmd" + # Uncomment to get notified of attempted chat spam + # $TELEGRAM m "Received message from unauthorized chat id: $chatId\nUser: $username($firstName)\nMessage: $cmd" else respond $cmd fi; diff --git a/firmware_mod/www/cgi-bin/audio_upload.cgi b/firmware_mod/www/cgi-bin/audio_upload.cgi new file mode 100644 index 0000000..6ff4bb7 --- /dev/null +++ b/firmware_mod/www/cgi-bin/audio_upload.cgi @@ -0,0 +1,14 @@ +#!/bin/sh + +echo "Content-type: text/html" +echo "Pragma: no-cache" +echo "Cache-Control: max-age=0, no-store, no-cache" +echo "" + +if [ "${REQUEST_METHOD}" = "POST" ] +then + in_raw=`dd bs=1 count=${CONTENT_LENGTH} 1>/tmp/playback.wav` + sed -i -e '1,/Content-Type:/d' /tmp/playback.wav + echo " CONTENT LENGTH ${CONTENT_LENGTH}" + /system/sdcard/bin/audioplay /tmp/playback.wav 60 +fi diff --git a/firmware_mod/www/cgi-bin/ui_control.cgi b/firmware_mod/www/cgi-bin/ui_control.cgi index f25adcf..51db5aa 100755 --- a/firmware_mod/www/cgi-bin/ui_control.cgi +++ b/firmware_mod/www/cgi-bin/ui_control.cgi @@ -41,7 +41,7 @@ if [ -n "$F_cmd" ]; then do if [[ -f $file ]]; then file_size=$(ls -lh $file | awk '{print $5}') - file_url=$(ls -lh $file | awk '{print $9}' | sed 's/\/system\/sdcard\/DCIM/\/viewer/') + file_url=$(ls -lh $file | awk '{print $9}' | sed 's/\/system\/sdcard\/DCIM/viewer/') file_date=$(ls -lh $file | awk '{print $6 "-" $7 "-" $8}') file_name=$(ls -lh $file | awk '{print $9}' | awk -F / '{print $(NF)}') echo "${file_name}#:#${file_size}#:#${file_date}#:#${file_url}" @@ -51,12 +51,12 @@ if [ -n "$F_cmd" ]; then ;; del_config) - F_file=$(echo ${F_file} | sed -e 's/%2F/\//g' | sed -e 's/viewer/system\/sdcard\/DCIM/') + F_file=$(echo ${F_file} | sed -e 's/%2F/\//g' | sed -e 's/viewer/\/system\/sdcard\/DCIM/') echo "Remove ${F_file}" rm $F_file ;; restore_config) - F_file=$(echo ${F_file} | sed -e 's/%2F/\//g' | sed -e 's/viewer/system\/sdcard\/DCIM/') + F_file=$(echo ${F_file} | sed -e 's/%2F/\//g' | sed -e 's/viewer/\/system\/sdcard\/DCIM/') tar -xf $F_file -C /system/sdcard/config/ echo "Restore done" /sbin/reboot diff --git a/firmware_mod/www/cgi-bin/ui_motion.cgi b/firmware_mod/www/cgi-bin/ui_motion.cgi index 4b36ce0..fafc021 100755 --- a/firmware_mod/www/cgi-bin/ui_motion.cgi +++ b/firmware_mod/www/cgi-bin/ui_motion.cgi @@ -40,6 +40,7 @@ if [ -n "$F_cmd" ]; then echo "dropboxVideosDir#:#${dropbox_videos_dir}" echo "dropboxSnapshot#:#${dropbox_snapshot}" echo "dropboxVideo#:#${dropbox_video}" + echo "dropboxUrl#:#${dropbox_url}" echo "dropboxToken#:#${dropbox_token}" echo "smbSnapshot#:#${smb_snapshot}" echo "smbVideo#:#${smb_video}" @@ -56,6 +57,7 @@ if [ -n "$F_cmd" ]; then echo "sendTelegram#:#${send_telegram}" echo "telegramAlertType#:#${telegram_alert_type}" echo "sendMatrix#:#${send_matrix}" + echo "matrixAlertType#:#${matrix_alert_type}" echo "nightModeEventDelay#:#${night_mode_event_delay}" ;; @@ -197,6 +199,11 @@ if [ -n "$F_cmd" ]; then rewrite_config /system/sdcard/config/motion.conf dropbox_video $F_dropboxVideo echo "Save video to dropbox set to $F_dropboxVideo
" fi + if [ -n "${F_dropboxUrl+x}" ]; then + F_dropboxUrl=$(printf '%b' "${F_dropboxUrl//%/\\x}" | sed 's/\//\\\//g') + rewrite_config /system/sdcard/config/motion.conf dropbox_url "\"$F_dropboxUrl\"" + echo "dropbox url set
" + fi if [ -n "${F_dropboxToken+x}" ]; then F_dropboxToken=$(printf '%b' "${F_dropboxToken//%/\\x}" | sed 's/\//\\\//g') rewrite_config /system/sdcard/config/motion.conf dropbox_token "\"$F_dropboxToken\"" @@ -252,6 +259,11 @@ if [ -n "$F_cmd" ]; then rewrite_config /system/sdcard/config/motion.conf send_matrix $F_sendMatrix echo "Send Matrix on motion set to $F_sendMatrix
" fi + if [ -n "${F_matrixAlertType+x}" ]; then + F_matrixAlertType=$(printf '%b' "${F_matrixAlertType//%/\\x}") + rewrite_config /system/sdcard/config/motion.conf matrix_alert_type $F_matrixAlertType + echo "Matrix alert type set to $F_matrixAlertType
" + fi if [ -n "${F_nightModeEventDelay+x}" ]; then F_nightModeEventDelay=$(printf '%b' "${F_nightModeEventDelay//%/\\x}") rewrite_config /system/sdcard/config/motion.conf night_mode_event_delay $F_nightModeEventDelay diff --git a/firmware_mod/www/cgi-bin/ui_sdcard.cgi b/firmware_mod/www/cgi-bin/ui_sdcard.cgi index 9b24843..7e3792c 100755 --- a/firmware_mod/www/cgi-bin/ui_sdcard.cgi +++ b/firmware_mod/www/cgi-bin/ui_sdcard.cgi @@ -31,7 +31,7 @@ if [ -n "$F_cmd" ]; then do if [[ -f $file ]]; then file_size=$(ls -lh $file | awk '{print $5}') - file_url=$(ls -lh $file | awk '{print $9}' | sed 's/\/system\/sdcard\/DCIM/\/viewer/') + file_url=$(ls -lh $file | awk '{print $9}' | sed 's/\/system\/sdcard\/DCIM/viewer/') file_date=$(ls -lh $file | awk '{print $6 "-" $7 "-" $8}') file_name=$(ls -lh $file | awk '{print $9}' | awk -F / '{print $(NF)}') echo "${file_name}#:#${file_size}#:#${file_date}#:#${file_url}" @@ -45,7 +45,7 @@ if [ -n "$F_cmd" ]; then echo "sdcardUsedPercent#:#$(df -h /system/sdcard | awk 'NR==2{print$5}')" ;; del_file) - F_file=$(echo ${F_file} | sed -e 's/%2F/\//g' | sed -e 's/viewer/system\/sdcard\/DCIM/') + F_file=$(echo ${F_file} | sed -e 's/%2F/\//g' | sed -e 's/viewer/\/system\/sdcard\/DCIM/') echo "Remove ${F_file}" rm $F_file ;; @@ -54,4 +54,4 @@ if [ -n "$F_cmd" ]; then ;; esac - fi \ No newline at end of file + fi diff --git a/firmware_mod/www/index.html b/firmware_mod/www/index.html index db31865..201c654 100644 --- a/firmware_mod/www/index.html +++ b/firmware_mod/www/index.html @@ -17,12 +17,12 @@ - - + + - + \ No newline at end of file + + + diff --git a/firmware_mod/www/motion.html b/firmware_mod/www/motion.html index a19a341..e7cbdf8 100755 --- a/firmware_mod/www/motion.html +++ b/firmware_mod/www/motion.html @@ -215,18 +215,14 @@

-
-
- - -
+
+ +

-
-
-
-
-
+
+ +

@@ -321,6 +317,15 @@
+
+ + +
diff --git a/integration/custom/dafangstor.php b/integration/custom/dafangstor.php new file mode 100644 index 0000000..a866547 --- /dev/null +++ b/integration/custom/dafangstor.php @@ -0,0 +1,142 @@ +. +*/ + + ##### CONFIG ############################################################### + + # Change this to some random long password. + # This key should match the key under Settings->Motion Settings->Storage->Dropbox storage->Dropbox Long Lived Token. + $APIKEY = "aw4QrDrz5Z94oyaYLx9ojh8ZDARt7tA8hRqosNG305shGD6NJtAcjOC3WS3odsBMdkPFvl0hJSZyIkCJ"; + + # This is the directory where all images and video will be stored. Missing subdirectories will be created here + # based on the values of "Dropbox snapshots remote directory" and "Dropbox videos remote directory". + # Make sure the web user has access permissions for this directory. + $OUTDIR = "/media/securitycam"; + + # Allowed file extensions + $ALLOWEDFILETYPES = array('jpg', 'mp4', 'avi'); + + # Maximum upload file size (50MB shown) + $MAXFILESIZE = 50 * 1024 * 1024; + + ############################################################################ + + if (!array_key_exists('HTTP_AUTHORIZATION', $_SERVER) || !array_key_exists('HTTP_DROPBOX_API_ARG', $_SERVER)) + { + header("HTTP/1.1 500 Internal Server Error"); + error_log("ERROR: Missing authorization or API argument"); + exit(); + } + + if ($_SERVER['HTTP_AUTHORIZATION'] != "Bearer $APIKEY") + { + header("HTTP/1.1 403 Forbidden"); + exit(); + } + + $path = json_decode($_SERVER['HTTP_DROPBOX_API_ARG'], true); + + if ($path == null || !array_key_exists('path', $path)) + { + header("HTTP/1.1 500 Internal Server Error"); + error_log("ERROR: Missing or bad file path `".$_SERVER['HTTP_DROPBOX_API_ARG']."'"); + exit(); + } + + $path = $path['path']; + + #----------- PATH SANITIZING ----------------------- + + # Only allow basic characters and digits + $path = str_replace("\\", "/", $path); + $path = preg_replace("([^a-zA-Z\d \-_./])", "_", $path); + + # Clean beginning of path + $path = preg_replace("(^[/.]+)", "", $path); + + # No path backwards; NOTE: this is a simplistic approach that will + # disallow any paths with multiple repeating periods. + $path = preg_replace("(\.+)", ".", $path); + + # Clean repeated path seperators + $path = preg_replace("(\/+)", "/", $path); + + # Remove all "current directory" paths + do { + $oldpath = $path; + $path = str_replace("/./", "/", $path); + } while ($path != $oldpath); + + #--------------------------------------------------- + + $dirname = dirname($path); + $filename = basename($path); + + $ext = pathinfo($filename, PATHINFO_EXTENSION); + + if (!$ext || strlen($filename) < 1) + { + header("HTTP/1.1 500 Internal Server Error"); + error_log("ERROR: Bad file path"); + exit(); + } + + if (!in_array(strtolower($ext), $ALLOWEDFILETYPES)) + { + header("HTTP/1.1 403 Forbidden"); + error_log("ERROR: File extension not allowed"); + exit(); + } + + $dirname = "$OUTDIR/$dirname"; + $filename = "$dirname/$filename"; + + if (!is_dir($dirname)) + { + if (!mkdir($dirname, 0777, true)) + { + header("HTTP/1.1 500 Internal Server Error"); + error_log("ERROR: Failed to create output directory `$dirname'"); + exit(); + } + } + + if (file_exists($filename)) + { + header("HTTP/1.1 500 Internal Server Error"); + error_log("ERROR: Output file already exists `$filename'"); + exit(); + } + + if (!($fp = fopen($filename, "wb"))) + { + header("HTTP/1.1 500 Internal Server Error"); + error_log("ERROR: Failed to create output file `$filename'"); + exit(); + } + + $data = file_get_contents('php://input', false, null, 0, $MAXFILESIZE); + $numbytes = fwrite($fp, $data); + fclose($fp); + + if (!$numbytes) + { + header("HTTP/1.1 500 Internal Server Error"); + error_log("ERROR: Failed to write output file `$filename'"); + exit(); + } +?> diff --git a/integration/custom/webserverstorage.md b/integration/custom/webserverstorage.md new file mode 100644 index 0000000..764338c --- /dev/null +++ b/integration/custom/webserverstorage.md @@ -0,0 +1,14 @@ +## Web server storage + +It's possible to use the Dropbox functionality to store snapshots or video on your own server. + +Look under Motion Settings»Motion Detection»Storage»Dropbox storage. There should be an option to change the Dropbox URL. This can be set to an internal or external web server. The default uses the Dropbox server. +Example: https[]()://yourserver/dafangstor.php + +[dafangstor.php](dafangstor.php) is an example PHP script that can be used on your own server. Inside this file there are two options: + * APIKEY + * OUTDIR + +APIKEY is the Long Lived Token value that is used to authenticate requests. This must match the value entered under Settings»Motion Detection»Storage»Dropbox storage»Dropbox Long Lived Token. The PHP script can be modified to include more fancy features like maybe for example changing the OUTDIR based on the authentication token or something similar. + +OUTDIR sets the output directory relative to where PHP is running. The www user (eg. www-data) will need access permissions for this directory so that it can create sub directories and output files or you can manually create directories beforehand. Paths specified by "Dropbox snapshots remote directory" and "Dropbox videos remote directory" will be relative to this OUTDIR directory.