diff options
Diffstat (limited to 'bin/pump_mqtt_bot.py')
-rwxr-xr-x | bin/pump_mqtt_bot.py | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/bin/pump_mqtt_bot.py b/bin/pump_mqtt_bot.py new file mode 100755 index 0000000..aea1451 --- /dev/null +++ b/bin/pump_mqtt_bot.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +import datetime +import __py_include + +from enum import Enum +from typing import Optional +from telegram import ReplyKeyboardMarkup, User + +from homekit.config import config +from homekit.telegram import bot +from homekit.telegram._botutil import user_any_name +from homekit.mqtt import MqttNode, MqttPayload +from homekit.mqtt.module.relay import MqttRelayState +from homekit.mqtt.module.diagnostics import InitialDiagnosticsPayload, DiagnosticsPayload + + +config.load_app('pump_mqtt_bot') + +bot.initialize() +bot.lang.ru( + start_message="Выберите команду на клавиатуре", + start_message_no_access="Доступ запрещён. Вы можете отправить заявку на получение доступа.", + unknown_command="Неизвестная команда", + send_access_request="Отправить заявку", + management="Админка", + + enable="Включить", + enabled="Включен ✅", + + disable="Выключить", + disabled="Выключен ❌", + + status="Статус", + status_updated=' (обновлено %s)', + + done="Готово 👌", + user_action_notification='Пользователь <a href="tg://user?id=%d">%s</a> <b>%s</b> насос.', + user_action_on="включил", + user_action_off="выключил", + date_yday="вчера", + date_yyday="позавчера", + date_at="в" +) +bot.lang.en( + start_message="Select command on the keyboard", + start_message_no_access="You have no access.", + unknown_command="Unknown command", + send_access_request="Send request", + management="Admin options", + + enable="Turn ON", + enable_silently="Turn ON silently", + enabled="Turned ON ✅", + + disable="Turn OFF", + disable_silently="Turn OFF silently", + disabled="Turned OFF ❌", + + status="Status", + status_updated=' (updated %s)', + + done="Done 👌", + user_action_notification='User <a href="tg://user?id=%d">%s</a> turned the pump <b>%s</b>.', + user_action_on="ON", + user_action_off="OFF", + + date_yday="yesterday", + date_yyday="the day before yesterday", + date_at="at" +) + + +mqtt: Optional[MqttNode] = None +relay_state = MqttRelayState() + + +class UserAction(Enum): + ON = 'on' + OFF = 'off' + + +def on_mqtt_message(home_id, message: MqttPayload): + if isinstance(message, InitialDiagnosticsPayload) or isinstance(message, DiagnosticsPayload): + kwargs = dict(rssi=message.rssi, enabled=message.flags.state) + if isinstance(message, InitialDiagnosticsPayload): + kwargs['fw_version'] = message.fw_version + relay_state.update(**kwargs) + + +def notify(user: User, action: UserAction) -> None: + def text_getter(lang: str): + action_name = bot.lang.get(f'user_action_{action.value}', lang) + user_name = user_any_name(user) + return 'ℹ ' + bot.lang.get('user_action_notification', lang, + user.id, user_name, action_name) + + bot.notify_all(text_getter, exclude=(user.id,)) + + +@bot.handler(message='enable') +def enable_handler(ctx: bot.Context) -> None: + mqtt.set_power(config['mqtt']['home_id'], True) + ctx.reply(ctx.lang('done')) + notify(ctx.user, UserAction.ON) + + +@bot.handler(message='disable') +def disable_handler(ctx: bot.Context) -> None: + mqtt.set_power(config['mqtt']['home_id'], False) + ctx.reply(ctx.lang('done')) + notify(ctx.user, UserAction.OFF) + + +@bot.handler(message='status') +def status(ctx: bot.Context) -> None: + label = ctx.lang('enabled') if relay_state.enabled else ctx.lang('disabled') + if relay_state.ever_updated: + date_label = '' + today = datetime.date.today() + if today != relay_state.update_time.date(): + yday = today - datetime.timedelta(days=1) + yyday = today - datetime.timedelta(days=2) + if yday == relay_state.update_time.date(): + date_label = ctx.lang('date_yday') + elif yyday == relay_state.update_time.date(): + date_label = ctx.lang('date_yyday') + else: + date_label = relay_state.update_time.strftime('%d.%m.%Y') + date_label += ' ' + date_label += ctx.lang('date_at') + ' ' + date_label += relay_state.update_time.strftime('%H:%M') + label += ctx.lang('status_updated', date_label) + ctx.reply(label) + + +def start(ctx: bot.Context) -> None: + if ctx.user_id in config['bot']['users'] or ctx.user_id in config['bot']['admin_users']: + ctx.reply(ctx.lang('start_message')) + else: + buttons = [ + [ctx.lang('send_access_request')] + ] + ctx.reply(ctx.lang('start_message_no_access'), markup=ReplyKeyboardMarkup(buttons, one_time_keyboard=False)) + + +@bot.exceptionhandler +def exception_handler(e: Exception, ctx: bot.Context) -> bool: + return False + + +@bot.defaultreplymarkup +def markup(ctx: Optional[bot.Context]) -> Optional[ReplyKeyboardMarkup]: + buttons = [[ctx.lang('enable'), ctx.lang('disable')], [ctx.lang('status')]] + if ctx.user_id in config['bot']['admin_users']: + buttons.append([ctx.lang('management')]) + return ReplyKeyboardMarkup(buttons, one_time_keyboard=False) + + +if __name__ == '__main__': + mqtt = MqttRelay(devices=MqttEspDevice(id=config['mqtt']['home_id'], + secret=config['mqtt']['home_secret'])) + mqtt.set_message_callback(on_mqtt_message) + mqtt.connect_and_loop(loop_forever=False) + + # bot.enable_logging(BotType.PUMP_MQTT) + bot.run(start_handler=start) + + mqtt.disconnect() |