Сучасна диджитал-освіта для дітей — безоплатне заняття в GoITeens ×
Mazda CX 5
×

Як налаштувати єСвітло. Приклади від розробника застосунку

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

Привіт, я Віталій, Software engineer в Chimplie. Останні 5 років працював з Python, розробляв мікросервісну архітектуру на AWS і маю досвід роботи з багатьма AWS-сервісами. За допомогою цих інструментів я вирішив побудувати систему телеграм-каналів, які будуть сповіщати мене про включення або відключення електроенергії у мене вдома, а також вдома у моєї мами та бабусі.

Щодня у мене вимикають світло, за графіком та без графіка, або ж за графіком світла не має бути, але воно чомусь є. І коли немає світла, мені доводиться шукати, де є світло та інтернет, щоб можна було попрацювати. Особливо це актуально, якщо весь день заповнений зустрічами, і потрібно постійно бути онлайн з можливістю прийняти відеодзвінок. І, сидячи онлайн десь у кафе по сусідству, хочеться знати, коли вдома увімкнулось світло, бо, як то кажуть, «в гостях добре, а вдома краще».

Особливість моєї розробки в тому, що вона дозволяє швидко підключати нові адреси. У цій статті я покроково розповім, як це робити.

Крок 1. Raspberry Pi + Lambda

Ще рік тому купив собі Raspberry Pi, і весь час шукав йому застосування, але ніяк не міг придумати. Але тепер, здається, настав «зоряний час» для Raspberry Pi: він вмикається автоматично, коли вмикають світло, і вимикається разом з відключенням світла. На Raspberry OS, як і на будь-яких UNIX-based операційних системах є CRON де можна програмувати, щоб з певною періодичністю виконувався будь-який програмний код.

На AWS створюємо Lambda. Лямбда є ефективним інструментом виконання будь-яких обчислень на AWS. AWS дозволяє зробити один мільйон викликів lambda протягом місяця безкоштовно (free tier). Тож пишемо Lambda, яка буде приймати id мого будинку, та буде записувати інформацію про виклик в базу DynamoDB, та час такого виклику. DynamoDB — нереляційна база даних від AWS, що ідеально працює з Lambda. AWS надає 25 ГБ DynamoDB безкоштовно, тож і тут не доведеться платити.

На Raspberry створюємо python-скрипт, який буде викликати нашу AWS lambda щохвилини, таким чином повідомляючи, що Raspberry Pi жива, тобто вдома є світло.

payload = {"id": os.environ["ADDRESS_ID"]}

if __name__ == "__main__":
    lambda_.invoke(
        FunctionName="eSvitloPong",
        InvocationType='RequestResponse',
        Payload=json.dumps(payload).encode(),
    )

AWS Lambda ж буде записувати час виклику в DynamoDB, таким чином в базі даних буде зберігатись час, коли востаннє Rasberry Pi подавала ознаки життя:

def lambda_handler(event, context):
    id = event['id']

    dynamodb.update_item(
        TableName='eSvitlo',
        Key={'id': {"S": id}},
        UpdateExpression="set pong=:pong",
        ExpressionAttributeValues={":pong": {"S": datetime.now().isoformat()}}
    )

    return {
        'statusCode': 200,
        'body': json.dumps('Ping')
    }

Крок 2. Telegram

Для наступного кроку створимо телеграм-канал. Це можна зробити, використовуючи клієнтський застосунок Telegram. Там же знаходимо бота, який створює телеграм-ботів @BotFather. Створюємо телеграм-бота та зберігаємо його токен.

Він нам буде потрібен, щоб надсилати повідомлення від телеграм-бота в телеграм-канал. Додаємо нашого телеграм-бота в телеграм-канал, і робимо його адміністратором. Тепер він зможе надсилати повідомлення в каналі.

Також нам потрібно буде знати id каналу, в який бот буде надсилати повідомлення, це можна зробити за допомогою хаку, описаного тут. Id каналу запишемо в тій же таблиці DynamoDB.

Крок 3. Ще одна Lambda

Тепер залишилось створити ще одну AWS Lambda, яка буде перевіряти коли за адресою востаннє було світло. Будемо вважати, що якщо Raspberry Pi востаннє була жива більш як 7 хвилин тому, то світла нема. А якщо вона після цього ожила, то світло зʼявилось. Програмуємо нашу лямбду на таку перевірку, і якщо світло вимкнулось або увімкнулось, будемо надсилати повідомлення в канал, використовуючи нашого телеграм-бота, створеного на минулому кроці.

def lambda_handler(event, context):
    items = dynamodb.scan(
        TableName='eSvitlo',
    )['Items']

    for item in items:
        id = item['id']['S']
        ts = datetime.fromisoformat(item['pong']['S'])
        status = item['electricity_status']['S']
        channel_id = int(item['channel_id']['S'])

        now = datetime.now()

        print(f"State: {status}")
        print(f"TS: {ts}")

        if ((now - ts).total_seconds() > 60 * 7) and status == "on":
            send_telegram_message(channel_id, "Немає світла 🕯")
            status = "off"

        if ((now - ts).total_seconds() <= 60 * 7) and status == "off":
            send_telegram_message(channel_id, "Є світло 💡")
            status = "on"

        dynamodb.update_item(
            TableName='eSvitlo',
            Key={'id': {"S": id}},
            UpdateExpression="set electricity_status=:electricity_status",
            ExpressionAttributeValues={":electricity_status": {"S": status}}
        )

    return {
        'statusCode': 200,
        'body': json.dumps('Ok')
    }

І все, готово, залишилось скинути цей телеграм канал у вайбер-чат ОСББ, і насолоджуватись тим як він працює.

Крок 4. Роутер зі статичною IP-адресою

Наступною моєю ціллю було підключити такі ж канали в моєї мами та бабусі. Що ж, у них немає Rasbperry PI, а звичайний ноутбук не залишиш постійно увімкненим.

На допомогу прийшов інтернет-провайдер. Майже кожен провайдер надає послугу статичної IP-адреси. Це коли ти можеш набрати в браузері щось типу 10.11.12.1 і зайти на адмінку роутера. Отже, через контакт-центр оператора (в моєму випадку — «Київстар» та «Воля») замовляємо цю послугу і налаштовуємо роутер, дозволяючи віддалений доступ до нього з IP-адреси нашої Lambda. Про налаштування роутера написано ось тут. Про налаштування IP-адреси для Lambda написано ось тут.

Оскільки я не сильно знайомий з AWS VPC, то ж просто мовчки виконав те, що написано в статті, створив VPC, Internet Gateway, і NAT Gateway з Elastic IP-адресою. На жаль, IP-адреса, видана AWS, буде вже коштувати певних грошей, орієнтовно 4$ в місяць. Тепер наш роутер можна пінгувати.

Крок 5. Ще одна AWS Lambda

Наостанок, залишилось створити AWS, що буде пінгувати роутер, виконуючи простий HEAD-запит (HEAD для мінімізації кількості трафіку): якщо роутер відповів, значить є світло, і ми оновлюємо DynamoDB таблицю, якщо роутер не відповідає — немає світла.

Для мінімізації кількості часу, який працює наша Lambda, будемо використовувати asyncio + aiohttp. Це дозволяє нам пінгувати багато роутерів одночасно:

async def ping_router(ip: str, port: str):
    async with aiohttp.ClientSession() as session:
        try:
            await session.head(url=f"http://{ip}:{port}", timeout=10)
            return True
        except (asyncio.exceptions.TimeoutError, aiohttp.ClientConnectorError):
            return False


async def item_handler(item):
    id = item['id']['S']

    if 'ip' not in item:
        print(f"skip {id}")
        return

    ip = item['ip']['S']
    port = item['port']['S']

    alive = await ping_router(ip, port)

    if alive:
        print(f"{id} is alive")
        pong = datetime.now().isoformat()

        dynamodb.update_item(
            TableName='eSvitlo',
            Key={'id': {"S": id}},
            UpdateExpression="set pong=:pong",
            ExpressionAttributeValues={":pong": {"S": pong}}
        )
    else:
        print(f"{id} is not alive")

Крок 6. Усе готово

Тепер залишилось створити телеграм-канали для кожної адреси і додати їх до нашої бази даних. Готово:

Архітектура

Код

Вирішив, що в моєму коді немає нічого секретного, тому користуйтесь.

А ще, якщо хтось має статичний IP та хоче підключити собі такий канал, пишіть.

👍ПодобаєтьсяСподобалось12
До обраногоВ обраному4
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Перепрошив sonoff, запустив на ньому веб-сервер для керування в локалці, та запустив тред що пингує API виртуалки в digitalocean
Потім ще телеграм бота прикрутив.
Тепер можу увімкнути та вимкнути настольну лампу на веб-сторінці сонофф-а, чи через телеграм. А якщо світло пропаде, то віртуалка відстежить що вже 5 хвилин ніхто не пінгає та також в телеграм напише. на все про все ~10 баксів сонофф та 100 гривень програматор

Теж стало цікаво зробити якісь сповіщення про вимикання або вмикання світла.

Що маю:
— роутер Mikrotik hap ac3 lte
— інтернет по кабелю від провайдера
— LTE картку
— Джерело безперебійного живлення для роутера

Налаштував автоматичне перемикання і сповіщення (СМС) про зникання інтернету на кабелі по цій інструкції. xn----7sba7aachdbqfnhtigrl.xn—j1amh/nastrojka-neskolkih-provajderov-na-mikrotik-balansirovka-i-avtopereklyuchenie/#Provajder-menyaet-shlyuz-v-DHCP-kliente-ne-rabotaet-pereklyuchenie-ili-balansirovka

(Хз чи ДОУ пропустить посилання, сайт називається настройка-микротик.укр і він супер ***єнний і корисний, та ще і український, схоже)

Але є маленька «проблема» (хоча і вельми приємна, усі б проблеми були такими) — провайдер у домі має також джерело безперебійного живлення, і кабельний інтернет ще декілька годин працює без світла.

Тому і не виходить визначати момент зникання світла за зниканням кабельного інтернету.

Ось моя ідея — у мене є старий роутер, підімкну його патчкордом до Мікротика, дам йому статичну адресу, і буду пінгувати через Netwatch.

Коли світло зникне — отримаю сповіщення.

Хороша ідея! Я думав якось над тим щоб перевіряти чи живі сусідські wi fi роутери, шукаючи доступні wi fi мережі. Більшість сусідів не заморожуються над резервним живленням.

Навіщо щось пінгувати і давати статичні адреси, якщо мікротік вміє дивитися чи активний порт чи ні.

У нетвоч моніторінг порту не запхнеш
Хоча завжди можна зробити завдання у шедулері

Лайфхак вам, додаєте правило у фаерволі, за яким забороняєте відправляти пакети з усіх прортів, на конкретну Dst. Adress, крім WAN(x) :)

Краще робити це за допомогою route rules бо воно згідно діаграми відпрацьовує до firewall filter.
Хоча тут свої нюанси є.

І знову таки тут потрібен другий/третій/n-ий канал інтернет для того щоб оповіщення працювали

достатньо одного, який буде працювати

Нетвотч відстежує зміну стану доступності, і шле повідомлення один раз.
Як це зробити у шедулері?

А як реализуваты щоб він щей виконував скріпт якщо порт напраклад Оф чи Он ?

Я мав наувазі про моніторинг порта . В не пінгувати через нетвотч. В нетвоч можна тільки хост моніторити !?

Ви можете налаштувати правила, за якими до конкретного хоста, пакети будуть ходити через конкретний порт.
Також можна вказувати порт, в скриптингу, якщо не використовувати нетвотч.

В мене подібна реалізація на мікротіку.
Є два провайдери, основний лягає при відключенні світла, резервний — ні.
Netwatch пінгує статичний ІР, який надає основній провайдер. Залишається додати команду відправлення повідомлення до телеги, у налаштуваннях on up/ on down (прописати /tool fetch url="api.telegram.org...)

Все просто, без лишньої мороки.
Створив для себе, щоб знати яка ситуація, доки я не вдома :)

