inverter_bot: setosp command

This commit is contained in:
Evgeny Zinoviev 2022-10-21 01:09:59 +03:00
parent a1ee00b436
commit b1badba55e
2 changed files with 92 additions and 0 deletions

View File

@ -80,6 +80,7 @@ setbatuv - Set battery under voltage
setgencc - Set AC charging current setgencc - Set AC charging current
setgenct - Set AC charging thresholds setgenct - Set AC charging thresholds
setacmode - Set AC input mode setacmode - Set AC input mode
setosp - Set output source priority
monstatus - Monitor: dump state monstatus - Monitor: dump state
monsetcur - Monitor: set charging currents monsetcur - Monitor: set charging currents
``` ```

View File

@ -4,6 +4,7 @@ import re
import datetime import datetime
import json import json
from enum import Enum
from inverterd import Format, InverterError from inverterd import Format, InverterError
from html import escape from html import escape
from typing import Optional, Tuple, Union from typing import Optional, Tuple, Union
@ -51,7 +52,14 @@ flags_map = {
'fault_code_record': 'FTCR', 'fault_code_record': 'FTCR',
} }
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
SETACMODE_STARTED, = range(1) SETACMODE_STARTED, = range(1)
SETOSP_STARTED, = range(1)
class OutputSourcePriority(Enum):
SolarUtilityBattery = 'SUB'
SolarBatteryUtility = 'SBU'
def monitor_charging(event: ChargingEvent, **kwargs) -> None: def monitor_charging(event: ChargingEvent, **kwargs) -> None:
@ -283,6 +291,14 @@ def setacmode(mode: ACMode):
inverter.exec('set-max-ac-charge-current', (0, a)) inverter.exec('set-max-ac-charge-current', (0, a))
def setosp(sp: OutputSourcePriority):
logger.debug(f'setosp: sp={sp}')
inverter.exec('set-output-charge-priority', (sp,))
# /setacmode
# ----------
def setacmode_start(ctx: Context) -> None: def setacmode_start(ctx: Context) -> None:
if monitor.active_current is not None: if monitor.active_current is not None:
raise RuntimeError('generator charging program is active') raise RuntimeError('generator charging program is active')
@ -338,6 +354,60 @@ def setacmode_cancel(ctx: Context):
return ConversationHandler.END return ConversationHandler.END
# /setosp
# ------
def setosp_start(ctx: Context) -> None:
buttons = []
for sp in OutputSourcePriority:
buttons.append(ctx.lang(f'setosp_{sp.value.lower()}'))
markup = ReplyKeyboardMarkup([buttons, [ctx.lang('cancel')]], one_time_keyboard=False)
ctx.reply(ctx.lang('select_ac_mode'), markup=markup)
return SETOSP_STARTED
def setosp_input(ctx: Context):
selected_sp = None
for sp in OutputSourcePriority:
if ctx.text == ctx.lang(f'setosp_{sp.value.lower()}'):
selected_sp = sp
break
if selected_sp is None:
raise ValueError('invalid sp')
# apply the mode
setosp(selected_sp)
# reply to user
ctx.reply(ctx.lang('saved'), markup=IgnoreMarkup())
# notify other users
bot.notify_all(
lambda lang: bot.lang.get('osp_changed_notification', lang,
ctx.user.id, ctx.user.name,
bot.lang.get(str(selected_sp.value), lang)),
exclude=(ctx.user_id,)
)
bot.start(ctx)
return ConversationHandler.END
def setosp_invalid(ctx: Context):
ctx.reply(ctx.lang('invalid_mode'), markup=IgnoreMarkup())
return SETOSP_STARTED
def setosp_cancel(ctx: Context):
bot.start(ctx)
return ConversationHandler.END
# other
# -----
def setbatuv(ctx: Context) -> None: def setbatuv(ctx: Context) -> None:
try: try:
v = float(ctx.args[0]) v = float(ctx.args[0])
@ -423,6 +493,7 @@ class InverterBot(Wrapper):
done="Готово", done="Готово",
unexpected_callback_data="Ошибка: неверные данные", unexpected_callback_data="Ошибка: неверные данные",
select_ac_mode="Выберите режим:", select_ac_mode="Выберите режим:",
select_priortiy="Установите приоритет:",
invalid_input="Неверное значение", invalid_input="Неверное значение",
flags_press_button='Нажмите кнопку для переключения настройки', flags_press_button='Нажмите кнопку для переключения настройки',
@ -457,6 +528,9 @@ class InverterBot(Wrapper):
setgenct_dv=f'напряжение отключения заряда, 48 {LT} DV {LT} 58', setgenct_dv=f'напряжение отключения заряда, 48 {LT} DV {LT} 58',
setgencc_a='максимальный ток заряда, допустимые значения: %s', setgencc_a='максимальный ток заряда, допустимые значения: %s',
setosp_sub='Solar-Utility-Battery',
setosp_sbu='Solar-Battery-Utility',
# monitor # monitor
chrg_evt_started='✅ Начали заряжать от генератора.', chrg_evt_started='✅ Начали заряжать от генератора.',
chrg_evt_finished='✅ Зарядили. Генератор пора выключать.', chrg_evt_finished='✅ Зарядили. Генератор пора выключать.',
@ -477,6 +551,7 @@ class InverterBot(Wrapper):
# other notifications # other notifications
ac_mode_changed_notification='Пользователь <a href="tg://user?id=%d">%s</a> установил режим AC: <b>%s</b>.', ac_mode_changed_notification='Пользователь <a href="tg://user?id=%d">%s</a> установил режим AC: <b>%s</b>.',
osp_changed_notification='Пользователь <a href="tg://user?id=%d">%s</a> установил приоритет источника питания нагрузки: <b>%s</b>.',
bat_state_normal='Нормальный', bat_state_normal='Нормальный',
bat_state_low='Низкий', bat_state_low='Низкий',
@ -493,6 +568,7 @@ class InverterBot(Wrapper):
done="Done", done="Done",
unexpected_callback_data="Unexpected callback data", unexpected_callback_data="Unexpected callback data",
select_ac_mode="Select AC input mode:", select_ac_mode="Select AC input mode:",
select_priortiy="Select priority:",
invalid_input="Invalid input", invalid_input="Invalid input",
flags_press_button='Press a button to toggle a flag.', flags_press_button='Press a button to toggle a flag.',
@ -527,6 +603,9 @@ class InverterBot(Wrapper):
setgenct_dv=f'discharging voltage, 48 {LT} DV {LT} 58', setgenct_dv=f'discharging voltage, 48 {LT} DV {LT} 58',
setgencc_a='max charging current, allowed values: %s', setgencc_a='max charging current, allowed values: %s',
setosp_sub='Solar-Utility-Battery',
setosp_sbu='Solar-Battery-Utility',
# monitor # monitor
chrg_evt_started='✅ Started charging from AC.', chrg_evt_started='✅ Started charging from AC.',
chrg_evt_finished='✅ Finished charging, it\'s time to stop the generator.', chrg_evt_finished='✅ Finished charging, it\'s time to stop the generator.',
@ -547,6 +626,7 @@ class InverterBot(Wrapper):
# other notifications # other notifications
ac_mode_changed_notification='User <a href="tg://user?id=%d">%s</a> set AC mode to <b>%s</b>.', ac_mode_changed_notification='User <a href="tg://user?id=%d">%s</a> set AC mode to <b>%s</b>.',
osp_changed_notification='Пользователь <a href="tg://user?id=%d">%s</a> set output source priority: <b>%s</b>.',
bat_state_normal='Normal', bat_state_normal='Normal',
bat_state_low='Low', bat_state_low='Low',
@ -585,6 +665,17 @@ class InverterBot(Wrapper):
fallbacks=[MessageHandler(self.user_filter & cancel_filter, self.wrap(setacmode_cancel))] fallbacks=[MessageHandler(self.user_filter & cancel_filter, self.wrap(setacmode_cancel))]
)) ))
self.add_handler(ConversationHandler(
entry_points=[CommandHandler('setosp', self.wrap(setosp_start), self.user_filter)],
states={
SETOSP_STARTED: [
*[MessageHandler(text_filter(self.lang.all(f'setosp_{sp.value.lower()}')), self.wrap(setosp_input)) for sp in OutputSourcePriority],
MessageHandler(self.user_filter & ~cancel_filter, self.wrap(setosp_invalid))
]
},
fallbacks=[MessageHandler(self.user_filter & cancel_filter, self.wrap(setosp_cancel))]
))
super().run() super().run()
def markup(self, ctx: Optional[Context]) -> Optional[ReplyKeyboardMarkup]: def markup(self, ctx: Optional[Context]) -> Optional[ReplyKeyboardMarkup]: