Як я створив віджет з інформацією, чи є електроенергія вдома
Ще до початку війни відкрив для себе Scriptable — iOS-додаток для створення віджетів на православному JavaScript. А так як нам Тім Кук ще й дозволив створювати віджети для домашнього екрана, то треба цим користуватись!
Колись було досить багато ідей (і я створював віджети з кількістю відвідувачів карти тривог, але коли їх стало дуже багато, то перестав гратись і продався Google Analytics), але в новій реальності у нас в країні війна, і поки агресор не розпався на багато інших, то одна з проблем їх існування – періодична відсутність світла вдома. Через те, що графік не сходиться з реальним вимкненням світла, не завжди зрозуміло, чи пора повертатись додому.
В результаті у мене вийшов ось такий віджет:
Далі йдуть технічні моменти, а внизу інструкція, як додати його собі – якщо хтось працює на 66-му поверсі Карнегі Центра, і не знає, чи вже можна їхати на Печерськ, щоб не підійматись сходами.
Оновлено: Як правильно зазначили в твітерах [1, 2], віджет фактично перевіряє, чи доступний ваш роутер в інтернеті. Можуть бути випадки, що електроенергія є, хоча самого інтернету немає – в такому випадку, віджет все ще буде червоним. В мене в таких випадках інтернет зʼявлявся протягом 5-ти хвилин, але можуть бути такі проблеми також.
No-Сode?
Спочатку я думав виводити віджет на заблокованому екрані, і знайшов Any Text, який підтримує інтеграцію з Shortcuts. Їх навіть можна запускати по розкладу, але мінімальна періодичність – день. Якщо я хочу оновлювати кожні 15 хвилин, то потрібно створити 96 автоматизацій, і кожну з них вручну. Інших варіантів я так і не знайшов, тому ідея з ноукодом швидко провалилась.
Шо по пінгу роутера?
Найпростіший спосіб перевірити, чи є інтернет вдома – зробити пінг на IP адресу роутера, а Scriptable (читай ES6) не вміє робити запити по icmp-протоколу. З доступних ресурсів я знайшов API, яке робить пінг, але там досить довго потрібно чекати на результати – мені достатньо хоча б одного результату, а не перевіряти, чи відповідає мій роутер з усіх материків. Тому треба було створити свій мікросервіс!
Підіймати сервер для одного запиту – така собі ідея, і я спочатку подумав про DigitalOcean Functions (а-ля AWS Lambda), але є проблема, що складно обмежувати кількість запитів в разі необхідності, раптом росіяни почнуть навантажувати сервіс своїми запитами, як і зробили з карти тривог.
А потім я згадав пост Антона (і ось зараз помітив, що там якраз і за Scriptable мова була), що в nginx можна писати на lua, і це виглядало ідеальним рішенням! Тому з гівна та палок за пару хвилин я зібрав швиденько ендпоінт, який робить ping заданої IP-адреси та повертає інформацію, чи доступний він.
server {
# ...
location /ping/ {
default_type 'application/json';
content_by_lua '
local cjson = require "cjson"
if ngx.var.arg_ip == nil then
ngx.say(cjson.encode({status="error", error="Передайте IP через ?ip= параметр. Наприклад, ?ip=127.0.0.1"}));
return
end
local ip = ngx.var.arg_ip;
local chunks = {ip:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")}
if #chunks == 4 then
for _,v in pairs(chunks) do
if tonumber(v) > 255 then ngx.say(cjson.encode({status="error", error="Додайте коректний IP в налаштуваннях"})) return end
end
else
ngx.say(cjson.encode({status="error", error="Додайте коректний IP в налаштуваннях"})); return
end
local handle = io.popen("ping -c 1 " .. ngx.var.arg_ip .. " -W 0.5", "r")
local out = handle:read("*all")
handle:close()
if string.find(out, "1 received") then
ngx.say(cjson.encode({status="ok"}))
else
ngx.say(cjson.encode({status="error"}))
end
';
}
}
І все запрацювало!
Віджет
Віджет виявився найпростішою частиною, і на основі інших прикладів я швиденько зробив віджет, який показує стан та дату оновлення. Сам код віджета в файлі нижче – там один запит, відображення його та часу генерації, і ніякого рокет саєнс!
Що треба ще знати
Вдома повинен бути завжди статичний IP так як з динамічним складно працювати.
Також iOS сама вирішує, коли їй оновити віджет, і робить це по документації в інтервалі 15..60 хвилин, але фактично в мене виходило 15-20 хвилин. Якщо тапнути по віджету – він оновиться з актуальними даними.
Як?
- Повинен бути статичний IP. Якщо роутер вимкнути-увімкнути, і IP зміниться – потрібно буде у провайдера замовляти додатково послугу статичного IP. Віджет постійно перевіряє лише одну і ту ж адресу.
- Роутер повинен відповідати на ping запити. Якщо повертається помилка при натисканні на кнопку «Надіслати пінг на мій IP», то треба гуглити щось «%router name% Respond to Pings from WAN» та вмикати на роутері
- Потрібно встановити Scriptable, завантажити файл нижче, поділитись ним в Scriptable та замінити IP в першому рядку на потрібний. Раптом що, ось відео, як це робиться.
- Створити віджет та додати його на домашній екран.
- Всьо!
Що далі?
Взагалі в мене ще була ідея пройтись по закладах та зробити невелику краудсорсинг-карту з закладами та станом вайфаю в реальному часі. Можна також зробити якогось телеграм-бота або надсилати сповіщення при зміні стану світла.
Або можна зробити якусь zapier-інтеграцію для слака, щоб всі бачили, що у вас немає світла, і що можлива якась затримка в для відповідей. Я якось робив таке для сирен, тому повинно бути максимально просто і зробити для світла також.