summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorEvgeny Zinoviev <me@ch1p.io>2023-09-27 00:54:57 +0300
committerEvgeny Zinoviev <me@ch1p.io>2023-09-27 00:54:57 +0300
commitd3a295872c49defb55fc8e4e43e55550991e0927 (patch)
treeb9dca15454f9027d5a9dad0d4443a20de04dbc5d /tools
parentb7cbc2571c1870b4582ead45277d0aa7f961bec8 (diff)
parentbdbb296697f55f4c3a07af43c9aaf7a9ea86f3d0 (diff)
Merge branch 'master' of ch1p.io:homekit
Diffstat (limited to 'tools')
-rw-r--r--tools/clickhouse-backup.sh31
-rwxr-xr-xtools/ipcam_capture.sh119
-rwxr-xr-xtools/ipcam_motion_worker.sh327
-rwxr-xr-xtools/ipcam_rtsp2hls.sh127
-rw-r--r--tools/lib.bash130
-rwxr-xr-xtools/mcuota.py98
-rwxr-xr-xtools/mcuota.sh14
-rwxr-xr-xtools/process-motion-timecodes.py61
-rw-r--r--tools/remove-old-recordings.sh5
-rwxr-xr-xtools/rotate-video.sh2
-rw-r--r--tools/sunxi-h3-i2c-reset.sh25
-rwxr-xr-xtools/sunxi-setup-amixer.sh114
-rwxr-xr-xtools/sync-recordings-to-remote.sh72
-rwxr-xr-xtools/video-util.sh2
14 files changed, 2 insertions, 1125 deletions
diff --git a/tools/clickhouse-backup.sh b/tools/clickhouse-backup.sh
deleted file mode 100644
index 6e938e4..0000000
--- a/tools/clickhouse-backup.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-
-DIR=/var/lib/clickhouse/backup
-MAX_COUNT=3
-NAME=backup_$(date -u +%Y-%m-%d)
-
-create() {
- local name="$1"
- clickhouse-backup create "$name"
-}
-
-del() {
- local name="$1"
- clickhouse-backup delete local "$name"
-}
-
-# create a backup
-create "$NAME"
-
-# compress backup
-cd "$DIR"
-tar czvf $NAME.tar.gz $NAME
-
-# delete uncompressed files
-del "$NAME"
-
-# delete old backups
-for file in $(ls -t "${DIR}" | tail -n +$(( MAX_COUNT+1 ))); do
- echo "removing $file..."
- rm "$file"
-done \ No newline at end of file
diff --git a/tools/ipcam_capture.sh b/tools/ipcam_capture.sh
deleted file mode 100755
index 08b9093..0000000
--- a/tools/ipcam_capture.sh
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/bin/bash
-
-PROGNAME="$0"
-PORT=554
-IP=
-CREDS=
-DEBUG=0
-CHANNEL=1
-FORCE_UDP=0
-FORCE_TCP=0
-EXTENSION="mp4"
-
-die() {
- echo >&2 "error: $@"
- exit 1
-}
-
-usage() {
- cat <<EOF
-usage: $PROGNAME [OPTIONS] COMMAND
-
-Options:
- --outdir output directory
- --ip camera IP
- --port RTSP port (default: 554)
- --creds
- --debug
- --force-tcp
- --force-udp
- --channel 1|2
-
-EOF
- exit
-}
-
-validate_channel() {
- local c="$1"
- case "$c" in
- 1 | 2)
- :
- ;;
- *)
- die "Invalid channel"
- ;;
- esac
-}
-
-[ -z "$1" ] && usage
-
-while [[ $# -gt 0 ]]; do
- case "$1" in
- --ip | --port | --creds | --outdir)
- _var=${1:2}
- _var=${_var^^}
- printf -v "$_var" '%s' "$2"
- shift
- ;;
-
- --debug)
- DEBUG=1
- ;;
-
- --force-tcp)
- FORCE_TCP=1
- ;;
-
- --force-udp)
- FORCE_UDP=1
- ;;
-
- --channel)
- CHANNEL="$2"
- shift
- ;;
-
- --mov)
- EXTENSION="mov"
- ;;
-
- --mpv)
- EXTENSION="mpv"
- ;;
-
- *)
- die "Unrecognized argument: $1"
- ;;
- esac
- shift
-done
-
-[ -z "$OUTDIR" ] && die "You must specify output directory (--outdir)."
-[ -z "$IP" ] && die "You must specify camera IP address (--ip)."
-[ -z "$PORT" ] && die "Port can't be empty."
-[ -z "$CREDS" ] && die "You must specify credentials (--creds)."
-validate_channel "$CHANNEL"
-
-if [ ! -d "${OUTDIR}" ]; then
- mkdir "${OUTDIR}" || die "Failed to create ${OUTDIR}/${NAME}!"
- echo "Created $OUTDIR."
-fi
-
-args=
-if [ "$DEBUG" = "1" ]; then
- args="$args -v info"
-else
- args="$args -nostats -loglevel warning"
-fi
-
-if [ "$FORCE_TCP" = "1" ]; then
- args="$args -rtsp_transport tcp"
-elif [ "$FORCE_UDP" = "1" ]; then
- args="$args -rtsp_transport udp"
-fi
-
-[ ! -z "$CREDS" ] && CREDS="${CREDS}@"
-
-ffmpeg $args -i rtsp://${CREDS}${IP}:${PORT}/Streaming/Channels/${CHANNEL} \
- -c copy -f segment -strftime 1 -segment_time 00:10:00 -segment_atclocktime 1 \
- "$OUTDIR/record_%Y-%m-%d-%H.%M.%S.${EXTENSION}"
diff --git a/tools/ipcam_motion_worker.sh b/tools/ipcam_motion_worker.sh
deleted file mode 100755
index c5f711d..0000000
--- a/tools/ipcam_motion_worker.sh
+++ /dev/null
@@ -1,327 +0,0 @@
-#!/bin/bash
-
-set -e
-
-DIR="$( cd "$( dirname "$(realpath "${BASH_SOURCE[0]}")" )" &>/dev/null && pwd )"
-PROGNAME="$0"
-
-. "$DIR/lib.bash"
-
-curl_opts="-s --connect-timeout 10 --retry 5 --max-time 180 --retry-delay 0 --retry-max-time 180"
-allow_multiple=
-fetch_limit=10
-
-config=
-config_camera=
-is_remote=
-api_url=
-
-dvr_scan_path="$HOME/.local/bin/dvr-scan"
-fs_root="/var/ipcam_motion_fs"
-fs_max_filesize=146800640
-
-declare -A config=()
-
-usage() {
- cat <<EOF
-usage: $PROGNAME OPTIONS
-
-Options:
- -v, -vx be verbose.
- -v enables debug logs.
- -vx does \`set -x\`, may be used to debug the script.
- --allow-multiple don't check for another instance
- --L, --fetch-limit default: $fetch_limit
- --remote
- --local
- --dvr-scan-path default: $dvr_scan_path
- --fs-root default: $fs_root
- --fs-max-filesize default: $fs_max_filesize
-EOF
- exit 1
-}
-
-get_recordings_dir() {
- local camera="$1"
- curl $curl_opts "${api_url}/api/camera/list" \
- | jq ".response.\"${camera}\".recordings_path" | tr -d '"'
-}
-
-# returns three words per line:
-# filename filesize camera
-get_recordings_list() {
- curl $curl_opts "${api_url}/api/recordings?limit=${fetch_limit}" \
- | jq '.response.files[] | [.name, .size, .cam] | join(" ")' | tr -d '"'
-}
-
-read_camera_motion_config() {
- local camera="$1"
- local dst=config
-
- if [ "$config_camera" != "$camera" ]; then
- local n=0
- local failed=
- local key
- local value
-
- while read line; do
- n=$(( n+1 ))
-
- # skip empty lines or comments
- if [ -z "$line" ] || [[ "$line" =~ ^#.* ]]; then
- continue
- fi
-
- if [[ $line = *"="* ]]; then
- key="${line%%=*}"
- value="${line#*=}"
- eval "$dst[$key]=\"$value\""
- else
- echoerr "config: invalid line $n"
- failed=1
- fi
- done < <(curl $curl_opts "${api_url}/api/motion/params/${camera}")
-
- config_camera="$camera"
-
- [ -z "$failed" ]
- else
- debug "read_camera_motion_config: config for $camera already loaded"
- fi
-}
-
-dump_config() {
- for key in min_event_length downscale_factor frame_skip threshold; do
- debug "config[$key]=${config[$key]}"
- done
-}
-
-get_camera_roi_config() {
- local camera="$1"
- curl $curl_opts "${api_url}/api/motion/params/${camera}/roi"
-}
-
-report_failure() {
- local camera="$1"
- local file="$2"
- local message="$3"
-
- local response=$(curl $curl_opts -X POST "${api_url}/api/motion/fail/${camera}" \
- -F "filename=$file" \
- -F "message=$message")
-
- print_response_error "$response" "report_failure"
-}
-
-report_timecodes() {
- local camera="$1"
- local file="$2"
- local timecodes="$3"
-
- local response=$(curl $curl_opts -X POST "${api_url}/api/motion/done/${camera}" \
- -F "filename=$file" \
- -F "timecodes=$timecodes")
-
- print_response_error "$response" "report_timecodes"
-}
-
-print_response_error() {
- local resp="$1"
- local sufx="$2"
-
- local error="$(echo "$resp" | jq '.error')"
- local message
-
- if [ "$error" != "null" ]; then
- message="$(echo "$resp" | jq '.message' | tr -d '"')"
- error="$(echo "$error" | tr -d '"')"
-
- echoerr "$sufx: $error ($message)"
- fi
-}
-
-process_queue() {
- local tc
- local url
- local words
- local file
- local size
- local camera
- local local_recs_dir
-
- if [ "$is_remote" = "1" ]; then
- pushd "${fs_root}" >/dev/null || die "failed to change to ${fs_root}"
- touch tmp || die "directory '${fs_root}' is not writable"
- rm tmp
-
- [ -f "video.mp4" ] && {
- echowarn "video.mp4 already exists in ${fs_root}, removing.."
- rm "video.mp4"
- }
- fi
-
- while read line; do
- words=($line)
- file=${words[0]}
- size=${words[1]}
- camera=${words[2]}
-
- debug "next video: cam=$camera file=$file"
-
- read_camera_motion_config "$camera"
-# dump_config
-
- if [ "$is_remote" = "0" ]; then
- local_recs_dir="$(get_recordings_dir "$camera")"
-
- debug "[$camera] processing $file..."
-
- tc=$(do_motion "$camera" "${local_recs_dir}/$file")
- debug "[$camera] $file: timecodes=$tc"
-
- report_timecodes "$camera" "$file" "$tc"
- else
- if (( size > fs_max_filesize )); then
- echoerr "[$camera] won't download $file, size exceeds fs_max_filesize ($size > ${fs_max_filesize})"
- report_failure "$camera" "$file" "too large file"
- continue
- fi
-
- url="${api_url}/api/recordings/${camera}/download/${file}"
- debug "[$camera] downloading $url..."
-
- if ! download "$url" "video.mp4"; then
- echoerr "[$camera] failed to download $file"
- report_failure "$camera" "$file" "download error"
- continue
- fi
-
- tc=$(do_motion "$camera" "video.mp4")
- debug "[$camera] $file: timecodes=$tc"
-
- report_timecodes "$camera" "$file" "$tc"
-
- rm "video.mp4"
- fi
- done < <(get_recordings_list)
-
- if [ "$is_remote" = "1" ]; then popd >/dev/null; fi
-}
-
-do_motion() {
- local camera="$1"
- local input="$2"
- local tc
-
- local timecodes=()
-
- time_start
- while read line; do
- if ! [[ "$line" =~ ^#.* ]]; then
- tc="$(do_dvr_scan "$input" "$line")"
- if [ -n "$tc" ]; then
- timecodes+=("$tc")
- fi
- fi
- done < <(get_camera_roi_config "$camera")
-
- debug "[$camera] do_motion: finished in $(time_elapsed)s"
-
- timecodes="$(echo "${timecodes[@]}" | sed 's/ */ /g' | xargs)"
- timecodes="${timecodes// /,}"
-
- echo "$timecodes"
-}
-
-dvr_scan() {
- "${dvr_scan_path}" "$@"
-}
-
-do_dvr_scan() {
- local input="$1"
- local args=
-
- if [ ! -z "$2" ]; then
- args="-roi $2"
- echoinfo "dvr_scan(${BOLD}${input}${RST}${CYAN}): roi=($2), mt=${config[threshold]}"
- else
- echoinfo "dvr_scan(${BOLD}${input}${RST}${CYAN}): no roi, mt=${config[threshold]}"
- fi
-
- dvr_scan -q -i "$input" -so \
- --min-event-length ${config[min_event_length]} \
- -df ${config[downscale_factor]} \
- --frame-skip ${config[frame_skip]} \
- -t ${config[threshold]} $args | tail -1
-}
-
-[[ $# -lt 1 ]] && usage
-
-while [[ $# -gt 0 ]]; do
- case $1 in
- -L|--fetch-limit)
- fetch_limit="$2"
- shift; shift
- ;;
-
- --allow-multiple)
- allow_multiple=1
- shift
- ;;
-
- --remote)
- is_remote=1
- shift
- ;;
-
- --local)
- is_remote=0
- shift
- ;;
-
- --dvr-scan-path)
- dvr_scan_path="$2"
- shift; shift
- ;;
-
- --fs-root)
- fs_root="$2"
- shift; shift
- ;;
-
- --fs-max-filesize)
- fs_max_filesize="$2"
- shift; shift
- ;;
-
- --api-url)
- api_url="$2"
- shift; shift
- ;;
-
- -v)
- VERBOSE=1
- shift
- ;;
-
- -vx)
- VERBOSE=1
- set -x
- shift
- ;;
-
- *)
- die "unrecognized argument '$1'"
- exit 1
- ;;
- esac
-done
-
-if [ -z "$allow_multiple" ] && pidof -o %PPID -x "$(basename "${BASH_SOURCE[0]}")" >/dev/null; then
- die "process already running"
-fi
-
-[ -z "$is_remote" ] && die "either --remote or --local is required"
-[ -z "$api_url" ] && die "--api-url is required"
-
-process_queue \ No newline at end of file
diff --git a/tools/ipcam_rtsp2hls.sh b/tools/ipcam_rtsp2hls.sh
deleted file mode 100755
index c321820..0000000
--- a/tools/ipcam_rtsp2hls.sh
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/bin/bash
-
-PROGNAME="$0"
-OUTDIR=/var/ipcamfs # should be tmpfs
-PORT=554
-NAME=
-IP=
-USER=
-PASSWORD=
-DEBUG=0
-CHANNEL=1
-FORCE_UDP=0
-FORCE_TCP=0
-CUSTOM_PATH=
-
-die() {
- echo >&2 "error: $@"
- exit 1
-}
-
-usage() {
- cat <<EOF
-usage: $PROGNAME [OPTIONS] COMMAND
-
-Options:
- --ip camera IP
- --port RTSP port (default: 554)
- --name camera name (chunks will be stored under $OUTDIR/{name}/)
- --user
- --password
- --debug
- --force-tcp
- --force-udp
- --channel 1|2
- --custom-path PATH
-
-EOF
- exit
-}
-
-validate_channel() {
- local c="$1"
- case "$c" in
- 1|2)
- :
- ;;
- *)
- die "Invalid channel"
- ;;
- esac
-}
-
-[ -z "$1" ] && usage
-
-while [[ $# -gt 0 ]]; do
- case "$1" in
- --ip|--port|--name|--user|--password)
- _var=${1:2}
- _var=${_var^^}
- printf -v "$_var" '%s' "$2"
- shift
- ;;
-
- --debug)
- DEBUG=1
- ;;
-
- --force-tcp)
- FORCE_TCP=1
- ;;
-
- --force-udp)
- FORCE_UDP=1
- ;;
-
- --channel)
- CHANNEL="$2"
- shift
- ;;
-
- --custom-path)
- CUSTOM_PATH="$2"
- shift
- ;;
-
- *)
- die "Unrecognized argument: $1"
- ;;
- esac
- shift
-done
-
-[ -z "$IP" ] && die "You must specify camera IP address (--ip)."
-[ -z "$PORT" ] && die "Port can't be empty."
-[ -z "$NAME" ] && die "You must specify camera name (--name)."
-[ -z "$USER" ] && die "You must specify username (--user)."
-[ -z "$PASSWORD" ] && die "You must specify username (--password)."
-validate_channel "$CHANNEL"
-
-if [ ! -d "${OUTDIR}/${NAME}" ]; then
- mkdir "${OUTDIR}/${NAME}" || die "Failed to create ${OUTDIR}/${NAME}!"
-fi
-
-args=
-if [ "$DEBUG" = "1" ]; then
- args="-v info"
-else
- args="-nostats -loglevel error"
-fi
-
-if [ "$FORCE_TCP" = "1" ]; then
- args="$args -rtsp_transport tcp"
-elif [ "$FORCE_UDP" = "1" ]; then
- args="$args -rtsp_transport udp"
-fi
-
-if [ -z "$CUSTOM_PATH" ]; then
- path="/Streaming/Channels/${CHANNEL}"
-else
- path="$CUSTOM_PATH"
-fi
-
-ffmpeg $args -i "rtsp://${USER}:${PASSWORD}@${IP}:${PORT}${path}" \
- -c:v copy -c:a copy -bufsize 1835k \
- -pix_fmt yuv420p \
- -flags -global_header -hls_time 2 -hls_list_size 3 -hls_flags delete_segments \
- ${OUTDIR}/${NAME}/live.m3u8
diff --git a/tools/lib.bash b/tools/lib.bash
deleted file mode 100644
index 1d73ab2..0000000
--- a/tools/lib.bash
+++ /dev/null
@@ -1,130 +0,0 @@
-# colored output
-# --------------
-
-BOLD=$(tput bold)
-RST=$(tput sgr0)
-RED=$(tput setaf 1)
-GREEN=$(tput setaf 2)
-YELLOW=$(tput setaf 3)
-CYAN=$(tput setaf 6)
-VERBOSE=
-
-echoinfo() {
- >&2 echo "${CYAN}$@${RST}"
-}
-
-echoerr() {
- >&2 echo "${RED}${BOLD}error:${RST}${RED} $@${RST}"
-}
-
-echowarn() {
- >&2 echo "${YELLOW}${BOLD}warning:${RST}${YELLOW} $@${RST}"
-}
-
-die() {
- echoerr "$@"
- exit 1
-}
-
-debug() {
- if [ -n "$VERBOSE" ]; then
- >&2 echo "$@"
- fi
-}
-
-
-# measuring executing time
-# ------------------------
-
-__time_started=
-
-time_start() {
- __time_started=$(date +%s)
-}
-
-time_elapsed() {
- local fin=$(date +%s)
- echo $(( fin - __time_started ))
-}
-
-
-# config parsing
-# --------------
-
-read_config() {
- local config_file="$1"
- local dst="$2"
-
- [ -f "$config_file" ] || die "read_config: $config_file: no such file"
-
- local n=0
- local failed=
- local key
- local value
-
- while read line; do
- n=$(( n+1 ))
-
- # skip empty lines or comments
- if [ -z "$line" ] || [[ "$line" =~ ^#.* ]]; then
- continue
- fi
-
- if [[ $line = *"="* ]]; then
- key="${line%%=*}"
- value="${line#*=}"
- eval "$dst[$key]=\"$value\""
- else
- echoerr "config: invalid line $n"
- failed=1
- fi
- done < <(cat "$config_file")
-
- [ -z "$failed" ]
-}
-
-check_config() {
- local var="$1"
- local keys="$2"
-
- local failed=
-
- for key in $keys; do
- if [ -z "$(eval "echo -n \${$var[$key]}")" ]; then
- echoerr "config: ${BOLD}${key}${RST}${RED} is missing"
- failed=1
- fi
- done
-
- [ -z "$failed" ]
-}
-
-
-# other functions
-# ---------------
-
-installed() {
- command -v "$1" > /dev/null
- return $?
-}
-
-download() {
- local source="$1"
- local target="$2"
-
- if installed curl; then
- curl -f -s -o "$target" "$source"
- elif installed wget; then
- wget -q -O "$target" "$source"
- else
- die "neither curl nor wget found, can't proceed"
- fi
-}
-
-file_in_use() {
- [ -n "$(lsof "$1")" ]
-}
-
-file_mtime() {
- stat -c %Y "$1"
-}
diff --git a/tools/mcuota.py b/tools/mcuota.py
deleted file mode 100755
index 46968a8..0000000
--- a/tools/mcuota.py
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/env python3
-import sys
-import os.path
-sys.path.extend([
- os.path.realpath(
- os.path.join(os.path.dirname(os.path.join(__file__)), '..')
- )
-])
-
-from time import sleep
-from argparse import ArgumentParser
-from src.home.config import config
-from src.home.mqtt import MqttRelay
-from src.home.mqtt.esp import MqttEspDevice
-
-
-def guess_filename(product: str, build_target: str):
- return os.path.join(
- products_dir,
- product,
- '.pio',
- 'build',
- build_target,
- 'firmware.bin'
- )
-
-
-def relayctl_publish_ota(filename: str,
- device_id: str,
- home_secret: str,
- qos: int):
- global stop
-
- def published():
- global stop
- stop = True
-
- mqtt_relay = MqttRelay(devices=MqttEspDevice(id=device_id, secret=home_secret))
- mqtt_relay.configure_tls()
- mqtt_relay.connect_and_loop(loop_forever=False)
- mqtt_relay.push_ota(device_id, filename, published, qos)
- while not stop:
- sleep(0.1)
- mqtt_relay.disconnect()
-
-
-stop = False
-products = {
- 'relayctl': {
- 'build_target': 'esp12e',
- 'callback': relayctl_publish_ota
- }
-}
-
-products_dir = os.path.join(
- os.path.dirname(__file__),
- '..',
- 'platformio'
-)
-
-
-def main():
- parser = ArgumentParser()
- parser.add_argument('--filename', type=str)
- parser.add_argument('--device-id', type=str, required=True)
- parser.add_argument('--product', type=str, required=True)
- parser.add_argument('--qos', type=int, default=1)
-
- config.load('mcuota_push', parser=parser)
- arg = parser.parse_args()
-
- if arg.product not in products:
- raise ValueError(f'invalid product: \'{arg.product}\' not found')
-
- if arg.device_id not in config['mqtt']['home_secrets']:
- raise ValueError(f'home_secret for home {arg.device_id} not found in config!')
-
- filename = arg.filename if arg.filename else guess_filename(arg.product, products[arg.product]['build_target'])
- if not os.path.exists(filename):
- raise OSError(f'file \'{filename}\' does not exists')
-
- print('Please confirm following OTA params.')
- print('')
- print(f' Device ID: {arg.device_id}')
- print(f' Product: {arg.product}')
- print(f'Firmware file: {filename}')
- print('')
- input('Press any key to continue or Ctrl+C to abort.')
-
- products[arg.product]['callback'](filename, arg.device_id, config['mqtt']['home_secrets'][arg.device_id], qos=arg.qos)
-
-
-if __name__ == '__main__':
- try:
- main()
- except Exception as e:
- print(str(e), file=sys.stderr)
- sys.exit(1)
diff --git a/tools/mcuota.sh b/tools/mcuota.sh
deleted file mode 100755
index b2e7910..0000000
--- a/tools/mcuota.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
-
-. "$DIR/lib.bash"
-
-if [ -d "$DIR/../venv" ]; then
- echoinfo "activating python venv"
- . "$DIR/../venv/bin/activate"
-else
- echowarn "python venv not found"
-fi
-
-"$DIR/mcuota.py" "$@" \ No newline at end of file
diff --git a/tools/process-motion-timecodes.py b/tools/process-motion-timecodes.py
deleted file mode 100755
index 7be7977..0000000
--- a/tools/process-motion-timecodes.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/env python3
-import os.path
-from src.home.camera.util import dvr_scan_timecodes
-
-from argparse import ArgumentParser
-from datetime import datetime, timedelta
-
-DATETIME_FORMAT = '%Y-%m-%d-%H.%M.%S'
-
-
-def chunks(lst, n):
- for i in range(0, len(lst), n):
- yield lst[i:i + n]
-
-
-def time2seconds(time: str) -> int:
- time, frac = time.split('.')
- frac = int(frac)
-
- h, m, s = [int(i) for i in time.split(':')]
-
- return round(s + m*60 + h*3600 + frac/1000)
-
-
-def filename_to_datetime(filename: str) -> datetime:
- filename = os.path.basename(filename).replace('record_', '').replace('.mp4', '')
- return datetime.strptime(filename, DATETIME_FORMAT)
-
-
-if __name__ == '__main__':
- parser = ArgumentParser()
- parser.add_argument('--source-filename', type=str, required=True,
- help='recording filename')
- parser.add_argument('--timecodes', type=str, required=True,
- help='timecodes')
- parser.add_argument('--padding', type=int, default=2,
- help='amount of seconds to add before and after each fragment')
- arg = parser.parse_args()
-
- if arg.padding < 0:
- raise ValueError('invalid padding')
-
- fragments = dvr_scan_timecodes(arg.timecodes)
- file_dt = filename_to_datetime(arg.source_filename)
-
- for fragment in fragments:
- start, end = fragment
-
- start -= arg.padding
- end += arg.padding
-
- if start < 0:
- start = 0
-
- duration = end - start
-
- dt1 = (file_dt + timedelta(seconds=start)).strftime(DATETIME_FORMAT)
- dt2 = (file_dt + timedelta(seconds=end)).strftime(DATETIME_FORMAT)
- filename = f'{dt1}__{dt2}.mp4'
-
- print(f'{start} {duration} {filename}')
diff --git a/tools/remove-old-recordings.sh b/tools/remove-old-recordings.sh
deleted file mode 100644
index d376572..0000000
--- a/tools/remove-old-recordings.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-# to be launched by cron on remote server
-
-find /var/recordings -type f -mtime +14 -delete
diff --git a/tools/rotate-video.sh b/tools/rotate-video.sh
index 6d27b44..5ce4efe 100755
--- a/tools/rotate-video.sh
+++ b/tools/rotate-video.sh
@@ -5,7 +5,7 @@ set -e
DIR="$( cd "$( dirname "$(realpath "${BASH_SOURCE[0]}")" )" &>/dev/null && pwd )"
PROGNAME="$0"
-. "$DIR/lib.bash"
+. "$DIR/../include/bash/include.bash"
usage() {
diff --git a/tools/sunxi-h3-i2c-reset.sh b/tools/sunxi-h3-i2c-reset.sh
deleted file mode 100644
index e654dfb..0000000
--- a/tools/sunxi-h3-i2c-reset.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-
-devices="1c2ac00.i2c 1c2b000.i2c"
-pins="8 9 28 30"
-driver_path="/sys/bus/platform/drivers/mv64xxx_i2c"
-
-driver_unbind() {
- echo -n "$1" > "$driver_path/unbind"
-}
-
-driver_bind() {
- echo -n "$1" > "$driver_path/bind"
-}
-
-for dev in $devices; do driver_unbind "$dev"; done
-echo "unbind done"
-
-for pin in pins; do
- gpio mode $pin out
- gpio write $pin 0
-done
-echo "gpio reset done"
-
-for dev in $devices; do driver_bind "$dev"; done
-echo "bind done" \ No newline at end of file
diff --git a/tools/sunxi-setup-amixer.sh b/tools/sunxi-setup-amixer.sh
deleted file mode 100755
index 5746514..0000000
--- a/tools/sunxi-setup-amixer.sh
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/bin/bash
-
-amixer() {
- /usr/bin/amixer "$@"
-}
-
-setup_opi_pc2() {
- for v in unmute cap; do
- amixer set "Line In" $v
- amixer set "Mic1" $v
- amixer set "Mic2" $v
- done
-
- for k in "Mic1 Boost" "Line In" "Mic1" "Mic2 Boost" "Mic2"; do
- amixer set "$k" "86%"
- done
-}
-
-setup_opi_one() {
- for v in unmute cap; do
- amixer set "Line In" $v
- amixer set "Mic1" $v
- done
-
- for k in "Mic1 Boost" "Line In" "Mic1"; do
- amixer set "$k" "86%"
- done
-}
-
-setup_opi3lts() {
- switches=(
- "Left DAC Mixer ADCL"
- "Left DAC Mixer I2SDACL"
- "Left I2S Mixer ADCL"
- "Left I2S Mixer I2SDACL"
- "Left Input Mixer LINEINL"
- "Left Input Mixer MIC1"
- "Left Input Mixer MIC2"
- "Left Input Mixer OMixerL"
- "Left Input Mixer OMixerR"
- "Left Input Mixer PhoneN"
- "Left Input Mixer PhonePN"
- "Left Output Mixer DACL"
- "Left Output Mixer DACR"
- "Left Output Mixer LINEINL"
- "Left Output Mixer MIC1"
- "Left Output Mixer MIC2"
- "Left Output Mixer PhoneN"
- "Left Output Mixer PhonePN"
- "Right DAC Mixer ADCR"
- "Right DAC Mixer I2SDACR"
- "Right I2S Mixer ADCR"
- "Right I2S Mixer I2SDACR"
- "Right Input Mixer LINEINR"
- "Right Input Mixer MIC1"
- "Right Input Mixer MIC2"
- "Right Input Mixer OMixerL"
- "Right Input Mixer OMixerR"
- "Right Input Mixer PhoneP"
- "Right Input Mixer PhonePN"
- "Right Output Mixer DACL"
- "Right Output Mixer DACR"
- "Right Output Mixer LINEINR"
- "Right Output Mixer MIC1"
- "Right Output Mixer MIC2"
- "Right Output Mixer PhoneP"
- "Right Output Mixer PhonePN"
- )
- for v in "${switches[@]}"; do
- value=on
- case "$v" in
- *Input*)
- value=on
- ;;
- *Output*)
- value=off
- ;;
- esac
- amixer set "$v" $value
- done
-
- to_mute=(
- "I2S Mixer ADC"
- "I2S Mixer DAC"
- "ADC Input"
- "DAC Mixer ADC"
- "DAC Mxier DAC" # this is not a typo
- )
- for v in "${to_mute[@]}"; do
- amixer set "$v" "0%"
- done
-
- amixer set "Master" "100%"
- amixer set "MIC1 Boost" "100%"
- amixer set "MIC2 Boost" "100%"
- amixer set "Line Out Mixer" "86%"
- amixer set "MIC Out Mixer" "71%"
-}
-
-device="$(tr -d '\0' < /sys/firmware/devicetree/base/model)"
-case "$device" in
- *"Orange Pi PC 2")
- setup_opi_pc2
- ;;
- *"Orange Pi One"|*"Orange Pi Lite")
- setup_opi_one
- ;;
- *"OrangePi 3 LTS")
- setup_opi3lts
- ;;
- *)
- >&2 echo "error: unidentified device: $device"
- ;;
-esac
diff --git a/tools/sync-recordings-to-remote.sh b/tools/sync-recordings-to-remote.sh
deleted file mode 100755
index cf979d1..0000000
--- a/tools/sync-recordings-to-remote.sh
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/bin/bash
-
-PROGNAME="$0"
-NODE_CONFIG="/etc/sound_node.toml"
-REMOTE_USER=user
-REMOTE_SERVER=solarmon.ru
-REMOTE_DIRECTORY=/var/recordings
-
-set -e
-
-echoerr() {
- >&2 echo "error: $@"
-}
-
-echowarn() {
- >&2 echo "warning: $@"
-}
-
-telegram_alert() {
- if [ -z "$TG_TOKEN" ] || [ -z "$TG_CHAT_ID" ]; then return; fi
- curl -X POST \
- -F "chat_id=${TG_CHAT_ID}" \
- -F "text=$1" \
- "https://api.telegram.org/bot${TG_TOKEN}/sendMessage"
-}
-
-fatal() {
- echoerr "$@"
- telegram_alert "$PROGNAME: $@"
- exit 1
-}
-
-get_config_var() {
- local varname="$1"
- cat "$NODE_CONFIG" | grep "^$varname = \"" | awk '{print $3}' | tr -d '"'
-}
-
-get_mp3_count() {
- find "$LOCAL_DIR" -mindepth 1 -type f -name "*.mp3" -printf x | wc -c
-}
-
-[ -z "$TG_TOKEN" ] && echowarn "TG_TOKEN is not set"
-[ -z "$TG_CHAT_ID" ] && echowarn "TG_CHAT_ID is not set"
-
-NODE_NAME=$(get_config_var name)
-LOCAL_DIR=$(get_config_var storage)
-
-[ -z "$NODE_NAME" ] && fatal "failed to parse NODE_NAME"
-[ -z "$LOCAL_DIR" ] && fatal "failed to parse LOCAL_DIR"
-
-[ -d "$LOCAL_DIR" ] || fatal "$LOCAL_DIR is not a directory"
-
-COUNT=$(get_mp3_count)
-(( $COUNT < 1 )) && {
- echo "seems there's nothing to sync"
- exit
-}
-
-cd "$LOCAL_DIR" || fatal "failed to change to $LOCAL_DIR"
-
-rsync -azPv -e "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR" \
- *.mp3 \
- ${REMOTE_USER}@${REMOTE_SERVER}:"${REMOTE_DIRECTORY}/${NODE_NAME}/" \
- --exclude temp.mp3
-
-RC=$?
-
-if [ $RC -eq 0 ]; then
- find "$LOCAL_DIR" -name "*.mp3" -type f -mmin +1440 -delete || fatal "find failed to delete old files"
-else
- fatal "failed to rsync: code $RC"
-fi
diff --git a/tools/video-util.sh b/tools/video-util.sh
index 0ee5560..6fe6109 100755
--- a/tools/video-util.sh
+++ b/tools/video-util.sh
@@ -5,7 +5,7 @@ set -e
DIR="$( cd "$( dirname "$(realpath "${BASH_SOURCE[0]}")" )" &> /dev/null && pwd )"
PROGNAME="$0"
-. "$DIR/lib.bash"
+. "$DIR/../include/bash/include.bash"
input=
output=