В принципі, для того хто має надійну БД статичних IP, з фізичними адресами, немає проблем створити атоматичну интерактивну мапу, або якщо користувачі згодні додати свої адреси :)
Достатньо одного мікротіку ))

Теж зробив би так, але оба канали не падають без світла.
В принципі, зробив, як планував (з другим роутером), працює прекрасно

В мене невватч також пінговалка стоїть , на публічний днс, і пакети йдуть через перший роут, якщо він падає , вмикається роут на другому лінку . Я думав що можно чисто на інтерфейс повісити скрипт , без пінговалки .

Як на мене якось складно.
AWS, лямбди, статична IP....

Я собі накидав бота на golang + mysql (хочу ще прикрутити стату по дням та хітмап по годинах).

github.com/aryzhenko/tg-light-bot

PS. Так, можна було щось простіше, без mysql, але на моєму vps мускуль вже був)

У всьго цього є мінуси. Світло може бути, а інтернету — ні. Якщо стоїть реле напруги , то конкретно на вашій фазі може бути низька або висока напруга і реле вирубить світло, хоча в вашому будинку воно буде.

Для конкретно моїх трох адрес спрацювало. Як тільки є світло, то є і Інтернет теж. Щоб світло зникло тільки у мене, це рідкісний випадок, можливо 1 на 1000, тому я думаю що це достатньо точний варіант.

Це я зі свого досвіду. Було й таке що у провайдера інтернет падав, плюс у на досить цікавий будинок, де перекос фаз це норма, і автомат часто відключає живлення а квартирі.
Зараз зробив на esp32, десь тут була стаття, але поправив під себе трохи. Вже з місяць працює без проблем.

Так само, сьогодні, для прикладу, в мене цілий день рубає реле, бо напруга 280 вольт.

А можно будь-ласка посилання, щось не знайшов :)

github.com/...​anha1/telegram-power-info

можу розказати як зробив в себе.
в підвалі підключив провід з розеткою після вхідного автомата ,перед реле напруги (в підвалі — бо в квартирі колхозити не хочеться, перед реле напруги — бо часто напруга скаче і реле вибиває, а хочеться знати чи є світло в принципі в будинку)
до розетки підключена зарядка з двома юсб портами . до одного порта підключений провід з резисторами що йде на esp, до другого модуль автономного живлення з двома 18650, через який підключений мобільний роутер і esp.
по цьому все . а так, до того ж модуля підключена ще частина типу розумного будинку, тобто мені довелося тільки зробити розетку і підключити esp . якби треба було купляти модем і модуль автономного живлення то не знаю чи поборов би себе на такі звершення )

Для трьох адрес так заморочуватися. У Вас напевне багато часу, а ще більше творчого натхнення.
Я особисто аплікуху-пінгувалку з сигналізацією на телефоні мав давно щоб
оперативно реагувати якщо десь щось впаде. Аплікух таких на плейстор вистачає.

Згоден що своя саморобка завжди рідніша і гнучкіша. Сам свої велосипедики самописні люблю як рідних дітей.

У мене вдома теж є розумна лампа, і як тільки з нею зникає світло (і інтернет) то зразу приходить сповіщення.
Але, наприклад коли світло вмикається то сповіщення не прийде, а лазити в додаток щоб перевірити чи лампа працює чи ні, якось ліньки) так так, написати три лямбди на AWS не ліньки, а перевіряти в додатку ліньки)
Також руки чесались написати щось таке от на AWS, щоб serverless, по найновішим рекомендціям, думаю в мене вийшло. Ще б воно було б безплатне, то було б ще краще, ну що ж, на й буде.
Також щасливі сусіди, які лайкають повідомлення в каналі зі світлом — це саме те, що надає мені натхнення.

raspberry pi + telegram + будьякий status page по бажанню github.com/...​vbeg/awesome-status-pages

ddns + eping bot?
10хв часу і 0 витрат

Так, але так не цікаво. Немає часопроводження з AWS :)

Или одна минута, если у тебя роутер микротик ))

І на ньому немає резервного живлення, і в провайдера немає проблем з живленням обладнання на шляху між інтернетом і квартирою.

І є білий IP для ddns

Підписатись на коментарі