henry_flower: A melancholy wolf (Default)
henry_flower ([personal profile] henry_flower) wrote2024-06-12 02:17 am

Електрохарчування та Termux

Побачив ув твіторі:

Robert @RobertZeltinsh · Jun 6

Діди самодєлкіни, викликаю вас. Є задача, зібрати якусь шляпу щоб коли вмикається і пропадає світло, вона відправляла про це смс.
Знайшов якісь вумні розетки з gsm, але воно криве і косе. Все що з розумним будинком не підходе, бо інтернет відсутній.

З будь-яким непотрібним ондроїдом з встановленим Termux можна написати нескладного скрипта, який буде використовувати 2 ютіліти:

  • termux-battery-status
  • termux-sms-send

(apt-get install termux-api, який вимагає також окрему ондроїдну аплікацію termux-api.)

1ша вертає json:

{
  "health": "GOOD",
  "percentage": 42,
  "plugged": "PLUGGED_AC",
  "status": "CHARGING",
  "temperature": 31.0,
  "current": -564452
}

2га відправляє рядок на телехфонний номер. Ув якості тесту я надіслав sms собі, після чого Київстар життєрадісно відповів що це коштувало мені 3 гривені (~7 євроцентів). Останній раз я таке робив, напевно, ув 2010 році, тому з подивом дізнався, що sms не тільки не є безплатні, а продаються пакетами по 300 штук.

Це означає, що якщо ув гаражі станеться перевантаження ланцюга і світло почне мерехтіти, за годину можна зайняти 1ше місце у Європі за кількістю відправлених sms та сертифікат від Київстару 'ідіот року'.

Отже скрипта має пам'ятати про sms ліміт на день.

Найпростіша скіма з опитуванням батареї може виглядати так: телехфон вмикається до розетки, на телехфоні запускається termux, ув якому запускається:

#!/usr/bin/env bash

set -e
poll_time=3
battery=${battery:-termux-battery-status}
sms=${sms:-termux-sms-send}

...

type jq $battery $sms > /dev/null
number=${1:?no phone number}

last=
while true; do
    status=`$battery | jq -r .plugged`; [ "$status" ]
    [ "$status" = "$last" ] && continue

    [ "$last" = "" ] || case $status in
        UNPLUGGED) send No electricity ;;
        PLUGGED_AC) send A keen and shared excitement ;;
        *) log "Unknown status: $status"
    esac

    last=$status
    sleep $poll_time
done

де poll_time ліпше виставляти не 3 секунди, а ув залежності від ліміту sms, наприклад для 100 штук на день--864 секунди (опитування кожні 14.4 хв).

Найнудніша частина є ув відстеженні кількості відісланих sms. Ви знали що bash вміє порівнювати рядки лексикоґрафічно? Я не знав!

$ [ 2024-06-11 \> 2024-06-10 ] ; echo $?
0
$ [ 2024-06-11 \> 2024-06-12 ] ; echo $?
1

Тоді перевіряючи mtime хфайла, де записується кількість sms, можна скидати ліміта:

sms_limit_file="${XDG_CACHE_HOME:-$HOME/.cache}/elektrokharchuvannia"
sms_limit=10

sms_limit_get() {
    local r=$sms_limit
    [ -r "$sms_limit_file" ] && {
        r=`head -c4 "$sms_limit_file" | awk '{print $0+0 == $0 ? $0 : 0}'`
        local today="`date +%Y-%m-%d`"
        local mtime="$(date -d "@$(stat -c %Y "$sms_limit_file")" +%Y-%m-%d)"
        [ "$today" \> "$mtime" ] && r=$sms_limit
    }
    echo "$r"
}

sms_limit_decr() {
    mkdir -p "`dirname "$sms_limit_file"`"
    echo $((`sms_limit_get` - 1)) > "$sms_limit_file"
}

log() { printf '%s: %s\n' "`date`" "$*"; }

send() {
    [ "`sms_limit_get`" -lt 1 ] && { log SMS dayly limit reached; return; }
    local msg="$* (SMS left: $((`sms_limit_get` - 1)))"
    log "$msg"; log "$msg" | xargs -d\\n $sms -n "$number";
    sms_limit_decr
}

Тестування цього ковгоспу без відсилання повідомлень:

$ sms=true ./elektrokharchuvannia +380148800000

Тут воно повинно показувати нічого. Далі, висмикування дроту з телехфону та вставляння його знову, друкує:

Wed 12 Jun 01:25:15 EEST 2024: No electricity (SMS left: 2)
Wed 12 Jun 01:25:20 EEST 2024: A keen and shared excitement (SMS left: 1)
Wed 12 Jun 01:25:25 EEST 2024: No electricity (SMS left: 0)
Wed 12 Jun 01:25:28 EEST 2024: SMS dayly limit reached