diff --git a/appdaemon/settings/apps/doorbells/doorbell.py b/appdaemon/settings/apps/doorbells/doorbell.py index 8854896..33617b6 100644 --- a/appdaemon/settings/apps/doorbells/doorbell.py +++ b/appdaemon/settings/apps/doorbells/doorbell.py @@ -1,5 +1,6 @@ import appdaemon.plugins.hass.hassapi as hass import os +import globals # # App to send notification when doorbell is ringing @@ -26,10 +27,9 @@ class Doorbell(hass.Hass): def ha_event(self, event_name, data, kwargs): self.log('{}:{}'.format(event_name, data)) - self.notify("Звонок в дверь!!!", name = self.args['notify']) + globals.send_telegram(self, "Звонок в дверь!!!", target = self.args['notify']) if 'doorbell_pic' in data: - extra_data = {'photo': {'url':data['doorbell_pic']}} - self.notify("Фото звонившего", name = self.args['notify'], data=extra_data) + globals.send_telegram_photo(self, data['doorbell_pic'], target = self.args['notify'], caption = "Фото звонившего") self.say('Звонок в дверь') @@ -38,6 +38,6 @@ class Doorbell(hass.Hass): def say(self, command): if 'alices' in self.args: - for alice in self.args['alices']: + for alice in self.args['alices']: self.log('command = {}'.format(command)) - self.call_service('media_player/play_media', entity_id=alice, media_content_type='text', media_content_id=command, extra={'volume_level': 0.8}) \ No newline at end of file + self.call_service('media_player/play_media', entity_id=alice, media_content_type='text', media_content_id=command, extra={'volume_level': 0.8}) diff --git a/appdaemon/settings/apps/globals.py b/appdaemon/settings/apps/globals.py index ebc8299..f3bb5e0 100644 --- a/appdaemon/settings/apps/globals.py +++ b/appdaemon/settings/apps/globals.py @@ -2,22 +2,59 @@ import importlib import subprocess from typing import Any, Tuple, Union -# -# Global module -# contain global functions -# -# Args: -# -# None -# -# Release Notes -# -# Version 1.0: -# Initial Version - """Define various constants.""" CONF_PEOPLE = 'people' +# --- Telegram notifications ------------------------------------------------- +# +# HA 2026.2 deprecated the per-platform notify.telegram* services in favour +# of entity-based targeting (see repairs.issue_registry: telegram/migrate_notify). +# The generic notify.send_message service only supports message/title, so it +# can't carry parse_mode/photo/keyboard payloads our apps rely on - instead we +# target the telegram_bot integration's own (non-deprecated) domain services +# (telegram_bot.send_message / telegram_bot.send_photo) with entity_id, which +# is the current 1:1 replacement for the old chat_id-based notify.telegram*. +# +# Entity ids come from .storage/core.entity_registry (platform: telegram_bot), +# mapped from the friendly names ('telegram', 'telegram_monster', +# 'telegram_sveta') used throughout apps.yaml configs. +TELEGRAM_TARGETS = { + 'telegram': 'notify.home_assistant_fonvizina_fonvizina_18_1001567589226', + 'telegram_monster': 'notify.home_assistant_fonvizina_monster_123622180', + 'telegram_sveta': 'notify.home_assistant_fonvizina_svetlana_205225134', +} + +def send_telegram(self, message, target='telegram', parse_mode='html', **kwargs): + """Send a Telegram text message via telegram_bot.send_message. + + Replacement for the deprecated `self.notify(message, name=target)`. + `target` is a friendly name from TELEGRAM_TARGETS (falls back to the + default group chat if unknown). Extra kwargs (title, keyboard, etc.) are + passed straight through to the service call. + """ + entity_id = TELEGRAM_TARGETS.get(target, TELEGRAM_TARGETS['telegram']) + service_data = {'entity_id': entity_id, 'message': message} + if parse_mode: + service_data['parse_mode'] = parse_mode + service_data.update(kwargs) + self.call_service('telegram_bot/send_message', **service_data) + +def send_telegram_photo(self, url, target='telegram', caption=None, parse_mode='html', **kwargs): + """Send a photo via telegram_bot.send_photo. + + Replacement for the deprecated `self.notify(msg, name=target, + data={'photo': {'url': url}})`. + """ + entity_id = TELEGRAM_TARGETS.get(target, TELEGRAM_TARGETS['telegram']) + service_data = {'entity_id': entity_id, 'url': url} + if caption: + service_data['caption'] = caption + if parse_mode: + service_data['parse_mode'] = parse_mode + service_data.update(kwargs) + self.call_service('telegram_bot/send_photo', **service_data) +# ----------------------------------------------------------------------------- + def most_common(the_list: list) -> Any: """Return the most common element in a list.""" return max(set(the_list), key=the_list.count) @@ -57,12 +94,8 @@ def get_group_entities(self, group): return [] if 'attributes' in attributes: attributes = attributes['attributes'] - - #group if "entity_id" in attributes: return attributes["entity_id"] - - #simple item return [group] def turn_on(self, entity_id, state): @@ -78,14 +111,12 @@ def turn_off(self, entity_id, state): self.turn_off(entity_id, state) def notification(self, to, message): - self.notify(message, name = "telegram") - + send_telegram(self, message, target = "telegram") def get_arg(args, key): key = args[key] return key - def get_arg_list(args, key): arg_list = [] if isinstance(args[key], list): @@ -94,4 +125,4 @@ def get_arg_list(args, key): arg = (args[key]).split(",") for key in arg: arg_list.append(key) - return arg_list \ No newline at end of file + return arg_list diff --git a/appdaemon/settings/apps/locks/aqara_lock.py b/appdaemon/settings/apps/locks/aqara_lock.py index 93fbb03..cd595c4 100644 --- a/appdaemon/settings/apps/locks/aqara_lock.py +++ b/appdaemon/settings/apps/locks/aqara_lock.py @@ -1,4 +1,5 @@ import appdaemon.plugins.hass.hassapi as hass +import globals # # Aqara lock notifications @@ -7,7 +8,7 @@ import appdaemon.plugins.hass.hassapi as hass # Args: # lock_state_entity - entity of aqara lock state # notify - notify entity to send message -# +# # Release Notes # # Version 1.0: @@ -18,17 +19,17 @@ class AqaraLock(hass.Hass): if 'lock_state_entity' not in self.args or 'notify' not in self.args: self.error("Please provide lock_state_entity and notify in config!") return - + lock_state_entity = self.args['lock_state_entity'] self.log(' [+] listening for lock_state_entity sensor {}'.format(lock_state_entity)) - self.listen_state(self.sensor_trigger, lock_state_entity) + self.listen_state(self.sensor_trigger, lock_state_entity) def sensor_trigger(self, entity, attribute, old, new, kwargs): if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']): return - #(old != "" and old != "unknown") or + #(old != "" and old != "unknown") or if new == "unknown" or new == "" or new == "unavailable": self.log('skiping event. {} changed from {} to {}'.format(entity, old, new)) return @@ -36,7 +37,7 @@ class AqaraLock(hass.Hass): action = new self.process_event(action) - + def process_event(self, eventname): if eventname == "ring_bell": self.fire_event('doorbell_call') @@ -51,5 +52,4 @@ class AqaraLock(hass.Hass): self.notify_tg("Неизвестное событие замка: {}".format(eventname)) def notify_tg(self, msg): - extra_data = {'parse_mode': 'html'} - self.notify(msg, name = self.args['notify'], data=extra_data) + globals.send_telegram(self, msg, target = self.args['notify']) diff --git a/appdaemon/settings/apps/notifiers/balance.py b/appdaemon/settings/apps/notifiers/balance.py index 77fcb38..a184a41 100644 --- a/appdaemon/settings/apps/notifiers/balance.py +++ b/appdaemon/settings/apps/notifiers/balance.py @@ -1,4 +1,5 @@ import datetime +import globals from automation import Automation, Base # type: ignore # @@ -21,7 +22,7 @@ class Balance(Base): super().initialize() self.check_balance({"force": 1}) self.run_daily(self.check_balance, datetime.time(10, 0, 0)) - + def check_balance(self, kwargs): # if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']): # return @@ -61,5 +62,4 @@ class Balance(Base): def notify_tg(self, msg): if not 'notify' in self.args: return - extra_data = {'parse_mode': 'html'} - self.notify(msg, name = self.args['notify'], data=extra_data) + globals.send_telegram(self, msg, target = self.args['notify']) diff --git a/appdaemon/settings/apps/notifiers/battery.py b/appdaemon/settings/apps/notifiers/battery.py index d0a49fa..16fd4e3 100644 --- a/appdaemon/settings/apps/notifiers/battery.py +++ b/appdaemon/settings/apps/notifiers/battery.py @@ -1,65 +1,66 @@ -import appdaemon.plugins.hass.hassapi as hass -import datetime - -# -# App to send email report for devices running low on battery -# -# Args: -# -# threshold = value below which battery levels are reported and email is sent -# always_send = set to 1 to override threshold and force send -# -# None -# -# Release Notes -# -# Version 1.0: -# Initial Version - -class Battery(hass.Hass): - - def initialize(self): - #self.check_batteries({"force": 1}) - time = datetime.time(10, 0, 0) - self.run_daily(self.check_batteries, time) - self.check_batteries(None) - - def check_batteries(self, kwargs): - if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']): - return - - devices = self.get_state() - values = {} - low = [] - for deviceName in devices: - device = devices[deviceName] - if device == None: - continue - battery = None - if "attributes" in device: - if "battery" in device["attributes"]: - battery = device["attributes"]["battery"] - elif "battery_level" in device["attributes"]: - battery = device["attributes"]["battery_level"] - elif '_battery' in device['entity_id']: - battery = self.get_state(device['entity_id']) - if not battery.isdigit(): - continue - battery = int(battery) - print('{} = {}'.format(device['entity_id'], battery)) - if battery != None: - print('{} = {}'.format(device['entity_id'], battery)) - if battery < self.args["threshold"] and battery != 0: - low.append(deviceName) - values[deviceName] = battery - - message="" - if low: - message += "У следующих датчиков садится батарея: (< {}) \n".format(self.args["threshold"]) - for device in low: - message += "{}: {}%\n".format(self.friendly_name(device), values[device]) - message += "\n\n" - - if low: # or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1): - if message != "": - self.notify(message, name = "telegram") +import appdaemon.plugins.hass.hassapi as hass +import datetime +import globals + +# +# App to send email report for devices running low on battery +# +# Args: +# +# threshold = value below which battery levels are reported and email is sent +# always_send = set to 1 to override threshold and force send +# +# None +# +# Release Notes +# +# Version 1.0: +# Initial Version + +class Battery(hass.Hass): + + def initialize(self): + #self.check_batteries({"force": 1}) + time = datetime.time(10, 0, 0) + self.run_daily(self.check_batteries, time) + self.check_batteries(None) + + def check_batteries(self, kwargs): + if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']): + return + + devices = self.get_state() + values = {} + low = [] + for deviceName in devices: + device = devices[deviceName] + if device == None: + continue + battery = None + if "attributes" in device: + if "battery" in device["attributes"]: + battery = device["attributes"]["battery"] + elif "battery_level" in device["attributes"]: + battery = device["attributes"]["battery_level"] + elif '_battery' in device['entity_id']: + battery = self.get_state(device['entity_id']) + if not battery.isdigit(): + continue + battery = int(battery) + print('{} = {}'.format(device['entity_id'], battery)) + if battery != None: + print('{} = {}'.format(device['entity_id'], battery)) + if battery < self.args["threshold"] and battery != 0: + low.append(deviceName) + values[deviceName] = battery + + message="" + if low: + message += "У следующих датчиков садится батарея: (< {}) \n".format(self.args["threshold"]) + for device in low: + message += "{}: {}%\n".format(self.friendly_name(device), values[device]) + message += "\n\n" + + if low: # or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1): + if message != "": + globals.send_telegram(self, message) diff --git a/appdaemon/settings/apps/notifiers/bms_monitor.py b/appdaemon/settings/apps/notifiers/bms_monitor.py index fff82e1..4b461d7 100644 --- a/appdaemon/settings/apps/notifiers/bms_monitor.py +++ b/appdaemon/settings/apps/notifiers/bms_monitor.py @@ -1,5 +1,6 @@ import appdaemon.plugins.hass.hassapi as hass import datetime +import globals class BMSMonitor(hass.Hass): def initialize(self): @@ -17,7 +18,7 @@ class BMSMonitor(hass.Hass): self.current_state = "IDLE" # IDLE, CHARGING, DISCHARGING self.timer_handle = None self.was_charging = False - + # Переменная для хранения времени начала отключения self.outage_start_time = None @@ -45,15 +46,15 @@ class BMSMonitor(hass.Hass): # Логика переходов состояний if self.current_state != new_state: self.log(f"Смена состояния BMS: {self.current_state} -> {new_state}") - + # 1. Переход в разрядку (Отключили питание) if new_state == "DISCHARGING" and self.current_state != "DISCHARGING": # Фиксируем время начала отключения self.outage_start_time = datetime.datetime.now() - + self.send_telegram("⚠️ ВНИМАНИЕ: Отключено питание!\nБатарея перешла в режим разрядки.", "html") self.start_discharge_timer() - + # 2. Выход из разрядки (Питание восстановлено) # Срабатывает при переходе DISCHARGING -> IDLE или DISCHARGING -> CHARGING elif self.current_state == "DISCHARGING" and new_state in ("IDLE", "CHARGING"): @@ -62,14 +63,14 @@ class BMSMonitor(hass.Hass): duration = datetime.datetime.now() - self.outage_start_time duration_msg = f"\n⏱ Время без электричества: {self._format_timedelta(duration)}" self.outage_start_time = None # Сбрасываем таймер - + self.send_telegram(f"✅ Питание восстановлено!\nБатарея вышла из режима разрядки.{duration_msg}", "html") self.stop_discharge_timer() - + # 3. Переход в простой после зарядки (Зарядка окончена) elif new_state == "IDLE" and self.current_state == "CHARGING": self.send_telegram("🔋 Зарядка завершена!\nБатарея полностью заряжена или нагрузка отключена.", "html") - + # 4. Переход IDLE -> CHARGING (если не было разрядки перед этим) elif new_state == "CHARGING" and self.current_state == "IDLE": # Можно добавить отдельное уведомление, если нужно @@ -84,14 +85,14 @@ class BMSMonitor(hass.Hass): soc = float(new) if soc >= 100 and self.current_state == "CHARGING" and not self.was_charging: # Небольшая защита от повторных уведомлений - self.was_charging = True + self.was_charging = True except (ValueError, TypeError): pass def start_discharge_timer(self): if self.timer_handle is None: # Запускаем таймер: сразу первое сообщение, потом каждые N секунд - self.send_status_report() + self.send_status_report() self.timer_handle = self.run_every(self.periodic_status, datetime.datetime.now(), self.interval) self.log("Таймер статуса разрядки запущен") @@ -113,12 +114,12 @@ class BMSMonitor(hass.Hass): total_seconds = int(td.total_seconds()) hours, remainder = divmod(total_seconds, 3600) minutes, _ = divmod(remainder, 60) - + parts = [] if hours > 0: parts.append(f"{hours} ч") parts.append(f"{minutes} мин") - + return " ".join(parts) def send_status_report(self): @@ -134,16 +135,16 @@ class BMSMonitor(hass.Hass): soc = round(float(soc_raw), 1) if soc_raw not in (None, 'unknown', 'unavailable') else 0 current = round(float(current_raw), 2) if current_raw not in (None, 'unknown', 'unavailable') else 0 voltage = round(float(voltage_raw), 2) if voltage_raw not in (None, 'unknown', 'unavailable') else 0 - + # Определяем цвет/иконку для направления тока direction = "🔻 Разряд" if power < 0 else "🔺 Заряд" - + # Добавляем время без электричества, если известно outage_info = "" if self.outage_start_time: duration = datetime.datetime.now() - self.outage_start_time outage_info = f"\n⏳ Без света: {self._format_timedelta(duration)}" - + msg = ( f"📊 Статус батареи (JK BMS)\n\n" f"🔋 SOC: {soc}%\n" @@ -159,7 +160,6 @@ class BMSMonitor(hass.Hass): def send_telegram(self, message, parse_mode="html"): try: - extra_data = {'parse_mode': parse_mode} - self.notify(message, name = self.notification_target, data=extra_data) + globals.send_telegram(self, message, target = self.notification_target, parse_mode = parse_mode) except Exception as e: - self.log(f"Ошибка отправки Telegram: {e}") \ No newline at end of file + self.log(f"Ошибка отправки Telegram: {e}") diff --git a/appdaemon/settings/apps/notifiers/dishwasher.py b/appdaemon/settings/apps/notifiers/dishwasher.py index e44ec88..c66661f 100644 --- a/appdaemon/settings/apps/notifiers/dishwasher.py +++ b/appdaemon/settings/apps/notifiers/dishwasher.py @@ -1,6 +1,4 @@ import appdaemon.plugins.hass.hassapi as hass -from datetime import timedelta -import datetime # # App to show dishwasher state @@ -18,58 +16,75 @@ import datetime class Dishwasher(hass.Hass): listen_event_handle_list = [] - run_state = "" def initialize(self): - if 'run_state' not in self.args or 'door_sensor' not in self.args or 'counter' not in self.args: + if 'run_state' not in self.args or 'door_sensor' not in self.args or 'counter' not in self.args or 'state_extended' not in self.args: self.log("Please define all args") return - self.listen_event_handle_list.append(self.listen_state(self.door_state_change, self.args['door_sensor'])) #, attribute='action' - self.listen_event_handle_list.append(self.listen_state(self.run_state_change, self.args['run_state'])) #, attribute='action' + self.listen_event_handle_list.append(self.listen_state(self.door_state_change, self.args['door_sensor'])) + self.listen_event_handle_list.append(self.listen_state(self.run_state_change, self.args['run_state'])) + def get_extended_state(self): + return self.get_state(self.args['state_extended']) + + def set_extended_state(self, state): + self.call_service("input_select/select_option", entity_id = self.args['state_extended'], option = state) + def door_state_change(self, entity, attribute, old, new, kwargs): - if (new == "on"): - self.call_service("counter/increment", entity_id = self.args['counter']) - if (self.run_state == "finished"): - self.run_state = "collecting" - self.set_light_state_by_counter() + if new != "on": + return + + self.call_service("counter/increment", entity_id = self.args['counter']) + extended_state = self.get_extended_state() + open_count = int(self.get_state(self.args['counter'])) + + if extended_state == "Washed": + self.set_extended_state("Empty") + elif extended_state == "Empty": + if open_count < 10: + self.set_extended_state("Collecting Dishes") + elif open_count > 10: + self.set_extended_state("Ready to wash") + elif extended_state == "Collecting Dishes" and open_count > 10: + self.set_extended_state("Ready to wash") + + self.set_light_state_by_counter() def run_state_change(self, entity, attribute, old, new, kwargs): - self.log("event: {}: {}->{}".format(attribute,old,new)) - if (new == "Run"): + self.log("event: {}: {}->{}".format(attribute, old, new)) + if new == "Run": self.log('resetting counter') self.call_service("counter/reset", entity_id = self.args['counter']) - self.run_state = "washing" - if (new == "Finished"): + self.set_extended_state("Washing") + elif new == "Finished": self.log('resetting counter') self.call_service("counter/reset", entity_id = self.args['counter']) - self.run_state = "finished" + self.set_extended_state("Washed") - self.log('Current state is: {}'.format(self.run_state)) + self.log('Current state is: {}'.format(self.get_extended_state())) self.set_light_state_by_counter() def set_light_state_by_counter(self): - state = self.get_state(self.args['counter']) - open_count = int(state) - self.log('counter state={}, machine state = {}'.format(state, self.run_state)) + open_count = self.get_state(self.args['counter']) + extended_state = self.get_extended_state() + self.log('counter state={}, machine state = {}'.format(open_count, extended_state)) - if (self.run_state == "finished"): - # Есть посуда, которую нужно разобрать - # red color + if extended_state == "Washed": self.log('Time to take dishes out.') if 'lamp' in self.args: - self.call_service("light/turn_on", entity_id = self.args['lamp'], rgb_color=[255, 0, 0]) #red + self.call_service("light/turn_on", entity_id = self.args['lamp'], rgb_color=[255, 0, 0]) - elif (self.run_state == "washing"): + elif extended_state == "Washing": self.log('washing in progress') - self.call_service("light/turn_off", entity_id = self.args['lamp']) + if 'lamp' in self.args: + self.call_service("light/turn_off", entity_id = self.args['lamp']) - elif (open_count > 10): + elif extended_state == "Ready to wash": self.log('Time to run dishwasher.') if 'lamp' in self.args: - self.call_service("light/turn_on", entity_id = self.args['lamp'], rgb_color=[245, 236, 0]) #yellow + self.call_service("light/turn_on", entity_id = self.args['lamp'], rgb_color=[245, 236, 0]) - else: - self.call_service("light/turn_off", entity_id = self.args['lamp']) \ No newline at end of file + elif 'lamp' in self.args: + self.call_service("light/turn_off", entity_id = self.args['lamp']) diff --git a/appdaemon/settings/apps/notifiers/dishwasher.yaml b/appdaemon/settings/apps/notifiers/dishwasher.yaml index 9460a07..7d8e0b2 100644 --- a/appdaemon/settings/apps/notifiers/dishwasher.yaml +++ b/appdaemon/settings/apps/notifiers/dishwasher.yaml @@ -5,9 +5,10 @@ dishwasher: class: Dishwasher module: dishwasher constraint: input_boolean.dishwasher_state_light - counter: counter.dishwasher_door_open_count - door_sensor: binary_sensor.hc_dishwasher_door - run_state: sensor.hc_dishwasher_state + counter: counter.bosch_dishwasher_door_open_count + door_sensor: binary_sensor.bosch_dishwasher_door + run_state: sensor.bosch_dishwasher_operation_state + state_extended: input_select.bosch_dishwasher_state_extended lamp: light.espresense_kitchen_led_1 global_dependencies: - globals \ No newline at end of file diff --git a/appdaemon/settings/apps/notifiers/dishwasher_reminder.py b/appdaemon/settings/apps/notifiers/dishwasher_reminder.py new file mode 100644 index 0000000..a1a1aab --- /dev/null +++ b/appdaemon/settings/apps/notifiers/dishwasher_reminder.py @@ -0,0 +1,90 @@ +import appdaemon.plugins.hass.hassapi as hass +import random + +# +# App to remind about dishwasher when someone enters the kitchen +# +# Args: +# +# state_extended = input_select with extended dishwasher state +# motion_sensors = list of motion sensors to watch +# alice = Yandex Station media_player entity +# cooldown (optional) = seconds between reminders, default 1800 +# constraint (optional) = input_boolean to enable/disable the app +# +# Release Notes +# +# Version 1.0: +# Initial Version +# Version 1.1: +# Added "Ready to wash" reminders + +class DishwasherReminder(hass.Hass): + PHRASES_WASHED = [ + "Посудомойка готова! Пора разобрать посуду.", + "Чистая посуда сидит в посудомойке как в Open Space — пора выпустить на волю.", + "Посудомойка отработала, теперь твоя очередь — разгрузить.", + "Тарелки уже высохли и скучают, спаси их из посудомойки.", + "Посудомойка не склад для чистого, разгрузи уже.", + "Грязной посуды нет, а чистая застряла внутри — спасательная операция!", + "Посудомойка помыла всё, осталось только разобрать. Ну же!", + "Чистые тарелки устроили вечеринку в посудомойке — пора их разогнать.", + "Не забудь разобрать посудомойку, иначе завтра некуда будет класть грязное.", + "Посудомойка ждёт разгрузки — всё помыто, высушено и нетерпеливо дребезжит.", + ] + + PHRASES_READY_TO_WASH = [ + "Посудомойка скучает без работы — пора её запустить.", + "Гора посуды накопилась, посудомойка просит смелости нажать пуск.", + "Тарелки в посудомойке собрались на митинг — жми старт и отпусти их мыться.", + "Посудомойка готова к бою, осталось только нажать кнопку.", + "Хватит кормить посудомойку тарелками — пора включить и отдохнуть.", + "Посудомойка смотрит на тебя с надеждой — запускай программу.", + "Грязная посуда накопилась как снежный ком — время пустить посудомойку в ход.", + "Твои тарелки ждут водных процедур — включай посудомойку!", + "Посудомойка обидится, если её ещё раз оставят без дела — жми пуск.", + "Посуда застряла в посудомойке без мытья — самое время нажать старт и уйти пить чай.", + ] + + STATE_PHRASES = { + "Washed": PHRASES_WASHED, + "Ready to wash": PHRASES_READY_TO_WASH, + } + + def initialize(self): + if 'state_extended' not in self.args or 'motion_sensors' not in self.args or 'alice' not in self.args: + self.log("Please define state_extended, motion_sensors and alice") + return + + self.cooldown = self.args.get('cooldown', 1800) + self.last_announced = {} + + for sensor in self.args['motion_sensors']: + self.listen_state(self.motion_detected, sensor) + + def motion_detected(self, entity, attribute, old, new, kwargs): + if new != "on" or old == "on": + return + + # if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']): + # self.log('disabled by constraint') + # return + + state = self.get_state(self.args['state_extended']) + phrases = self.STATE_PHRASES.get(state) + if phrases is None: + return + + last = self.last_announced.get(state) + if last is not None: + elapsed = (self.datetime() - last).total_seconds() + if elapsed < self.cooldown: + self.log('cooldown active for {}, skipping'.format(state)) + return + + self.say(random.choice(phrases)) + self.last_announced[state] = self.datetime() + + def say(self, command): + self.log('command = {}'.format(command)) + self.call_service('media_player/play_media', entity_id=self.args['alice'], media_content_type='text', media_content_id=command) diff --git a/appdaemon/settings/apps/notifiers/dishwasher_reminder.yaml b/appdaemon/settings/apps/notifiers/dishwasher_reminder.yaml new file mode 100644 index 0000000..06e22af --- /dev/null +++ b/appdaemon/settings/apps/notifiers/dishwasher_reminder.yaml @@ -0,0 +1,15 @@ +################################# +# DISHWASHER REMINDER # +################################# +dishwasher_reminder: + class: DishwasherReminder + module: dishwasher_reminder + # constraint: input_boolean.dishwasher_reminder + state_extended: input_select.bosch_dishwasher_state_extended + motion_sensors: + - binary_sensor.motion_kitchenset_left_occupancy + - binary_sensor.motion_kitchenset_right_occupancy + alice: media_player.yandex_station_m00r46000m53db + cooldown: 3600 + global_dependencies: + - globals diff --git a/appdaemon/settings/apps/notifiers/security.py b/appdaemon/settings/apps/notifiers/security.py index 3bfc17a..acaa418 100644 --- a/appdaemon/settings/apps/notifiers/security.py +++ b/appdaemon/settings/apps/notifiers/security.py @@ -1,28 +1,29 @@ -import appdaemon.plugins.hass.hassapi as hass -import datetime - -# -# App to send reports about unsuccessfull auths -# -# Args: -# -# threshold = value below which battery levels are reported and email is sent -# always_send = set to 1 to override threshold and force send -# -# None -# -# Release Notes -# -# Version 1.0: -# Initial Version - -class Security(hass.Hass): - def initialize(self): - self.log('---------------------') - self.listen_event_handle_list = [] - self.listen_event_handle_list.append(self.listen_state(self.state_change, 'persistent_notification.http_login', attribute='message')) - - def state_change(self, entity, attribute, old, new, kwargs): - notifier = self.args.get('notify', 'telegram') - self.notify(new, name = notifier) - self.log(new) \ No newline at end of file +import appdaemon.plugins.hass.hassapi as hass +import datetime +import globals + +# +# App to send reports about unsuccessfull auths +# +# Args: +# +# threshold = value below which battery levels are reported and email is sent +# always_send = set to 1 to override threshold and force send +# +# None +# +# Release Notes +# +# Version 1.0: +# Initial Version + +class Security(hass.Hass): + def initialize(self): + self.log('---------------------') + self.listen_event_handle_list = [] + self.listen_event_handle_list.append(self.listen_state(self.state_change, 'persistent_notification.http_login', attribute='message')) + + def state_change(self, entity, attribute, old, new, kwargs): + notifier = self.args.get('notify', 'telegram') + globals.send_telegram(self, new, target = notifier) + self.log(new) diff --git a/appdaemon/settings/apps/notifiers/teeth_brushing.py b/appdaemon/settings/apps/notifiers/teeth_brushing.py index dc3b6ed..fad4d7c 100644 --- a/appdaemon/settings/apps/notifiers/teeth_brushing.py +++ b/appdaemon/settings/apps/notifiers/teeth_brushing.py @@ -1,6 +1,7 @@ import appdaemon.plugins.hass.hassapi as hass from datetime import timedelta import datetime +import globals # # App to send email report for devices running low on battery @@ -24,10 +25,10 @@ class Teeth(hass.Hass): # Устанавливаем сброс в 10 утра reset_time = datetime.time(10, 0, 0) self.run_daily(self.reset_action, reset_time) - + # Запускаем проверку напоминаний self.timer = self.run_every(self.remind_if_needed, self.datetime()+timedelta(seconds=1), self.args['remind_interval']) - + # Слушаем изменения состояния кнопки self.listen_event_handle_list.append(self.listen_state(self.button_state_change, self.args['mute_button'])) @@ -78,5 +79,4 @@ class Teeth(hass.Hass): notify = self.args["notify"] now = datetime.datetime.now()+timedelta(hours=3) message="Уже {}, а ты еще не почистил зубы. Самое время =)".format(now.strftime("%H:%M")) - self.notify(message, name = notify) - + globals.send_telegram(self, message, target = notify) diff --git a/appdaemon/settings/apps/notifiers/water_counters.py b/appdaemon/settings/apps/notifiers/water_counters.py index 9e67c3b..8c980dc 100644 --- a/appdaemon/settings/apps/notifiers/water_counters.py +++ b/appdaemon/settings/apps/notifiers/water_counters.py @@ -24,7 +24,7 @@ class WaterCountersAlarm(hass.Hass): return self.checkup_threasold = self.args['checkup_threasold'] self.send_threasold = self.args['send_threasold'] - + self.check_send_dates({"force": 1}) self.run_daily(self.check_checkup_dates, datetime.time(10, 0, 0)) self.run_daily(self.check_send_dates, datetime.time(10, 1, 0)) @@ -69,8 +69,8 @@ class WaterCountersAlarm(hass.Hass): if send_devices or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1): if message != "": - self.notify(message, name = "telegram") - + globals.send_telegram(self, message) + def check_checkup_dates(self, kwargs): if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']): return @@ -78,7 +78,7 @@ class WaterCountersAlarm(hass.Hass): entities = self.get_state() if entities == None: return - + values = {} checkup_devices = [] for entity_id in entities: @@ -106,4 +106,4 @@ class WaterCountersAlarm(hass.Hass): if checkup_devices or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1): if message != "": - self.notify(message, name = "telegram") \ No newline at end of file + globals.send_telegram(self, message) diff --git a/appdaemon/settings/apps/notify.py b/appdaemon/settings/apps/notify.py index 631cc84..3fd7291 100644 --- a/appdaemon/settings/apps/notify.py +++ b/appdaemon/settings/apps/notify.py @@ -1,10 +1,11 @@ import appdaemon.plugins.hass.hassapi as hass +import globals # # Notification system # # Args: -# +# # Release Notes # # Version 1.0: @@ -42,7 +43,7 @@ class TelegramNotifyTarget(BaseNotifyTarget): target = self.target_sveta hass.log('notifying over telegram person {} with message: {}'.format(target, message)) - hass.notify(message, name=target) + globals.send_telegram(hass, message, target=target) class Notification(hass.Hass): home_targets = [AliceNotifyTarget()] @@ -60,4 +61,4 @@ class Notification(hass.Hass): notifyTarget = self.home_targets[0] self.log('message: {}'.format(message)) - notifyTarget.notify(self, message, person=target) \ No newline at end of file + notifyTarget.notify(self, message, person=target) diff --git a/appdaemon/settings/apps/presence/report_action.py b/appdaemon/settings/apps/presence/report_action.py index 17f5918..0018a1e 100644 --- a/appdaemon/settings/apps/presence/report_action.py +++ b/appdaemon/settings/apps/presence/report_action.py @@ -4,11 +4,11 @@ import globals # # Home and away report # Send report about home state after presence_actions was done. -# +# # Args: # entity - group of entities to send state report # notify - notify entity to send message -# +# # Release Notes # # Version 1.0: @@ -32,7 +32,7 @@ class ReportByPresence(hass.Hass): def return_home_mode(self, event_id, event_args, kwargs): if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']): return - self.notify("Добро пожаловать домой!", name = self.args['notify']) + globals.send_telegram(self, "Добро пожаловать домой!", target = self.args['notify']) ############# AWAY REPORT ########################## def send_report(self, kwargs): @@ -46,6 +46,6 @@ class ReportByPresence(hass.Hass): message += '{} ({}) = {}\n'.format(self.friendly_name(entity), entity, self.get_state(entity)) if any: message = "В доме остались работать следующие устройства:\n" + message - self.notify(message, name = self.args['notify']) + globals.send_telegram(self, message, target = self.args['notify']) else: - self.notify("Все устройства в доме выключены.", name = self.args['notify']) + globals.send_telegram(self, "Все устройства в доме выключены.", target = self.args['notify']) diff --git a/appdaemon/settings/apps/presence/water_action.py b/appdaemon/settings/apps/presence/water_action.py index 83f022e..4775873 100644 --- a/appdaemon/settings/apps/presence/water_action.py +++ b/appdaemon/settings/apps/presence/water_action.py @@ -1,15 +1,16 @@ import appdaemon.plugins.hass.hassapi as hass import datetime +import globals # # Water control application. # Controls water valve when all leave and no water needed devices is working. -# +# # Args: # water_valve = water valve entity # notify - notify entity to send message # constraint (optional) = input_boolean to enable\disable this automation -# +# # Release Notes # # Version 1.0: @@ -56,11 +57,11 @@ class WaterValveControl(hass.Hass): if name is None: name = device device_names += name - self.notify('В доме остались требующие воды устройства ({}), подача воды не будет отключена.'.format(device_names), name = self.args['notify']) + globals.send_telegram(self, 'В доме остались требующие воды устройства ({}), подача воды не будет отключена.'.format(device_names), target = self.args['notify']) self.cancel_current_timer() self.timers.append(self.run_every(self.wait_when_device_is_done, self.datetime()+datetime.timedelta(seconds=5), 5*60)) else: - self.notify('Отключаю подачу воды.', name = self.args['notify']) + globals.send_telegram(self, 'Отключаю подачу воды.', target = self.args['notify']) self.turn_off(self.args['water_valve']) # for device in self.args['water_devices']: # self.turn_off(device) @@ -77,7 +78,7 @@ class WaterValveControl(hass.Hass): self.current_wait_cycle = self.current_wait_cycle+1 elif len(powered_on) == 0 and self.current_wait_cycle>=self.wait_cycles: self.current_wait_cycle = 0 - self.notify('Устройства требующие воды закончили свою работу, отключаю подачу воды.', name = self.args['notify']) + globals.send_telegram(self, 'Устройства требующие воды закончили свою работу, отключаю подачу воды.', target = self.args['notify']) self.turn_off_water_devices() self.cancel_current_timer() diff --git a/appdaemon/settings/apps/presence/water_action.yaml b/appdaemon/settings/apps/presence/water_action.yaml index 2a4cb67..ed492c9 100644 --- a/appdaemon/settings/apps/presence/water_action.yaml +++ b/appdaemon/settings/apps/presence/water_action.yaml @@ -9,6 +9,6 @@ water_action: constraint: input_boolean.water_control water_devices: - binary_sensor.washer_running # стиралка - - binary_sensor.hc_dishwasher_running # посудомойка + - binary_sensor.bosch_dishwasher_running # посудомойка global_dependencies: - globals \ No newline at end of file diff --git a/appdaemon/settings/apps/router/keenetic.py b/appdaemon/settings/apps/router/keenetic.py index 5ce6709..442bad5 100644 --- a/appdaemon/settings/apps/router/keenetic.py +++ b/appdaemon/settings/apps/router/keenetic.py @@ -1,5 +1,6 @@ import appdaemon.plugins.hass.hassapi as hass import requests +import globals from datetime import datetime class TelegramInternetControl(hass.Hass): @@ -7,50 +8,50 @@ class TelegramInternetControl(hass.Hass): Управление интернетом через Telegram команды. Поддерживает множественные MAC-адреса. """ - + def initialize(self): """ Инициализация приложения. """ self.log("Telegram Internet Control initialized") - + # Конфигурация из apps.yaml self.api_url = self.args.get("api_url", "http://localhost:8000/run") self.api_user = self.args.get("api_user", "api_user") self.api_password = self.args.get("api_password", "strong_password") - + # Команды Telegram self.block_command = self.args.get("block_command", "Коля наказан").lower() self.unblock_command = self.args.get("unblock_command", "Включи Коле интернет").lower() - + # MAC адреса для управления (массив) self.target_macs = self.args.get("target_macs", []) if isinstance(self.target_macs, str): self.target_macs = [self.target_macs] - + # Разрешенные user_id (безопасность) self.allowed_users = self.args.get("allowed_users", []) if isinstance(self.allowed_users, int): self.allowed_users = [self.allowed_users] - + # Entity для прослушивания событий Telegram self.telegram_event_entity = self.args.get( - "telegram_event_entity", + "telegram_event_entity", "event.home_assistant_fonvizina_update_event" ) - - # Сервис для отправки ответов в Telegram - self.notify_service = self.args.get("notify_service", "notify/telegram") - + + # Цель (friendly name из globals.TELEGRAM_TARGETS) для отправки ответов в Telegram + self.notify_target = self.args.get("notify_target", "telegram") + # Сохраняем последнее обработанное время (для пропуска дублей) self.last_processed_time = None - + # Слушаем изменения состояния события Telegram self.listen_state( self.on_telegram_event, self.telegram_event_entity ) - + self.log(f"Listening to: {self.telegram_event_entity}") self.log(f"Block command: '{self.block_command}'") self.log(f"Unblock command: '{self.unblock_command}'") @@ -78,80 +79,80 @@ class TelegramInternetControl(hass.Hass): try: # Получаем полный объект состояния с атрибутами state_data = self.get_state(entity, attribute="all") - + if state_data is None: self.log("State data is None") return - + # Получаем атрибуты attributes = state_data.get("attributes", {}) - + if not attributes: self.log("No attributes in state data") return - + # Проверяем тип события (должно быть telegram_text) event_type = attributes.get("event_type", "") if event_type != "telegram_text": return - + # Получаем текст сообщения text = attributes.get("text", "").strip() if not text: return - + # Получаем user_id отправителя user_id = attributes.get("user_id") from_first = attributes.get("from_first", "Unknown") - + # Получаем время события для защиты от дублей event_time = attributes.get("date", "") - + # Пропускаем если уже обработали это событие if event_time == self.last_processed_time: self.log(f"Skipping duplicate event: {event_time}") return - + self.last_processed_time = event_time - + self.log(f"Telegram message from {from_first} (user_id: {user_id}): '{text}'") - + # Проверяем, разрешен ли пользователь if user_id not in self.allowed_users: self.log(f"User {user_id} not in allowed list. Ignoring.") return - + # Обрабатываем команды (регистронезависимо) text_lower = text.lower() - + if text_lower == self.block_command: self.handle_block_command(from_first) elif text_lower == self.unblock_command: self.handle_unblock_command(from_first) - + except Exception as e: self.log(f"Error processing Telegram event: {str(e)}") self.log(f"State data: {state_data if 'state_data' in locals() else 'N/A'}") - + def handle_block_command(self, user_name): """ Блокировка интернета для всех MAC-адресов. """ self.log(f"Blocking internet for {user_name}") - + if not self.target_macs: self.send_telegram_message(f"❌ {user_name}, не настроены MAC-адреса для блокировки!") self.log("No MAC addresses configured") return - + success_count = 0 failed_macs = [] - + for mac in self.target_macs: # Формируем команду для роутера - command = f"ip hotspot host {mac} schedule schedule1" + command = f"ip hotspot host {mac} schedule schedule1" self.log(f"Sending command: {command}") - + if self.send_to_router(command): success_count += 1 else: @@ -159,7 +160,7 @@ class TelegramInternetControl(hass.Hass): command = "system configuration save" self.log(f"Sending command: {command}") cmd = self.send_to_router(command) - + # Формируем отчет if success_count == len(self.target_macs): self.send_telegram_message( @@ -175,21 +176,21 @@ class TelegramInternetControl(hass.Hass): else: self.send_telegram_message(f"❌ {user_name}, ошибка при блокировке интернета!") self.log("Failed to block internet") - + def handle_unblock_command(self, user_name): """ Разблокировка интернета для всех MAC-адресов. """ self.log(f"Unblocking internet for {user_name}") - + if not self.target_macs: self.send_telegram_message(f"❌ {user_name}, не настроены MAC-адреса для разблокировки!") self.log("No MAC addresses configured") return - + success_count = 0 failed_macs = [] - + for mac in self.target_macs: # Формируем команду для роутера command = f"ip hotspot host {mac} schedule schedule0" @@ -203,7 +204,7 @@ class TelegramInternetControl(hass.Hass): command = "system configuration save" self.log(f"Sending command: {command}") cmd = self.send_to_router(command) - + # Формируем отчет if success_count == len(self.target_macs): self.send_telegram_message( @@ -219,7 +220,7 @@ class TelegramInternetControl(hass.Hass): else: self.send_telegram_message(f"❌ {user_name}, ошибка при включении интернета!") self.log("Failed to unblock internet") - + def send_to_router(self, command): """ Отправка команды на роутер через API. @@ -231,11 +232,11 @@ class TelegramInternetControl(hass.Hass): auth=(self.api_user, self.api_password), timeout=10 ) - + if response.status_code == 200: result = response.json() exit_code = result.get("exit_code", -1) - + if exit_code == 0: return True else: @@ -247,20 +248,17 @@ class TelegramInternetControl(hass.Hass): self.log(f"API request failed with status: {response.status_code}") self.log(f"Response: {response.text}") return False - + except Exception as e: self.log(f"Error sending command to router: {str(e)}") return False - + def send_telegram_message(self, message): """ Отправка ответа в Telegram. """ try: - self.call_service( - self.notify_service, - message=message - ) + globals.send_telegram(self, message, target = self.notify_target) self.log(f"Telegram message sent: {message}") except Exception as e: - self.log(f"Error sending Telegram message: {str(e)}") \ No newline at end of file + self.log(f"Error sending Telegram message: {str(e)}") diff --git a/appdaemon/settings/apps/router/keenetic.yaml b/appdaemon/settings/apps/router/keenetic.yaml index bbf040e..bf6f179 100644 --- a/appdaemon/settings/apps/router/keenetic.yaml +++ b/appdaemon/settings/apps/router/keenetic.yaml @@ -1,27 +1,29 @@ keenetic: module: keenetic class: TelegramInternetControl - + # URL вашего API (адрес контейнера с API) api_url: "http://192.168.1.6:8001/run" api_user: !secret router_username api_password: !secret router_password - + # Команды Telegram (регистронезависимые) block_command: "Коля наказан" unblock_command: "Включи Коле интернет" - + # MAC адреса для управления (массив) target_macs: - "cc:4b:73:04:ed:34" - "b8:41:d9:d8:3f:58" - + # Разрешенные user_id из Telegram (безопасность!) allowed_users: - 123622180 - + # Entity для прослушивания событий telegram_event_entity: "event.home_assistant_fonvizina_update_event" - - # Сервис для отправки уведомлений в Telegram - notify_service: "notify/telegram" \ No newline at end of file + + # Цель отправки уведомлений (friendly name из globals.TELEGRAM_TARGETS, + # см. appdaemon/settings/apps/globals.py). Раньше здесь был deprecated + # notify_service: "notify/telegram". + notify_target: "telegram" diff --git a/appdaemon/settings/apps/security/fire_sensors.py b/appdaemon/settings/apps/security/fire_sensors.py index 4661629..88e9a7d 100644 --- a/appdaemon/settings/apps/security/fire_sensors.py +++ b/appdaemon/settings/apps/security/fire_sensors.py @@ -1,5 +1,6 @@ import appdaemon.plugins.hass.hassapi as hass import fnmatch +import globals # # Fire sensors alarm notification @@ -10,7 +11,7 @@ import fnmatch # sensor - gorup of sensors to listen # ha_panel - alarm panel entity # notify - notify entity to send message -# +# # Release Notes # # Version 1.0: @@ -21,7 +22,7 @@ class FireSensorsReport(hass.Hass): if 'sensor_parts' not in self.args or 'notify' not in self.args: self.error("Please provide sensor_parts, ha_panel and notify in config!") return - + sensor_parts = self.args['sensor_parts'] all_sensors = self.get_state() @@ -29,7 +30,7 @@ class FireSensorsReport(hass.Hass): for part in sensor_parts: if fnmatch.fnmatch(entity_id, part): self.log(' [+] listening for security sensor {}'.format(entity_id)) - self.listen_state(self.sensor_trigger, entity_id) + self.listen_state(self.sensor_trigger, entity_id) def sensor_trigger(self, entity, attribute, old, new, kwargs): if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']): @@ -45,4 +46,4 @@ class FireSensorsReport(hass.Hass): friendly_name = self.friendly_name(entity) entity = entity.replace('_', '-') message = "Сработал датчик пожарной сигнализации {} ({}) = {}-{}!".format(friendly_name, entity, old, new) - self.notify(message, name = self.args['notify']) \ No newline at end of file + globals.send_telegram(self, message, target = self.args['notify']) diff --git a/appdaemon/settings/apps/security/security_sensors.py b/appdaemon/settings/apps/security/security_sensors.py index 06f606b..c18b349 100644 --- a/appdaemon/settings/apps/security/security_sensors.py +++ b/appdaemon/settings/apps/security/security_sensors.py @@ -1,5 +1,6 @@ import appdaemon.plugins.hass.hassapi as hass import fnmatch +import globals # # Security sensors alarm notification @@ -10,7 +11,7 @@ import fnmatch # sensor - gorup of sensors to listen # ha_panel - alarm panel entity # notify - notify entity to send message -# +# # Release Notes # # Version 1.0: @@ -21,7 +22,7 @@ class SecuritySensorsReport(hass.Hass): if 'sensor_parts' not in self.args or 'ha_panel' not in self.args or 'notify' not in self.args: self.error("Please provide sensor_parts, ha_panel and notify in config!") return - + sensor_parts = self.args['sensor_parts'] all_sensors = self.get_state() @@ -29,7 +30,7 @@ class SecuritySensorsReport(hass.Hass): for part in sensor_parts: if fnmatch.fnmatch(entity_id, part): self.log(' [+] listening for security sensor {}'.format(entity_id)) - self.listen_state(self.sensor_trigger, entity_id) + self.listen_state(self.sensor_trigger, entity_id) def sensor_trigger(self, entity, attribute, old, new, kwargs): if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']): @@ -56,4 +57,4 @@ class SecuritySensorsReport(hass.Hass): friendly_name = self.friendly_name(entity) entity = entity.replace('_', '-') message = "В ваше отсутствие сработал датчик безопастности {} ({}) = {}->{}!".format(friendly_name, entity, old, new) - self.notify(message, name = self.args['notify']) \ No newline at end of file + globals.send_telegram(self, message, target = self.args['notify']) diff --git a/appdaemon/settings/apps/security/water_leak.py b/appdaemon/settings/apps/security/water_leak.py index 4c50988..e8f6adb 100644 --- a/appdaemon/settings/apps/security/water_leak.py +++ b/appdaemon/settings/apps/security/water_leak.py @@ -1,4 +1,5 @@ import appdaemon.plugins.hass.hassapi as hass +import globals # # Water leak detector @@ -54,9 +55,9 @@ class WaterLeak(hass.Hass): self.call_service("mqtt/publish", topic = 'home/watercontrol/bath/valve/set', payload = 'close') message = "ВНИМАНИЕ! В ваше отстутствие сработал датчик протечки воды ({})!!! Выключаю подачу воды.".format(self.friendly_name(entity_id)) - self.notify(message, name = self.args['notify']) + globals.send_telegram(self, message, target = self.args['notify']) message = "Состояние датчиков протечки:\n" for entity_id in self.sensors: message += '{} ({}) = {}\n'.format(self.friendly_name(entity_id), entity_id, self.get_state(entity_id)) - self.notify(message, name = self.args['notify']) \ No newline at end of file + globals.send_telegram(self, message, target = self.args['notify']) diff --git a/appdaemon/settings/apps/sensors/uniservice.py b/appdaemon/settings/apps/sensors/uniservice.py index e7c0366..044e833 100644 --- a/appdaemon/settings/apps/sensors/uniservice.py +++ b/appdaemon/settings/apps/sensors/uniservice.py @@ -97,7 +97,7 @@ class EpdBalanceSensor(hass.Hass): doc = BeautifulSoup(r.content, 'html.parser') address = doc.find("div", string="Вы собственник по адресу:").parent.find_all('div')[1].text result['address'] = address - + service_to_pay = doc.find('div', string="ЖКУ, к оплате:").parent.find_all('div')[1].text.replace(' Р.', '') result['service_to_pay'] = service_to_pay @@ -167,5 +167,4 @@ class EpdBalanceSensor(hass.Hass): def notify_tg(self, msg): if not 'notify' in self.args: return - extra_data = {'parse_mode': 'html'} - self.notify(msg, name = self.args['notify'], data=extra_data) + globals.send_telegram(self, msg, target = self.args['notify']) diff --git a/appdaemon/settings/apps/test/test.py b/appdaemon/settings/apps/test/test.py index e886ce4..bcdb1f2 100644 --- a/appdaemon/settings/apps/test/test.py +++ b/appdaemon/settings/apps/test/test.py @@ -7,14 +7,17 @@ Arguments: - events: List of events to monitor """ class Test(hass.Hass): - notify = None + # notify = None def initialize(self) -> None: - self.listen_state(self.sensor_trigger, 'sensor.0x00158d0003a361d8_action') - self.listen_state(self.sensor_trigger, 'binary_sensor.0x00158d0003f26d61_occupancy') - # self.listen_state(self.sensor_trigger, 'sensor.remote20_action') + self.log("hello") + # notifier = self.args.get("notify", "telegram") + # self.notify("hello world", name = "telegram") + # self.listen_state(self.sensor_trigger, "sensor.0x00158d0003a361d8_action") + # self.listen_state(self.sensor_trigger, "binary_sensor.0x00158d0003f26d61_occupancy") + # self.listen_state(self.sensor_trigger, "sensor.remote20_action") - def sensor_trigger(self, entity, attribute, old, new, kwargs): - if new != "" and new != "unknown": - self.log("doorbell call") - self.toggle("switch.0x00158d00020f3a29_switch") \ No newline at end of file + # def sensor_trigger(self, entity, attribute, old, new, kwargs): + # if new != "" and new != "unknown": + # self.log("doorbell call") + # self.toggle("switch.0x00158d00020f3a29_switch") diff --git a/docker-compose.yaml b/docker-compose.yaml index ab1bc20..cc6dbc9 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -32,7 +32,7 @@ services: max-size: 50m hass: - image: "homeassistant/home-assistant:stable" #stable + image: "homeassistant/home-assistant:stable" #2026.4.2 #image: ghcr.io/home-assistant/home-assistant:stable container_name: hass volumes: @@ -121,10 +121,12 @@ services: volumes: - ./zigbee2mqtt/settings:/app/data healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8080"] + # в образе нет curl (Alpine), используем wget --spider + test: ["CMD", "wget", "--spider", "-q", "http://localhost:8080"] interval: 30s timeout: 10s retries: 6 + start_period: 60s restart: always logging: driver: json-file @@ -184,22 +186,22 @@ services: max-size: "10m" max-file: "5" - homeconnect2mqtt: - build: - context: ./homeconnect2mqtt/docker - dockerfile: Dockerfile - restart: always - container_name: homeconnect2mqtt - ports: - - "5001:5000" - env_file: ./homeconnect2mqtt/settings/homeconnect2mqtt.env - volumes: - - ./homeconnect2mqtt/settings/config.json:/app/config.json:ro - logging: - driver: json-file - options: - max-size: "10m" - max-file: "5" + #homeconnect2mqtt: + # build: + # context: ./homeconnect2mqtt/docker + # dockerfile: Dockerfile + # restart: always + # container_name: homeconnect2mqtt + # ports: + # - "5001:5000" + # env_file: ./homeconnect2mqtt/settings/homeconnect2mqtt.env + # volumes: + # - ./homeconnect2mqtt/settings/config.json:/app/config.json:ro + # logging: + # driver: json-file + # options: + # max-size: "10m" + # max-file: "5" matter-bridge: image: ghcr.io/t0bst4r/home-assistant-matter-hub:latest diff --git a/hass/settings/.HA_VERSION b/hass/settings/.HA_VERSION index 381e50a..2398eb2 100644 --- a/hass/settings/.HA_VERSION +++ b/hass/settings/.HA_VERSION @@ -1 +1 @@ -2026.4.2 \ No newline at end of file +2026.7.2 \ No newline at end of file diff --git a/hass/settings/.cache/brands/integrations/ai_task/dark_icon.png b/hass/settings/.cache/brands/integrations/ai_task/dark_icon.png new file mode 100644 index 0000000..5461512 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/ai_task/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/aurora/dark_icon.png b/hass/settings/.cache/brands/integrations/aurora/dark_icon.png new file mode 100644 index 0000000..d657ee1 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/aurora/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/beewi_smartclim/dark_icon.png b/hass/settings/.cache/brands/integrations/beewi_smartclim/dark_icon.png new file mode 100644 index 0000000..a21da44 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/beewi_smartclim/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/ble_monitor/dark_icon.png b/hass/settings/.cache/brands/integrations/ble_monitor/dark_icon.png new file mode 100644 index 0000000..f6e2ea8 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/ble_monitor/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/camera/dark_icon.png b/hass/settings/.cache/brands/integrations/camera/dark_icon.png new file mode 100644 index 0000000..69a2a57 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/camera/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/clicksend/dark_icon.png b/hass/settings/.cache/brands/integrations/clicksend/dark_icon.png new file mode 100644 index 0000000..5c57552 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/clicksend/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/derivative/dark_icon.png b/hass/settings/.cache/brands/integrations/derivative/dark_icon.png new file mode 100644 index 0000000..a75e302 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/derivative/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/esera_onewire/dark_icon.png b/hass/settings/.cache/brands/integrations/esera_onewire/dark_icon.png new file mode 100644 index 0000000..d57e886 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/esera_onewire/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/essent/dark_icon.png b/hass/settings/.cache/brands/integrations/essent/dark_icon.png new file mode 100644 index 0000000..38faa8b Binary files /dev/null and b/hass/settings/.cache/brands/integrations/essent/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/hisense_aehw4a1/dark_icon.png b/hass/settings/.cache/brands/integrations/hisense_aehw4a1/dark_icon.png new file mode 100644 index 0000000..d41b71d Binary files /dev/null and b/hass/settings/.cache/brands/integrations/hisense_aehw4a1/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/image/dark_icon.png b/hass/settings/.cache/brands/integrations/image/dark_icon.png new file mode 100644 index 0000000..c10f094 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/image/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/image_upload/dark_icon.png b/hass/settings/.cache/brands/integrations/image_upload/dark_icon.png new file mode 100644 index 0000000..c10f094 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/image_upload/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/integration/dark_icon.png b/hass/settings/.cache/brands/integrations/integration/dark_icon.png new file mode 100644 index 0000000..8b36986 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/integration/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/luftdaten/dark_icon.png b/hass/settings/.cache/brands/integrations/luftdaten/dark_icon.png new file mode 100644 index 0000000..e590e2c Binary files /dev/null and b/hass/settings/.cache/brands/integrations/luftdaten/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/media_source/dark_icon.png b/hass/settings/.cache/brands/integrations/media_source/dark_icon.png new file mode 100644 index 0000000..a0f3dbe Binary files /dev/null and b/hass/settings/.cache/brands/integrations/media_source/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/mysensors/dark_icon.png b/hass/settings/.cache/brands/integrations/mysensors/dark_icon.png new file mode 100644 index 0000000..f2d928d Binary files /dev/null and b/hass/settings/.cache/brands/integrations/mysensors/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/opensensemap/dark_icon.png b/hass/settings/.cache/brands/integrations/opensensemap/dark_icon.png new file mode 100644 index 0000000..2e600a0 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/opensensemap/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/opnsense/dark_icon.png b/hass/settings/.cache/brands/integrations/opnsense/dark_icon.png new file mode 100644 index 0000000..b3f71a2 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/opnsense/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/overseerr/dark_icon.png b/hass/settings/.cache/brands/integrations/overseerr/dark_icon.png new file mode 100644 index 0000000..9ecc71d Binary files /dev/null and b/hass/settings/.cache/brands/integrations/overseerr/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/poolsense/dark_icon.png b/hass/settings/.cache/brands/integrations/poolsense/dark_icon.png new file mode 100644 index 0000000..6f5bc4b Binary files /dev/null and b/hass/settings/.cache/brands/integrations/poolsense/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/renson/dark_icon.png b/hass/settings/.cache/brands/integrations/renson/dark_icon.png new file mode 100644 index 0000000..86920a4 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/renson/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/sabnzbd/dark_icon.png b/hass/settings/.cache/brands/integrations/sabnzbd/dark_icon.png new file mode 100644 index 0000000..730b34c Binary files /dev/null and b/hass/settings/.cache/brands/integrations/sabnzbd/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/samsam/dark_icon.png b/hass/settings/.cache/brands/integrations/samsam/dark_icon.png new file mode 100644 index 0000000..0f97252 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/samsam/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/samsung/dark_icon.png b/hass/settings/.cache/brands/integrations/samsung/dark_icon.png new file mode 100644 index 0000000..a3bde39 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/samsung/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/sanix/dark_icon.png b/hass/settings/.cache/brands/integrations/sanix/dark_icon.png new file mode 100644 index 0000000..8c64a67 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/sanix/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/screenaway/dark_icon.png b/hass/settings/.cache/brands/integrations/screenaway/dark_icon.png new file mode 100644 index 0000000..76de014 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/screenaway/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/season/dark_icon.png b/hass/settings/.cache/brands/integrations/season/dark_icon.png new file mode 100644 index 0000000..f9c8a7f Binary files /dev/null and b/hass/settings/.cache/brands/integrations/season/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/sense/dark_icon.png b/hass/settings/.cache/brands/integrations/sense/dark_icon.png new file mode 100644 index 0000000..236cec6 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/sense/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/sensibo/dark_icon.png b/hass/settings/.cache/brands/integrations/sensibo/dark_icon.png new file mode 100644 index 0000000..80ca61a Binary files /dev/null and b/hass/settings/.cache/brands/integrations/sensibo/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/sensirion_ble/dark_icon.png b/hass/settings/.cache/brands/integrations/sensirion_ble/dark_icon.png new file mode 100644 index 0000000..3b53357 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/sensirion_ble/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/sensorblue/dark_icon.png b/hass/settings/.cache/brands/integrations/sensorblue/dark_icon.png new file mode 100644 index 0000000..c055391 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/sensorblue/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/sensorpro/dark_icon.png b/hass/settings/.cache/brands/integrations/sensorpro/dark_icon.png new file mode 100644 index 0000000..dd46271 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/sensorpro/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/sensorpush/dark_icon.png b/hass/settings/.cache/brands/integrations/sensorpush/dark_icon.png new file mode 100644 index 0000000..700892e Binary files /dev/null and b/hass/settings/.cache/brands/integrations/sensorpush/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/sensoterra/dark_icon.png b/hass/settings/.cache/brands/integrations/sensoterra/dark_icon.png new file mode 100644 index 0000000..2332dc9 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/sensoterra/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/sentry/dark_icon.png b/hass/settings/.cache/brands/integrations/sentry/dark_icon.png new file mode 100644 index 0000000..b89e708 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/sentry/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/senz/dark_icon.png b/hass/settings/.cache/brands/integrations/senz/dark_icon.png new file mode 100644 index 0000000..71fb94a Binary files /dev/null and b/hass/settings/.cache/brands/integrations/senz/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/shelly/dark_icon.png b/hass/settings/.cache/brands/integrations/shelly/dark_icon.png new file mode 100644 index 0000000..348b9f4 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/shelly/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/sky/dark_icon.png b/hass/settings/.cache/brands/integrations/sky/dark_icon.png new file mode 100644 index 0000000..05c3962 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/sky/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/slide/dark_icon.png b/hass/settings/.cache/brands/integrations/slide/dark_icon.png new file mode 100644 index 0000000..aae4857 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/slide/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/smart_blinds/dark_icon.png b/hass/settings/.cache/brands/integrations/smart_blinds/dark_icon.png new file mode 100644 index 0000000..15c99bf Binary files /dev/null and b/hass/settings/.cache/brands/integrations/smart_blinds/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/solaredge/dark_icon.png b/hass/settings/.cache/brands/integrations/solaredge/dark_icon.png new file mode 100644 index 0000000..8a902cd Binary files /dev/null and b/hass/settings/.cache/brands/integrations/solaredge/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/sony/dark_icon.png b/hass/settings/.cache/brands/integrations/sony/dark_icon.png new file mode 100644 index 0000000..29644f0 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/sony/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/switchbot/dark_icon.png b/hass/settings/.cache/brands/integrations/switchbot/dark_icon.png new file mode 100644 index 0000000..deb24e3 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/switchbot/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/synology/dark_icon.png b/hass/settings/.cache/brands/integrations/synology/dark_icon.png new file mode 100644 index 0000000..f5867d9 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/synology/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/telegram/dark_icon@2x.png b/hass/settings/.cache/brands/integrations/telegram/dark_icon@2x.png new file mode 100644 index 0000000..2e8457d Binary files /dev/null and b/hass/settings/.cache/brands/integrations/telegram/dark_icon@2x.png differ diff --git a/hass/settings/.cache/brands/integrations/threshold/dark_icon.png b/hass/settings/.cache/brands/integrations/threshold/dark_icon.png new file mode 100644 index 0000000..c5fc3e8 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/threshold/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/tod/dark_icon.png b/hass/settings/.cache/brands/integrations/tod/dark_icon.png new file mode 100644 index 0000000..20a509b Binary files /dev/null and b/hass/settings/.cache/brands/integrations/tod/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/tts/dark_icon.png b/hass/settings/.cache/brands/integrations/tts/dark_icon.png new file mode 100644 index 0000000..93b5aa4 Binary files /dev/null and b/hass/settings/.cache/brands/integrations/tts/dark_icon.png differ diff --git a/hass/settings/.cache/brands/integrations/wirelesstag/dark_icon.png b/hass/settings/.cache/brands/integrations/wirelesstag/dark_icon.png new file mode 100644 index 0000000..a3192ec Binary files /dev/null and b/hass/settings/.cache/brands/integrations/wirelesstag/dark_icon.png differ diff --git a/hass/settings/.ha_run.lock b/hass/settings/.ha_run.lock index bee06f6..d59a93a 100644 --- a/hass/settings/.ha_run.lock +++ b/hass/settings/.ha_run.lock @@ -1 +1 @@ -{"pid": 238780, "version": 1, "ha_version": "2026.4.2", "start_ts": 1781684834.86627} \ No newline at end of file +{"pid": 71, "version": 1, "ha_version": "2026.7.2", "start_ts": 1784034083.5601983} \ No newline at end of file diff --git a/hass/settings/packages/dishwasher.yaml b/hass/settings/packages/dishwasher.yaml index c02fd64..332a7c9 100644 --- a/hass/settings/packages/dishwasher.yaml +++ b/hass/settings/packages/dishwasher.yaml @@ -21,55 +21,65 @@ # {{ states('sensor.dishwasher_program_progress') + "%" }} # {% endif %} -mqtt: - sensor: - - name: hc_dishwasher_state - unique_id: hc_dishwasher_state - state_topic: "homeconnect/dishwasher/state" - value_template: "{{ value_json.state }}" - json_attributes_topic: "homeconnect/dishwasher/state" - - name: hc_dishwasher_remaining - unique_id: hc_dishwasher_remaining - state_topic: "homeconnect/dishwasher/state" - value_template: "{{ value_json.remaining }}" - json_attributes_topic: "homeconnect/dishwasher/state" - binary_sensor: - - state_topic: "homeconnect/dishwasher/state" - name: hc_dishwasher_door - unique_id: hc_dishwasher_door - device_class: opening - payload_on: "Open" - payload_off: "Closed" - value_template: "{{ value_json.door }}" - json_attributes_topic: "homeconnect/dishwasher/state" - - state_topic: "homeconnect/dishwasher/state" - name: hc_dishwasher_power - unique_id: hc_dishwasher_power - payload_on: true - payload_off: false - value_template: "{{ value_json.power }}" - json_attributes_topic: "homeconnect/dishwasher/state" +# mqtt: +# sensor: +# - name: hc_dishwasher_state +# unique_id: hc_dishwasher_state +# state_topic: "homeconnect/dishwasher/state" +# value_template: "{{ value_json.state }}" +# json_attributes_topic: "homeconnect/dishwasher/state" +# - name: hc_dishwasher_remaining +# unique_id: hc_dishwasher_remaining +# state_topic: "homeconnect/dishwasher/state" +# value_template: "{{ value_json.remaining }}" +# json_attributes_topic: "homeconnect/dishwasher/state" +# binary_sensor: +# - state_topic: "homeconnect/dishwasher/state" +# name: hc_dishwasher_door +# unique_id: hc_dishwasher_door +# device_class: opening +# payload_on: "Open" +# payload_off: "Closed" +# value_template: "{{ value_json.door }}" +# json_attributes_topic: "homeconnect/dishwasher/state" +# - state_topic: "homeconnect/dishwasher/state" +# name: hc_dishwasher_power +# unique_id: hc_dishwasher_power +# payload_on: true +# payload_off: false +# value_template: "{{ value_json.power }}" +# json_attributes_topic: "homeconnect/dishwasher/state" template: binary_sensor: - - name: hc_dishwasher_running - unique_id: hc_dishwasher_running - state: "{{ is_state('sensor.hc_dishwasher_state', 'Run') }}" + - name: bosch_dishwasher_running + unique_id: bosch_dishwasher_running + state: "{{ is_state('sensor.bosch_dishwasher_operation_state', 'Run') }}" counter: - dishwasher_door_open_count: - name: dishwasher_door_open_count + bosch_dishwasher_door_open_count: + name: bosch_dishwasher_door_open_count + +input_select: + bosch_dishwasher_state_extended: + name: bosch_dishwasher_state_extended + options: + - 'Empty' + - 'Washing' + - 'Washed' + - 'Collecting Dishes' + - 'Ready to wash' homeassistant: customize: - sensor.hc_dishwasher_state: + sensor.bosch_dishwasher_state: friendly_name: Посудомойка Статус - binary_sensor.hc_dishwasher_door: + binary_sensor.bosch_dishwasher_door: friendly_name: Посудомойка Дверца - binary_sensor.hc_dishwasher_remaining: + binary_sensor.bosch_dishwasher_remaining: friendly_name: Посудомойка До конца программы - sensor.hc_dishwasher_running: + sensor.bosch_dishwasher_running: friendly_name: Посудомоечная машина - binary_sensor.hc_dishwasher_power: + binary_sensor.bosch_dishwasher_power: friendly_name: Посудомойка Питание diff --git a/hass/settings/packages/notifications/telegram.yaml b/hass/settings/packages/notifications/telegram.yaml index 132d378..9260a26 100644 --- a/hass/settings/packages/notifications/telegram.yaml +++ b/hass/settings/packages/notifications/telegram.yaml @@ -1,21 +1,14 @@ -telegram_bot: - - platform: polling - api_key: !secret telegram_key - allowed_chat_ids: - - !secret telegram_group_chat - - !secret telegram_monster_chat - - !secret telegram_sveta_chat - -notify: - - platform: telegram - name: telegram - chat_id: !secret telegram_group_chat - parse_mode: html - - platform: telegram - name: telegram_monster - chat_id: !secret telegram_monster_chat - parse_mode: html - - platform: telegram - name: telegram_sveta - chat_id: !secret telegram_sveta_chat - parse_mode: html +# telegram_bot: секция удалена — интеграция уже настроена через config entry +# (UI, импортирован 2025-12-28), YAML-платформа с ней конфликтовала: +# ERROR integration telegram_bot cannot be merged, expected a dict +# +# notify: платформы (legacy, deprecated) тоже убраны — все appdaemon-скрипты +# мигрированы на entity-based telegram_bot.send_message/send_photo (см. +# appdaemon/settings/apps/globals.py: TELEGRAM_TARGETS, send_telegram(), +# send_telegram_photo()). Проверено: тестовые сообщения через новый механизм +# успешно доставлены во все 3 чата (группа, Monster, Svetlana) 2026-07-14. +# +# Telegram bot notify-сущности теперь берутся из config entry: +# notify.home_assistant_fonvizina_fonvizina_18_1001567589226 +# notify.home_assistant_fonvizina_monster_123622180 +# notify.home_assistant_fonvizina_svetlana_205225134 diff --git a/hass/settings/packages/notifications/telegram.yaml.bak-pre-migration b/hass/settings/packages/notifications/telegram.yaml.bak-pre-migration new file mode 100644 index 0000000..132d378 --- /dev/null +++ b/hass/settings/packages/notifications/telegram.yaml.bak-pre-migration @@ -0,0 +1,21 @@ +telegram_bot: + - platform: polling + api_key: !secret telegram_key + allowed_chat_ids: + - !secret telegram_group_chat + - !secret telegram_monster_chat + - !secret telegram_sveta_chat + +notify: + - platform: telegram + name: telegram + chat_id: !secret telegram_group_chat + parse_mode: html + - platform: telegram + name: telegram_monster + chat_id: !secret telegram_monster_chat + parse_mode: html + - platform: telegram + name: telegram_sveta + chat_id: !secret telegram_sveta_chat + parse_mode: html diff --git a/hass/settings/www/community/jk-bms-card/jk-bms-card.js b/hass/settings/www/community/jk-bms-card/jk-bms-card.js index 9bbcd88..2303285 100644 --- a/hass/settings/www/community/jk-bms-card/jk-bms-card.js +++ b/hass/settings/www/community/jk-bms-card/jk-bms-card.js @@ -9,13 +9,13 @@ const n=globalThis,a=n.ShadowRoot&&(void 0===n.ShadyCSS||n.ShadyCSS.nativeShadow * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */,{is:c,defineProperty:_,getOwnPropertyDescriptor:h,getOwnPropertyNames:d,getOwnPropertySymbols:g,getPrototypeOf:p}=Object,m=globalThis,u=m.trustedTypes,v=u?u.emptyScript:"",f=m.reactiveElementPolyfillSupport,b=(e,t)=>e,y={toAttribute(e,t){switch(t){case Boolean:e=e?v:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let n=e;switch(t){case Boolean:n=null!==e;break;case Number:n=null===e?null:Number(e);break;case Object:case Array:try{n=JSON.parse(e)}catch(e){n=null}}return n}},w=(e,t)=>!c(e,t),C={attribute:!0,type:String,converter:y,reflect:!1,useDefault:!1,hasChanged:w};Symbol.metadata??=Symbol("metadata"),m.litPropertyMetadata??=new WeakMap;let x=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=C){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){const n=Symbol(),a=this.getPropertyDescriptor(e,n,t);void 0!==a&&_(this.prototype,e,a)}}static getPropertyDescriptor(e,t,n){const{get:a,set:l}=h(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:a,set(t){const s=a?.call(this);l?.call(this,t),this.requestUpdate(e,s,n)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??C}static _$Ei(){if(this.hasOwnProperty(b("elementProperties")))return;const e=p(this);e.finalize(),void 0!==e.l&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(b("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(b("properties"))){const e=this.properties,t=[...d(e),...g(e)];for(const n of t)this.createProperty(n,e[n])}const e=this[Symbol.metadata];if(null!==e){const t=litPropertyMetadata.get(e);if(void 0!==t)for(const[e,n]of t)this.elementProperties.set(e,n)}this._$Eh=new Map;for(const[e,t]of this.elementProperties){const n=this._$Eu(e,t);void 0!==n&&this._$Eh.set(n,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const n=new Set(e.flat(1/0).reverse());for(const e of n)t.unshift(r(e))}else void 0!==e&&t.push(r(e));return t}static _$Eu(e,t){const n=t.attribute;return!1===n?void 0:"string"==typeof n?n:"string"==typeof e?e.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise((e=>this.enableUpdating=e)),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach((e=>e(this)))}addController(e){(this._$EO??=new Set).add(e),void 0!==this.renderRoot&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const n of t.keys())this.hasOwnProperty(n)&&(e.set(n,this[n]),delete this[n]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const e=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((e,t)=>{if(a)e.adoptedStyleSheets=t.map((e=>e instanceof CSSStyleSheet?e:e.styleSheet));else for(const a of t){const t=document.createElement("style"),l=n.litNonce;void 0!==l&&t.setAttribute("nonce",l),t.textContent=a.cssText,e.appendChild(t)}})(e,this.constructor.elementStyles),e}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach((e=>e.hostConnected?.()))}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach((e=>e.hostDisconnected?.()))}attributeChangedCallback(e,t,n){this._$AK(e,n)}_$ET(e,t){const n=this.constructor.elementProperties.get(e),a=this.constructor._$Eu(e,n);if(void 0!==a&&!0===n.reflect){const l=(void 0!==n.converter?.toAttribute?n.converter:y).toAttribute(t,n.type);this._$Em=e,null==l?this.removeAttribute(a):this.setAttribute(a,l),this._$Em=null}}_$AK(e,t){const n=this.constructor,a=n._$Eh.get(e);if(void 0!==a&&this._$Em!==a){const e=n.getPropertyOptions(a),l="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:y;this._$Em=a,this[a]=l.fromAttribute(t,e.type)??this._$Ej?.get(a)??null,this._$Em=null}}requestUpdate(e,t,n){if(void 0!==e){const a=this.constructor,l=this[e];if(n??=a.getPropertyOptions(e),!((n.hasChanged??w)(l,t)||n.useDefault&&n.reflect&&l===this._$Ej?.get(e)&&!this.hasAttribute(a._$Eu(e,n))))return;this.C(e,t,n)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(e,t,{useDefault:n,reflect:a,wrapped:l},s){n&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,s??t??this[e]),!0!==l||void 0!==s)||(this._$AL.has(e)||(this.hasUpdated||n||(t=void 0),this._$AL.set(e,t)),!0===a&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[e,t]of this._$Ep)this[e]=t;this._$Ep=void 0}const e=this.constructor.elementProperties;if(e.size>0)for(const[t,n]of e){const{wrapped:e}=n,a=this[t];!0!==e||this._$AL.has(t)||void 0===a||this.C(t,void 0,n,a)}}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach((e=>e.hostUpdate?.())),this.update(t)):this._$EM()}catch(t){throw e=!1,this._$EM(),t}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach((e=>e.hostUpdated?.())),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach((e=>this._$ET(e,this[e]))),this._$EM()}updated(e){}firstUpdated(e){}};x.elementStyles=[],x.shadowRootOptions={mode:"open"},x[b("elementProperties")]=new Map,x[b("finalized")]=new Map,f?.({ReactiveElement:x}),(m.reactiveElementVersions??=[]).push("2.1.0"); + */,{is:c,defineProperty:h,getOwnPropertyDescriptor:_,getOwnPropertyNames:d,getOwnPropertySymbols:g,getPrototypeOf:p}=Object,m=globalThis,u=m.trustedTypes,v=u?u.emptyScript:"",f=m.reactiveElementPolyfillSupport,b=(e,t)=>e,y={toAttribute(e,t){switch(t){case Boolean:e=e?v:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let n=e;switch(t){case Boolean:n=null!==e;break;case Number:n=null===e?null:Number(e);break;case Object:case Array:try{n=JSON.parse(e)}catch(e){n=null}}return n}},w=(e,t)=>!c(e,t),C={attribute:!0,type:String,converter:y,reflect:!1,useDefault:!1,hasChanged:w};Symbol.metadata??=Symbol("metadata"),m.litPropertyMetadata??=new WeakMap;let x=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=C){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){const n=Symbol(),a=this.getPropertyDescriptor(e,n,t);void 0!==a&&h(this.prototype,e,a)}}static getPropertyDescriptor(e,t,n){const{get:a,set:l}=_(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:a,set(t){const s=a?.call(this);l?.call(this,t),this.requestUpdate(e,s,n)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??C}static _$Ei(){if(this.hasOwnProperty(b("elementProperties")))return;const e=p(this);e.finalize(),void 0!==e.l&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(b("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(b("properties"))){const e=this.properties,t=[...d(e),...g(e)];for(const n of t)this.createProperty(n,e[n])}const e=this[Symbol.metadata];if(null!==e){const t=litPropertyMetadata.get(e);if(void 0!==t)for(const[e,n]of t)this.elementProperties.set(e,n)}this._$Eh=new Map;for(const[e,t]of this.elementProperties){const n=this._$Eu(e,t);void 0!==n&&this._$Eh.set(n,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const n=new Set(e.flat(1/0).reverse());for(const e of n)t.unshift(r(e))}else void 0!==e&&t.push(r(e));return t}static _$Eu(e,t){const n=t.attribute;return!1===n?void 0:"string"==typeof n?n:"string"==typeof e?e.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise((e=>this.enableUpdating=e)),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach((e=>e(this)))}addController(e){(this._$EO??=new Set).add(e),void 0!==this.renderRoot&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const n of t.keys())this.hasOwnProperty(n)&&(e.set(n,this[n]),delete this[n]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const e=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((e,t)=>{if(a)e.adoptedStyleSheets=t.map((e=>e instanceof CSSStyleSheet?e:e.styleSheet));else for(const a of t){const t=document.createElement("style"),l=n.litNonce;void 0!==l&&t.setAttribute("nonce",l),t.textContent=a.cssText,e.appendChild(t)}})(e,this.constructor.elementStyles),e}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach((e=>e.hostConnected?.()))}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach((e=>e.hostDisconnected?.()))}attributeChangedCallback(e,t,n){this._$AK(e,n)}_$ET(e,t){const n=this.constructor.elementProperties.get(e),a=this.constructor._$Eu(e,n);if(void 0!==a&&!0===n.reflect){const l=(void 0!==n.converter?.toAttribute?n.converter:y).toAttribute(t,n.type);this._$Em=e,null==l?this.removeAttribute(a):this.setAttribute(a,l),this._$Em=null}}_$AK(e,t){const n=this.constructor,a=n._$Eh.get(e);if(void 0!==a&&this._$Em!==a){const e=n.getPropertyOptions(a),l="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:y;this._$Em=a,this[a]=l.fromAttribute(t,e.type)??this._$Ej?.get(a)??null,this._$Em=null}}requestUpdate(e,t,n){if(void 0!==e){const a=this.constructor,l=this[e];if(n??=a.getPropertyOptions(e),!((n.hasChanged??w)(l,t)||n.useDefault&&n.reflect&&l===this._$Ej?.get(e)&&!this.hasAttribute(a._$Eu(e,n))))return;this.C(e,t,n)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(e,t,{useDefault:n,reflect:a,wrapped:l},s){n&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,s??t??this[e]),!0!==l||void 0!==s)||(this._$AL.has(e)||(this.hasUpdated||n||(t=void 0),this._$AL.set(e,t)),!0===a&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[e,t]of this._$Ep)this[e]=t;this._$Ep=void 0}const e=this.constructor.elementProperties;if(e.size>0)for(const[t,n]of e){const{wrapped:e}=n,a=this[t];!0!==e||this._$AL.has(t)||void 0===a||this.C(t,void 0,n,a)}}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach((e=>e.hostUpdate?.())),this.update(t)):this._$EM()}catch(t){throw e=!1,this._$EM(),t}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach((e=>e.hostUpdated?.())),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach((e=>this._$ET(e,this[e]))),this._$EM()}updated(e){}firstUpdated(e){}};x.elementStyles=[],x.shadowRootOptions={mode:"open"},x[b("elementProperties")]=new Map,x[b("finalized")]=new Map,f?.({ReactiveElement:x}),(m.reactiveElementVersions??=[]).push("2.1.0"); /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ -const S=globalThis,k=S.trustedTypes,A=k?k.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",$=`lit$${Math.random().toFixed(9).slice(2)}$`,V="?"+$,T=`<${V}>`,E=document,O=()=>E.createComment(""),z=e=>null===e||"object"!=typeof e&&"function"!=typeof e,D=Array.isArray,N="[ \t\n\f\r]",U=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,R=/-->/g,B=/>/g,P=RegExp(`>|${N}(?:([^\\s"'>=/]+)(${N}*=${N}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),j=/'/g,L=/"/g,H=/^(?:script|style|textarea|title)$/i,I=(e=>(t,...n)=>({_$litType$:e,strings:t,values:n}))(1),F=Symbol.for("lit-noChange"),K=Symbol.for("lit-nothing"),J=new WeakMap,q=E.createTreeWalker(E,129);function W(e,t){if(!D(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==A?A.createHTML(t):t}const Z=(e,t)=>{const n=e.length-1,a=[];let l,s=2===t?"":3===t?"":"",i=U;for(let t=0;t"===r[0]?(i=l??U,c=-1):void 0===r[1]?c=-2:(c=i.lastIndex-r[2].length,o=r[1],i=void 0===r[3]?P:'"'===r[3]?L:j):i===L||i===j?i=P:i===R||i===B?i=U:(i=P,l=void 0);const h=i===P&&e[t+1].startsWith("/>")?" ":"";s+=i===U?n+T:c>=0?(a.push(o),n.slice(0,c)+M+n.slice(c)+$+h):n+$+(-2===c?t:h)}return[W(e,s+(e[n]||"")+(2===t?"":3===t?"":"")),a]};class G{constructor({strings:e,_$litType$:t},n){let a;this.parts=[];let l=0,s=0;const i=e.length-1,o=this.parts,[r,c]=Z(e,t);if(this.el=G.createElement(r,n),q.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(a=q.nextNode())&&o.length0){a.textContent=k?k.emptyScript:"";for(let n=0;nD(e)||"function"==typeof e?.[Symbol.iterator])(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==K&&z(this._$AH)?this._$AA.nextSibling.data=e:this.T(E.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:n}=e,a="number"==typeof n?this._$AC(e):(void 0===n.el&&(n.el=G.createElement(W(n.h,n.h[0]),this.options)),n);if(this._$AH?._$AD===a)this._$AH.p(t);else{const e=new Q(a,this),n=e.u(this.options);e.p(t),this.T(n),this._$AH=e}}_$AC(e){let t=J.get(e.strings);return void 0===t&&J.set(e.strings,t=new G(e)),t}k(e){D(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let n,a=0;for(const l of e)a===t.length?t.push(n=new X(this.O(O()),this.O(O()),this,this.options)):n=t[a],n._$AI(l),a++;a2||""!==n[0]||""!==n[1]?(this._$AH=Array(n.length-1).fill(new String),this.strings=n):this._$AH=K}_$AI(e,t=this,n,a){const l=this.strings;let s=!1;if(void 0===l)e=Y(this,e,t,0),s=!z(e)||e!==this._$AH&&e!==F,s&&(this._$AH=e);else{const a=e;let i,o;for(e=l[0],i=0;ie}):void 0,$="$lit$",M=`lit$${Math.random().toFixed(9).slice(2)}$`,V="?"+M,T=`<${V}>`,E=document,O=()=>E.createComment(""),z=e=>null===e||"object"!=typeof e&&"function"!=typeof e,B=Array.isArray,R="[ \t\n\f\r]",D=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,N=/-->/g,U=/>/g,L=RegExp(`>|${R}(?:([^\\s"'>=/]+)(${R}*=${R}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),P=/'/g,j=/"/g,H=/^(?:script|style|textarea|title)$/i,I=(e=>(t,...n)=>({_$litType$:e,strings:t,values:n}))(1),F=Symbol.for("lit-noChange"),K=Symbol.for("lit-nothing"),q=new WeakMap,J=E.createTreeWalker(E,129);function W(e,t){if(!B(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==A?A.createHTML(t):t}const Z=(e,t)=>{const n=e.length-1,a=[];let l,s=2===t?"":3===t?"":"",i=D;for(let t=0;t"===r[0]?(i=l??D,c=-1):void 0===r[1]?c=-2:(c=i.lastIndex-r[2].length,o=r[1],i=void 0===r[3]?L:'"'===r[3]?j:P):i===j||i===P?i=L:i===N||i===U?i=D:(i=L,l=void 0);const _=i===L&&e[t+1].startsWith("/>")?" ":"";s+=i===D?n+T:c>=0?(a.push(o),n.slice(0,c)+$+n.slice(c)+M+_):n+M+(-2===c?t:_)}return[W(e,s+(e[n]||"")+(2===t?"":3===t?"":"")),a]};class G{constructor({strings:e,_$litType$:t},n){let a;this.parts=[];let l=0,s=0;const i=e.length-1,o=this.parts,[r,c]=Z(e,t);if(this.el=G.createElement(r,n),J.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(a=J.nextNode())&&o.length0){a.textContent=k?k.emptyScript:"";for(let n=0;nB(e)||"function"==typeof e?.[Symbol.iterator])(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==K&&z(this._$AH)?this._$AA.nextSibling.data=e:this.T(E.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:n}=e,a="number"==typeof n?this._$AC(e):(void 0===n.el&&(n.el=G.createElement(W(n.h,n.h[0]),this.options)),n);if(this._$AH?._$AD===a)this._$AH.p(t);else{const e=new Q(a,this),n=e.u(this.options);e.p(t),this.T(n),this._$AH=e}}_$AC(e){let t=q.get(e.strings);return void 0===t&&q.set(e.strings,t=new G(e)),t}k(e){B(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let n,a=0;for(const l of e)a===t.length?t.push(n=new X(this.O(O()),this.O(O()),this,this.options)):n=t[a],n._$AI(l),a++;a2||""!==n[0]||""!==n[1]?(this._$AH=Array(n.length-1).fill(new String),this.strings=n):this._$AH=K}_$AI(e,t=this,n,a){const l=this.strings;let s=!1;if(void 0===l)e=Y(this,e,t,0),s=!z(e)||e!==this._$AH&&e!==F,s&&(this._$AH=e);else{const a=e;let i,o;for(e=l[0],i=0;i(t,n)=>{void 0!==n?n.addInitializer((()=>{customElements.define(e,t) * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */,_e={attribute:!0,type:String,converter:y,reflect:!1,hasChanged:w},he=(e=_e,t,n)=>{const{kind:a,metadata:l}=n;let s=globalThis.litPropertyMetadata.get(l);if(void 0===s&&globalThis.litPropertyMetadata.set(l,s=new Map),"setter"===a&&((e=Object.create(e)).wrapped=!0),s.set(n.name,e),"accessor"===a){const{name:a}=n;return{set(n){const l=t.get.call(this);t.set.call(this,n),this.requestUpdate(a,l,e)},init(t){return void 0!==t&&this.C(a,void 0,e,t),t}}}if("setter"===a){const{name:a}=n;return function(n){const l=this[a];t.call(this,n),this.requestUpdate(a,l,e)}}throw Error("Unsupported decorator location: "+a)};function de(e){return(t,n)=>"object"==typeof n?he(e,t,n):((e,t,n)=>{const a=t.hasOwnProperty(n);return t.constructor.createProperty(n,e),a?Object.getOwnPropertyDescriptor(t,n):void 0})(e,t,n) + */,he={attribute:!0,type:String,converter:y,reflect:!1,hasChanged:w},_e=(e=he,t,n)=>{const{kind:a,metadata:l}=n;let s=globalThis.litPropertyMetadata.get(l);if(void 0===s&&globalThis.litPropertyMetadata.set(l,s=new Map),"setter"===a&&((e=Object.create(e)).wrapped=!0),s.set(n.name,e),"accessor"===a){const{name:a}=n;return{set(n){const l=t.get.call(this);t.set.call(this,n),this.requestUpdate(a,l,e)},init(t){return void 0!==t&&this.C(a,void 0,e,t),t}}}if("setter"===a){const{name:a}=n;return function(n){const l=this[a];t.call(this,n),this.requestUpdate(a,l,e)}}throw Error("Unsupported decorator location: "+a)};function de(e){return(t,n)=>"object"==typeof n?_e(e,t,n):((e,t,n)=>{const a=t.hasOwnProperty(n);return t.constructor.createProperty(n,e),a?Object.getOwnPropertyDescriptor(t,n):void 0})(e,t,n) /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */}const ge="jk-bms-content-card-editor",pe="jk-bms-card";var me;!function(e){e.delta_cell_voltage="delta_cell_voltage",e.balancing="balancing",e.balancing_current="balancing_current",e.power="power",e.balance_trigger_voltage="balance_trigger_voltage",e.balance_starting_voltage="balance_starting_voltage",e.total_runtime_formatted="total_runtime_formatted",e.charging="charging",e.charging_power="charging_power",e.discharging="discharging",e.discharging_power="discharging_power",e.balancer="balancer",e.heater="heater",e.total_voltage="total_voltage",e.total_battery_capacity_setting="total_battery_capacity_setting",e.total_charging_cycle_capacity="total_charging_cycle_capacity",e.average_cell_voltage="average_cell_voltage",e.current="current",e.state_of_charge="state_of_charge",e.capacity_remaining="capacity_remaining",e.charging_cycles="charging_cycles",e.power_tube_temperature="power_tube_temperature",e.min_voltage_cell="min_voltage_cell",e.max_voltage_cell="max_voltage_cell",e.min_cell_voltage="min_cell_voltage",e.max_cell_voltage="max_cell_voltage",e.errors="errors",e.software_version="software_version",e.hardware_version="hardware_version",e.cell_voltage_1="cell_voltage_1",e.cell_voltage_2="cell_voltage_2",e.cell_voltage_3="cell_voltage_3",e.cell_voltage_4="cell_voltage_4",e.cell_voltage_5="cell_voltage_5",e.cell_voltage_6="cell_voltage_6",e.cell_voltage_7="cell_voltage_7",e.cell_voltage_8="cell_voltage_8",e.cell_voltage_9="cell_voltage_9",e.cell_voltage_10="cell_voltage_10",e.cell_voltage_11="cell_voltage_11",e.cell_voltage_12="cell_voltage_12",e.cell_voltage_13="cell_voltage_13",e.cell_voltage_14="cell_voltage_14",e.cell_voltage_15="cell_voltage_15",e.cell_voltage_16="cell_voltage_16",e.cell_voltage_17="cell_voltage_17",e.cell_voltage_18="cell_voltage_18",e.cell_voltage_19="cell_voltage_19",e.cell_voltage_20="cell_voltage_20",e.cell_voltage_21="cell_voltage_21",e.cell_voltage_22="cell_voltage_22",e.cell_voltage_23="cell_voltage_23",e.cell_voltage_24="cell_voltage_24",e.cell_voltage_25="cell_voltage_25",e.cell_voltage_26="cell_voltage_26",e.cell_voltage_27="cell_voltage_27",e.cell_voltage_28="cell_voltage_28",e.cell_voltage_29="cell_voltage_29",e.cell_voltage_30="cell_voltage_30",e.cell_voltage_31="cell_voltage_31",e.cell_voltage_32="cell_voltage_32",e.cell_voltage_33="cell_voltage_33",e.cell_voltage_34="cell_voltage_34",e.cell_voltage_35="cell_voltage_35",e.cell_voltage_36="cell_voltage_36",e.cell_voltage_37="cell_voltage_37",e.cell_voltage_38="cell_voltage_38",e.cell_voltage_39="cell_voltage_39",e.cell_voltage_40="cell_voltage_40",e.cell_voltage_41="cell_voltage_41",e.cell_voltage_42="cell_voltage_42",e.cell_voltage_43="cell_voltage_43",e.cell_voltage_44="cell_voltage_44",e.cell_voltage_45="cell_voltage_45",e.cell_voltage_46="cell_voltage_46",e.cell_voltage_47="cell_voltage_47",e.cell_voltage_48="cell_voltage_48",e.cell_voltage_49="cell_voltage_49",e.cell_voltage_50="cell_voltage_50",e.cell_voltage_51="cell_voltage_51",e.cell_voltage_52="cell_voltage_52",e.cell_voltage_53="cell_voltage_53",e.cell_voltage_54="cell_voltage_54",e.cell_voltage_55="cell_voltage_55",e.cell_voltage_56="cell_voltage_56",e.cell_voltage_57="cell_voltage_57",e.cell_voltage_58="cell_voltage_58",e.cell_voltage_59="cell_voltage_59",e.cell_voltage_60="cell_voltage_60",e.cell_voltage_61="cell_voltage_61",e.cell_voltage_62="cell_voltage_62",e.cell_voltage_63="cell_voltage_63",e.cell_voltage_64="cell_voltage_64",e.cell_voltage_65="cell_voltage_65",e.cell_voltage_66="cell_voltage_66",e.cell_voltage_67="cell_voltage_67",e.cell_voltage_68="cell_voltage_68",e.cell_voltage_69="cell_voltage_69",e.cell_voltage_70="cell_voltage_70",e.cell_voltage_71="cell_voltage_71",e.cell_voltage_72="cell_voltage_72",e.cell_voltage_73="cell_voltage_73",e.cell_voltage_74="cell_voltage_74",e.cell_voltage_75="cell_voltage_75",e.cell_voltage_76="cell_voltage_76",e.cell_voltage_77="cell_voltage_77",e.cell_voltage_78="cell_voltage_78",e.cell_voltage_79="cell_voltage_79",e.cell_voltage_80="cell_voltage_80",e.cell_voltage_81="cell_voltage_81",e.cell_voltage_82="cell_voltage_82",e.cell_voltage_83="cell_voltage_83",e.cell_voltage_84="cell_voltage_84",e.cell_voltage_85="cell_voltage_85",e.cell_voltage_86="cell_voltage_86",e.cell_voltage_87="cell_voltage_87",e.cell_voltage_88="cell_voltage_88",e.cell_voltage_89="cell_voltage_89",e.cell_voltage_90="cell_voltage_90",e.cell_voltage_91="cell_voltage_91",e.cell_voltage_92="cell_voltage_92",e.cell_voltage_93="cell_voltage_93",e.cell_voltage_94="cell_voltage_94",e.cell_voltage_95="cell_voltage_95",e.cell_voltage_96="cell_voltage_96",e.cell_resistance_1="cell_resistance_1",e.cell_resistance_2="cell_resistance_2",e.cell_resistance_3="cell_resistance_3",e.cell_resistance_4="cell_resistance_4",e.cell_resistance_5="cell_resistance_5",e.cell_resistance_6="cell_resistance_6",e.cell_resistance_7="cell_resistance_7",e.cell_resistance_8="cell_resistance_8",e.cell_resistance_9="cell_resistance_9",e.cell_resistance_10="cell_resistance_10",e.cell_resistance_11="cell_resistance_11",e.cell_resistance_12="cell_resistance_12",e.cell_resistance_13="cell_resistance_13",e.cell_resistance_14="cell_resistance_14",e.cell_resistance_15="cell_resistance_15",e.cell_resistance_16="cell_resistance_16",e.cell_resistance_17="cell_resistance_17",e.cell_resistance_18="cell_resistance_18",e.cell_resistance_19="cell_resistance_19",e.cell_resistance_20="cell_resistance_20",e.cell_resistance_21="cell_resistance_21",e.cell_resistance_22="cell_resistance_22",e.cell_resistance_23="cell_resistance_23",e.cell_resistance_24="cell_resistance_24",e.cell_resistance_25="cell_resistance_25",e.cell_resistance_26="cell_resistance_26",e.cell_resistance_27="cell_resistance_27",e.cell_resistance_28="cell_resistance_28",e.cell_resistance_29="cell_resistance_29",e.cell_resistance_30="cell_resistance_30",e.cell_resistance_31="cell_resistance_31",e.cell_resistance_32="cell_resistance_32",e.cell_resistance_33="cell_resistance_33",e.cell_resistance_34="cell_resistance_34",e.cell_resistance_35="cell_resistance_35",e.cell_resistance_36="cell_resistance_36",e.cell_resistance_37="cell_resistance_37",e.cell_resistance_38="cell_resistance_38",e.cell_resistance_39="cell_resistance_39",e.cell_resistance_40="cell_resistance_40",e.cell_resistance_41="cell_resistance_41",e.cell_resistance_42="cell_resistance_42",e.cell_resistance_43="cell_resistance_43",e.cell_resistance_44="cell_resistance_44",e.cell_resistance_45="cell_resistance_45",e.cell_resistance_46="cell_resistance_46",e.cell_resistance_47="cell_resistance_47",e.cell_resistance_48="cell_resistance_48",e.cell_resistance_49="cell_resistance_49",e.cell_resistance_50="cell_resistance_50",e.cell_resistance_51="cell_resistance_51",e.cell_resistance_52="cell_resistance_52",e.cell_resistance_53="cell_resistance_53",e.cell_resistance_54="cell_resistance_54",e.cell_resistance_55="cell_resistance_55",e.cell_resistance_56="cell_resistance_56",e.cell_resistance_57="cell_resistance_57",e.cell_resistance_58="cell_resistance_58",e.cell_resistance_59="cell_resistance_59",e.cell_resistance_60="cell_resistance_60",e.cell_resistance_61="cell_resistance_61",e.cell_resistance_62="cell_resistance_62",e.cell_resistance_63="cell_resistance_63",e.cell_resistance_64="cell_resistance_64",e.cell_resistance_65="cell_resistance_65",e.cell_resistance_66="cell_resistance_66",e.cell_resistance_67="cell_resistance_67",e.cell_resistance_68="cell_resistance_68",e.cell_resistance_69="cell_resistance_69",e.cell_resistance_70="cell_resistance_70",e.cell_resistance_71="cell_resistance_71",e.cell_resistance_72="cell_resistance_72",e.cell_resistance_73="cell_resistance_73",e.cell_resistance_74="cell_resistance_74",e.cell_resistance_75="cell_resistance_75",e.cell_resistance_76="cell_resistance_76",e.cell_resistance_77="cell_resistance_77",e.cell_resistance_78="cell_resistance_78",e.cell_resistance_79="cell_resistance_79",e.cell_resistance_80="cell_resistance_80",e.cell_resistance_81="cell_resistance_81",e.cell_resistance_82="cell_resistance_82",e.cell_resistance_83="cell_resistance_83",e.cell_resistance_84="cell_resistance_84",e.cell_resistance_85="cell_resistance_85",e.cell_resistance_86="cell_resistance_86",e.cell_resistance_87="cell_resistance_87",e.cell_resistance_88="cell_resistance_88",e.cell_resistance_89="cell_resistance_89",e.cell_resistance_90="cell_resistance_90",e.cell_resistance_91="cell_resistance_91",e.cell_resistance_92="cell_resistance_92",e.cell_resistance_93="cell_resistance_93",e.cell_resistance_94="cell_resistance_94",e.cell_resistance_95="cell_resistance_95",e.cell_resistance_96="cell_resistance_96",e.temperature_sensor_1="temperature_sensor_1",e.temperature_sensor_2="temperature_sensor_2",e.temperature_sensor_3="temperature_sensor_3",e.temperature_sensor_4="temperature_sensor_4"}(me||(me={}));var ue={title:"JK BMS Card",description:"A customizable Home Assistant card to emulate the JK BMS screen",version:"Version"},ve={language:"Language",title:"Title",prefix:"Prefix of the sensors",batteryName:"Battery name",cellCount:"Number of cells",cellColumns:"Number of columns",cellLayout:"Cell Layout",layout:"Layout",deltaVoltageUnit:"Delta Voltage Unit",resistanceUnit:"Resistance Unit",cellColorMode:"Cell Color Mode",cellOrientation:"Cell Orientation",minCellVoltage:"Min Cell Voltage (V)",maxCellVoltage:"Max Cell Voltage (V)",manualAssignment:"Manual entity assignment",tempSensorsCount:"No. of temp. sensors available",hasHeater:"Heater option is used",socDecimals:"SoC Decimals",customDecimals:"Custom Decimals",titleShowHide:"Show / Hide zones",showTitle:"Title",showButtons:"Buttons",showMain:"Main",showCondensed:"Condensed",showMainStats:"Stats",showCells:"Cells",showResistances:"Cell R.",showCardVersion:"Version"},fe={charge:"Charge",discharge:"Discharge",balance:"Balance",heater:"Heater"},be={power:"Power:",capacity:"Capacity:",cycleCapacity:"Cycle Cap:",averageCellV:"Avg Cell V:",balanceCurrent:"Balance Cur:",stateOfCharge:"SOC:",remainingAmps:"Remaining:",cycles:"Cycles:",delta:"Delta Voltage:",mosfetTemp:"MOS Temp:",minCellV:"Min Cell V:",maxCellV:"Max Cell V:",temperature_sensor_1:"Temp. 1:",temperature_sensor_2:"Temp. 2:",temperature_sensor_3:"Temp. 3:",temperature_sensor_4:"Temp. 4:"},ye={capacity:"Capacity",time:"Time","grid-solar":"Grid/Solar",load:"Load","total-voltage":"Total Voltage",current:"Current",mosfetTemp:"MOS Temp",delta:"Delta",temperature_sensor:"Temp",balancing:"Balancing",volt:"V",charge:"Charge",discharge:"Discharge",remaining:"Remaining"},we={common:ue,config:ve,switches:fe,stats:be,html_texts:ye},Ce={title:"Карта JK BMS",description:"Налаштовувана картка Home Assistant для емуляції екрану JK BMS",version:"Версія"},xe={language:"Мова",title:"Заголовок",prefix:"Префікс сенсорів",batteryName:"Назва батареї",cellCount:"Кількість комірок",cellColumns:"Кількість стовпців",cellLayout:"Розташування комірок",layout:"Макет",deltaVoltageUnit:"Одиниця дельта напруги",resistanceUnit:"Одиниця вимірювання опору",cellColorMode:"Режим кольору комірок",cellOrientation:"Орієнтація комірок",minCellVoltage:"Мін. напруга комірки (В)",maxCellVoltage:"Макс. напруга комірки (В)",manualAssignment:"Ручне призначення сутності",tempSensorsCount:"Кількість доступних датчиків температури",hasHeater:"Використовується опція підігріву",socDecimals:"знаки від коми",customDecimals:"Власні десяткові дроби",titleShowHide:"Показати / Сховати зони",showTitle:"Заголовок",showButtons:"Кнопки",showMain:"Панель",showCondensed:"Компактно",showMainStats:"Стат.",showCells:"Елементи",showResistances:"Опір ел",showCardVersion:"Версія"},Se={charge:"Заряд",discharge:"Розряд",balance:"Баланс",heater:"Підігрів"},ke={power:"Потужн.:",capacity:"Ємн.:",cycleCapacity:"Цикл. ємн.:",averageCellV:"Сер V ком.:",balanceCurrent:"Бал. струм:",stateOfCharge:"SOC:",remainingAmps:"Залишок:",cycles:"Цикли:",delta:"Δ напруга:",mosfetTemp:"Темп MOS:",minCellV:"Мін V ком.:",maxCellV:"Макс V ком.:",temperature_sensor_1:"Темп. 1:",temperature_sensor_2:"Темп. 2:",temperature_sensor_3:"Темп. 3:",temperature_sensor_4:"Темп. 4:"},Ae={capacity:"Ємність",time:"Час","grid-solar":"Мережа/Сонячна",load:"Навантаження","total-voltage":"Загальна напруга",current:"Струм",mosfetTemp:"Темп. MOS",delta:"Дельта",temperature_sensor:"Темп",balancing:"Балансування",volt:"В",charge:"Заряд",discharge:"Розряд",remaining:"Залишок"},Me={common:Ce,config:xe,switches:Se,stats:ke,html_texts:Ae},$e={title:"Card JK BMS",description:"Un card Home Assistant personalizabil care imită ecranul JK BMS",version:"Versiune"},Ve={language:"Limba",title:"Titlu",prefix:"Prefixul senzorilor",batteryName:"Numele bateriei",cellCount:"Număr de celule",cellColumns:"Număr de coloane",cellLayout:"Aranjament celule",layout:"Aranjament general",deltaVoltageUnit:"UM pentru diferență tensiune",resistanceUnit:"UM pentru rezistență",cellColorMode:"Mod colorare celule",cellOrientation:"Orientare celule",minCellVoltage:"Tensiune minimă celulă (V)",maxCellVoltage:"Tensiune maximă celulă (V)",manualAssignment:"Atribuire manuală entități",tempSensorsCount:"Număr senzori temperatură",hasHeater:"Opțiunea încălzitor este utilizată",socDecimals:"Zecimale SoC",customDecimals:"Zecimale alte controale",titleShowHide:"Afișează / Ascunde zone",showTitle:"Titlul",showButtons:"Butoane",showMain:"Principală",showCondensed:"Compact",showMainStats:"Stat.",showCells:"Celule",showResistances:"Rezist.",showCardVersion:"Versiune"},Te={charge:"Încărcare",discharge:"Descărcare",balance:"Echilibrare",heater:"Încălzitor"},Ee={power:"Putere:",capacity:"Capac.:",cycleCapacity:"Cap. Ciclu:",averageCellV:"V Cel. Med:",balanceCurrent:"Cur. Bal:",stateOfCharge:"SOC:",remainingAmps:"Rămas:",cycles:"Cicluri:",delta:"Δ Tensiune:",mosfetTemp:"Temp MOS:",minCellV:"Min V Cel.:",maxCellV:"Max V Cel.:",temperature_sensor_1:"Temp. 1:",temperature_sensor_2:"Temp. 2:",temperature_sensor_3:"Temp. 3:",temperature_sensor_4:"Temp. 4:"},Oe={capacity:"Capacitate",time:"Timp","grid-solar":"Rețea/Solar",load:"Consum","total-voltage":"Tensiune totală",current:"Curent",mosfetTemp:"Temp. MOSFET",delta:"Diferență",temperature_sensor:"Temp",balancing:"Echilibrare",volt:"V",charge:"Încărcare",discharge:"Descărcare",remaining:"Rămas"},ze={common:$e,config:Ve,switches:Te,stats:Ee,html_texts:Oe},De={title:"JK BMS Karte",description:"Eine anpassbare Home Assistant Karte, die den JK BMS Bildschirm nachbildet",version:"Version"},Ne={language:"Sprache",title:"Titel",prefix:"Präfix der Sensoren",batteryName:"Batteriename",cellCount:"Anzahl der Zellen",cellColumns:"Anzahl der Spalten",cellLayout:"Zellen-Layout",layout:"Layout",deltaVoltageUnit:"Einheit der Spannungsdifferenz",resistanceUnit:"Einheit des elektrischen Widerstands",cellColorMode:"Zellen-Farbmodus",cellOrientation:"Zellen-Ausrichtung",minCellVoltage:"Min. Zellspannung (V)",maxCellVoltage:"Max. Zellspannung (V)",manualAssignment:"Manuelle Entitäten-Zuweisung",tempSensorsCount:"Anzahl verfügbarer Temperatursensoren",hasHeater:"Heizungs-Option wird verwendet",socDecimals:"SOC Dezimalstellen",customDecimals:"Benutzerdefinierte Dezimalzahlen",titleShowHide:"Zonen ein-/ausblenden",showTitle:"Titel",showButtons:"Schaltfl.",showMain:"Hauptteil",showCondensed:"Kompakt",showMainStats:"Stats",showCells:"Zellen",showResistances:"Zellen R.",showCardVersion:"Kartenvers."},Ue={charge:"Laden",discharge:"Entladen",balance:"Balancing",heater:"Heizung"},Re={power:"Leistung:",capacity:"Kapaz.:",cycleCapacity:"Zykl. Kap.:",averageCellV:"Ø Zell V:",balanceCurrent:"Bal. Strom:",stateOfCharge:"SOC:",remainingAmps:"Rest:",cycles:"Zyklen:",delta:"Δ Spannung:",mosfetTemp:"MOS Temp:",minCellV:"Min Zell V:",maxCellV:"Max Zell V:",temperature_sensor_1:"Temp. 1:",temperature_sensor_2:"Temp. 2:",temperature_sensor_3:"Temp. 3:",temperature_sensor_4:"Temp. 4:"},Be={capacity:"Kapazität",time:"Zeit","grid-solar":"Netz/Solar",load:"Last","total-voltage":"Gesamtspannung",current:"Stromstärke",mosfetTemp:"MOS Temp",delta:"Differenz",temperature_sensor:"Temp",balancing:"Balancing",volt:"V",charge:"Laden",discharge:"Entladen",remaining:"Restzeit"},Pe={common:De,config:Ne,switches:Ue,stats:Re,html_texts:Be},je={title:"Карта JK BMS",description:"Настраиваемая карточка Home Assistant для эмуляции экрана JK BMS",version:"Версия"},Le={language:"Язык",title:"Заголовок",prefix:"Префикс датчиков",batteryName:"Название батареи",cellCount:"Количество ячеек",cellColumns:"Количество столбцов",cellLayout:"Расположение ячеек",layout:"Макет",deltaVoltageUnit:"Единица дельта-напряжения",resistanceUnit:"Единица измерения сопротивления",cellColorMode:"Режим цвета ячеек",cellOrientation:"Ориентация ячеек",minCellVoltage:"Мин. напряжение ячейки (В)",maxCellVoltage:"Макс. напряжение ячейки (В)",manualAssignment:"Ручное назначение сущностей",tempSensorsCount:"Количество доступных датчиков температуры",hasHeater:"Используется подогрев",socDecimals:"Знаков после запятой",customDecimals:"Пользовательские десятичные",titleShowHide:"Показать / Скрыть зоны",showTitle:"Заголовок",showButtons:"Кнопки",showMain:"Панель",showCondensed:"Компактно",showMainStats:"Стат.",showCells:"Ячейки",showResistances:"Сопр. яч.",showCardVersion:"Версия"},He={charge:"Заряд",discharge:"Разряд",balance:"Балансировка",heater:"Подогрев"},Ie={power:"Мощн.:",capacity:"Ёмк.:",cycleCapacity:"Цикл. ёмк.:",averageCellV:"Ср V яч.:",balanceCurrent:"Бал. ток:",stateOfCharge:"SOC:",remainingAmps:"Остаток:",cycles:"Циклы:",delta:"Δ напр.:",mosfetTemp:"Темп MOS:",minCellV:"Мин V яч.:",maxCellV:"Макс V яч.:",temperature_sensor_1:"Темп. 1:",temperature_sensor_2:"Темп. 2:",temperature_sensor_3:"Темп. 3:",temperature_sensor_4:"Темп. 4:"},Fe={capacity:"Ёмкость",time:"Время","grid-solar":"Сеть/Солнце",load:"Нагрузка","total-voltage":"Общее напряжение",current:"Ток",mosfetTemp:"Темп. MOS",delta:"Дельта",temperature_sensor:"Темп",balancing:"Балансировка",volt:"В",charge:"Заряд",discharge:"Разряд",remaining:"Остаток"},Ke={common:je,config:Le,switches:He,stats:Ie,html_texts:Fe},Je={title:"JK 电池管理系统",description:"用于显示 JK-BMS 实时状态 de 自定义卡片",version:"版本"},qe={language:"语言",title:"标题",prefix:"实体前缀",batteryName:"电池名称",cellCount:"电芯数量",cellColumns:"每行电芯数",cellLayout:"电芯布局方式",layout:"布局",deltaVoltageUnit:"电压差单位",resistanceUnit:"电阻单位",cellColorMode:"电池颜色模式",cellOrientation:"电池方向",minCellVoltage:"最小电池电压 (V)",maxCellVoltage:"最大电池电压 (V)",manualAssignment:"手动分配实体",tempSensorsCount:"温度传感器数量",hasHeater:"是否有加热器",socDecimals:"SOC 小数位数",customDecimals:"自定义小数位",titleShowHide:"显示 / 隐藏区域",showTitle:"标题",showButtons:"按钮",showMain:"主面板",showCondensed:"紧凑",showMainStats:"统计",showCells:"电池",showResistances:"电池 R.",showCardVersion:"版本"},We={charge:"充电",discharge:"放电",balance:"均衡",heater:"加热"},Ze={power:"功率:",capacity:"容量:",cycleCapacity:"循环:",averageCellV:"平均V:",balanceCurrent:"均衡:",stateOfCharge:"SOC:",remainingAmps:"剩余:",cycles:"循环数:",delta:"ΔV:",mosfetTemp:"MOS温:",minCellV:"最低V:",maxCellV:"最高V:",temperature_sensor_1:"温度1:",temperature_sensor_2:"温度2:",temperature_sensor_3:"温度3:",temperature_sensor_4:"温度4:"},Ge={capacity:"总容量设定",time:"运行时长","grid-solar":"电网/太阳能",load:"负载","total-voltage":"总电压",current:"实时电流",mosfetTemp:"功率管温度",delta:"单体电池压差",temperature_sensor:"温度传感器",balancing:"均衡状态",volt:"V",charge:"充电状态",discharge:"放电状态",remaining:"剩余容量"},Ye={common:Je,config:qe,switches:We,stats:Ze,html_texts:Ge},Qe={title:"JK BMS Karta",description:"Konfigurowalna karta Home Assistant do emulacji ekranu JK BMS",version:"Wersja"},Xe={language:"Język",title:"Tytuł",prefix:"Prefiks sensorów",batteryName:"Nazwa baterii",cellCount:"Liczba ogniw",cellColumns:"Liczba kolumn",cellLayout:"Układ ogniw",layout:"Układ",deltaVoltageUnit:"Jednostka różnicy napięcia",resistanceUnit:"Jednostka miary rezystancji",cellColorMode:"Tryb koloru ogniw",cellOrientation:"Orientacja ogniw",minCellVoltage:"Minimalne napięcie ogniwa (V)",maxCellVoltage:"Maksymalne napięcie ogniwa (V)",manualAssignment:"Ręczne przypisanie encji",tempSensorsCount:"Liczba dostępnych czujników temperatury",hasHeater:"Opcja grzałki włączona",socDecimals:"Miejsca po przecinku SOC",customDecimals:"Własne miejsca po przecinku",titleShowHide:"Pokaż / Ukryj strefy",showTitle:"Tytuł",showButtons:"Przyciski",showMain:"Panel",showCondensed:"Zwarte",showMainStats:"Stat.",showCells:"Ogniwa",showResistances:"R. ogniwa",showCardVersion:"Wersja"},et={charge:"Ładowanie",discharge:"Rozładowanie",balance:"Balansowanie",heater:"Grzałka"},tt={power:"Moc:",capacity:"Pojem.:",cycleCapacity:"Poj. Cykl:",averageCellV:"Śr V Ogniwa:",balanceCurrent:"Prąd Bal:",stateOfCharge:"SOC:",remainingAmps:"Pozostało:",cycles:"Cykle:",delta:"Δ Napięcie:",mosfetTemp:"Temp MOS:",minCellV:"Min V Ogniwa:",maxCellV:"Max V Ogniwa:",temperature_sensor_1:"Temp. 1:",temperature_sensor_2:"Temp. 2:",temperature_sensor_3:"Temp. 3:",temperature_sensor_4:"Temp. 4:"},nt={capacity:"Pojemność",time:"Czas","grid-solar":"Sieć/Solar",load:"Obciążenie","total-voltage":"Całkowite napięcie",current:"Prąd",mosfetTemp:"Temp. MOSFET",delta:"Delta",temperature_sensor:"Temp",balancing:"Balansowanie",volt:"V",charge:"Ładowanie",discharge:"Rozładowanie",remaining:"Pozostałe"},at={common:Qe,config:Xe,switches:et,stats:tt,html_texts:nt},lt={title:"Tarjeta JK BMS",description:"Una tarjeta personalizable de Home Assistant para emular la pantalla JK BMS",version:"Versión"},st={language:"Idioma",title:"Título",prefix:"Prefijo de los sensores",batteryName:"Nombre de la batería",cellCount:"Número de celdas",cellColumns:"Número de columnas",cellLayout:"Diseño de celdas",layout:"Diseño",deltaVoltageUnit:"Unidad de medida de voltaje delta",resistanceUnit:"Unidad de medida de la resistencia",cellColorMode:"Modo de color de celdas",cellOrientation:"Orientación de celdas",minCellVoltage:"Voltaje mínimo de celda (V)",maxCellVoltage:"Voltaje máximo de celda (V)",manualAssignment:"Asignación manual de entidades",tempSensorsCount:"Número de sensores de temperatura disponibles",hasHeater:"Opción de calefactor activada",socDecimals:"Decimales de SOC",customDecimals:"Decimales personalizados",titleShowHide:"Mostrar / Ocultar zonas",showTitle:"Título",showButtons:"Botones",showMain:"Principal",showCondensed:"Condensado",showMainStats:"Stats",showCells:"Celdas",showResistances:"R. celda",showCardVersion:"Versión"},it={charge:"Cargar",discharge:"Descargar",balance:"Balancear",heater:"Calefactor"},ot={power:"Potencia:",capacity:"Capac.:",cycleCapacity:"Cap. Ciclo:",averageCellV:"V Celda Prom:",balanceCurrent:"Bal. Corr:",stateOfCharge:"SOC:",remainingAmps:"Restante:",cycles:"Ciclos:",delta:"Δ Voltaje:",mosfetTemp:"Temp MOS:",minCellV:"Min V Celda:",maxCellV:"Max V Celda:",temperature_sensor_1:"Temp. 1:",temperature_sensor_2:"Temp. 2:",temperature_sensor_3:"Temp. 3:",temperature_sensor_4:"Temp. 4:"},rt={capacity:"Capacidad",time:"Tiempo","grid-solar":"Red/Solar",load:"Carga","total-voltage":"Voltaje total",current:"Corriente",mosfetTemp:"Temp MOSFET",delta:"Delta",temperature_sensor:"Temp",balancing:"Balanceo",volt:"V",charge:"Cargar",discharge:"Descargar",remaining:"Restante"},ct={common:lt,config:st,switches:it,stats:ot,html_texts:rt},_t={title:"Carte JK BMS",description:"Une carte Home Assistant personnalisable pour émuler l'écran JK BMS",version:"Version"},ht={language:"Langue",title:"Titre",prefix:"Préfixe des capteurs",batteryName:"Nom de la batterie",cellCount:"Nombre de cellules",cellColumns:"Nombre de colonnes",cellLayout:"Disposition des cellules",layout:"Disposition",deltaVoltageUnit:"Unité de mesure de tension delta",resistanceUnit:"Unité de mesure de la résistance",cellColorMode:"Mode couleur des cellules",cellOrientation:"Orientation des cellules",minCellVoltage:"Tension minimale de la cellule (V)",maxCellVoltage:"Tension maximale de la cellule (V)",manualAssignment:"Attribution manuelle des entités",tempSensorsCount:"Nombre de capteurs de température disponibles",hasHeater:"Option chauffage activée",socDecimals:"Décimales SOC",customDecimals:"Décimales personnalisées",titleShowHide:"Afficher / Masquer les zones",showTitle:"Titre",showButtons:"Boutons",showMain:"Principal",showCondensed:"Condensé",showMainStats:"Stats",showCells:"Cellules",showResistances:"R. cellule",showCardVersion:"Version"},dt={charge:"Charge",discharge:"Décharge",balance:"Équilibrage",heater:"Chauffage"},gt={power:"Puiss.:",capacity:"Capac.:",cycleCapacity:"Cap. Cycle:",averageCellV:"V Cell Moy:",balanceCurrent:"Cour. Bal:",stateOfCharge:"SOC:",remainingAmps:"Restant:",cycles:"Cycles:",delta:"Δ Tension:",mosfetTemp:"Temp MOS:",minCellV:"Min V Cell:",maxCellV:"Max V Cell:",temperature_sensor_1:"Temp. 1:",temperature_sensor_2:"Temp. 2:",temperature_sensor_3:"Temp. 3:",temperature_sensor_4:"Temp. 4:"},pt={capacity:"Capacité",time:"Temps","grid-solar":"Réseau/Solaire",load:"Charge","total-voltage":"Tension totale",current:"Courant",mosfetTemp:"Temp MOSFET",delta:"Delta",temperature_sensor:"Temp",balancing:"Équilibrage",volt:"V",charge:"Charge",discharge:"Décharge",remaining:"Restant"},mt={common:_t,config:ht,switches:dt,stats:gt,html_texts:pt};const ut={hass:null},vt={en:Object.freeze({__proto__:null,common:ue,config:ve,default:we,html_texts:ye,stats:be,switches:fe}),uk:Object.freeze({__proto__:null,common:Ce,config:xe,default:Me,html_texts:Ae,stats:ke,switches:Se}),ro:Object.freeze({__proto__:null,common:$e,config:Ve,default:ze,html_texts:Oe,stats:Ee,switches:Te}),de:Object.freeze({__proto__:null,common:De,config:Ne,default:Pe,html_texts:Be,stats:Re,switches:Ue}),ru:Object.freeze({__proto__:null,common:je,config:Le,default:Ke,html_texts:Fe,stats:Ie,switches:He}),zh:Object.freeze({__proto__:null,common:Je,config:qe,default:Ye,html_texts:Ge,stats:Ze,switches:We}),pl:Object.freeze({__proto__:null,common:Qe,config:Xe,default:at,html_texts:nt,stats:tt,switches:et}),es:Object.freeze({__proto__:null,common:lt,config:st,default:ct,html_texts:rt,stats:ot,switches:it}),fr:Object.freeze({__proto__:null,common:_t,config:ht,default:mt,html_texts:pt,stats:gt,switches:dt})};function ft(e,t="",n=""){try{let a=ut.cardConfig?.language,l=localStorage.getItem("selectedLanguage");null===l&&(l=localStorage.getItem("assist_debug_language")),null===l&&(l=localStorage.getItem("editor-language")),null===l&&(l="en"),l=l.replace(/['"]+/g,"").replace("-","_");const s=ut.hass?.selectedLanguage||ut.hass?.locale?.language||ut.hass?.language,i=a&&"auto"!==a?a:s||l;let o;try{o=e?.split(".").reduce(((e,t)=>e[t]),vt[i])}catch(t){o=e?.split(".")?.reduce(((e,t)=>e[t]),vt.en)}return void 0===o&&(o=e?.split(".")?.reduce(((e,t)=>e[t]),vt.en)),""!==t&&""!==n&&(o=o.replace(t,n)),o}catch(t){return e}}var bt="1.2.20";function yt(e,t,n,a){a=a||{},n=null==n?{}:n;const l=new Event(t,{bubbles:void 0===a.bubbles||a.bubbles,cancelable:Boolean(a.cancelable),composed:void 0===a.composed||a.composed});return l.detail=n,e.dispatchEvent(l),l}const wt=(e,t)=>{const n=e?.entities[t]?.toString()?.trim();return n&&n.length>1?n:t?.toString()},Ct=(e,t,n,a="sensor")=>{if(!e)return;e.stopPropagation();const l=wt(t,n),s=l.includes("sensor.")||l.includes("switch.")||l.includes("number.")||l.includes("binary_sensor.")?l:a+"."+t?.prefix+"_"+l;let i=new CustomEvent("hass-more-info",{detail:{entityId:s},composed:!0});e.target.dispatchEvent(i)},xt=(e,t,n,a="sensor")=>{const l=wt(t,n);if(!l)return null;const s=l.includes(".")?l:"".concat(a,".").concat(t.prefix,"_").concat(l);return e?.states[s]??null},St=(e,t,n,a=2,l="",s="sensor")=>{const i=xt(e,t,n,s);if(!i)return l;const o=i.state,r=Number(o);return isNaN(r)?o??l:r.toFixed(a)},kt=(e,t,n,a="sensor")=>{const l=xt(e,t,n,a);return l?.attributes?.unit_of_measurement??""},At=e=>{if(!e)return null;switch(e.trim().toLowerCase()){case"v":return"V";case"mv":return"mV";case"ω":case"ohm":case"ohms":return"Ω";case"mω":case"mohm":case"mohms":return"mΩ";default:return null}},Mt={V:{toBase:1},mV:{toBase:.001},"Ω":{toBase:1},"mΩ":{toBase:.001}},$t=(e,t,n)=>{const a="string"==typeof n?parseFloat(n):n;if(isNaN(a))return"-";const l=At(e),s=At(t);if(!l||!s)return"".concat(a," ").concat(t??"").trim();const i=a*Mt[l].toBase/Mt[s].toBase,o=s.startsWith("m")?0:3,r=i.toLocaleString("en-US",{minimumFractionDigits:o,maximumFractionDigits:o});return"".concat(r," ").concat(s)};var Vt,Tt,Et,Ot,zt,Dt,Nt,Ut,Rt,Bt,Pt,jt,Lt,Ht,It,Ft,Kt,Jt,qt,Wt,Zt,Gt,Yt,Qt,Xt;let en=class extends oe{constructor(){super(...arguments),this.minCellId="",this.maxCellId="",this.deltaV=0,this.shouldBalance=!1,this.VERSION=bt}_navigate(e,t,n="sensor"){Ct(e,this.config,t,n)}getState(e,t=2,n="",a="sensor"){return St(this.hass,this.config,e,t,n,a)}getUnit(e){return kt(this.hass,this.config,e)}_renderSwitch(t,n){const a=this.getState(t,0,"","switch"),l="on"===a?"status-on":"status-off";return I(Vt||(Vt=e(['\n
',"\n
\n "])),(e=>this._navigate(e,t,"switch")),ft("switches."+n),l,a.toUpperCase())}configOrEnum(e){return wt(this.config,e)}render(){if(ut.hass=this.hass,!this.hass||!this.config)return I(Tt||(Tt=e([""])));const t=this.getState(me.hardware_version),n=this.getState(me.software_version),a=this.getState(me.total_runtime_formatted),l=a&&"unknown"!=a?I(Et||(Et=e(["",': ',""])),ft("html_texts.time"),a.toUpperCase()):"",s=this.config.batteryName||"",i=this.config.title&&this.config.title.toLocaleLowerCase()!=ft("config.title").toLocaleLowerCase()?this.config.title:I(Ot||(Ot=e(["","",": "," Ah
\n HW: "," | SW: "," | ",""])),""===s?"":s+" | ",ft("html_texts.capacity"),this.getState(me.total_battery_capacity_setting),t,n,l);this.deltaV=parseFloat(this.getState(me.delta_cell_voltage,3,"0"));const o=parseFloat(this.getState(me.balancing_current,2,"0")),r=parseFloat(this.getState(me.power,2,"0"));this.shouldBalance=0!=o;const c=r>0?"power-positive":r<0?"power-negative":"power-even",_=o>0?"balance-positive":o<0?"balance-negative":"balance-even",h=this.shouldBalance?"delta-needs-balancing":"delta-ok",d=this.config.socDecimals??0,g=this.config.customDecimals??0,p=this.config.showTitle,m=this.config.showButtons,u=this.config.showMain,v=this.config.showCondensed,f=this.config.showCells,b=this.config.showResistances,y=this.config.showCardVersion,w=v?"stats data-row":"stats data-row split";this.minCellId=this.getState(me.min_voltage_cell,0),this.maxCellId=this.getState(me.max_voltage_cell,0);const C=e=>{if(null==e||""===e)return!1;const t=Number(e);return!isNaN(t)&&isFinite(t)&&t>=0},x=C(this.minCellId)&&C(this.maxCellId),S=(e=>{if(null==e)return!1;const t=Number(e);return!isNaN(t)&&isFinite(t)&&t>0})(this.deltaV);return x&&S||this.calculateDynamicMinMaxCellId(this.config?.cellCount??16),I(zt||(zt=e(['\n \n
\n
\n ',"\n ","\n ","\n ","\n
\n "])),"1"==this.config.hasHeater?"4":"3",this._renderSwitch(me.charging,"charge"),this._renderSwitch(me.discharging,"discharge"),this._renderSwitch(me.balancer,"balance"),"1"==this.config.hasHeater?this._renderSwitch(me.heater,"heater"):""):I(Nt||(Nt=e([""]))),this._renderError(),u?I(Ut||(Ut=e(['\n
\n
\n
\n '," ",'\n
\n
','
\n
','
\n
','
\n
',' ',' '," A
\n ",'\n
\n\n
\n
\n ',' A\n
\n
','
\n
','
\n
','
\n
',' ',' ',' ',' \n \n ']))):""):I(jt||(jt=e([""]))),f?I(Lt||(Lt=e(['\n
\n ',"\n
\n "])),this.config.cellColumns??2,this._renderCells("bankMode"==this.config.cellLayout,b)):I(Ht||(Ht=e([""]))),y?I(It||(It=e(['\n
\n \n v.',"\n \n
\n "])),this.VERSION):I(Ft||(Ft=e([""]))))}updated(){requestAnimationFrame((()=>this._updateFlowLine()))}connectedCallback(){super.connectedCallback(),window.addEventListener("resize",this._updateFlowLine.bind(this))}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("resize",this._updateFlowLine.bind(this))}_renderError(){const t=this.getState(me.errors,0);return t.trim().length<=1||"0"==t?I(Kt||(Kt=e([""]))):I(Jt||(Jt=e(['',""])),t)}_renderTemps(t){const n=[],a=this.config?.tempSensorsCount??0,l=this.config.showCondensed?"data-row":"data-row split";for(let s=t;s<=a;s+=2)n.push(I(qt||(qt=e(['\n
',' \n
\n
\n ','\n ',"","\n ","\n
\n
\n
\n "])),t,t,n>4||n>3&&!0===h?"multi-line":"single-line",(e=>this._navigate(e,me["cell_voltage_".concat(t)])),t.toString().padStart(2,"0"),_,l,h?d:"",g)}_updateFlowLine(){const e=parseFloat(this.getState(me.balancing_current,3,"0")),t=this.renderRoot.querySelector(".cell-div-".concat(this.minCellId)),n=this.renderRoot.querySelector(".cell-div-".concat(this.maxCellId)),a=this.renderRoot.querySelector("#flow-path");if(!a||!t||!n)return;if(!this.shouldBalance&&0===e)return a.setAttribute("d",""),void(a.style.display="none");a.style.display="inline";const l=(this.renderRoot instanceof ShadowRoot?this.renderRoot.host:this).getBoundingClientRect(),s=t.getBoundingClientRect(),i=n.getBoundingClientRect(),o=this.config?.cellColumns??2,r=l.width/o,c=Math.floor((i.left+i.width/2-l.left)/r),_=Math.floor((s.left+s.width/2-l.left)/r),h=(e,t)=>({x:"right"===t?e.right-l.left:e.left-l.left,y:e.top+e.height/2-l.top});let d,g;if(Math.abs(i.top-s.top)<10)d=i.leftthis.fetchHistory()),6e4)}_navigate(e,t,n="sensor"){Ct(e,this.config,t,n)}updated(e){e.has("hass")&&this._updateRealtimeHistory()}_updateRealtimeHistory(){if(!this.hass||!this.config)return;const e=[me.total_voltage,me.current,me.power_tube_temperature,me.delta_cell_voltage],t=Date.now()-36e5;e.forEach((e=>{const n=this._resolveEntityId(e);if(!n)return;const a=this.hass.states[n];if(!a)return;const l=parseFloat(a.state),s=new Date(a.last_updated).getTime();if(isNaN(l))return;const i=this.historyData[n]||[],o=i.length>0?i[i.length-1]:null;if(!o||s>o.time){const e=[...i,{state:l,time:s}];for(;e.length>0&&e[0].timee)),t=[...new Set(e)];if(0===t.length)return;const n=new Date,a=new Date(n.getTime()-36e5);try{const e=await this.hass.callWS({type:"history/history_during_period",start_time:a.toISOString(),end_time:n.toISOString(),entity_ids:t,minimal_response:!0,no_attributes:!0});if(e){const t={};Object.keys(e).forEach((n=>{const a=e[n];Array.isArray(a)&&(t[n]=a.map((e=>({state:parseFloat(e.s||e.state),time:1e3*(e.lu||new Date(e.last_updated).getTime()/1e3)}))).filter((e=>!isNaN(e.state))))})),this.historyData={...this.historyData,...t}}}catch(e){console.warn("JK BMS Card: Failed to fetch history via WS",e)}}configOrEnum(e){return wt(this.config,e)}_resolveEntityId(e){const t=this.configOrEnum(e);if(t)return t.includes(".")?t:"sensor.".concat(this.config.prefix,"_").concat(t)}_renderSparkline(t,n){const a=this._resolveEntityId(t);if(!a||!this.historyData[a]||this.historyData[a].length<2)return I(tn||(tn=e([""])));const l=this.historyData[a];let s=1/0,i=-1/0;l.forEach((e=>{const t=Number(Number(e.state).toFixed(3));ti&&(i=t)}));let o=i-s;if(o<1){const e=(s+i)/2;s=e-.5,i=e+.5}else s-=.05*o,i+=.05*o;const r=l[0].time,c=l[l.length-1].time-r;if(c<=0)return I(nn||(nn=e([""])));let _="";return l.forEach(((e,t)=>{const n=(e.time-r)/c*100,a=100-(e.state-s)/(i-s)*100;_+="".concat(0===t?"M":"L"," ").concat(n.toFixed(1),",").concat(a.toFixed(1)," ")})),I(an||(an=e(['\n
\n \n \n \n \n
\n '])),_,n,_,n)}getState(e,t=2,n="",a="sensor"){return St(this.hass,this.config,e,t,n,a)}getUnit(e){return kt(this.hass,this.config,e)}render(){if(ut.hass=this.hass,!this.hass||!this.config)return I(ln||(ln=e([""])));const t=this.config.socDecimals??0,n=this.getState(me.state_of_charge,t),a=this.config.customDecimals??0,l=this.getState(me.hardware_version),s=this.getState(me.software_version),i=this.getState(me.total_battery_capacity_setting,a),o=this.getState(me.total_runtime_formatted),r=o&&"unknown"!=o?I(sn||(sn=e([" | ",": ",""])),ft("html_texts.time"),o.toUpperCase()):"",c=this.config.batteryName||"",_=this.config.title&&this.config.title.toLocaleLowerCase()!=ft("config.title").toLocaleLowerCase()?this.config.title:I(on||(on=e(["","",": "," Ah
\n HW: "," | SW: ","",""])),""===c?"":c+" | ",ft("html_texts.capacity"),i,l,s,r),h=parseFloat(this.getState(me.current)),d=this.getState(me.charging_power,a),g=this.getState(me.discharging_power,a),p=h>0,m=h<0,u="on"===this.getState(me.charging,0,"","switch"),v="on"===this.getState(me.discharging,0,"","switch"),f="on"===this.getState(me.balancing,0,"","binary_sensor"),b=parseFloat(this.getState(me.balancing_current)),y=this.getState(me.total_voltage),w=this.getState(me.power_tube_temperature),C=this.getUnit(me.power_tube_temperature),x=this.getState(me.total_charging_cycle_capacity,a),S=parseFloat(this.getState(me.charging_cycles)).toFixed(0).toString();this.tempSensorsCount=this.config.tempSensorsCount;const k=this.config.showTitle,A=this.config.showButtons,M=this.config.showMain,$=this.config.showCells,V=this.config.showResistances,T=this.config.showCardVersion;this.minCellId=this.getState(me.min_voltage_cell,0),this.maxCellId=this.getState(me.max_voltage_cell,0),this.deltaV=parseFloat(this.getState(me.delta_cell_voltage,3,"0"));const E=e=>{if(null==e||""===e)return!1;const t=Number(e);return!isNaN(t)&&isFinite(t)&&t>=0},O=E(this.minCellId)&&E(this.maxCellId),z=(e=>{if(null==e)return!1;const t=Number(e);return!isNaN(t)&&isFinite(t)&&t>0})(this.deltaV);O&&z||this.calculateDynamicMinMax();const D=this.config.showMainStats;return I(rn||(rn=e(['\n \n ',"\n \n ","\n \n \x3c!-- Cells --\x3e\n ","\n ","\n \n "])),k?I(cn||(cn=e(['\n
\n \x3c!-- Solar/Grid Node --\x3e\n
\n
\n \n
\n
',"
\n ",'\n
\n
\n
\n
\n\n \x3c!-- Reactor (SOC) --\x3e\n
\n
\n
SoC:
\n
',"%
\n ",'\n
\n
\n\n \x3c!-- Load Node --\x3e\n
\n
\n \n
\n
',"
\n ",'\n \n
\n
\n
\n
\n\n \x3c!-- SVG Flow Lines --\x3e\n \n \x3c!-- Left path (Charge) - Rough coordinates for now, will refine --\x3e\n \n \x3c!-- Right path (Discharge) --\x3e\n \n\n \n \n \n \n \n \n
\n \n \x3c!-- Stats Panels --\x3e\n ',"\n \n "])),A?" clickable":"",A?e=>this._navigate(e,me.charging,"switch"):void 0,p?"var(--solar-color)":"#444",ft("html_texts.grid-solar"),A?I(hn||(hn=e(['\n
\n ',': ',"\n
\n "])),ft("html_texts.charge"),u?"status-on":"status-off",u?"ON":"OFF"):I(dn||(dn=e([""]))),(e=>this._navigate(e,me.charging_power)),d,f&&0!=b?"reactor-ring-balancing":"reactor-ring-base",(e=>this._navigate(e,me.state_of_charge)),n,f&&0!=b?I(gn||(gn=e(['
\n ',': ',"\n
\n "])),ft("html_texts.discharge"),v?"status-on":"status-off",v?"ON":"OFF"):I(un||(un=e([""]))),(e=>this._navigate(e,me.discharging_power)),g,p?"path-charge":"path-inactive",m?"path-discharge":"path-inactive",v?"#3090c7":"#444",D?I(vn||(vn=e(['\n
\n
\n
\n ','\n
',':
\n
\n
\n\n
\n ','\n
',':
\n
\n
\n
\n\n
\n
\n ','\n
',':
\n
\n
\n\n
\n ','\n
'," ",':
\n
\n
\n
','
\n
\n
\n \n
\n
\n
\n
\n
\n \n \x3c!-- Add number of cycles --\x3e\n
\n
\n
','
\n
\n
\n \n
\n
\n ',"\n
"])),this.config.cellColumns??2,this._renderCells(V)):I(wn||(wn=e([""]))),T?I(Cn||(Cn=e(['\n
\n \n v.',"\n \n
\n "])),this.VERSION):I(xn||(xn=e([""]))))}calculateDynamicMinMax(){let e=1/0,t=-1/0,n=-1,a=-1;const l=this.config.cellCount||16;for(let s=1;s<=l;s++){const l=this.getState(me["cell_voltage_".concat(s)],3,""),i=parseFloat(l);isNaN(i)||(it&&(t=i,a=s))}e===1/0||t===-1/0?(this.deltaV=0,this.minCellId="",this.maxCellId=""):(this.minCellId=n.toString(),this.maxCellId=a.toString(),this.deltaV=parseFloat((t-e).toFixed(3)))}getTemperatureColor(e,t="°C"){("°F"===t||"F"===t)&&(e=5*(e-32)/9);const n=[{temp:-10,color:"#0000FF"},{temp:0,color:"#00BFFF"},{temp:20,color:"#41CD52"},{temp:30,color:"#FFD700"},{temp:40,color:"#FF8C00"},{temp:50,color:"#FF4500"},{temp:60,color:"#DC143C"}];for(let t=0;t=l.temp)continue;const s=(e-a.temp)/(l.temp-a.temp),i=parseInt(a.color.slice(1,3),16),o=parseInt(a.color.slice(3,5),16),r=parseInt(a.color.slice(5,7),16),c=parseInt(l.color.slice(1,3),16),_=parseInt(l.color.slice(3,5),16),h=parseInt(l.color.slice(5,7),16),d=Math.round(i+s*(c-i)),g=Math.round(o+s*(_-o)),p=Math.round(r+s*(h-r));return"#".concat(d.toString(16).padStart(2,"0")).concat(g.toString(16).padStart(2,"0")).concat(p.toString(16).padStart(2,"0"))}return n[n.length-1].color}renderTemperatureSensors(){if(!this.tempSensorsCount||0===this.tempSensorsCount)return I(Sn||(Sn=e([""])));const t=this.tempSensorsCount>=1,n=this.tempSensorsCount>=2,a=this.tempSensorsCount>=3,l=this.tempSensorsCount>=4,s=(t,n)=>{const a=this.getState(t,1,"—"),l=this.getUnit(t)||"°C",s=parseFloat(a),i=isNaN(s)?"#777777":this.getTemperatureColor(s,l);return I(kn||(kn=e(['\n
\n ','\n
\n '," ",'\n
\n
\n ',"\n ",'\n
\n\n \x3c!-- Right column (2 and 4) --\x3e\n
\n ',"\n ","\n
\n "])),t?s(me.temperature_sensor_1,1):"",a?s(me.temperature_sensor_3,3):"",n?s(me.temperature_sensor_2,2):"",l?s(me.temperature_sensor_4,4):"")}_renderCells(e){const t=[],n="bankMode"===this.config.cellLayout,a=this.config.cellColumns||2,l=this.config.cellCount||16,s=Math.floor(l/a),i=n?Math.ceil(l/a):l,o=l%a;for(let r=1;r<=i;r++){const c=[];if(n)if(o&&r===i)c.push(l);else for(let e=0;e100&&(p=100));const m=parseFloat(o),u=!isNaN(m)&&m>0&&a,v=$t(s,i,m).replace(" ",""),f=this.config.cellColorMode||"progress";let b="";if("gradient"===f){const e=[{r:180,g:60,b:60},{r:180,g:180,b:50},{r:60,g:180,b:60},{r:60,g:120,b:200},{r:90,g:60,b:200}];let t=Math.floor(p/25);t>=4&&(t=3);const n=p%25/25,a=e[t],l=e[t+1],s=Math.round(a.r+(l.r-a.r)*n),i=Math.round(a.g+(l.g-a.g)*n),o=Math.round(a.b+(l.b-a.b)*n);b="background: rgba(".concat(s,", ").concat(i,", ").concat(o,", 0.85);")}const y="gradient"===f?"background: rgba(0, 0, 0, 0.25); padding: 1px 3px; border-radius: 3px;":"",w=this.config.cellColumns>4||!0===this.config.showResistances&&this.config.cellColumns>3?"vertical":this.config.cellOrientation||"horizontal",C="vertical"===w?"cell-item cell-item-vertical":"cell-item",x=ft("html_texts.volt");t.push(I(Mn||(Mn=e(['\n
\n ',"\n ","\n
\n "])),C,b,"progress"===f?I($n||($n=e(['\n
'])),p):"","vertical"===w?I(Vn||(Vn=e(['\n ','\n \n ','\n ',"","\n \n ","\n "])),(e=>this._navigate(e,me["cell_voltage_".concat(n)])),String(n).padStart(2,"0"),_,y,l,u?x:"",u?I(On||(On=e(['\n .icon-circle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: clamp(20px, round(4cqi + 4px, 2px), 30px);\n height: clamp(20px, round(4cqi + 4px, 2px), 30px);\n justify-self: start;\n }\n\n .icon-stats > :nth-child(2) {\n justify-self: end;\n padding-right: 5px;\n }\n\n .icon-stats > .stat-value {\n white-space: nowrap;\n font-size: clamp(0.8em, round(8cqi + 0.25rem, 0.1em), 1.2em);\n font-weight: bold;\n }\n\n /* Cell Grid */\n\n .cell-grid {\n display: grid;\n gap: 6px;\n }\n\n .grid-1 {\n grid-template-columns: 1fr;\n }\n\n .grid-2 {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .grid-3 {\n grid-template-columns: repeat(3, 1fr);\n }\n\n .grid-4 {\n grid-template-columns: repeat(4, 1fr);\n }\n\n .grid-5 {\n grid-template-columns: repeat(5, 1fr);\n }\n\n .grid-6 {\n grid-template-columns: repeat(6, 1fr);\n }\n\n .grid-7 {\n grid-template-columns: repeat(7, 1fr);\n }\n\n .grid-8 {\n grid-template-columns: repeat(8, 1fr);\n }\n\n .cell-item {\n container-type: inline-size;\n background: var(--secondary-background-color, #2a2a2a);\n border-radius: 8px;\n padding: 3px 2px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 4px;\n position: relative;\n z-index: 0;\n overflow: hidden;\n white-space: nowrap;\n }\n\n .cell-item-vertical {\n container-type: inline-size;\n flex-direction: column;\n justify-content: center;\n padding: 2px 3px;\n gap: 3px;\n white-space: nowrap;\n }\n\n .cell-item-vertical .cell-id {\n padding-top: 2px;\n }\n\n .cell-item-bg {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: rgba(48, 144, 199, 0.2);\n z-index: -1;\n transition: width 0.5s ease-out;\n }\n\n .cell-id {\n display: inline-block;\n padding: 0.2rem 0.5rem;\n background-color: #195569;\n color: #e4f3f8;\n border-radius: 999px;\n font-weight: 600;\n font-size: clamp(0.8rem, round(14cqi, 0.05rem), 1rem) !important;\n min-width: 1.2rem;\n text-align: center;\n margin-right: 3px;\n flex-shrink: 0;\n }\n\n .cell-volts {\n color: var(--primary-text-color);\n font-family: monospace;\n font-size: clamp(0.9rem, round(14cqi, 0.05rem), 1.2rem) !important;\n white-space: nowrap;\n }\n\n .cell-res {\n color: var(--secondary-text-color);\n font-family: monospace;\n font-size: clamp(0.6rem, round(12cqi, 0.05rem), 0.8rem) !important;\n white-space: nowrap;\n }\n\n .cell-low {\n color: #FFA500;\n }\n\n /* Example warning color */\n\n .cell-high {\n color: var(--discharge-color);\n }\n\n .status-on {\n color: var(--accent-color);\n font-weight: bold;\n }\n\n .status-off {\n color: var(--disabled-text-color, #666);\n font-weight: bold;\n }\n\n .clickable {\n cursor: pointer;\n }\n\n /* SVG Overlay for Lines */\n\n .flow-svg {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 1;\n }\n\n .flow-svg path {\n fill: none;\n stroke-width: 2;\n stroke-dasharray: 8;\n }\n\n .path-charge {\n stroke: var(--solar-color);\n animation: flow 1s linear infinite;\n }\n\n .path-discharge {\n stroke: var(--discharge-color);\n animation: flow 1s linear infinite;\n }\n\n .path-inactive {\n stroke: #444;\n stroke-dasharray: 0;\n animation: none;\n }\n\n @keyframes flow {\n from {\n stroke-dashoffset: 16;\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n\n /* Sparkline CSS */\n /* Sparkline CSS */\n\n .metric-group {\n position: relative;\n width: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n z-index: 1;\n }\n\n .sparkline-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n overflow: hidden;\n opacity: 0.3;\n z-index: -1;\n pointer-events: none;\n }\n\n .sparkline-svg {\n width: 100%;\n height: 100%;\n }\n\n .spark-line {\n fill: none;\n stroke-width: 2;\n vector-effect: non-scaling-stroke;\n }\n\n .spark-area {\n fill-opacity: 0.2;\n stroke: none;\n }\n \n .cardVersion {\n text-align: right;\n margin-right: 5px;\n }\n \n .version {\n font-style: italic;\n font-size: 0.8rem;\n }\n "]))),t([de()],Dn.prototype,"hass",void 0),t([de()],Dn.prototype,"config",void 0),t([de()],Dn.prototype,"historyData",void 0),Dn=t([ce("jk-bms-core-reactor-layout")],Dn);const Pn=bt;console.groupCollapsed("%c🔋 JK-BMS Battery Card%c ready! 🚀 (v".concat(Pn,")"),"background: linear-gradient(to right, #41cd52, #3090c7); color: white; font-weight: bold; padding: 2px 8px; border-radius: 6px;","background: none; color: #AAA; font-style: italic;"),console.log("%c📖 Docs:","color: #41cd52; font-weight: bold;","https://github.com/Pho3niX90/jk-bms-card"),console.groupEnd();let jn=Bn=class extends oe{setConfig(e){this._config=Bn.getStubConfig(),this._config={...this._config,...e},ut.cardConfig=this._config}static getStubConfig(){return{language:"auto",title:ft("title"),prefix:"jk_bms",batteryName:"",cellCount:16,cellColumns:2,cellLayout:"bankMode",deltaVoltageUnit:"V",resistanceUnit:"Ω",tempSensorsCount:0,hasHeater:0,socDecimals:2,customDecimals:2,showTitle:!0,showButtons:!0,showMain:!0,showCondensed:!0,showMainStats:!0,showCells:!0,showResistances:!0,showCardVersion:!1,entities:Object.keys(me).reduce(((e,t)=>(e[t]="",e)),{})}}static async getConfigElement(){return await Promise.resolve().then((function(){return qn})),document.createElement(ge)}getCardSize(){return 3}render(){return ut.hass=this.hass,this.hass&&this._config?"core-reactor"===this._config.layout?I(Un||(Un=e([""])),this.hass,this._config):I(Rn||(Rn=e(["\n \n "])),this.hass,this._config):I(Nn||(Nn=e([""])))}};var Ln,Hn,In,Fn,Kn;t([de()],jn.prototype,"hass",void 0),t([de()],jn.prototype,"_config",void 0),jn=Bn=t([ce(pe)],jn),window.customCards.push({type:pe,name:"JK BMS Card",preview:!0,description:ft("common.description"),configurable:!0});let Jn=class extends oe{constructor(){super(...arguments),this._dynamicEntitySchema=[],this._fixedEntities=Object.values(me).filter((e=>!e.startsWith("cell_voltage_")&&!e.startsWith("cell_resistance_"))),this._computeLabelCallback=e=>ft("config.".concat(e.name))??e.name}static get styles(){return o(Ln||(Ln=e(["\n .boolean-wrapper {\n display: block;\n padding: 12px 0;\n }\n .boolean-row {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin-bottom: 16px;\n gap: 6px;\n }\n .label {\n font-size: 14px;\n color: var(--primary-text-color);\n line-height: 1.3;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n text-overflow: ellipsis;\n max-height: 2.6em;\n word-break: break-word;\n }\n "])))}setConfig(e){this._config={...e},this._updateDynamicEntitySchema()}_updateDynamicEntitySchema(){const e=Math.min(this._config?.cellCount??16,96),t=[];for(let n=1;n<=e;n++){const e="cell_voltage_".concat(n);e in me&&t.push({name:e,selector:{entity:{}}})}for(let n=1;n<=e;n++){const e="cell_resistance_".concat(n);e in me&&t.push({name:e,selector:{entity:{}}})}this._dynamicEntitySchema=t}willUpdate(e){if(super.willUpdate(e),e.has("_config")){const t=e.get("_config");t?.cellCount!==this._config?.cellCount&&this._updateDynamicEntitySchema()}}renderBoolean(t,n){return I(Hn||(Hn=e(['\n
\n ',"\n \n
\n "])),t,Boolean(this._config?.[n]??!1),(e=>this._handleSwitchChange(n,e)))}_handleSwitchChange(e,t){const n=!!t.target.checked,a={...this._config};a[e]=n;const l=!0===a.showMain&&"core-reactor"===a.layout;l||void 0===a.showMainStats||delete a.showMainStats,l&&void 0===a.showMainStats&&(a.showMainStats=!0),this._config=a,yt(this,"config-changed",{config:this._config})}render(){if(!this._config||!this.hass)return I(In||(In=e([""])));const t=[...this._fixedEntities.map((e=>({name:e,selector:{entity:{}}}))),...this._dynamicEntitySchema];return I(Fn||(Fn=e(["\n\t\t\t\n\n ","\n\t\t"])),this.hass,this._config,this._computeLabelCallback.bind(this),[{type:"grid",title:ft("config.language"),schema:[{type:"grid",schema:[{name:"language",selector:{select:{options:[{label:"Auto (follow HA)",value:"auto"},{label:"English",value:"en"},{label:"Română",value:"ro"},{label:"Українська",value:"uk"},{label:"German",value:"de"},{label:"Русский",value:"ru"},{label:"Polski",value:"pl"},{label:"Français",value:"fr"},{label:"Español",value:"es"},{label:"中文",value:"zh"}],mode:"dropdown"}}}]}]},{type:"grid",title:ft("config.title"),schema:[{type:"grid",schema:[{name:"title",selector:{text:{}}}]}]},{type:"grid",title:ft("config.prefix"),schema:[{type:"grid",column_min_width:"200px",schema:[{name:"prefix",selector:{text:{}}},{name:"batteryName",selector:{text:{}}}]}]},{type:"grid",title:ft("config.layout"),schema:[{type:"grid",schema:[{name:"layout",selector:{select:{options:[{label:"Default",value:"default"},{label:"Core Reactor",value:"core-reactor"}]}}},{name:"deltaVoltageUnit",selector:{select:{options:[{label:"Volts (V)",value:"V"},{label:"Millivolts (mV)",value:"mV"}]}}},{name:"resistanceUnit",selector:{select:{options:[{label:"Ohms (Ω)",value:"Ω"},{label:"MilliOhms (mΩ)",value:"mΩ"}]}}}]},{type:"grid",column_min_width:"200px",schema:[{name:"cellColorMode",selector:{select:{options:[{label:"Progress Bar",value:"progress"},{label:"Voltage Gradient",value:"gradient"}]}}},{name:"cellOrientation",selector:{select:{options:[{label:"Vertical",value:"vertical"},{label:"Horizontal",value:"horizontal"}]}}}]}]},{type:"grid",schema:[{type:"grid",column_min_width:"200px",schema:[{name:"minCellVoltage",selector:{number:{min:2,max:4,step:.01,mode:"box"}}},{name:"maxCellVoltage",selector:{number:{min:2,max:4,step:.01,mode:"box"}}}]}]},{type:"grid",title:ft("config.cellCount"),schema:[{type:"grid",schema:[{name:"cellCount",selector:{number:{min:2,max:48,step:2}}},{name:"cellColumns",selector:{number:{min:1,max:8,step:1}}}]}]},{type:"grid",schema:[{name:"cellLayout",selector:{select:{options:[{label:"Incremental",value:"incremental"},{label:"Bank Mode",value:"bankMode"}]}}},{name:"socDecimals",title:ft("config.socDecimals"),selector:{number:{min:0,max:2,step:1}}}]},{type:"grid",title:ft("config.tempSensorsCount"),schema:[{type:"grid",schema:[{name:"tempSensorsCount",selector:{number:{min:0,max:4,step:2}}},{name:"customDecimals",title:ft("config.customDecimals"),selector:{number:{min:0,max:2,step:1}}}]}]},{type:"grid",title:ft("config.hasHeater"),schema:[{type:"grid",schema:[{name:"hasHeater",selector:{select:{multiple:!1,mode:"list",options:[{label:"Yes",value:"1"},{label:"No",value:"0"}]}}}]}]},{type:"expandable",title:ft("config.manualAssignment"),schema:[{name:"entities",type:"grid",schema:t}]}],this._valueChanged.bind(this),I(Kn||(Kn=e(['\n \n
\n ','\n
\n
\n ',"\n ","\n ","\n ","\n ","\n\n ","\n ","\n ","\n
\n
\n "])),ft("config.titleShowHide"),this.renderBoolean(ft("config.showTitle"),"showTitle"),!0===this._config?.showMain&&"core-reactor"===this._config?.layout||"default"===this._config?.layout?this.renderBoolean(ft("config.showButtons"),"showButtons"):"",this.renderBoolean(ft("config.showMain"),"showMain"),!0===this._config?.showMain&&"default"===this._config?.layout?this.renderBoolean(ft("config.showCondensed"),"showCondensed"):"",!0===this._config?.showMain&&"core-reactor"===this._config?.layout?this.renderBoolean(ft("config.showMainStats"),"showMainStats"):"",this.renderBoolean(ft("config.showCells"),"showCells"),!0===this._config?.showCells?this.renderBoolean(ft("config.showResistances"),"showResistances"):"",this.renderBoolean(ft("config.showCardVersion"),"showCardVersion")))}_valueChanged(e){const t={...this._config};Object.assign(t,e.detail.value),this._config=t,"cellCount"in e.detail.value&&this._updateDynamicEntitySchema();const n=!0===t?.showMain&&"core-reactor"===t?.layout,a=!0===t?.showCells;n||void 0===t.showMainStats||delete t.showMainStats,n&&void 0===t.showMainStats&&(t.showMainStats=!0),a||void 0===t.showResistances||delete t.showResistances,a&&void 0===t.showResistances&&(t.showResistances=!0),yt(this,"config-changed",{config:this._config})}};t([de()],Jn.prototype,"hass",void 0),t([de()],Jn.prototype,"_config",void 0),t([de()],Jn.prototype,"lovelace",void 0),t([function(e){return de({...e,state:!0,attribute:!1})}()],Jn.prototype,"_dynamicEntitySchema",void 0),Jn=t([ce(ge)],Jn);var qn=Object.freeze({__proto__:null,get JkBmsCardEditor(){return Jn}});export{Pn as CARD_VERSION,jn as JkBmsCard}; + */}const ge="jk-bms-content-card-editor",pe="jk-bms-card";var me;!function(e){e.delta_cell_voltage="delta_cell_voltage",e.balancing="balancing",e.balancing_current="balancing_current",e.balancer_status_bitmask="balancer_status_bitmask",e.power="power",e.balance_trigger_voltage="balance_trigger_voltage",e.balance_starting_voltage="balance_starting_voltage",e.total_runtime_formatted="total_runtime_formatted",e.charging="charging",e.charging_power="charging_power",e.discharging="discharging",e.discharging_power="discharging_power",e.balancer="balancer",e.heater="heater",e.total_voltage="total_voltage",e.total_battery_capacity_setting="total_battery_capacity_setting",e.total_charging_cycle_capacity="total_charging_cycle_capacity",e.average_cell_voltage="average_cell_voltage",e.current="current",e.state_of_charge="state_of_charge",e.capacity_remaining="capacity_remaining",e.charging_cycles="charging_cycles",e.power_tube_temperature="power_tube_temperature",e.min_voltage_cell="min_voltage_cell",e.max_voltage_cell="max_voltage_cell",e.min_cell_voltage="min_cell_voltage",e.max_cell_voltage="max_cell_voltage",e.errors="errors",e.software_version="software_version",e.hardware_version="hardware_version",e.cell_voltage_1="cell_voltage_1",e.cell_voltage_2="cell_voltage_2",e.cell_voltage_3="cell_voltage_3",e.cell_voltage_4="cell_voltage_4",e.cell_voltage_5="cell_voltage_5",e.cell_voltage_6="cell_voltage_6",e.cell_voltage_7="cell_voltage_7",e.cell_voltage_8="cell_voltage_8",e.cell_voltage_9="cell_voltage_9",e.cell_voltage_10="cell_voltage_10",e.cell_voltage_11="cell_voltage_11",e.cell_voltage_12="cell_voltage_12",e.cell_voltage_13="cell_voltage_13",e.cell_voltage_14="cell_voltage_14",e.cell_voltage_15="cell_voltage_15",e.cell_voltage_16="cell_voltage_16",e.cell_voltage_17="cell_voltage_17",e.cell_voltage_18="cell_voltage_18",e.cell_voltage_19="cell_voltage_19",e.cell_voltage_20="cell_voltage_20",e.cell_voltage_21="cell_voltage_21",e.cell_voltage_22="cell_voltage_22",e.cell_voltage_23="cell_voltage_23",e.cell_voltage_24="cell_voltage_24",e.cell_voltage_25="cell_voltage_25",e.cell_voltage_26="cell_voltage_26",e.cell_voltage_27="cell_voltage_27",e.cell_voltage_28="cell_voltage_28",e.cell_voltage_29="cell_voltage_29",e.cell_voltage_30="cell_voltage_30",e.cell_voltage_31="cell_voltage_31",e.cell_voltage_32="cell_voltage_32",e.cell_voltage_33="cell_voltage_33",e.cell_voltage_34="cell_voltage_34",e.cell_voltage_35="cell_voltage_35",e.cell_voltage_36="cell_voltage_36",e.cell_voltage_37="cell_voltage_37",e.cell_voltage_38="cell_voltage_38",e.cell_voltage_39="cell_voltage_39",e.cell_voltage_40="cell_voltage_40",e.cell_voltage_41="cell_voltage_41",e.cell_voltage_42="cell_voltage_42",e.cell_voltage_43="cell_voltage_43",e.cell_voltage_44="cell_voltage_44",e.cell_voltage_45="cell_voltage_45",e.cell_voltage_46="cell_voltage_46",e.cell_voltage_47="cell_voltage_47",e.cell_voltage_48="cell_voltage_48",e.cell_voltage_49="cell_voltage_49",e.cell_voltage_50="cell_voltage_50",e.cell_voltage_51="cell_voltage_51",e.cell_voltage_52="cell_voltage_52",e.cell_voltage_53="cell_voltage_53",e.cell_voltage_54="cell_voltage_54",e.cell_voltage_55="cell_voltage_55",e.cell_voltage_56="cell_voltage_56",e.cell_voltage_57="cell_voltage_57",e.cell_voltage_58="cell_voltage_58",e.cell_voltage_59="cell_voltage_59",e.cell_voltage_60="cell_voltage_60",e.cell_voltage_61="cell_voltage_61",e.cell_voltage_62="cell_voltage_62",e.cell_voltage_63="cell_voltage_63",e.cell_voltage_64="cell_voltage_64",e.cell_voltage_65="cell_voltage_65",e.cell_voltage_66="cell_voltage_66",e.cell_voltage_67="cell_voltage_67",e.cell_voltage_68="cell_voltage_68",e.cell_voltage_69="cell_voltage_69",e.cell_voltage_70="cell_voltage_70",e.cell_voltage_71="cell_voltage_71",e.cell_voltage_72="cell_voltage_72",e.cell_voltage_73="cell_voltage_73",e.cell_voltage_74="cell_voltage_74",e.cell_voltage_75="cell_voltage_75",e.cell_voltage_76="cell_voltage_76",e.cell_voltage_77="cell_voltage_77",e.cell_voltage_78="cell_voltage_78",e.cell_voltage_79="cell_voltage_79",e.cell_voltage_80="cell_voltage_80",e.cell_voltage_81="cell_voltage_81",e.cell_voltage_82="cell_voltage_82",e.cell_voltage_83="cell_voltage_83",e.cell_voltage_84="cell_voltage_84",e.cell_voltage_85="cell_voltage_85",e.cell_voltage_86="cell_voltage_86",e.cell_voltage_87="cell_voltage_87",e.cell_voltage_88="cell_voltage_88",e.cell_voltage_89="cell_voltage_89",e.cell_voltage_90="cell_voltage_90",e.cell_voltage_91="cell_voltage_91",e.cell_voltage_92="cell_voltage_92",e.cell_voltage_93="cell_voltage_93",e.cell_voltage_94="cell_voltage_94",e.cell_voltage_95="cell_voltage_95",e.cell_voltage_96="cell_voltage_96",e.cell_resistance_1="cell_resistance_1",e.cell_resistance_2="cell_resistance_2",e.cell_resistance_3="cell_resistance_3",e.cell_resistance_4="cell_resistance_4",e.cell_resistance_5="cell_resistance_5",e.cell_resistance_6="cell_resistance_6",e.cell_resistance_7="cell_resistance_7",e.cell_resistance_8="cell_resistance_8",e.cell_resistance_9="cell_resistance_9",e.cell_resistance_10="cell_resistance_10",e.cell_resistance_11="cell_resistance_11",e.cell_resistance_12="cell_resistance_12",e.cell_resistance_13="cell_resistance_13",e.cell_resistance_14="cell_resistance_14",e.cell_resistance_15="cell_resistance_15",e.cell_resistance_16="cell_resistance_16",e.cell_resistance_17="cell_resistance_17",e.cell_resistance_18="cell_resistance_18",e.cell_resistance_19="cell_resistance_19",e.cell_resistance_20="cell_resistance_20",e.cell_resistance_21="cell_resistance_21",e.cell_resistance_22="cell_resistance_22",e.cell_resistance_23="cell_resistance_23",e.cell_resistance_24="cell_resistance_24",e.cell_resistance_25="cell_resistance_25",e.cell_resistance_26="cell_resistance_26",e.cell_resistance_27="cell_resistance_27",e.cell_resistance_28="cell_resistance_28",e.cell_resistance_29="cell_resistance_29",e.cell_resistance_30="cell_resistance_30",e.cell_resistance_31="cell_resistance_31",e.cell_resistance_32="cell_resistance_32",e.cell_resistance_33="cell_resistance_33",e.cell_resistance_34="cell_resistance_34",e.cell_resistance_35="cell_resistance_35",e.cell_resistance_36="cell_resistance_36",e.cell_resistance_37="cell_resistance_37",e.cell_resistance_38="cell_resistance_38",e.cell_resistance_39="cell_resistance_39",e.cell_resistance_40="cell_resistance_40",e.cell_resistance_41="cell_resistance_41",e.cell_resistance_42="cell_resistance_42",e.cell_resistance_43="cell_resistance_43",e.cell_resistance_44="cell_resistance_44",e.cell_resistance_45="cell_resistance_45",e.cell_resistance_46="cell_resistance_46",e.cell_resistance_47="cell_resistance_47",e.cell_resistance_48="cell_resistance_48",e.cell_resistance_49="cell_resistance_49",e.cell_resistance_50="cell_resistance_50",e.cell_resistance_51="cell_resistance_51",e.cell_resistance_52="cell_resistance_52",e.cell_resistance_53="cell_resistance_53",e.cell_resistance_54="cell_resistance_54",e.cell_resistance_55="cell_resistance_55",e.cell_resistance_56="cell_resistance_56",e.cell_resistance_57="cell_resistance_57",e.cell_resistance_58="cell_resistance_58",e.cell_resistance_59="cell_resistance_59",e.cell_resistance_60="cell_resistance_60",e.cell_resistance_61="cell_resistance_61",e.cell_resistance_62="cell_resistance_62",e.cell_resistance_63="cell_resistance_63",e.cell_resistance_64="cell_resistance_64",e.cell_resistance_65="cell_resistance_65",e.cell_resistance_66="cell_resistance_66",e.cell_resistance_67="cell_resistance_67",e.cell_resistance_68="cell_resistance_68",e.cell_resistance_69="cell_resistance_69",e.cell_resistance_70="cell_resistance_70",e.cell_resistance_71="cell_resistance_71",e.cell_resistance_72="cell_resistance_72",e.cell_resistance_73="cell_resistance_73",e.cell_resistance_74="cell_resistance_74",e.cell_resistance_75="cell_resistance_75",e.cell_resistance_76="cell_resistance_76",e.cell_resistance_77="cell_resistance_77",e.cell_resistance_78="cell_resistance_78",e.cell_resistance_79="cell_resistance_79",e.cell_resistance_80="cell_resistance_80",e.cell_resistance_81="cell_resistance_81",e.cell_resistance_82="cell_resistance_82",e.cell_resistance_83="cell_resistance_83",e.cell_resistance_84="cell_resistance_84",e.cell_resistance_85="cell_resistance_85",e.cell_resistance_86="cell_resistance_86",e.cell_resistance_87="cell_resistance_87",e.cell_resistance_88="cell_resistance_88",e.cell_resistance_89="cell_resistance_89",e.cell_resistance_90="cell_resistance_90",e.cell_resistance_91="cell_resistance_91",e.cell_resistance_92="cell_resistance_92",e.cell_resistance_93="cell_resistance_93",e.cell_resistance_94="cell_resistance_94",e.cell_resistance_95="cell_resistance_95",e.cell_resistance_96="cell_resistance_96",e.temperature_sensor_1="temperature_sensor_1",e.temperature_sensor_2="temperature_sensor_2",e.temperature_sensor_3="temperature_sensor_3",e.temperature_sensor_4="temperature_sensor_4"}(me||(me={}));var ue={title:"JK BMS Card",description:"A customizable Home Assistant card to emulate the JK BMS screen",version:"Version"},ve={language:"Language",title:"Title",prefix:"Prefix of the sensors",batteryName:"Battery name",cellCount:"Number of cells",cellColumns:"Number of columns",cellLayout:"Cell Layout",layout:"Layout",deltaVoltageUnit:"Delta Voltage Unit",resistanceUnit:"Resistance Unit",cellColorMode:"Cell Color Mode",cellOrientation:"Cell Orientation",minCellVoltage:"Min Cell Voltage (V)",maxCellVoltage:"Max Cell Voltage (V)",manualAssignment:"Manual entity assignment",tempSensorsCount:"No. of temp. sensors available",hasHeater:"Heater option is used",socDecimals:"SoC Decimals",customDecimals:"Custom Decimals",titleShowHide:"Show / Hide zones",showTitle:"Title",showButtons:"Buttons",showMain:"Main",showCondensed:"Condensed",showMainStats:"Stats",showCells:"Cells",showResistances:"Cell R.",showCardVersion:"Version"},fe={charge:"Charge",discharge:"Discharge",balance:"Balance",heater:"Heater"},be={power:"Power:",capacity:"Capacity:",cycleCapacity:"Cycle Cap:",averageCellV:"Avg Cell V:",balanceCurrent:"Balance Cur:",stateOfCharge:"SOC:",remainingAmps:"Remaining:",cycles:"Cycles:",delta:"Delta Voltage:",mosfetTemp:"MOS Temp:",minCellV:"Min Cell V:",maxCellV:"Max Cell V:",temperature_sensor_1:"Temp. 1:",temperature_sensor_2:"Temp. 2:",temperature_sensor_3:"Temp. 3:",temperature_sensor_4:"Temp. 4:"},ye={capacity:"Capacity",time:"Time","grid-solar":"Grid/Solar",load:"Load","total-voltage":"Total Voltage",current:"Current",mosfetTemp:"MOS Temp",delta:"Delta",temperature_sensor:"Temp",balancing:"Balancing",volt:"V",charge:"Charge",discharge:"Discharge",remaining:"Remaining"},we={common:ue,config:ve,switches:fe,stats:be,html_texts:ye},Ce={title:"Карта JK BMS",description:"Налаштовувана картка Home Assistant для емуляції екрану JK BMS",version:"Версія"},xe={language:"Мова",title:"Заголовок",prefix:"Префікс сенсорів",batteryName:"Назва батареї",cellCount:"Кількість комірок",cellColumns:"Кількість стовпців",cellLayout:"Розташування комірок",layout:"Макет",deltaVoltageUnit:"Одиниця дельта напруги",resistanceUnit:"Одиниця вимірювання опору",cellColorMode:"Режим кольору комірок",cellOrientation:"Орієнтація комірок",minCellVoltage:"Мін. напруга комірки (В)",maxCellVoltage:"Макс. напруга комірки (В)",manualAssignment:"Ручне призначення сутності",tempSensorsCount:"Кількість доступних датчиків температури",hasHeater:"Використовується опція підігріву",socDecimals:"знаки від коми",customDecimals:"Власні десяткові дроби",titleShowHide:"Показати / Сховати зони",showTitle:"Заголовок",showButtons:"Кнопки",showMain:"Панель",showCondensed:"Компактно",showMainStats:"Стат.",showCells:"Елементи",showResistances:"Опір ел",showCardVersion:"Версія"},Se={charge:"Заряд",discharge:"Розряд",balance:"Баланс",heater:"Підігрів"},ke={power:"Потужн.:",capacity:"Ємн.:",cycleCapacity:"Цикл. ємн.:",averageCellV:"Сер V ком.:",balanceCurrent:"Бал. струм:",stateOfCharge:"SOC:",remainingAmps:"Залишок:",cycles:"Цикли:",delta:"Δ напруга:",mosfetTemp:"Темп MOS:",minCellV:"Мін V ком.:",maxCellV:"Макс V ком.:",temperature_sensor_1:"Темп. 1:",temperature_sensor_2:"Темп. 2:",temperature_sensor_3:"Темп. 3:",temperature_sensor_4:"Темп. 4:"},Ae={capacity:"Ємність",time:"Час","grid-solar":"Мережа/Сонячна",load:"Навантаження","total-voltage":"Загальна напруга",current:"Струм",mosfetTemp:"Темп. MOS",delta:"Дельта",temperature_sensor:"Темп",balancing:"Балансування",volt:"В",charge:"Заряд",discharge:"Розряд",remaining:"Залишок"},$e={common:Ce,config:xe,switches:Se,stats:ke,html_texts:Ae},Me={title:"Card JK BMS",description:"Un card Home Assistant personalizabil care imită ecranul JK BMS",version:"Versiune"},Ve={language:"Limba",title:"Titlu",prefix:"Prefixul senzorilor",batteryName:"Numele bateriei",cellCount:"Număr de celule",cellColumns:"Număr de coloane",cellLayout:"Aranjament celule",layout:"Aranjament general",deltaVoltageUnit:"UM pentru diferență tensiune",resistanceUnit:"UM pentru rezistență",cellColorMode:"Mod colorare celule",cellOrientation:"Orientare celule",minCellVoltage:"Tensiune minimă celulă (V)",maxCellVoltage:"Tensiune maximă celulă (V)",manualAssignment:"Atribuire manuală entități",tempSensorsCount:"Număr senzori temperatură",hasHeater:"Opțiunea încălzitor este utilizată",socDecimals:"Zecimale SoC",customDecimals:"Zecimale alte controale",titleShowHide:"Afișează / Ascunde zone",showTitle:"Titlul",showButtons:"Butoane",showMain:"Principală",showCondensed:"Compact",showMainStats:"Stat.",showCells:"Celule",showResistances:"Rezist.",showCardVersion:"Versiune"},Te={charge:"Încărcare",discharge:"Descărcare",balance:"Echilibrare",heater:"Încălzitor"},Ee={power:"Putere:",capacity:"Capac.:",cycleCapacity:"Cap. Ciclu:",averageCellV:"V Cel. Med:",balanceCurrent:"Cur. Bal:",stateOfCharge:"SOC:",remainingAmps:"Rămas:",cycles:"Cicluri:",delta:"Δ Tensiune:",mosfetTemp:"Temp MOS:",minCellV:"Min V Cel.:",maxCellV:"Max V Cel.:",temperature_sensor_1:"Temp. 1:",temperature_sensor_2:"Temp. 2:",temperature_sensor_3:"Temp. 3:",temperature_sensor_4:"Temp. 4:"},Oe={capacity:"Capacitate",time:"Timp","grid-solar":"Rețea/Solar",load:"Consum","total-voltage":"Tensiune totală",current:"Curent",mosfetTemp:"Temp. MOSFET",delta:"Diferență",temperature_sensor:"Temp",balancing:"Echilibrare",volt:"V",charge:"Încărcare",discharge:"Descărcare",remaining:"Rămas"},ze={common:Me,config:Ve,switches:Te,stats:Ee,html_texts:Oe},Be={title:"JK BMS Karte",description:"Eine anpassbare Home Assistant Karte, die den JK BMS Bildschirm nachbildet",version:"Version"},Re={language:"Sprache",title:"Titel",prefix:"Präfix der Sensoren",batteryName:"Batteriename",cellCount:"Anzahl der Zellen",cellColumns:"Anzahl der Spalten",cellLayout:"Zellen-Layout",layout:"Layout",deltaVoltageUnit:"Einheit der Spannungsdifferenz",resistanceUnit:"Einheit des elektrischen Widerstands",cellColorMode:"Zellen-Farbmodus",cellOrientation:"Zellen-Ausrichtung",minCellVoltage:"Min. Zellspannung (V)",maxCellVoltage:"Max. Zellspannung (V)",manualAssignment:"Manuelle Entitäten-Zuweisung",tempSensorsCount:"Anzahl verfügbarer Temperatursensoren",hasHeater:"Heizungs-Option wird verwendet",socDecimals:"SOC Dezimalstellen",customDecimals:"Benutzerdefinierte Dezimalzahlen",titleShowHide:"Zonen ein-/ausblenden",showTitle:"Titel",showButtons:"Schaltfl.",showMain:"Hauptteil",showCondensed:"Kompakt",showMainStats:"Stats",showCells:"Zellen",showResistances:"Zellen R.",showCardVersion:"Kartenvers."},De={charge:"Laden",discharge:"Entladen",balance:"Balancing",heater:"Heizung"},Ne={power:"Leistung:",capacity:"Kapaz.:",cycleCapacity:"Zykl. Kap.:",averageCellV:"Ø Zell V:",balanceCurrent:"Bal. Strom:",stateOfCharge:"SOC:",remainingAmps:"Rest:",cycles:"Zyklen:",delta:"Δ Spannung:",mosfetTemp:"MOS Temp:",minCellV:"Min Zell V:",maxCellV:"Max Zell V:",temperature_sensor_1:"Temp. 1:",temperature_sensor_2:"Temp. 2:",temperature_sensor_3:"Temp. 3:",temperature_sensor_4:"Temp. 4:"},Ue={capacity:"Kapazität",time:"Zeit","grid-solar":"Netz/Solar",load:"Last","total-voltage":"Gesamtspannung",current:"Stromstärke",mosfetTemp:"MOS Temp",delta:"Differenz",temperature_sensor:"Temp",balancing:"Balancing",volt:"V",charge:"Laden",discharge:"Entladen",remaining:"Restzeit"},Le={common:Be,config:Re,switches:De,stats:Ne,html_texts:Ue},Pe={title:"Карта JK BMS",description:"Настраиваемая карточка Home Assistant для эмуляции экрана JK BMS",version:"Версия"},je={language:"Язык",title:"Заголовок",prefix:"Префикс датчиков",batteryName:"Название батареи",cellCount:"Количество ячеек",cellColumns:"Количество столбцов",cellLayout:"Расположение ячеек",layout:"Макет",deltaVoltageUnit:"Единица дельта-напряжения",resistanceUnit:"Единица измерения сопротивления",cellColorMode:"Режим цвета ячеек",cellOrientation:"Ориентация ячеек",minCellVoltage:"Мин. напряжение ячейки (В)",maxCellVoltage:"Макс. напряжение ячейки (В)",manualAssignment:"Ручное назначение сущностей",tempSensorsCount:"Количество доступных датчиков температуры",hasHeater:"Используется подогрев",socDecimals:"Знаков после запятой",customDecimals:"Пользовательские десятичные",titleShowHide:"Показать / Скрыть зоны",showTitle:"Заголовок",showButtons:"Кнопки",showMain:"Панель",showCondensed:"Компактно",showMainStats:"Стат.",showCells:"Ячейки",showResistances:"Сопр. яч.",showCardVersion:"Версия"},He={charge:"Заряд",discharge:"Разряд",balance:"Балансировка",heater:"Подогрев"},Ie={power:"Мощн.:",capacity:"Ёмк.:",cycleCapacity:"Цикл. ёмк.:",averageCellV:"Ср V яч.:",balanceCurrent:"Бал. ток:",stateOfCharge:"SOC:",remainingAmps:"Остаток:",cycles:"Циклы:",delta:"Δ напр.:",mosfetTemp:"Темп MOS:",minCellV:"Мин V яч.:",maxCellV:"Макс V яч.:",temperature_sensor_1:"Темп. 1:",temperature_sensor_2:"Темп. 2:",temperature_sensor_3:"Темп. 3:",temperature_sensor_4:"Темп. 4:"},Fe={capacity:"Ёмкость",time:"Время","grid-solar":"Сеть/Солнце",load:"Нагрузка","total-voltage":"Общее напряжение",current:"Ток",mosfetTemp:"Темп. MOS",delta:"Дельта",temperature_sensor:"Темп",balancing:"Балансировка",volt:"В",charge:"Заряд",discharge:"Разряд",remaining:"Остаток"},Ke={common:Pe,config:je,switches:He,stats:Ie,html_texts:Fe},qe={title:"JK 电池管理系统",description:"用于显示 JK-BMS 实时状态 de 自定义卡片",version:"版本"},Je={language:"语言",title:"标题",prefix:"实体前缀",batteryName:"电池名称",cellCount:"电芯数量",cellColumns:"每行电芯数",cellLayout:"电芯布局方式",layout:"布局",deltaVoltageUnit:"电压差单位",resistanceUnit:"电阻单位",cellColorMode:"电池颜色模式",cellOrientation:"电池方向",minCellVoltage:"最小电池电压 (V)",maxCellVoltage:"最大电池电压 (V)",manualAssignment:"手动分配实体",tempSensorsCount:"温度传感器数量",hasHeater:"是否有加热器",socDecimals:"SOC 小数位数",customDecimals:"自定义小数位",titleShowHide:"显示 / 隐藏区域",showTitle:"标题",showButtons:"按钮",showMain:"主面板",showCondensed:"紧凑",showMainStats:"统计",showCells:"电池",showResistances:"电池 R.",showCardVersion:"版本"},We={charge:"充电",discharge:"放电",balance:"均衡",heater:"加热"},Ze={power:"功率:",capacity:"容量:",cycleCapacity:"循环:",averageCellV:"平均V:",balanceCurrent:"均衡:",stateOfCharge:"SOC:",remainingAmps:"剩余:",cycles:"循环数:",delta:"ΔV:",mosfetTemp:"MOS温:",minCellV:"最低V:",maxCellV:"最高V:",temperature_sensor_1:"温度1:",temperature_sensor_2:"温度2:",temperature_sensor_3:"温度3:",temperature_sensor_4:"温度4:"},Ge={capacity:"总容量设定",time:"运行时长","grid-solar":"电网/太阳能",load:"负载","total-voltage":"总电压",current:"实时电流",mosfetTemp:"功率管温度",delta:"单体电池压差",temperature_sensor:"温度传感器",balancing:"均衡状态",volt:"V",charge:"充电状态",discharge:"放电状态",remaining:"剩余容量"},Ye={common:qe,config:Je,switches:We,stats:Ze,html_texts:Ge},Qe={title:"JK BMS Karta",description:"Konfigurowalna karta Home Assistant do emulacji ekranu JK BMS",version:"Wersja"},Xe={language:"Język",title:"Tytuł",prefix:"Prefiks sensorów",batteryName:"Nazwa baterii",cellCount:"Liczba ogniw",cellColumns:"Liczba kolumn",cellLayout:"Układ ogniw",layout:"Układ",deltaVoltageUnit:"Jednostka różnicy napięcia",resistanceUnit:"Jednostka miary rezystancji",cellColorMode:"Tryb koloru ogniw",cellOrientation:"Orientacja ogniw",minCellVoltage:"Minimalne napięcie ogniwa (V)",maxCellVoltage:"Maksymalne napięcie ogniwa (V)",manualAssignment:"Ręczne przypisanie encji",tempSensorsCount:"Liczba dostępnych czujników temperatury",hasHeater:"Opcja grzałki włączona",socDecimals:"Miejsca po przecinku SOC",customDecimals:"Własne miejsca po przecinku",titleShowHide:"Pokaż / Ukryj strefy",showTitle:"Tytuł",showButtons:"Przyciski",showMain:"Panel",showCondensed:"Zwarte",showMainStats:"Stat.",showCells:"Ogniwa",showResistances:"R. ogniwa",showCardVersion:"Wersja"},et={charge:"Ładowanie",discharge:"Rozładowanie",balance:"Balansowanie",heater:"Grzałka"},tt={power:"Moc:",capacity:"Pojem.:",cycleCapacity:"Poj. Cykl:",averageCellV:"Śr V Ogniwa:",balanceCurrent:"Prąd Bal:",stateOfCharge:"SOC:",remainingAmps:"Pozostało:",cycles:"Cykle:",delta:"Δ Napięcie:",mosfetTemp:"Temp MOS:",minCellV:"Min V Ogniwa:",maxCellV:"Max V Ogniwa:",temperature_sensor_1:"Temp. 1:",temperature_sensor_2:"Temp. 2:",temperature_sensor_3:"Temp. 3:",temperature_sensor_4:"Temp. 4:"},nt={capacity:"Pojemność",time:"Czas","grid-solar":"Sieć/Solar",load:"Obciążenie","total-voltage":"Całkowite napięcie",current:"Prąd",mosfetTemp:"Temp. MOSFET",delta:"Delta",temperature_sensor:"Temp",balancing:"Balansowanie",volt:"V",charge:"Ładowanie",discharge:"Rozładowanie",remaining:"Pozostałe"},at={common:Qe,config:Xe,switches:et,stats:tt,html_texts:nt},lt={title:"Tarjeta JK BMS",description:"Una tarjeta personalizable de Home Assistant para emular la pantalla JK BMS",version:"Versión"},st={language:"Idioma",title:"Título",prefix:"Prefijo de los sensores",batteryName:"Nombre de la batería",cellCount:"Número de celdas",cellColumns:"Número de columnas",cellLayout:"Diseño de celdas",layout:"Diseño",deltaVoltageUnit:"Unidad de medida de voltaje delta",resistanceUnit:"Unidad de medida de la resistencia",cellColorMode:"Modo de color de celdas",cellOrientation:"Orientación de celdas",minCellVoltage:"Voltaje mínimo de celda (V)",maxCellVoltage:"Voltaje máximo de celda (V)",manualAssignment:"Asignación manual de entidades",tempSensorsCount:"Número de sensores de temperatura disponibles",hasHeater:"Opción de calefactor activada",socDecimals:"Decimales de SOC",customDecimals:"Decimales personalizados",titleShowHide:"Mostrar / Ocultar zonas",showTitle:"Título",showButtons:"Botones",showMain:"Principal",showCondensed:"Condensado",showMainStats:"Stats",showCells:"Celdas",showResistances:"R. celda",showCardVersion:"Versión"},it={charge:"Cargar",discharge:"Descargar",balance:"Balancear",heater:"Calefactor"},ot={power:"Potencia:",capacity:"Capac.:",cycleCapacity:"Cap. Ciclo:",averageCellV:"V Celda Prom:",balanceCurrent:"Bal. Corr:",stateOfCharge:"SOC:",remainingAmps:"Restante:",cycles:"Ciclos:",delta:"Δ Voltaje:",mosfetTemp:"Temp MOS:",minCellV:"Min V Celda:",maxCellV:"Max V Celda:",temperature_sensor_1:"Temp. 1:",temperature_sensor_2:"Temp. 2:",temperature_sensor_3:"Temp. 3:",temperature_sensor_4:"Temp. 4:"},rt={capacity:"Capacidad",time:"Tiempo","grid-solar":"Red/Solar",load:"Carga","total-voltage":"Voltaje total",current:"Corriente",mosfetTemp:"Temp MOSFET",delta:"Delta",temperature_sensor:"Temp",balancing:"Balanceo",volt:"V",charge:"Cargar",discharge:"Descargar",remaining:"Restante"},ct={common:lt,config:st,switches:it,stats:ot,html_texts:rt},ht={title:"Carte JK BMS",description:"Une carte Home Assistant personnalisable pour émuler l'écran JK BMS",version:"Version"},_t={language:"Langue",title:"Titre",prefix:"Préfixe des capteurs",batteryName:"Nom de la batterie",cellCount:"Nombre de cellules",cellColumns:"Nombre de colonnes",cellLayout:"Disposition des cellules",layout:"Disposition",deltaVoltageUnit:"Unité de mesure de tension delta",resistanceUnit:"Unité de mesure de la résistance",cellColorMode:"Mode couleur des cellules",cellOrientation:"Orientation des cellules",minCellVoltage:"Tension minimale de la cellule (V)",maxCellVoltage:"Tension maximale de la cellule (V)",manualAssignment:"Attribution manuelle des entités",tempSensorsCount:"Nombre de capteurs de température disponibles",hasHeater:"Option chauffage activée",socDecimals:"Décimales SOC",customDecimals:"Décimales personnalisées",titleShowHide:"Afficher / Masquer les zones",showTitle:"Titre",showButtons:"Boutons",showMain:"Principal",showCondensed:"Condensé",showMainStats:"Stats",showCells:"Cellules",showResistances:"R. cellule",showCardVersion:"Version"},dt={charge:"Charge",discharge:"Décharge",balance:"Équilibrage",heater:"Chauffage"},gt={power:"Puiss.:",capacity:"Capac.:",cycleCapacity:"Cap. Cycle:",averageCellV:"V Cell Moy:",balanceCurrent:"Cour. Bal:",stateOfCharge:"SOC:",remainingAmps:"Restant:",cycles:"Cycles:",delta:"Δ Tension:",mosfetTemp:"Temp MOS:",minCellV:"Min V Cell:",maxCellV:"Max V Cell:",temperature_sensor_1:"Temp. 1:",temperature_sensor_2:"Temp. 2:",temperature_sensor_3:"Temp. 3:",temperature_sensor_4:"Temp. 4:"},pt={capacity:"Capacité",time:"Temps","grid-solar":"Réseau/Solaire",load:"Charge","total-voltage":"Tension totale",current:"Courant",mosfetTemp:"Temp MOSFET",delta:"Delta",temperature_sensor:"Temp",balancing:"Équilibrage",volt:"V",charge:"Charge",discharge:"Décharge",remaining:"Restant"},mt={common:ht,config:_t,switches:dt,stats:gt,html_texts:pt};const ut={hass:null},vt={en:Object.freeze({__proto__:null,common:ue,config:ve,default:we,html_texts:ye,stats:be,switches:fe}),uk:Object.freeze({__proto__:null,common:Ce,config:xe,default:$e,html_texts:Ae,stats:ke,switches:Se}),ro:Object.freeze({__proto__:null,common:Me,config:Ve,default:ze,html_texts:Oe,stats:Ee,switches:Te}),de:Object.freeze({__proto__:null,common:Be,config:Re,default:Le,html_texts:Ue,stats:Ne,switches:De}),ru:Object.freeze({__proto__:null,common:Pe,config:je,default:Ke,html_texts:Fe,stats:Ie,switches:He}),zh:Object.freeze({__proto__:null,common:qe,config:Je,default:Ye,html_texts:Ge,stats:Ze,switches:We}),pl:Object.freeze({__proto__:null,common:Qe,config:Xe,default:at,html_texts:nt,stats:tt,switches:et}),es:Object.freeze({__proto__:null,common:lt,config:st,default:ct,html_texts:rt,stats:ot,switches:it}),fr:Object.freeze({__proto__:null,common:ht,config:_t,default:mt,html_texts:pt,stats:gt,switches:dt})};function ft(e,t="",n=""){try{let a=ut.cardConfig?.language,l=localStorage.getItem("selectedLanguage");null===l&&(l=localStorage.getItem("assist_debug_language")),null===l&&(l=localStorage.getItem("editor-language")),null===l&&(l="en"),l=l.replace(/['"]+/g,"").replace("-","_");const s=ut.hass?.selectedLanguage||ut.hass?.locale?.language||ut.hass?.language,i=a&&"auto"!==a?a:s||l;let o;try{o=e?.split(".").reduce(((e,t)=>e[t]),vt[i])}catch(t){o=e?.split(".")?.reduce(((e,t)=>e[t]),vt.en)}return void 0===o&&(o=e?.split(".")?.reduce(((e,t)=>e[t]),vt.en)),""!==t&&""!==n&&(o=o.replace(t,n)),o}catch(t){return e}}var bt,yt,wt="1.2.21";!function(e){e.language="language",e.system="system",e.comma_decimal="comma_decimal",e.decimal_comma="decimal_comma",e.space_comma="space_comma",e.none="none"}(bt||(bt={})),function(e){e.language="language",e.system="system",e.am_pm="12",e.twenty_four="24"}(yt||(yt={}));var Ct=function(e,t,n){void 0===n&&(n=!1),n?history.replaceState(null,"",t):history.pushState(null,"",t),function(e,t,n,a){a=a||{},n=null==n?{}:n;var l=new Event(t,{bubbles:void 0===a.bubbles||a.bubbles,cancelable:Boolean(a.cancelable),composed:void 0===a.composed||a.composed});l.detail=n,e.dispatchEvent(l)}(window,"location-changed",{replace:n})};const xt={[me.power_tube_temperature]:["mosfet_temperature"],[me.total_battery_capacity_setting]:["full_charge_capacity"],[me.balance_starting_voltage]:["balancing_start_voltage"],[me.balance_trigger_voltage]:["balancing_trigger_voltage"],[me.capacity_remaining]:["remaining_capacity"],[me.total_charging_cycle_capacity]:["total_charging_cycle_capacity","total_battery_cycle_capacity"],[me.balancing_current]:["balance_current"],[me.balancing]:["balancer_status"],[me.balancer_status_bitmask]:["balancer_status_bitmask"]},St=e=>e.includes("."),kt=(e,t)=>St(e)?e:"".concat(t,".").concat(e),At=(e,t,n)=>"".concat(n,".").concat(e?.prefix,"_").concat(t),$t=(e,t)=>{const n=e?.toString()?.match(new RegExp("^".concat(t,"_(\\d+)$")));return n?Number(n[1]):null},Mt=(e,t)=>{const n=e?.[t-1]?.toString()?.trim();return n&&n.length>1?n:null},Vt=(e,t,n)=>{const a=(e?.entities?.[t]??e?.[n])?.toString()?.trim();return a&&a.length>1?a:null},Tt=(e,t,n)=>{const a=((e,t,n)=>{const a=$t(t,"cell_voltage");if(a){const t=Mt(e?.cells,a);if(t)return kt(t,n);const l=Vt(e,"cell_prefix","cellPrefix");if(l)return kt("".concat(l).concat(a),n)}const l=$t(t,"cell_resistance");if(l){const t=Mt(e?.cellResistances??e?.cell_resistances,l);if(t)return kt(t,n);const a=Vt(e,"cell_resistance_prefix","cellResistancePrefix");if(a)return kt("".concat(a).concat(l),n)}return null})(e,t,n);if(a)return[a];const l=e?.entities?.[t]?.toString()?.trim(),s=t?.toString(),i=(xt[t]??[]).map((t=>At(e,t,n))),o=s?At(e,s,n):void 0,r=l&&l.length>1?[St(l)?l:At(e,l,n),...i,o]:[...i,o];return[...new Set(r.filter(Boolean))]},Et=(e,t,n,a="sensor")=>Dt(e,t,n,a)?.entity_id??Tt(t,n,a)[0];function Ot(e,t,n,a){a=a||{},n=null==n?{}:n;const l=new Event(t,{bubbles:void 0===a.bubbles||a.bubbles,cancelable:Boolean(a.cancelable),composed:void 0===a.composed||a.composed});return l.detail=n,e.dispatchEvent(l),l}const zt=(e,t)=>{const n=e?.entities?.[t]?.toString()?.trim();return n&&n.length>1?n:t?.toString()},Bt=(e,t,n,a="sensor",l)=>{if(!e)return;e.stopPropagation();const s=l?Dt(l,t,n,a):null,i=s?.entity_id??Tt(t,n,a)[0];let o=new CustomEvent("hass-more-info",{detail:{entityId:i},composed:!0});e.target.dispatchEvent(o)},Rt=(e,t,n)=>{if("device"!==n?.titleAction)return void Bt(e,n,me.total_runtime_formatted,"sensor",t);e?.stopPropagation();const a=Et(t,n,me.total_runtime_formatted),l=n?.deviceId?.trim()??n?.entities?.device_id?.toString()?.trim()??(a?t?.entities?.[a]?.device_id:void 0);l?Ct(0,"/config/devices/device/".concat(l)):Bt(e,n,me.total_runtime_formatted,"sensor",t)},Dt=(e,t,n,a="sensor")=>{for(const l of Tt(t,n,a)){const t=e?.states[l];if(t)return{...t,entity_id:l}}return null},Nt=(e,t,n,a=2,l="",s="sensor")=>{const i=Dt(e,t,n,s);if(!i)return l;const o=i.state,r=Number(o);return isNaN(r)?o??l:r.toFixed(a)},Ut=(e,t,n,a="sensor")=>{const l=Dt(e,t,n,a);return l?.attributes?.unit_of_measurement??""},Lt=(e,t,n)=>{const a=Dt(e,t,me.balancer_status_bitmask)?.state??"",l=a?.toString()?.trim();if(!l||"unknown"===l||"unavailable"===l)return!1;let s;try{if(/^0b[01]+$/i.test(l))s=BigInt(l);else if(/^[01]+$/.test(l)&&l.length===t?.cellCount)s=BigInt("0b".concat(l));else if(/^0x[0-9a-f]+$/i.test(l))s=BigInt(l);else{if(!/^\d+$/.test(l))return!1;s=BigInt(l)}}catch{return!1}return 0n!==(s&1n<{if(!e)return null;switch(e.trim().toLowerCase()){case"v":return"V";case"mv":return"mV";case"ω":case"ohm":case"ohms":return"Ω";case"mω":case"mohm":case"mohms":return"mΩ";default:return null}},jt={V:{toBase:1},mV:{toBase:.001},"Ω":{toBase:1},"mΩ":{toBase:.001}},Ht=(e,t,n)=>{const a="string"==typeof n?parseFloat(n):n;if(isNaN(a))return"-";const l=Pt(e),s=Pt(t);if(!l||!s)return"".concat(a," ").concat(t??"").trim();const i=a*jt[l].toBase/jt[s].toBase,o=s.startsWith("m")?0:3,r=i.toLocaleString("en-US",{minimumFractionDigits:o,maximumFractionDigits:o});return"".concat(r," ").concat(s)};var It,Ft,Kt,qt,Jt,Wt,Zt,Gt,Yt,Qt,Xt,en,tn,nn,an,ln,sn,on,rn,cn,hn,_n,dn,gn,pn;let mn=class extends oe{constructor(){super(...arguments),this.minCellId="",this.maxCellId="",this.deltaV=0,this.shouldBalance=!1,this.VERSION=wt}_navigate(e,t,n="sensor"){Bt(e,this.config,t,n,this.hass)}_navigateTitle(e){Rt(e,this.hass,this.config)}getState(e,t=2,n="",a="sensor"){return Nt(this.hass,this.config,e,t,n,a)}getUnit(e){return Ut(this.hass,this.config,e)}_renderSwitch(t,n){const a=this.getState(t,0,"","switch"),l="on"===a?"status-on":"status-off";return I(It||(It=e(['\n
',"\n
\n "])),(e=>this._navigate(e,t,"switch")),ft("switches."+n),l,a.toUpperCase())}configOrEnum(e){return zt(this.config,e)}render(){if(ut.hass=this.hass,!this.hass||!this.config)return I(Ft||(Ft=e([""])));const t=this.getState(me.hardware_version),n=this.getState(me.software_version),a=this.getState(me.total_runtime_formatted),l=a&&"unknown"!=a?I(Kt||(Kt=e(["",': ',""])),ft("html_texts.time"),a.toUpperCase()):"",s=this.config.batteryName||"",i=this.config.title&&this.config.title.toLocaleLowerCase()!=ft("config.title").toLocaleLowerCase()?this.config.title:I(qt||(qt=e(["","",": "," Ah
\n HW: "," | SW: "," | ",""])),""===s?"":s+" | ",ft("html_texts.capacity"),this.getState(me.total_battery_capacity_setting),t,n,l);this.deltaV=parseFloat(this.getState(me.delta_cell_voltage,3,"0"));const o=parseFloat(this.getState(me.balancing_current,2,"0")),r=parseFloat(this.getState(me.power,2,"0"));this.shouldBalance=0!=o;const c=r>0?"power-positive":r<0?"power-negative":"power-even",h=o>0?"balance-positive":o<0?"balance-negative":"balance-even",_=this.shouldBalance?"delta-needs-balancing":"delta-ok",d=this.config.socDecimals??0,g=this.config.customDecimals??0,p=this.config.showTitle,m=this.config.showButtons,u=this.config.showMain,v=this.config.showCondensed,f=this.config.showCells,b=this.config.showResistances,y=this.config.showCardVersion,w=v?"stats data-row":"stats data-row split";this.minCellId=this.getState(me.min_voltage_cell,0),this.maxCellId=this.getState(me.max_voltage_cell,0);const C=e=>{if(null==e||""===e)return!1;const t=Number(e);return!isNaN(t)&&isFinite(t)&&t>=0},x=C(this.minCellId)&&C(this.maxCellId),S=(e=>{if(null==e)return!1;const t=Number(e);return!isNaN(t)&&isFinite(t)&&t>0})(this.deltaV);return x&&S||this.calculateDynamicMinMaxCellId(this.config?.cellCount??16),I(Jt||(Jt=e(['\n \n
\n
\n ',"\n ","\n ","\n ","\n
\n "])),"1"==this.config.hasHeater?"4":"3",this._renderSwitch(me.charging,"charge"),this._renderSwitch(me.discharging,"discharge"),this._renderSwitch(me.balancer,"balance"),"1"==this.config.hasHeater?this._renderSwitch(me.heater,"heater"):""):I(Zt||(Zt=e([""]))),this._renderError(),u?I(Gt||(Gt=e(['\n
\n
\n
\n '," ",'\n
\n
','
\n
','
\n
','
\n
',' ',' '," A
\n ",'\n
\n\n
\n
\n ',' A\n
\n
','
\n
','
\n
','
\n
',' ',' ',' ',' \n \n ']))):""):I(en||(en=e([""]))),f?I(tn||(tn=e(['\n
\n ',"\n
\n "])),this.config.cellColumns??2,this._renderCells("bankMode"==this.config.cellLayout,b)):I(nn||(nn=e([""]))),y?I(an||(an=e(['\n
\n \n v.',"\n \n
\n "])),this.VERSION):I(ln||(ln=e([""]))))}updated(){requestAnimationFrame((()=>this._updateFlowLine()))}connectedCallback(){super.connectedCallback(),window.addEventListener("resize",this._updateFlowLine.bind(this))}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("resize",this._updateFlowLine.bind(this))}_renderError(){const t=this.getState(me.errors,0);return t.trim().length<=1||"0"==t?I(sn||(sn=e([""]))):I(on||(on=e(['',""])),t)}_renderTemps(t){const n=[],a=this.config?.tempSensorsCount??0,l=this.config.showCondensed?"data-row":"data-row split";for(let s=t;s<=a;s+=2)n.push(I(rn||(rn=e(['\n
',' \n
\n
\n ','\n ',"","\n ","\n
\n
\n
\n "])),_,t,t,n>4||n>3&&!0===d?"multi-line":"single-line",(e=>this._navigate(e,me["cell_voltage_".concat(t)])),t.toString().padStart(2,"0"),h,l,d?g:"",p)}_updateFlowLine(){const e=parseFloat(this.getState(me.balancing_current,3,"0")),t=this.renderRoot.querySelector(".cell-div-".concat(this.minCellId)),n=this.renderRoot.querySelector(".cell-div-".concat(this.maxCellId)),a=this.renderRoot.querySelector("#flow-path");if(!a||!t||!n)return;if(!this.shouldBalance&&0===e)return a.setAttribute("d",""),void(a.style.display="none");a.style.display="inline";const l=(this.renderRoot instanceof ShadowRoot?this.renderRoot.host:this).getBoundingClientRect(),s=t.getBoundingClientRect(),i=n.getBoundingClientRect(),o=this.config?.cellColumns??2,r=l.width/o,c=Math.floor((i.left+i.width/2-l.left)/r),h=Math.floor((s.left+s.width/2-l.left)/r),_=(e,t)=>({x:"right"===t?e.right-l.left:e.left-l.left,y:e.top+e.height/2-l.top});let d,g;if(Math.abs(i.top-s.top)<10)d=i.leftthis._updateCellFlowLine()}firstUpdated(){this.fetchHistory(),this._historyInterval=window.setInterval((()=>this.fetchHistory()),6e4),window.addEventListener("resize",this._boundUpdateCellFlowLine)}_navigate(e,t,n="sensor"){Bt(e,this.config,t,n,this.hass)}_navigateTitle(e){Rt(e,this.hass,this.config)}updated(e){e.has("hass")&&this._updateRealtimeHistory(),requestAnimationFrame(this._boundUpdateCellFlowLine)}_updateRealtimeHistory(){if(!this.hass||!this.config)return;const e=[me.total_voltage,me.current,me.power_tube_temperature,me.delta_cell_voltage],t=Date.now()-36e5;e.forEach((e=>{const n=this._resolveEntityId(e);if(!n)return;const a=this.hass.states[n];if(!a)return;const l=parseFloat(a.state),s=new Date(a.last_updated).getTime();if(isNaN(l))return;const i=this.historyData[n]||[],o=i.length>0?i[i.length-1]:null;if(!o||s>o.time){const e=[...i,{state:l,time:s}];for(;e.length>0&&e[0].timee)),t=[...new Set(e)];if(0===t.length)return;const n=new Date,a=new Date(n.getTime()-36e5);try{const e=await this.hass.callWS({type:"history/history_during_period",start_time:a.toISOString(),end_time:n.toISOString(),entity_ids:t,minimal_response:!0,no_attributes:!0});if(e){const t={};Object.keys(e).forEach((n=>{const a=e[n];Array.isArray(a)&&(t[n]=a.map((e=>({state:parseFloat(e.s||e.state),time:1e3*(e.lu||new Date(e.last_updated).getTime()/1e3)}))).filter((e=>!isNaN(e.state))))})),this.historyData={...this.historyData,...t}}}catch(e){console.warn("JK BMS Card: Failed to fetch history via WS",e)}}configOrEnum(e){return zt(this.config,e)}_resolveEntityId(e){return Et(this.hass,this.config,e)}_renderSparkline(t,n){const a=this._resolveEntityId(t);if(!a||!this.historyData[a]||this.historyData[a].length<2)return I(un||(un=e([""])));const l=this.historyData[a];let s=1/0,i=-1/0;l.forEach((e=>{const t=Number(Number(e.state).toFixed(3));ti&&(i=t)}));let o=i-s;if(o<1){const e=(s+i)/2;s=e-.5,i=e+.5}else s-=.05*o,i+=.05*o;const r=l[0].time,c=l[l.length-1].time-r;if(c<=0)return I(vn||(vn=e([""])));let h="";return l.forEach(((e,t)=>{const n=(e.time-r)/c*100,a=100-(e.state-s)/(i-s)*100;h+="".concat(0===t?"M":"L"," ").concat(n.toFixed(1),",").concat(a.toFixed(1)," ")})),I(fn||(fn=e(['\n
\n \n \n \n \n
\n '])),h,n,h,n)}getState(e,t=2,n="",a="sensor"){return Nt(this.hass,this.config,e,t,n,a)}getUnit(e){return Ut(this.hass,this.config,e)}render(){if(ut.hass=this.hass,!this.hass||!this.config)return I(bn||(bn=e([""])));const t=this.config.socDecimals??0,n=this.getState(me.state_of_charge,t),a=this.config.customDecimals??0,l=this.getState(me.hardware_version),s=this.getState(me.software_version),i=this.getState(me.total_battery_capacity_setting,a),o=this.getState(me.total_runtime_formatted),r=o&&"unknown"!=o?I(yn||(yn=e([" | ",": ",""])),ft("html_texts.time"),o.toUpperCase()):"",c=this.config.batteryName||"",h=this.config.title&&this.config.title.toLocaleLowerCase()!=ft("config.title").toLocaleLowerCase()?this.config.title:I(wn||(wn=e(["","",": "," Ah
\n HW: "," | SW: ","",""])),""===c?"":c+" | ",ft("html_texts.capacity"),i,l,s,r),_=parseFloat(this.getState(me.current)),d=this.getState(me.charging_power,a),g=this.getState(me.discharging_power,a),p=_>0,m=_<0,u="on"===this.getState(me.charging,0,"","switch"),v="on"===this.getState(me.discharging,0,"","switch"),f="on"===this.getState(me.balancer,0,"","switch"),b="on"===this.getState(me.heater,0,"","switch"),y="on"===this.getState(me.balancing,0,"","binary_sensor"),w=parseFloat(this.getState(me.balancing_current)),C=!isNaN(w)&&0!==w;this.shouldBalance=C;const x=this.getState(me.total_voltage),S=this.getState(me.power_tube_temperature),k=this.getUnit(me.power_tube_temperature),A=this.getState(me.total_charging_cycle_capacity,a),$=parseFloat(this.getState(me.charging_cycles)).toFixed(0).toString();this.tempSensorsCount=this.config.tempSensorsCount;const M=this.config.showTitle,V=this.config.showButtons,T=this.config.showMain,E=this.config.showCells,O=this.config.showResistances,z=this.config.showCardVersion;this.minCellId=this.getState(me.min_voltage_cell,0),this.maxCellId=this.getState(me.max_voltage_cell,0),this.deltaV=parseFloat(this.getState(me.delta_cell_voltage,3,"0"));const B=e=>{if(null==e||""===e)return!1;const t=Number(e);return!isNaN(t)&&isFinite(t)&&t>=0},R=B(this.minCellId)&&B(this.maxCellId),D=(e=>{if(null==e)return!1;const t=Number(e);return!isNaN(t)&&isFinite(t)&&t>0})(this.deltaV);R&&D||this.calculateDynamicMinMax();const N=this.config.showMainStats;return I(Cn||(Cn=e(['\n \n ',"\n \n ","\n \n \x3c!-- Cells --\x3e\n ","\n ","\n \n "])),M?I(xn||(xn=e(['\n
\n \x3c!-- Solar/Grid Node --\x3e\n
\n
\n \n
\n
',"
\n ",'\n
\n
\n
\n
\n\n \x3c!-- Reactor (SOC) --\x3e\n
\n
\n
SoC:
\n
',"%
\n ","\n
\n ",'\n
\n\n \x3c!-- Load Node --\x3e\n
\n
\n \n
\n
',"
\n ",'\n \n
\n
\n
\n
\n\n \x3c!-- SVG Flow Lines --\x3e\n \n \x3c!-- Left path (Charge) - Rough coordinates for now, will refine --\x3e\n \n \x3c!-- Right path (Discharge) --\x3e\n \n\n \n \n \n \n \n \n
\n \n \x3c!-- Stats Panels --\x3e\n ',"\n \n "])),V?" clickable":"",V?e=>this._navigate(e,me.charging,"switch"):void 0,p?"var(--solar-color)":"#444",ft("html_texts.grid-solar"),V?I(kn||(kn=e(['\n
\n ',': ',"\n
\n "])),ft("html_texts.charge"),u?"status-on":"status-off",u?"ON":"OFF"):I(An||(An=e([""]))),(e=>this._navigate(e,me.charging_power)),d,y&&C?"reactor-ring-balancing":"reactor-ring-base",(e=>this._navigate(e,me.state_of_charge)),n,y&&C?I($n||($n=e(['
\n
\n \n ',": ","\n
\n ","\n
\n "])),f?"reactor-control-on":"",(e=>this._navigate(e,me.balancer,"switch")),ft("switches.balance"),f?"ON":"OFF","1"==this.config.hasHeater?I(Tn||(Tn=e(['\n
\n \n ',": ","\n
\n "])),b?"reactor-control-on":"",(e=>this._navigate(e,me.heater,"switch")),ft("switches.heater"),b?"ON":"OFF"):I(En||(En=e([""])))):I(On||(On=e([""]))),V?" clickable":"",V?e=>this._navigate(e,me.discharging,"switch"):void 0,m?"var(--discharge-color)":"#444",ft("html_texts.load"),V?I(zn||(zn=e(['\n
\n ',': ',"\n
\n "])),ft("html_texts.discharge"),v?"status-on":"status-off",v?"ON":"OFF"):I(Bn||(Bn=e([""]))),(e=>this._navigate(e,me.discharging_power)),g,p?"path-charge":"path-inactive",m?"path-discharge":"path-inactive",v?"#3090c7":"#444",N?I(Rn||(Rn=e(['\n
\n
\n
\n ','\n
',':
\n
\n
\n\n
\n ','\n
',':
\n
\n
\n
\n\n
\n
\n ','\n
',':
\n
\n
\n\n
\n ','\n
'," ",':
\n
\n
\n
','
\n
\n
\n \n
\n
\n
\n
\n
\n \n \x3c!-- Add number of cycles --\x3e\n
\n
\n
','
\n
\n
\n \n
\n
\n ',"\n
\n ",""])),this.config.cellColumns??2,this._renderCells(O),this.shouldBalance?I(Ln||(Ln=e(['\n \n \n \n ']))):I(Pn||(Pn=e([""])))):I(jn||(jn=e([""]))),z?I(Hn||(Hn=e(['\n
\n \n v.',"\n \n
\n "])),this.VERSION):I(In||(In=e([""]))))}calculateDynamicMinMax(){let e=1/0,t=-1/0,n=-1,a=-1;const l=this.config.cellCount||16;for(let s=1;s<=l;s++){const l=this.getState(me["cell_voltage_".concat(s)],3,""),i=parseFloat(l);isNaN(i)||(it&&(t=i,a=s))}e===1/0||t===-1/0?(this.deltaV=0,this.minCellId="",this.maxCellId=""):(this.minCellId=n.toString(),this.maxCellId=a.toString(),this.deltaV=parseFloat((t-e).toFixed(3)))}getTemperatureColor(e,t="°C"){("°F"===t||"F"===t)&&(e=5*(e-32)/9);const n=[{temp:-10,color:"#0000FF"},{temp:0,color:"#00BFFF"},{temp:20,color:"#41CD52"},{temp:30,color:"#FFD700"},{temp:40,color:"#FF8C00"},{temp:50,color:"#FF4500"},{temp:60,color:"#DC143C"}];for(let t=0;t=l.temp)continue;const s=(e-a.temp)/(l.temp-a.temp),i=parseInt(a.color.slice(1,3),16),o=parseInt(a.color.slice(3,5),16),r=parseInt(a.color.slice(5,7),16),c=parseInt(l.color.slice(1,3),16),h=parseInt(l.color.slice(3,5),16),_=parseInt(l.color.slice(5,7),16),d=Math.round(i+s*(c-i)),g=Math.round(o+s*(h-o)),p=Math.round(r+s*(_-r));return"#".concat(d.toString(16).padStart(2,"0")).concat(g.toString(16).padStart(2,"0")).concat(p.toString(16).padStart(2,"0"))}return n[n.length-1].color}renderTemperatureSensors(){if(!this.tempSensorsCount||0===this.tempSensorsCount)return I(Fn||(Fn=e([""])));const t=this.tempSensorsCount>=1,n=this.tempSensorsCount>=2,a=this.tempSensorsCount>=3,l=this.tempSensorsCount>=4,s=(t,n)=>{const a=this.getState(t,1,"—"),l=this.getUnit(t)||"°C",s=parseFloat(a),i=isNaN(s)?"#777777":this.getTemperatureColor(s,l);return I(Kn||(Kn=e(['\n
\n ','\n
\n '," ",'\n
\n
\n ',"\n ",'\n
\n\n \x3c!-- Right column (2 and 4) --\x3e\n
\n ',"\n ","\n
\n "])),t?s(me.temperature_sensor_1,1):"",a?s(me.temperature_sensor_3,3):"",n?s(me.temperature_sensor_2,2):"",l?s(me.temperature_sensor_4,4):"")}_renderCells(e){const t=[],n="bankMode"===this.config.cellLayout,a=this.config.cellColumns||2,l=this.config.cellCount||16,s=Math.floor(l/a),i=n?Math.ceil(l/a):l,o=l%a;for(let r=1;r<=i;r++){const c=[];if(n)if(o&&r===i)c.push(l);else for(let e=0;e100&&(p=100));const m=parseFloat(o),u=!isNaN(m)&&m>0&&a,v=Ht(s,i,m).replace(" ",""),f=this.config.cellColorMode||"progress";let b="";if("gradient"===f){const e=[{r:180,g:60,b:60},{r:180,g:180,b:50},{r:60,g:180,b:60},{r:60,g:120,b:200},{r:90,g:60,b:200}];let t=Math.floor(p/25);t>=4&&(t=3);const n=p%25/25,a=e[t],l=e[t+1],s=Math.round(a.r+(l.r-a.r)*n),i=Math.round(a.g+(l.g-a.g)*n),o=Math.round(a.b+(l.b-a.b)*n);b="background: rgba(".concat(s,", ").concat(i,", ").concat(o,", 0.85);")}const y="gradient"===f?"background: rgba(0, 0, 0, 0.25); padding: 1px 3px; border-radius: 3px;":"",w=this.config.cellColumns>4||!0===this.config.showResistances&&this.config.cellColumns>3?"vertical":this.config.cellOrientation||"horizontal",C=Lt(this.hass,this.config,n)?"cell-balancing":"",x="vertical"===w?"cell-item cell-item-vertical ".concat(C):"cell-item ".concat(C),S=ft("html_texts.volt");t.push(I(Jn||(Jn=e(['\n
\n ',"\n ","\n
\n "])),x,n,b,"progress"===f?I(Wn||(Wn=e(['\n
'])),p):"","vertical"===w?I(Zn||(Zn=e(['\n ','\n \n ','\n ',"","\n \n ","\n "])),(e=>this._navigate(e,me["cell_voltage_".concat(n)])),String(n).padStart(2,"0"),h,y,l,u?S:"",u?I(Qn||(Qn=e(['\n .icon-circle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: clamp(20px, round(4cqi + 4px, 2px), 30px);\n height: clamp(20px, round(4cqi + 4px, 2px), 30px);\n justify-self: start;\n }\n\n .icon-stats > :nth-child(2) {\n justify-self: end;\n padding-right: 5px;\n }\n\n .icon-stats > .stat-value {\n white-space: nowrap;\n font-size: clamp(0.8em, round(8cqi + 0.25rem, 0.1em), 1.2em);\n font-weight: bold;\n }\n\n /* Cell Grid */\n\n .cell-grid {\n display: grid;\n gap: 6px;\n }\n\n .grid-1 {\n grid-template-columns: 1fr;\n }\n\n .grid-2 {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .grid-3 {\n grid-template-columns: repeat(3, 1fr);\n }\n\n .grid-4 {\n grid-template-columns: repeat(4, 1fr);\n }\n\n .grid-5 {\n grid-template-columns: repeat(5, 1fr);\n }\n\n .grid-6 {\n grid-template-columns: repeat(6, 1fr);\n }\n\n .grid-7 {\n grid-template-columns: repeat(7, 1fr);\n }\n\n .grid-8 {\n grid-template-columns: repeat(8, 1fr);\n }\n\n .cell-item {\n container-type: inline-size;\n background: var(--secondary-background-color, #2a2a2a);\n border-radius: 8px;\n padding: 3px 2px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 4px;\n position: relative;\n z-index: 0;\n overflow: hidden;\n white-space: nowrap;\n }\n\n .cell-item-vertical {\n container-type: inline-size;\n flex-direction: column;\n justify-content: center;\n padding: 2px 3px;\n gap: 3px;\n white-space: nowrap;\n }\n\n .cell-item-vertical .cell-id {\n padding-top: 2px;\n }\n\n .cell-item-bg {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: rgba(48, 144, 199, 0.2);\n z-index: -1;\n transition: width 0.5s ease-out;\n }\n\n .cell-id {\n display: inline-block;\n padding: 0.2rem 0.5rem;\n background-color: #195569;\n color: #e4f3f8;\n border-radius: 999px;\n font-weight: 600;\n font-size: clamp(0.8rem, round(14cqi, 0.05rem), 1rem) !important;\n min-width: 1.2rem;\n text-align: center;\n margin-right: 3px;\n flex-shrink: 0;\n }\n\n .cell-volts {\n color: var(--primary-text-color);\n font-family: monospace;\n font-size: clamp(0.9rem, round(14cqi, 0.05rem), 1.2rem) !important;\n white-space: nowrap;\n }\n\n .cell-res {\n color: var(--secondary-text-color);\n font-family: monospace;\n font-size: clamp(0.6rem, round(12cqi, 0.05rem), 0.8rem) !important;\n white-space: nowrap;\n }\n\n .cell-low {\n color: #FFA500;\n }\n\n /* Example warning color */\n\n .cell-high {\n color: var(--discharge-color);\n }\n\n .cell-balancing {\n border: 1px solid var(--accent-color);\n }\n\n .cell-balancing .cell-id,\n .cell-balancing .cell-volts,\n .cell-balancing .cell-res {\n color: var(--accent-color);\n font-weight: bold;\n }\n\n .status-on {\n color: var(--accent-color);\n font-weight: bold;\n }\n\n .status-off {\n color: var(--disabled-text-color, #666);\n font-weight: bold;\n }\n\n .clickable {\n cursor: pointer;\n }\n\n /* SVG Overlay for Lines */\n\n .flow-svg {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 1;\n }\n\n .flow-svg path {\n fill: none;\n stroke-width: 2;\n stroke-dasharray: 8;\n }\n\n .cell-flow-line {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 2;\n }\n\n .cell-flow-line path {\n stroke: var(--accent-color);\n stroke-width: 3;\n stroke-linecap: round;\n fill: none;\n stroke-dasharray: 10;\n animation: flow 1.2s linear infinite;\n filter: drop-shadow(0 0 4px var(--accent-color));\n }\n\n .path-charge {\n stroke: var(--solar-color);\n animation: flow 1s linear infinite;\n }\n\n .path-discharge {\n stroke: var(--discharge-color);\n animation: flow 1s linear infinite;\n }\n\n .path-inactive {\n stroke: #444;\n stroke-dasharray: 0;\n animation: none;\n }\n\n @keyframes flow {\n from {\n stroke-dashoffset: 16;\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n\n /* Sparkline CSS */\n /* Sparkline CSS */\n\n .metric-group {\n position: relative;\n width: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n z-index: 1;\n }\n\n .sparkline-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n overflow: hidden;\n opacity: 0.3;\n z-index: -1;\n pointer-events: none;\n }\n\n .sparkline-svg {\n width: 100%;\n height: 100%;\n }\n\n .spark-line {\n fill: none;\n stroke-width: 2;\n vector-effect: non-scaling-stroke;\n }\n\n .spark-area {\n fill-opacity: 0.2;\n stroke: none;\n }\n \n .cardVersion {\n text-align: right;\n margin-right: 5px;\n }\n \n .version {\n font-style: italic;\n font-size: 0.8rem;\n }\n "]))),t([de()],ea.prototype,"hass",void 0),t([de()],ea.prototype,"config",void 0),t([de()],ea.prototype,"historyData",void 0),ea=t([ce("jk-bms-core-reactor-layout")],ea);const sa=wt;console.groupCollapsed("%c🔋 JK-BMS Battery Card%c ready! 🚀 (v".concat(sa,")"),"background: linear-gradient(to right, #41cd52, #3090c7); color: white; font-weight: bold; padding: 2px 8px; border-radius: 6px;","background: none; color: #AAA; font-style: italic;"),console.log("%c📖 Docs:","color: #41cd52; font-weight: bold;","https://github.com/Pho3niX90/jk-bms-card"),console.groupEnd();let ia=la=class extends oe{setConfig(e){this._config=la.getStubConfig(),this._config={...this._config,...e},ut.cardConfig=this._config}static getStubConfig(){return{language:"auto",title:ft("title"),prefix:"jk_bms",batteryName:"",cellCount:16,cellColumns:2,cellLayout:"bankMode",deltaVoltageUnit:"V",resistanceUnit:"Ω",tempSensorsCount:0,hasHeater:0,socDecimals:2,customDecimals:2,titleAction:"more-info",showTitle:!0,showButtons:!0,showMain:!0,showCondensed:!0,showMainStats:!0,showCells:!0,showResistances:!0,showCardVersion:!1,entities:Object.keys(me).reduce(((e,t)=>(e[t]="",e)),{})}}static async getConfigElement(){return await Promise.resolve().then((function(){return ga})),document.createElement(ge)}getCardSize(){return 3}render(){return ut.hass=this.hass,this.hass&&this._config?"core-reactor"===this._config.layout?I(na||(na=e([""])),this.hass,this._config):I(aa||(aa=e(["\n \n "])),this.hass,this._config):I(ta||(ta=e([""])))}};var oa,ra,ca,ha,_a;t([de()],ia.prototype,"hass",void 0),t([de()],ia.prototype,"_config",void 0),ia=la=t([ce(pe)],ia),window.customCards.push({type:pe,name:"JK BMS Card",preview:!0,description:ft("common.description"),configurable:!0});let da=class extends oe{constructor(){super(...arguments),this._dynamicEntitySchema=[],this._fixedEntities=Object.values(me).filter((e=>!e.startsWith("cell_voltage_")&&!e.startsWith("cell_resistance_"))),this._computeLabelCallback=e=>ft("config.".concat(e.name))??e.name}static get styles(){return o(oa||(oa=e(["\n .boolean-wrapper {\n display: block;\n padding: 12px 0;\n }\n .boolean-row {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin-bottom: 16px;\n gap: 6px;\n }\n .label {\n font-size: 14px;\n color: var(--primary-text-color);\n line-height: 1.3;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n text-overflow: ellipsis;\n max-height: 2.6em;\n word-break: break-word;\n }\n "])))}setConfig(e){this._config={...e},this._updateDynamicEntitySchema()}_updateDynamicEntitySchema(){const e=Math.min(this._config?.cellCount??16,96),t=[];for(let n=1;n<=e;n++){const e="cell_voltage_".concat(n);e in me&&t.push({name:e,selector:{entity:{}}})}for(let n=1;n<=e;n++){const e="cell_resistance_".concat(n);e in me&&t.push({name:e,selector:{entity:{}}})}this._dynamicEntitySchema=t}willUpdate(e){if(super.willUpdate(e),e.has("_config")){const t=e.get("_config");t?.cellCount!==this._config?.cellCount&&this._updateDynamicEntitySchema()}}renderBoolean(t,n){return I(ra||(ra=e(['\n
\n ',"\n \n
\n "])),t,Boolean(this._config?.[n]??!1),(e=>this._handleSwitchChange(n,e)))}_handleSwitchChange(e,t){const n=!!t.target.checked,a={...this._config};a[e]=n;const l=!0===a.showMain&&"core-reactor"===a.layout;l||void 0===a.showMainStats||delete a.showMainStats,l&&void 0===a.showMainStats&&(a.showMainStats=!0),this._config=a,Ot(this,"config-changed",{config:this._config})}render(){if(!this._config||!this.hass)return I(ca||(ca=e([""])));const t=[{name:"cell_prefix",selector:{text:{}}},{name:"cell_resistance_prefix",selector:{text:{}}},...this._fixedEntities.map((e=>({name:e,selector:{entity:{}}}))),...this._dynamicEntitySchema];return I(ha||(ha=e(["\n\t\t\t\n\n ","\n\t\t"])),this.hass,this._config,this._computeLabelCallback.bind(this),[{type:"grid",title:ft("config.language"),schema:[{type:"grid",schema:[{name:"language",selector:{select:{options:[{label:"Auto (follow HA)",value:"auto"},{label:"English",value:"en"},{label:"Română",value:"ro"},{label:"Українська",value:"uk"},{label:"German",value:"de"},{label:"Русский",value:"ru"},{label:"Polski",value:"pl"},{label:"Français",value:"fr"},{label:"Español",value:"es"},{label:"中文",value:"zh"}],mode:"dropdown"}}}]}]},{type:"grid",title:ft("config.title"),schema:[{type:"grid",schema:[{name:"title",selector:{text:{}}},{name:"titleAction",selector:{select:{options:[{label:"Device page",value:"device"},{label:"Runtime history",value:"more-info"}]}}}]}]},{type:"grid",title:ft("config.prefix"),schema:[{type:"grid",column_min_width:"200px",schema:[{name:"prefix",selector:{text:{}}},{name:"batteryName",selector:{text:{}}},{name:"deviceId",selector:{text:{}}}]}]},{type:"grid",title:ft("config.layout"),schema:[{type:"grid",schema:[{name:"layout",selector:{select:{options:[{label:"Default",value:"default"},{label:"Core Reactor",value:"core-reactor"}]}}},{name:"deltaVoltageUnit",selector:{select:{options:[{label:"Volts (V)",value:"V"},{label:"Millivolts (mV)",value:"mV"}]}}},{name:"resistanceUnit",selector:{select:{options:[{label:"Ohms (Ω)",value:"Ω"},{label:"MilliOhms (mΩ)",value:"mΩ"}]}}}]},{type:"grid",column_min_width:"200px",schema:[{name:"cellColorMode",selector:{select:{options:[{label:"Progress Bar",value:"progress"},{label:"Voltage Gradient",value:"gradient"}]}}},{name:"cellOrientation",selector:{select:{options:[{label:"Vertical",value:"vertical"},{label:"Horizontal",value:"horizontal"}]}}}]}]},{type:"grid",schema:[{type:"grid",column_min_width:"200px",schema:[{name:"minCellVoltage",selector:{number:{min:2,max:4,step:.01,mode:"box"}}},{name:"maxCellVoltage",selector:{number:{min:2,max:4,step:.01,mode:"box"}}}]}]},{type:"grid",title:ft("config.cellCount"),schema:[{type:"grid",schema:[{name:"cellCount",selector:{number:{min:2,max:48,step:2}}},{name:"cellColumns",selector:{number:{min:1,max:8,step:1}}}]}]},{type:"grid",schema:[{name:"cellLayout",selector:{select:{options:[{label:"Incremental",value:"incremental"},{label:"Bank Mode",value:"bankMode"}]}}},{name:"socDecimals",title:ft("config.socDecimals"),selector:{number:{min:0,max:2,step:1}}}]},{type:"grid",title:ft("config.tempSensorsCount"),schema:[{type:"grid",schema:[{name:"tempSensorsCount",selector:{number:{min:0,max:4,step:2}}},{name:"customDecimals",title:ft("config.customDecimals"),selector:{number:{min:0,max:2,step:1}}}]}]},{type:"grid",title:ft("config.hasHeater"),schema:[{type:"grid",schema:[{name:"hasHeater",selector:{select:{multiple:!1,mode:"list",options:[{label:"Yes",value:"1"},{label:"No",value:"0"}]}}}]}]},{type:"expandable",title:ft("config.manualAssignment"),schema:[{name:"entities",type:"grid",schema:t}]}],this._valueChanged.bind(this),I(_a||(_a=e(['\n \n
\n ','\n
\n
\n ',"\n ","\n ","\n ","\n ","\n\n ","\n ","\n ","\n
\n
\n "])),ft("config.titleShowHide"),this.renderBoolean(ft("config.showTitle"),"showTitle"),!0===this._config?.showMain&&"core-reactor"===this._config?.layout||"default"===this._config?.layout?this.renderBoolean(ft("config.showButtons"),"showButtons"):"",this.renderBoolean(ft("config.showMain"),"showMain"),!0===this._config?.showMain&&"default"===this._config?.layout?this.renderBoolean(ft("config.showCondensed"),"showCondensed"):"",!0===this._config?.showMain&&"core-reactor"===this._config?.layout?this.renderBoolean(ft("config.showMainStats"),"showMainStats"):"",this.renderBoolean(ft("config.showCells"),"showCells"),!0===this._config?.showCells?this.renderBoolean(ft("config.showResistances"),"showResistances"):"",this.renderBoolean(ft("config.showCardVersion"),"showCardVersion")))}_valueChanged(e){const t={...this._config};Object.assign(t,e.detail.value),this._config=t,"cellCount"in e.detail.value&&this._updateDynamicEntitySchema();const n=!0===t?.showMain&&"core-reactor"===t?.layout,a=!0===t?.showCells;n||void 0===t.showMainStats||delete t.showMainStats,n&&void 0===t.showMainStats&&(t.showMainStats=!0),a||void 0===t.showResistances||delete t.showResistances,a&&void 0===t.showResistances&&(t.showResistances=!0),Ot(this,"config-changed",{config:this._config})}};t([de()],da.prototype,"hass",void 0),t([de()],da.prototype,"_config",void 0),t([de()],da.prototype,"lovelace",void 0),t([function(e){return de({...e,state:!0,attribute:!1})}()],da.prototype,"_dynamicEntitySchema",void 0),da=t([ce(ge)],da);var ga=Object.freeze({__proto__:null,get JkBmsCardEditor(){return da}});export{sa as CARD_VERSION,ia as JkBmsCard}; diff --git a/hass/settings/www/community/jk-bms-card/jk-bms-card.js.gz b/hass/settings/www/community/jk-bms-card/jk-bms-card.js.gz index 2708cf4..23fd089 100644 Binary files a/hass/settings/www/community/jk-bms-card/jk-bms-card.js.gz and b/hass/settings/www/community/jk-bms-card/jk-bms-card.js.gz differ diff --git a/hass/settings/www/community/lovelace-multiple-entity-row/multiple-entity-row.js b/hass/settings/www/community/lovelace-multiple-entity-row/multiple-entity-row.js index 9550673..6a5e343 100644 --- a/hass/settings/www/community/lovelace-multiple-entity-row/multiple-entity-row.js +++ b/hass/settings/www/community/lovelace-multiple-entity-row/multiple-entity-row.js @@ -1 +1,2 @@ -(()=>{"use strict";const t=window,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,n=Symbol(),i=new WeakMap;class r{constructor(t,e,i){if(this._$cssResult$=!0,i!==n)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const n=this.t;if(e&&void 0===t){const e=void 0!==n&&1===n.length;e&&(t=i.get(n)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&i.set(n,t))}return t}toString(){return this.cssText}}const o=(t,...e)=>{const i=1===t.length?t[0]:e.reduce(((e,n,i)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(n)+t[i+1]),t[0]);return new r(i,t,n)},s=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const n of t.cssRules)e+=n.cssText;return(t=>new r("string"==typeof t?t:t+"",void 0,n))(e)})(t):t;var a;const c=window,l=c.trustedTypes,u=l?l.emptyScript:"",h=c.reactiveElementPolyfillSupport,f={toAttribute(t,e){switch(e){case Boolean:t=t?u:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let n=t;switch(e){case Boolean:n=null!==t;break;case Number:n=null===t?null:Number(t);break;case Object:case Array:try{n=JSON.parse(t)}catch(t){n=null}}return n}},d=(t,e)=>e!==t&&(e==e||t==t),p={attribute:!0,type:String,converter:f,reflect:!1,hasChanged:d};class m extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this.u()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,n)=>{const i=this._$Ep(n,e);void 0!==i&&(this._$Ev.set(i,n),t.push(i))})),t}static createProperty(t,e=p){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const n="symbol"==typeof t?Symbol():"__"+t,i=this.getPropertyDescriptor(t,n,e);void 0!==i&&Object.defineProperty(this.prototype,t,i)}}static getPropertyDescriptor(t,e,n){return{get(){return this[e]},set(i){const r=this[t];this[e]=i,this.requestUpdate(t,r,n)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||p}static finalize(){if(this.hasOwnProperty("finalized"))return!1;this.finalized=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const n of e)this.createProperty(n,t[n])}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const n=new Set(t.flat(1/0).reverse());for(const t of n)e.unshift(s(t))}else void 0!==t&&e.push(s(t));return e}static _$Ep(t,e){const n=e.attribute;return!1===n?void 0:"string"==typeof n?n:"string"==typeof t?t.toLowerCase():void 0}u(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,n;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(n=t.hostConnected)||void 0===n||n.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])}))}createRenderRoot(){var n;const i=null!==(n=this.shadowRoot)&&void 0!==n?n:this.attachShadow(this.constructor.shadowRootOptions);return((n,i)=>{e?n.adoptedStyleSheets=i.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):i.forEach((e=>{const i=document.createElement("style"),r=t.litNonce;void 0!==r&&i.setAttribute("nonce",r),i.textContent=e.cssText,n.appendChild(i)}))})(i,this.constructor.elementStyles),i}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,n){this._$AK(t,n)}_$EO(t,e,n=p){var i;const r=this.constructor._$Ep(t,n);if(void 0!==r&&!0===n.reflect){const o=(void 0!==(null===(i=n.converter)||void 0===i?void 0:i.toAttribute)?n.converter:f).toAttribute(e,n.type);this._$El=t,null==o?this.removeAttribute(r):this.setAttribute(r,o),this._$El=null}}_$AK(t,e){var n;const i=this.constructor,r=i._$Ev.get(t);if(void 0!==r&&this._$El!==r){const t=i.getPropertyOptions(r),o="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(n=t.converter)||void 0===n?void 0:n.fromAttribute)?t.converter:f;this._$El=r,this[r]=o.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,n){let i=!0;void 0!==t&&(((n=n||this.constructor.getPropertyOptions(t)).hasChanged||d)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===n.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,n))):i=!1),!this.isUpdatePending&&i&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,e)=>this[e]=t)),this._$Ei=void 0);let e=!1;const n=this._$AL;try{e=this.shouldUpdate(n),e?(this.willUpdate(n),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(n)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(n)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,e)=>this._$EO(e,this[e],t))),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}var y;m.finalized=!0,m.elementProperties=new Map,m.elementStyles=[],m.shadowRootOptions={mode:"open"},null==h||h({ReactiveElement:m}),(null!==(a=c.reactiveElementVersions)&&void 0!==a?a:c.reactiveElementVersions=[]).push("1.6.1");const v=window,b=v.trustedTypes,_=b?b.createPolicy("lit-html",{createHTML:t=>t}):void 0,g="$lit$",$=`lit$${(Math.random()+"").slice(9)}$`,w="?"+$,A=`<${w}>`,S=document,O=()=>S.createComment(""),E=t=>null===t||"object"!=typeof t&&"function"!=typeof t,j=Array.isArray,P="[ \t\n\f\r]",k=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,x=/-->/g,C=/>/g,N=RegExp(`>|${P}(?:([^\\s"'>=/]+)(${P}*=${P}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),D=/'/g,T=/"/g,U=/^(?:script|style|textarea|title)$/i,R=t=>(e,...n)=>({_$litType$:t,strings:e,values:n}),H=R(1),M=(R(2),Symbol.for("lit-noChange")),I=Symbol.for("lit-nothing"),z=new WeakMap,L=S.createTreeWalker(S,129,null,!1),F=(t,e)=>{const n=t.length-1,i=[];let r,o=2===e?"":"",s=k;for(let e=0;e"===c[0]?(s=null!=r?r:k,l=-1):void 0===c[1]?l=-2:(l=s.lastIndex-c[2].length,a=c[1],s=void 0===c[3]?N:'"'===c[3]?T:D):s===T||s===D?s=N:s===x||s===C?s=k:(s=N,r=void 0);const h=s===N&&t[e+1].startsWith("/>")?" ":"";o+=s===k?n+A:l>=0?(i.push(a),n.slice(0,l)+g+n.slice(l)+$+h):n+$+(-2===l?(i.push(void 0),e):h)}const a=o+(t[n]||"")+(2===e?"":"");if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return[void 0!==_?_.createHTML(a):a,i]};class B{constructor({strings:t,_$litType$:e},n){let i;this.parts=[];let r=0,o=0;const s=t.length-1,a=this.parts,[c,l]=F(t,e);if(this.el=B.createElement(c,n),L.currentNode=this.el.content,2===e){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(i=L.nextNode())&&a.length0){i.textContent=b?b.emptyScript:"";for(let n=0;nj(t)||"function"==typeof(null==t?void 0:t[Symbol.iterator]))(t)?this.T(t):this._(t)}k(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}$(t){this._$AH!==t&&(this._$AR(),this._$AH=this.k(t))}_(t){this._$AH!==I&&E(this._$AH)?this._$AA.nextSibling.data=t:this.$(S.createTextNode(t)),this._$AH=t}g(t){var e;const{values:n,_$litType$:i}=t,r="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=B.createElement(i.h,this.options)),i);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===r)this._$AH.v(n);else{const t=new W(r,this),e=t.u(this.options);t.v(n),this.$(e),this._$AH=t}}_$AC(t){let e=z.get(t.strings);return void 0===e&&z.set(t.strings,e=new B(t)),e}T(t){j(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let n,i=0;for(const r of t)i===e.length?e.push(n=new J(this.k(O()),this.k(O()),this,this.options)):n=e[i],n._$AI(r),i++;i2||""!==n[0]||""!==n[1]?(this._$AH=Array(n.length-1).fill(new String),this.strings=n):this._$AH=I}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,n,i){const r=this.strings;let o=!1;if(void 0===r)t=V(this,t,e,0),o=!E(t)||t!==this._$AH&&t!==M,o&&(this._$AH=t);else{const i=t;let s,a;for(t=r[0],s=0;s{var i,r;const o=null!==(i=null==n?void 0:n.renderBefore)&&void 0!==i?i:e;let s=o._$litPart$;if(void 0===s){const t=null!==(r=null==n?void 0:n.renderBefore)&&void 0!==r?r:null;o._$litPart$=s=new J(e.insertBefore(O(),t),t,void 0,null!=n?n:{})}return s._$AI(t),s})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return M}}nt.finalized=!0,nt._$litElement$=!0,null===(tt=globalThis.litElementHydrateSupport)||void 0===tt||tt.call(globalThis,{LitElement:nt});const it=globalThis.litElementPolyfillSupport;null==it||it({LitElement:nt}),(null!==(et=globalThis.litElementVersions)&&void 0!==et?et:globalThis.litElementVersions=[]).push("3.3.2");var rt="\\d\\d?",ot="\\d\\d",st="[^\\s]+";function at(t,e){for(var n=[],i=0,r=t.length;i-1?r:null}};function lt(t){for(var e=[],n=1;n3?0:(t-t%10!=10?1:0)*t%10]}},pt=(lt({},dt),function(t){return+t-1}),mt=[null,rt],yt=[null,st],vt=["isPm",st,function(t,e){var n=t.toLowerCase();return n===e.amPm[0]?0:n===e.amPm[1]?1:null}],bt=["timezoneOffset","[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z?",function(t){var e=(t+"").match(/([+-]|\d\d)/gi);if(e){var n=60*+e[1]+parseInt(e[2],10);return"+"===e[0]?n:-n}return 0}];ct("monthNamesShort"),ct("monthNames");function _t(){return(_t=Object.assign||function(t){for(var e=1;e0?"".concat(e,":").concat(Dt(n),":").concat(Dt(i)):n>0?"".concat(n,":").concat(Dt(i)):i>0?""+i:null}function Ut(t){return Ut="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},Ut(t)}function Rt(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function Ht(t,e,n){return(e=function(t){var e=function(t,e){if("object"!==Ut(t)||null===t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var i=n.call(t,"string");if("object"!==Ut(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"===Ut(e)?e:String(e)}(e))in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var Mt=function(t,e,n){var i=e?function(t){switch(t.number_format){case"comma_decimal":return["en-US","en"];case"decimal_comma":return["de","es","it"];case"space_comma":return["fr","sv","cs"];case"system":return;default:return t.language}}(e):void 0;if(Number.isNaN=Number.isNaN||function t(e){return"number"==typeof e&&t(e)},"none"!==(null==e?void 0:e.number_format)&&!Number.isNaN(Number(t))&&Intl)try{return new Intl.NumberFormat(i,It(t,n)).format(Number(t))}catch(e){return console.error(e),new Intl.NumberFormat(void 0,It(t,n)).format(Number(t))}return"string"==typeof t?t:"".concat(function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;return Math.round(t*Math.pow(10,e))/Math.pow(10,e)}(t,null==n?void 0:n.maximumFractionDigits).toString()).concat("currency"===(null==n?void 0:n.style)?" ".concat(n.currency):"")},It=function(t,e){var n=function(t){for(var e=1;e-1?t.split(".")[1].length:0;n.minimumFractionDigits=i,n.maximumFractionDigits=i}return n},zt=Number.isNaN||function(t){return"number"==typeof t&&t!=t};function Lt(t,e){if(t.length!==e.length)return!1;for(var n=0;ne.hide_if.above)return!0;e.hide_if.value&&(i=i.concat(e.hide_if.value))}else i=i.concat(e.hide_if);return i.some((function(t){return"number"==typeof t?t===+n:t===n}))};function te(t){return te="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},te(t)}function ee(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function ne(t){for(var e=1;e\n
\n ',"","\n
\n "])),this._hass,this.config,this.renderSecondaryInfo(),!1,this.config.column?"entities-column":"entities-row",this.entities.map((function(e){return t.renderEntity(e.stateObj,e)})),this.renderMainEntity()):this.renderWarning():H(oe||(oe=we([""])))}},{key:"renderSecondaryInfo",value:function(){if(!this.config.secondary_info||"string"==typeof(t=this.config.secondary_info)&&Ct.includes(t)||Xt(this.info,this.config.secondary_info))return null;var t;if("string"==typeof this.config.secondary_info)return H(ae||(ae=we(["",""])),this.config.secondary_info);var e=_e(this.info,this.config.secondary_info);return H(ce||(ce=we([""," ",""])),e,this.renderValue(this.info,this.config.secondary_info))}},{key:"renderMainEntity",value:function(){return!1===this.config.show_state?null:H(le||(le=we(['
\n ',"\n
","
\n
"])),ge(this.config),this.onRowClick,this.config.state_header&&H(ue||(ue=we(["",""])),this.config.state_header),this.renderValue(this.stateObj,this.config))}},{key:"renderEntity",value:function(t,e){if(!t||Xt(t,e))return e.default?H(he||(he=we(['
\n ',"\n
","
\n
"])),ge(e),e.name,e.default):null;var n=this.clickHandler(t.entity_id,e.tap_action);return H(fe||(fe=we(['
\n ',"\n
","
\n
"])),ge(e),n,_e(t,e),e.icon?this.renderIcon(t,e):this.renderValue(t,e))}},{key:"renderValue",value:function(t,e){if(!0===e.toggle)return H(de||(de=we([''])),t,this._hass);var n;if(e.attribute&&[Pt,kt].includes(e.attribute))return H(pe||(pe=we([""])),this._hass,t[null===(n=e.attribute)||void 0===n?void 0:n.replace("-","_")]);if(e.format&&xt.includes(e.format)){var i,r=e.attribute?null!==(i=t.attributes[e.attribute])&&void 0!==i?i:t[e.attribute]:t.state,o=new Date(r);return o instanceof Date&&!isNaN(o.getTime())?H(me||(me=we([""])),this._hass,o,e.format):r}return function(t,e,n){if(Qt(e))return t.localize("state.default.".concat(e.state));var i=n.attribute?e.attributes[n.attribute]:e.state,r=!1===n.unit?void 0:void 0!==n.attribute?n.unit:n.unit||e.attributes.unit_of_measurement;if(n.format){if(isNaN(parseFloat(i))||!isFinite(i));else if("brightness"===n.format)i=Math.round(i/255*100),r="%";else if("duration"===n.format)i=Tt(i),r=void 0;else if("duration-m"===n.format)i=Tt(i/1e3),r=void 0;else if("duration-h"===n.format)i=Tt(3600*i),r=void 0;else if(n.format.startsWith("precision")){var o=parseInt(n.format.slice(-1),10);i=Mt(parseFloat(i),t.locale,{minimumFractionDigits:o,maximumFractionDigits:o})}else"kilo"===n.format?i=Mt(i/1e3,t.locale,{maximumFractionDigits:2}):"invert"===n.format?i=Mt(i-2*i,t.locale):"position"===n.format?i=Mt(100-i,t.locale):"celsius_to_fahrenheit"===n.format?i=Mt(1.8*i+32,t.locale,{maximumFractionDigits:0}):"fahrenheit_to_celsius"===n.format&&(i=Mt(5*(i-32)/9,t.locale,{maximumFractionDigits:1}));return"".concat(i).concat(r?" ".concat(r):"")}if(n.attribute)return"".concat(isNaN(i)?i:Mt(i,t.locale)).concat(r?" ".concat(r):"");var s=ne(ne({},e),{},{attributes:ne(ne({},e.attributes),{},{unit_of_measurement:r})});return function(t,e,n,i,r){var o=e.state;if(o===Et||o===Ot)return t("state.default.".concat(o));if(function(t){return!!t.attributes.unit_of_measurement||!!t.attributes.state_class}(e)){if("monetary"===e.attributes.device_class)try{return Mt(o,n,{style:"currency",currency:e.attributes.unit_of_measurement})}catch(t){}return"".concat(Mt(o,n)).concat(e.attributes.unit_of_measurement?" "+e.attributes.unit_of_measurement:"")}var s,a=function(t){return t.entity_id.substr(0,t.entity_id.indexOf("."))}(e);if("input_datetime"===a)return e.attributes.has_date&&e.attributes.has_time?(s=new Date(e.attributes.year,e.attributes.month-1,e.attributes.day,e.attributes.hour,e.attributes.minute),Jt(s,n)):e.attributes.has_date?(s=new Date(e.attributes.year,e.attributes.month-1,e.attributes.day),Bt(s,n)):e.attributes.has_time?((s=new Date).setHours(e.attributes.hour,e.attributes.minute),Zt(s,n)):e.state;if("humidifier"===a&&"on"===o&&e.attributes.humidity)return"".concat(e.attributes.humidity," %");if("counter"===a||"number"===a||"input_number"===a)return Mt(o,n);if("button"===a||"sensor"===a&&"timestamp"===e.attributes.device_class)return Jt(new Date(o),n);var c=i&&i[e.entity_id];return(null==c?void 0:c.translation_key)&&t("component.".concat(c.platform,".entity.").concat(a,".").concat(c.translation_key,".state.").concat(o))||e.attributes.device_class&&t("component.".concat(a,".entity_component.").concat(e.attributes.device_class,".state.").concat(o))||t("component.".concat(a,".entity_component._.state.").concat(o))||o}(t.localize,s,t.locale,t.entities)}(this._hass,t,e)}},{key:"renderIcon",value:function(t,e){return H(ye||(ye=we([''])),this._hass,t,!0===e.icon?t.attributes.icon||null:e.icon,e.state_color)}},{key:"renderWarning",value:function(){return H(ve||(ve=we(["\n ","\n "])),this._hass.localize("ui.panel.lovelace.warning.entity_not_found","entity",this.config.entity))}},{key:"clickHandler",value:function(t,e){var n=this;return function(){return function(t,e,n,i,r){var o;if(n.tap_action&&(o=n.tap_action),o||(o={action:"more-info"}),!o.confirmation||o.confirmation.exemptions&&o.confirmation.exemptions.some((function(t){return t.user===e.user.id}))||confirm(o.confirmation.text||"Are you sure you want to "+o.action+"?"))switch(o.action){case"more-info":(o.entity||n.entity||n.camera_image)&&(At(t,"hass-more-info",{entityId:o.entity?o.entity:n.entity?n.entity:n.camera_image}),o.haptic&&St(o.haptic));break;case"navigate":o.navigation_path&&(function(t,e,n){void 0===n&&(n=!1),n?history.replaceState(null,"",e):history.pushState(null,"",e),At(window,"location-changed",{replace:n})}(0,o.navigation_path),o.haptic&&St(o.haptic));break;case"url":o.url_path&&window.open(o.url_path),o.haptic&&St(o.haptic);break;case"toggle":n.entity&&(function(t,e){(function(t,e,n){void 0===n&&(n=!0);var i,r=function(t){return t.substr(0,t.indexOf("."))}(e),o="group"===r?"homeassistant":r;switch(r){case"lock":i=n?"unlock":"lock";break;case"cover":i=n?"open_cover":"close_cover";break;default:i=n?"turn_on":"turn_off"}t.callService(o,i,{entity_id:e})})(t,e,wt.includes(t.states[e].state))}(e,n.entity),o.haptic&&St(o.haptic));break;case"call-service":if(!o.service)return;var s=o.service.split(".",2),a=s[0],c=s[1],l=_t({},o.service_data);"entity"===l.entity_id&&(l.entity_id=n.entity),e.callService(a,c,l),o.haptic&&St(o.haptic);break;case"fire-dom-event":At(t,"ll-custom",o),o.haptic&&St(o.haptic)}}(n,n._hass,{entity:t,tap_action:e})}}}],i=[{key:"properties",get:function(){return{_hass:Object,config:Object,stateObj:Object}}},{key:"styles",get:function(){return o(re||(t=["\n .icon-small {\n width: auto;\n }\n .entity {\n text-align: center;\n cursor: pointer;\n }\n .entity span {\n font-size: 10px;\n color: var(--secondary-text-color);\n }\n .entities-row {\n flex-direction: row;\n display: inline-flex;\n justify-content: space-between;\n align-items: center;\n }\n .entities-row .entity {\n margin-right: 16px;\n }\n .entities-row .entity:last-of-type {\n margin-right: 0;\n }\n .entities-column {\n flex-direction: column;\n display: flex;\n align-items: flex-end;\n justify-content: space-evenly;\n }\n .entities-column .entity div {\n display: inline-block;\n vertical-align: middle;\n }\n"],e||(e=t.slice(0)),re=Object.freeze(Object.defineProperties(t,{raw:{value:Object.freeze(e)}}))));var t,e}}],n&&Ee(e.prototype,n),i&&Ee(e,i),Object.defineProperty(e,"prototype",{writable:!1}),c}(nt);customElements.define("multiple-entity-row",xe)})(); \ No newline at end of file +/*! For license information please see multiple-entity-row.js.LICENSE.txt */ +(()=>{"use strict";const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,n=Symbol(),i=new WeakMap;class o{constructor(t,e,i){if(this._$cssResult$=!0,i!==n)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const n=this.t;if(e&&void 0===t){const e=void 0!==n&&1===n.length;e&&(t=i.get(n)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&i.set(n,t))}return t}toString(){return this.cssText}}const r=(t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,n,i)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(n)+t[i+1],t[0]);return new o(i,t,n)},a=(n,i)=>{if(e)n.adoptedStyleSheets=i.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of i){const i=document.createElement("style"),o=t.litNonce;void 0!==o&&i.setAttribute("nonce",o),i.textContent=e.cssText,n.appendChild(i)}},s=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const n of t.cssRules)e+=n.cssText;return(t=>new o("string"==typeof t?t:t+"",void 0,n))(e)})(t):t,{is:c,defineProperty:l,getOwnPropertyDescriptor:u,getOwnPropertyNames:d,getOwnPropertySymbols:f,getPrototypeOf:h}=Object,p=globalThis,m=p.trustedTypes,v=m?m.emptyScript:"",y=p.reactiveElementPolyfillSupport,b=(t,e)=>t,_={toAttribute(t,e){switch(e){case Boolean:t=t?v:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let n=t;switch(e){case Boolean:n=null!==t;break;case Number:n=null===t?null:Number(t);break;case Object:case Array:try{n=JSON.parse(t)}catch(t){n=null}}return n}},g=(t,e)=>!c(t,e),w={attribute:!0,type:String,converter:_,reflect:!1,useDefault:!1,hasChanged:g};Symbol.metadata??=Symbol("metadata"),p.litPropertyMetadata??=new WeakMap;class A extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=w){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const n=Symbol(),i=this.getPropertyDescriptor(t,n,e);void 0!==i&&l(this.prototype,t,i)}}static getPropertyDescriptor(t,e,n){const{get:i,set:o}=u(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:i,set(e){const r=i?.call(this);o?.call(this,e),this.requestUpdate(t,r,n)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??w}static _$Ei(){if(this.hasOwnProperty(b("elementProperties")))return;const t=h(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(b("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(b("properties"))){const t=this.properties,e=[...d(t),...f(t)];for(const n of e)this.createProperty(n,t[n])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,n]of e)this.elementProperties.set(t,n)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const n=this._$Eu(t,e);void 0!==n&&this._$Eh.set(n,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const n=new Set(t.flat(1/0).reverse());for(const t of n)e.unshift(s(t))}else void 0!==t&&e.push(s(t));return e}static _$Eu(t,e){const n=e.attribute;return!1===n?void 0:"string"==typeof n?n:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const n of e.keys())this.hasOwnProperty(n)&&(t.set(n,this[n]),delete this[n]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return a(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,n){this._$AK(t,n)}_$ET(t,e){const n=this.constructor.elementProperties.get(t),i=this.constructor._$Eu(t,n);if(void 0!==i&&!0===n.reflect){const o=(void 0!==n.converter?.toAttribute?n.converter:_).toAttribute(e,n.type);this._$Em=t,null==o?this.removeAttribute(i):this.setAttribute(i,o),this._$Em=null}}_$AK(t,e){const n=this.constructor,i=n._$Eh.get(t);if(void 0!==i&&this._$Em!==i){const t=n.getPropertyOptions(i),o="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:_;this._$Em=i;const r=o.fromAttribute(e,t.type);this[i]=r??this._$Ej?.get(i)??r,this._$Em=null}}requestUpdate(t,e,n,i=!1,o){if(void 0!==t){const r=this.constructor;if(!1===i&&(o=this[t]),n??=r.getPropertyOptions(t),!((n.hasChanged??g)(o,e)||n.useDefault&&n.reflect&&o===this._$Ej?.get(t)&&!this.hasAttribute(r._$Eu(t,n))))return;this.C(t,e,n)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:n,reflect:i,wrapped:o},r){n&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??e??this[t]),!0!==o||void 0!==r)||(this._$AL.has(t)||(this.hasUpdated||n||(e=void 0),this._$AL.set(t,e)),!0===i&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,n]of t){const{wrapped:t}=n,i=this[e];!0!==t||this._$AL.has(e)||void 0===i||this.C(e,void 0,n,i)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}}A.elementStyles=[],A.shadowRootOptions={mode:"open"},A[b("elementProperties")]=new Map,A[b("finalized")]=new Map,y?.({ReactiveElement:A}),(p.reactiveElementVersions??=[]).push("2.1.2");const $=globalThis,S=t=>t,O=$.trustedTypes,x=O?O.createPolicy("lit-html",{createHTML:t=>t}):void 0,E="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,j="?"+C,k=`<${j}>`,P=document,T=()=>P.createComment(""),M=t=>null===t||"object"!=typeof t&&"function"!=typeof t,I=Array.isArray,H=t=>I(t)||"function"==typeof t?.[Symbol.iterator],F="[ \t\n\f\r]",D=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,R=/-->/g,N=/>/g,U=RegExp(`>|${F}(?:([^\\s"'>=/]+)(${F}*=${F}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),L=/'/g,V=/"/g,z=/^(?:script|style|textarea|title)$/i,B=t=>(e,...n)=>({_$litType$:t,strings:e,values:n}),W=B(1),Z=(B(2),B(3),Symbol.for("lit-noChange")),q=Symbol.for("lit-nothing"),J=new WeakMap,G=P.createTreeWalker(P,129);function K(t,e){if(!I(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==x?x.createHTML(e):e}const Y=(t,e)=>{const n=t.length-1,i=[];let o,r=2===e?"":3===e?"":"",a=D;for(let e=0;e"===c[0]?(a=o??D,l=-1):void 0===c[1]?l=-2:(l=a.lastIndex-c[2].length,s=c[1],a=void 0===c[3]?U:'"'===c[3]?V:L):a===V||a===L?a=U:a===R||a===N?a=D:(a=U,o=void 0);const d=a===U&&t[e+1].startsWith("/>")?" ":"";r+=a===D?n+k:l>=0?(i.push(s),n.slice(0,l)+E+n.slice(l)+C+d):n+C+(-2===l?e:d)}return[K(t,r+(t[n]||"")+(2===e?"":3===e?"":"")),i]};class Q{constructor({strings:t,_$litType$:e},n){let i;this.parts=[];let o=0,r=0;const a=t.length-1,s=this.parts,[c,l]=Y(t,e);if(this.el=Q.createElement(c,n),G.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(i=G.nextNode())&&s.length0){i.textContent=O?O.emptyScript:"";for(let n=0;n2||""!==n[0]||""!==n[1]?(this._$AH=Array(n.length-1).fill(new String),this.strings=n):this._$AH=q}_$AI(t,e=this,n,i){const o=this.strings;let r=!1;if(void 0===o)t=X(this,t,e,0),r=!M(t)||t!==this._$AH&&t!==Z,r&&(this._$AH=t);else{const i=t;let a,s;for(t=o[0],a=0;a{const i=n?.renderBefore??e;let o=i._$litPart$;if(void 0===o){const t=n?.renderBefore??null;i._$litPart$=o=new et(e.insertBefore(T(),t),t,void 0,n??{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return Z}}ut._$litElement$=!0,ut.finalized=!0,lt.litElementHydrateSupport?.({LitElement:ut});const dt=lt.litElementPolyfillSupport;dt?.({LitElement:ut}),(lt.litElementVersions??=[]).push("4.2.2");var ft=["unavailable","unknown"],ht="last-changed",pt="last-updated",mt=["relative","total","date","time","datetime"],vt=["entity-id","last-changed","last-updated","last-triggered","position","tilt-position","brightness"],yt=function(t){return t<10?"0".concat(t):t};function bt(t){var e=Math.floor(t/3600),n=Math.floor(t%3600/60),i=Math.floor(t%3600%60);return e>0?"".concat(e,":").concat(yt(n),":").concat(yt(i)):n>0?"".concat(n,":").concat(yt(i)):i>0?""+i:null}function _t(t){return _t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},_t(t)}function gt(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),n.push.apply(n,i)}return n}function wt(t,e,n){return(e=function(t){var e=function(t){if("object"!=_t(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var n=e.call(t,"string");if("object"!=_t(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==_t(e)?e:e+""}(e))in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var At=function(t,e,n){var i=e?function(t){switch(t.number_format){case"comma_decimal":return["en-US","en"];case"decimal_comma":return["de","es","it"];case"space_comma":return["fr","sv","cs"];case"system":return;default:return t.language}}(e):void 0;if(Number.isNaN=Number.isNaN||function t(e){return"number"==typeof e&&t(e)},"none"!==(null==e?void 0:e.number_format)&&!Number.isNaN(Number(t))&&Intl)try{return new Intl.NumberFormat(i,$t(t,n)).format(Number(t))}catch(e){return console.error(e),new Intl.NumberFormat(void 0,$t(t,n)).format(Number(t))}return"string"==typeof t?t:"".concat(function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;return Math.round(t*Math.pow(10,e))/Math.pow(10,e)}(t,null==n?void 0:n.maximumFractionDigits).toString()).concat("currency"===(null==n?void 0:n.style)?" ".concat(n.currency):"")},$t=function(t,e){var n=function(t){for(var e=1;e-1?t.split(".")[1].length:0;n.minimumFractionDigits=i,n.maximumFractionDigits=i}return n};function St(t){return St="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},St(t)}var Ot=function(t){return"object"===St(t)&&!Array.isArray(t)&&!!t},xt=function(t,e,n){var i=new Event(e,{bubbles:!0,composed:!0});i.detail=n,t.dispatchEvent(i)},Et=function(t){return!t||ft.includes(t.state)},Ct=function(t,e,n){if(function(t,e){return e.hide_unavailable&&(Et(t)||e.attribute&&![ht,pt].includes(e.attribute)&&void 0===t.attributes[e.attribute])}(t,e))return!0;if(void 0===e.hide_if)return!1;var i;if(Ot(e.hide_if)&&(e.hide_if.entity||e.hide_if.attribute)){var o=e.hide_if.entity?null==n?void 0:n.states[e.hide_if.entity]:t;i=e.hide_if.attribute?null==o?void 0:o.attributes[e.hide_if.attribute]:null==o?void 0:o.state}else i=e.attribute?t.attributes[e.attribute]:t.state;var r=[];if(Ot(e.hide_if)){if(e.hide_if.below&&ie.hide_if.above)return!0;e.hide_if.value&&(r=r.concat(e.hide_if.value))}else r=r.concat(e.hide_if);return r.some(function(t){return"number"==typeof t?t===+i:t===i})},jt=["formatEntityName","formatEntityState","formatEntityAttributeValue"];function kt(t){return kt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},kt(t)}function Pt(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),n.push.apply(n,i)}return n}function Tt(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,i=Array(e);n1&&a.every(function(t){return Vt.test(t)})){var s=o??0;return!isNaN(parseFloat(s))&&isFinite(s)?function(t,e,n,i){var o,r,a=parseFloat(e),s=Rt(e),c=!1,l=function(t){c||(s=void 0,o=t)},u=function(t){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!e){if(Array.isArray(t)||(e=It(t))){e&&(t=e);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,r=!0,a=!1;return{s:function(){e=e.call(t)},n:function(){var t=e.next();return r=t.done,t},e:function(t){a=!0,o=t},f:function(){try{r||null==e.return||e.return()}finally{if(a)throw o}}}}(t);try{for(u.s();!(r=u.n()).done;){var d=r.value,f=Ut.exec(d);if(f&&"precision"===f[1])s=parseInt(f[2],10),o=void 0,c=!0;else if(f)a/={kilo:1e3,mega:1e6,milli:.001}[f[1]],void 0!==f[2]?(s=parseInt(f[2],10),o=void 0,c=!0):l(2);else switch(d){case"brightness":a=Math.round(a/255*100),n="%",l(0);break;case"percent":a*=100,n="%",l(2);break;case"invert":a=-a;break;case"position":a=100-a;break;case"celsius_to_fahrenheit":a=1.8*a+32,l(0);break;case"fahrenheit_to_celsius":a=5*(a-32)/9,l(1)}}}catch(t){u.e(t)}finally{u.f()}return"".concat(At(a,i,void 0!==s?{minimumFractionDigits:s,maximumFractionDigits:s}:void 0!==o?{maximumFractionDigits:o}:void 0)).concat(n?" ".concat(n):"")}(a,s,r,t.locale):"".concat(s).concat(r?" ".concat(r):"")}if(n.format&&!function(t){return Nt.some(function(e){return null==t?void 0:t.startsWith(e)})&&!Lt(t)}(n.format)){if(null==o&&(o=zt.includes(n.format)?"":0),zt.includes(n.format))return"".concat(function(t,e){switch(t){case"upper":return e.toUpperCase();case"lower":return e.toLowerCase();case"capitalize":return e.charAt(0).toUpperCase()+e.slice(1);case"title":return e.split(/(\s+)/).map(function(t){return t.charAt(0).toUpperCase()+t.slice(1)}).join("")}}(n.format,String(o))).concat(r?" ".concat(r):"");if(isNaN(parseFloat(o))||!isFinite(o));else if("brightness"===n.format)o=Math.round(o/255*100),r="%";else if("percent"===n.format)o=At(100*o,t.locale,{maximumFractionDigits:2}),r="%";else if("duration"===n.format){var c;o=null!==(c=bt(o))&&void 0!==c?c:"0",r=void 0}else if("duration-m"===n.format){var l;o=null!==(l=bt(o/1e3))&&void 0!==l?l:"0",r=void 0}else if("duration-h"===n.format){var u;o=null!==(u=bt(3600*o))&&void 0!==u?u:"0",r=void 0}else if(Lt(n.format)){var d=function(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=n){var i,o,r,a,s=[],c=!0,l=!1;try{if(r=(n=n.call(t)).next,0===e){if(Object(n)!==n)return;c=!1}else for(;!(c=(i=r.call(n)).done)&&(s.push(i.value),s.length!==e);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(l)throw o}}return s}}(t,e)||It(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(Lt(n.format),3),f=d[1],h=d[2];if("precision"===f){var p=parseInt(h,10);o=At(parseFloat(o),t.locale,{minimumFractionDigits:p,maximumFractionDigits:p})}else o=function(t,e,n,i){if(void 0===n)return At(t/e,i,{maximumFractionDigits:2});var o=parseInt(n,10);return At(t/e,i,{minimumFractionDigits:o,maximumFractionDigits:o})}(o,{kilo:1e3,mega:1e6,milli:.001}[f],h,t.locale)}else if("invert"===n.format){var m=Rt(o);o=At(o-2*o,t.locale,void 0!==m?{minimumFractionDigits:m,maximumFractionDigits:m}:void 0)}else if("position"===n.format){var v=Rt(o);o=At(100-o,t.locale,void 0!==v?{minimumFractionDigits:v,maximumFractionDigits:v}:void 0)}else"celsius_to_fahrenheit"===n.format?o=At(1.8*o+32,t.locale,{maximumFractionDigits:0}):"fahrenheit_to_celsius"===n.format&&(o=At(5*(o-32)/9,t.locale,{maximumFractionDigits:1}));return"".concat(o).concat(r?" ".concat(r):"")}var y=Tt(Tt({},e),{},{attributes:Tt(Tt({},e.attributes),{},{unit_of_measurement:r})});return n.attribute?t.formatEntityAttributeValue(y,n.attribute):t.formatEntityState(y)},Jt=function(t){return Ot(null==t?void 0:t.styles)?Object.keys(t.styles).map(function(e){return"".concat(e,": ").concat(t.styles[e],";")}).join(""):""};class Gt{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,n){this._$Ct=t,this._$AM=e,this._$Ci=n}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}const{I:Kt}=st,Yt={},Qt=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends Gt{constructor(){super(...arguments),this.key=q}render(t,e){return this.key=t,e}update(t,[e,n]){return e!==this.key&&(((t,e=Yt)=>{t._$AH=e})(t),this.key=e),n}});var Xt,te,ee,ne,ie,oe,re,ae,se,ce,le,ue,de,fe,he,pe,me,ve="__custom__",ye=[{value:"",label:"No format"},{value:"brightness",label:"Brightness (0-255 → %)"},{value:"percent",label:"Percent (value × 100 → x %)"},{value:"duration",label:"Duration (seconds → h:mm:ss)"},{value:"duration-m",label:"Duration (milliseconds)"},{value:"duration-h",label:"Duration (hours)"},{value:"precision0",label:"Precision 0 decimals"},{value:"precision1",label:"Precision 1 decimal"},{value:"precision2",label:"Precision 2 decimals"},{value:"precision3",label:"Precision 3 decimals"},{value:"kilo",label:"Kilo (value / 1,000)"},{value:"mega",label:"Mega (value / 1,000,000)"},{value:"milli",label:"Milli (value × 1,000)"},{value:"invert",label:"Invert (value × -1)"},{value:"position",label:"Position (100 - value)"},{value:"celsius_to_fahrenheit",label:"°C → °F"},{value:"fahrenheit_to_celsius",label:"°F → °C"},{value:"upper",label:"Text: UPPERCASE"},{value:"lower",label:"Text: lowercase"},{value:"capitalize",label:"Text: Capitalize first letter"},{value:"title",label:"Text: Title Case"},{value:"relative",label:"Timestamp: relative"},{value:"total",label:"Timestamp: total"},{value:"date",label:"Timestamp: date"},{value:"time",label:"Timestamp: time"},{value:"datetime",label:"Timestamp: date + time"},{value:ve,label:"Custom…"}],be=new Set(ye.map(function(t){return t.value}).filter(function(t){return t&&t!==ve})),_e=[{name:"entity",required:!0,selector:{entity:{}}},{type:"grid",schema:[{name:"name",selector:{text:{}}},{name:"attribute",selector:{text:{}}}]},{type:"grid",schema:[{name:"unit",selector:{text:{}}},{name:"icon",selector:{icon:{}}}]},{name:"icon_color",selector:{text:{}}},{type:"grid",schema:[{name:"show_state",default:!0,selector:{boolean:{}}},{name:"state_color",selector:{boolean:{}}}]},{type:"grid",schema:[{name:"toggle",selector:{boolean:{}}},{name:"column",selector:{boolean:{}}}]},{type:"grid",schema:[{name:"show_state_first",selector:{boolean:{}}},{name:"hide_unavailable",selector:{boolean:{}}}]},{name:"state_header",selector:{text:{}}},{name:"image",selector:{text:{}}},{name:"format",selector:{select:{mode:"dropdown",options:ye}}}],ge=[{name:"tap_action",selector:{ui_action:{default_action:"more-info"}}},{name:"hold_action",selector:{ui_action:{default_action:"none"}}},{name:"double_tap_action",selector:{ui_action:{default_action:"none"}}}],we=[{name:"entity",selector:{entity:{}}},{type:"grid",schema:[{name:"name",selector:{text:{}}},{name:"attribute",selector:{text:{}}}]},{type:"grid",schema:[{name:"unit",selector:{text:{}}},{name:"icon",selector:{icon:{}}}]},{name:"icon_color",selector:{text:{}}},{type:"grid",schema:[{name:"state_color",selector:{boolean:{}}},{name:"toggle",selector:{boolean:{}}}]},{name:"hide_unavailable",selector:{boolean:{}}},{name:"format",selector:{select:{mode:"dropdown",options:ye}}}],Ae={entity:"Entity",attribute:"Attribute",name:"Name override",unit:"Unit",icon:"Icon",icon_color:"Icon color (CSS value, e.g. red, #ff0000, var(--my-color))",image:"Image URL",format:"Format",show_state:"Show main entity state",show_state_first:"State before entities",state_header:"State header label",state_color:"State color",column:"Column layout",toggle:"Show as toggle",hide_unavailable:"Hide if unavailable",tap_action:"Tap action",hold_action:"Hold action",double_tap_action:"Double-tap action"};function $e(t,e){return e||(e=t.slice(0)),Object.freeze(Object.defineProperties(t,{raw:{value:Object.freeze(e)}}))}function Se(t){return function(t){if(Array.isArray(t))return Fe(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||He(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Oe(t,e){for(var n=0;n=t.length?{done:!0}:{done:!1,value:t[i++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,a=!0,s=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return a=t.done,t},e:function(t){s=!0,r=t},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw r}}}}function Ie(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=n){var i,o,r,a,s=[],c=!0,l=!1;try{if(r=(n=n.call(t)).next,0===e){if(Object(n)!==n)return;c=!1}else for(;!(c=(i=r.call(n)).done)&&(s.push(i.value),s.length!==e);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(l)throw o}}return s}}(t,e)||He(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function He(t,e){if(t){if("string"==typeof t)return Fe(t,e);var n={}.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Fe(t,e):void 0}}function Fe(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=Array(e);ni.length&&(t._selectedTab=i.length),t._keys.clear(),t._updateConfig({entities:i.length?i:void 0})}}),Pe(t,"_moveAdditional",function(e,n){var i;if(t._config){var o=Se(null!==(i=t._config.entities)&&void 0!==i?i:[]),r=e+n;if(!(r<0||r>=o.length)){var a=[o[r],o[e]];o[e]=a[0],o[r]=a[1],t._selectedTab=r+1,t._keys.clear(),t._updateConfig({entities:o})}}}),Pe(t,"_copyAdditional",function(e){var n,i=null===(n=t._config)||void 0===n||null===(n=n.entities)||void 0===n?void 0:n[e];null!=i&&t._writeClipboard("string"==typeof i?{entity:i}:ke({},i))}),Pe(t,"_cutAdditional",function(e){t._copyAdditional(e),t._deleteAdditional(e)}),Pe(t,"_copyMainAsTemplate",function(){if(t._config){var e,n={},i=Me(pn);try{for(i.s();!(e=i.n()).done;){var o=e.value,r=t._config[o];void 0!==r&&(n[o]=r)}}catch(t){i.e(t)}finally{i.f()}t._writeClipboard(n)}}),Pe(t,"_pasteEntity",function(){var e;if(t._config){var n=t._readClipboard();if(n){var i=[].concat(Se(null!==(e=t._config.entities)&&void 0!==e?e:[]),[n]);t._selectedTab=i.length,t._keys.clear(),t._updateConfig({entities:i})}}}),Pe(t,"_secondaryModeChanged",function(e){if(t._config){var n=e.detail.value.mode;if(n!==t._secondaryInfoMode()){var i;switch(n){case"none":i=void 0;break;case"text":i="";break;case"generic":i="last-changed";break;case"entity":i={entity:t._config.entity}}t._updateConfig({secondary_info:i})}}}),Pe(t,"_secondaryTextChanged",function(e){t._updateConfig({secondary_info:e.detail.value.text})}),Pe(t,"_secondaryTokenChanged",function(e){t._updateConfig({secondary_info:e.detail.value.token})}),Pe(t,"_secondaryEntityChanged",function(e){var n,i=Ot(null===(n=t._config)||void 0===n?void 0:n.secondary_info)?t._config.secondary_info.format:void 0;t._updateConfig({secondary_info:t._formatFromForm("secondary",fn(e.detail.value),i)})}),t._selectedTab=0,t._entitiesExpanded=!0,t._stateIconRowsMain=[],t._stateIconRowsAdditional=new Map,t._customFormatScopes=new Set,t}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&Ce(t,e)}(e,t),function(t,e,n){return e&&Oe(t.prototype,e),n&&Oe(t,n),Object.defineProperty(t,"prototype",{writable:!1}),t}(e,[{key:"setConfig",value:function(t){var e,n,i,o=this;this._config=t;var r,a=null!==(e=null===(n=t.entities)||void 0===n?void 0:n.length)&&void 0!==e?e:0;this._selectedTab>a&&(this._selectedTab=a),this._clipboardEntity=this._readClipboard(),this._stateIconRowsMatch(this._stateIconRowsMain,t.state_icon)||(this._stateIconRowsMain=Object.entries(null!==(r=t.state_icon)&&void 0!==r?r:{}));var s=new Map;null===(i=t.entities)||void 0===i||i.forEach(function(t,e){var n=Ot(t)?t.state_icon:void 0,i=o._stateIconRowsAdditional.get(e);i&&o._stateIconRowsMatch(i,n)?s.set(e,i):n&&s.set(e,Object.entries(n))}),this._stateIconRowsAdditional=s}},{key:"_stateIconRowsMatch",value:function(t,e){var n,i={},o=Me(t);try{for(o.s();!(n=o.n()).done;){var r=Ie(n.value,2),a=r[0],s=r[1];a.trim()&&s.trim()&&(i[a.trim()]=s.trim())}}catch(t){o.e(t)}finally{o.f()}var c=null!=e?e:{},l=Object.keys(i);return l.length===Object.keys(c).length&&l.every(function(t){return i[t]===c[t]})}},{key:"_readClipboard",value:function(){try{var t=sessionStorage.getItem(hn);if(!t)return;var e=JSON.parse(t);if(e&&"object"===De(e))return e}catch(t){}}},{key:"_writeClipboard",value:function(t){try{sessionStorage.setItem(hn,JSON.stringify(t)),this._clipboardEntity=t}catch(t){}}},{key:"_hasNativeTabs",get:function(){return!!customElements.get("ha-tab-group")&&!!customElements.get("ha-tab-group-tab")}},{key:"render",value:function(){return this.hass&&this._config?W(Xt||(Xt=$e(["\n \n ",'\n \n\n \n "])),"Entities",this._entitiesExpanded,this._onEntitiesExpandedChanged,this._renderEntitiesPanel(),"4.7.0","2026-07-08T23:41:43.781Z"):q}},{key:"_isCustomFormat",value:function(t,e){return this._customFormatScopes.has(t)||!!e&&!be.has(e)}},{key:"_setCustomFormatScope",value:function(t,e){if(e!==this._customFormatScopes.has(t)){var n=new Set(this._customFormatScopes);e?n.add(t):n.delete(t),this._customFormatScopes=n}}},{key:"_formatToForm",value:function(t,e){return this._isCustomFormat(t,e.format)?ke(ke({},e),{},{format:ve}):e}},{key:"_formatFromForm",value:function(t,e,n){if(e.format===ve){this._setCustomFormatScope(t,!0);var i=ke({},e);return void 0!==n?i.format=n:delete i.format,i}return this._setCustomFormatScope(t,!1),e}},{key:"_renderCustomFormatField",value:function(t,e,n){return this._isCustomFormat(t,e)?W(te||(te=$e(["\n \n "])),this.hass,{custom_format:null!=e?e:""},[{name:"custom_format",selector:{text:{}}}],function(){return"Custom format (e.g. invert, precision3)"},function(t){var e,i=(null!==(e=t.detail.value.custom_format)&&void 0!==e?e:"").trim();n(i||void 0)}):q}},{key:"_keyFor",value:function(t){return this._keys.has(t)||this._keys.set(t,"".concat(t,"-").concat(Math.random().toString(36).slice(2,10))),this._keys.get(t)}},{key:"_renderEntitiesPanel",value:function(){var t,e,n=this,i=null!==(t=null===(e=this._config)||void 0===e?void 0:e.entities)&&void 0!==t?t:[],o=Math.min(this._selectedTab,i.length);return W(ee||(ee=$e(['\n
\n
\n ','\n \n
\n\n
\n ',"\n
\n
\n "])),this._hasNativeTabs?W(ne||(ne=$e(['\n \n \n \n \n
\n
\n
\n \n \n ','\n \n ','\n \n ',"\n
\n "])),"Copy main as template",nn,this._copyMainAsTemplate,"Paste as new entity",on,!this._clipboardEntity,this._pasteEntity,this.hass,this._mainFormData(),_e,this._computeLabel,this._mainValueChanged,this._renderCustomFormatField("main",null===(t=this._config)||void 0===t?void 0:t.format,function(t){return n._updateConfig({format:t})}),this.hass,this._mainFormData(),ge,this._computeLabel,this._mainValueChanged,this._renderSecondaryInfoBlock(),this._renderStateIconRows("main"),this._renderStylesBlock(null===(e=this._config)||void 0===e?void 0:e.styles,function(t){return n._mainStylesChanged(t)}))}},{key:"_renderStylesBlock",value:function(t,e){return W(se||(se=$e(['\n \n ','\n \n \n \n
\n
\n
\n \n \n ','\n \n ',"\n
\n "])),"Move before","M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z",0===t,function(){return i._moveAdditional(t,-1)},"Move after","M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z",t===a,function(){return i._moveAdditional(t,1)},"Copy entity",nn,function(){return i._copyAdditional(t)},"Cut entity","M19,3L13,9L15,11L22,4V3M12,12.5A0.5,0.5 0 0,1 11.5,12A0.5,0.5 0 0,1 12,11.5A0.5,0.5 0 0,1 12.5,12A0.5,0.5 0 0,1 12,12.5M6,20A2,2 0 0,1 4,18C4,16.89 4.9,16 6,16A2,2 0 0,1 8,18C8,19.11 7.1,20 6,20M6,8A2,2 0 0,1 4,6C4,4.89 4.9,4 6,4A2,2 0 0,1 8,6C8,7.11 7.1,8 6,8M9.64,7.64C9.87,7.14 10,6.59 10,6A4,4 0 0,0 6,2A4,4 0 0,0 2,6A4,4 0 0,0 6,10C6.59,10 7.14,9.87 7.64,9.64L10,12L7.64,14.36C7.14,14.13 6.59,14 6,14A4,4 0 0,0 2,18A4,4 0 0,0 6,22A4,4 0 0,0 10,18C10,17.41 9.87,16.86 9.64,16.36L12,14L19,21H22V20L9.64,7.64Z",function(){return i._cutAdditional(t)},"Paste from clipboard",on,!this._clipboardEntity,this._pasteEntity,"Delete entity",en,function(){return i._deleteAdditional(t)},this.hass,this._formatToForm("sub-".concat(t),dn(r)),we,this._computeLabel,function(e){return i._additionalValueChanged(e,t)},this._renderCustomFormatField("sub-".concat(t),r.format,function(e){return i._setAdditionalFormat(t,e)}),this.hass,this._formatToForm("sub-".concat(t),dn(r)),ge,this._computeLabel,function(e){return i._additionalValueChanged(e,t)},this._renderStateIconRows(t),this._renderStylesBlock(r.styles,function(e){return i._additionalStylesChanged(e,t)}))}},{key:"_mainFormData",value:function(){return this._formatToForm("main",dn(ke({show_state:!0},this._config)))}},{key:"_setAdditionalFormat",value:function(t,e){var n;if(this._config){var i=Se(null!==(n=this._config.entities)&&void 0!==n?n:[]),o=i[t],r="string"==typeof o?{entity:o}:ke({},o);e?r.format=e:delete r.format,i[t]=r,this._updateConfig({entities:i})}}},{key:"_secondaryInfoMode",value:function(){var t,e=null===(t=this._config)||void 0===t?void 0:t.secondary_info;return null==e?"none":"object"===De(e)?"entity":vt.includes(e)?"generic":"text"}},{key:"_renderSecondaryInfoBlock",value:function(){var t,e=this,n=this._secondaryInfoMode(),i=null===(t=this._config)||void 0===t?void 0:t.secondary_info;return W(de||(de=$e(["\n
\n \n ","\n ","\n ","\n
\n "])),this.hass,{mode:n},rn,function(){return"Mode"},this._secondaryModeChanged,"text"===n?W(fe||(fe=$e(['
\n \n \n \n
\n ',"\n
\n "])),Bt(this.config.icon_color),this._hass,n,this.renderSecondaryInfo(),!0,this.config.column?"entities-column":"entities-row",this.config.show_state_first?W(Ue||(Ue=yn(["","",""])),this.renderMainEntity(),this.entities.map(function(e,n){return t.renderEntity(e.stateObj,e,n)})):W(Le||(Le=yn(["","",""])),this.entities.map(function(e,n){return t.renderEntity(e.stateObj,e,n)}),this.renderMainEntity()))}},{key:"renderSecondaryInfo",value:function(){if(!this.config.secondary_info||"string"==typeof(t=this.config.secondary_info)&&vt.includes(t)||Ct(this.info,this.config.secondary_info,this._hass))return null;var t;if("string"==typeof this.config.secondary_info)return W(Ve||(Ve=yn(["",""])),this.config.secondary_info);var e=Zt(this.info,this.config.secondary_info);return W(ze||(ze=yn([""," ",""])),e,this.renderValue(this.info,this.config.secondary_info))}},{key:"renderMainEntity",value:function(){if(!1===this.config.show_state)return null;if(Ct(this.stateObj,this.config,this._hass))return this.config.default?W(Be||(Be=yn(['
\n ',"\n
","
\n
"])),Jt(this.config),this.config.state_header&&W(We||(We=yn(["",""])),this.config.state_header),this.config.default):null;var t=this.getGestureHandlers("main",this.config.entity,this.config);return W(Ze||(Ze=yn(['\n ',"\n
","
\n
"])),Jt(this.config),null==t?void 0:t.onDown,null==t?void 0:t.onUp,null==t?void 0:t.onCancel,xn,xn,xn,xn,xn,xn,this.config.state_header&&W(qe||(qe=yn(["",""])),this.config.state_header),this.renderValue(this.stateObj,this.config))}},{key:"renderEntity",value:function(t,e,n){if(!t||Ct(t,e,this._hass))return e.default?W(Je||(Je=yn(['
\n ',"\n
","
\n
"])),Jt(e),e.name,e.default):null;var i=this.getGestureHandlers("sub-".concat(n),t.entity_id,e);return W(Ge||(Ge=yn(['\n ',"\n
\n ","\n
\n
"])),Jt(e),null==i?void 0:i.onDown,null==i?void 0:i.onUp,null==i?void 0:i.onCancel,xn,xn,xn,xn,xn,xn,Zt(t,e),e.icon||Ot(e.state_icon)?this.renderIcon(t,e):this.renderValue(t,e))}},{key:"renderValue",value:function(t,e){if(!0===e.toggle)return W(Ke||(Ke=yn([''])),t,this._hass);var n;if(e.attribute&&[ht,pt].includes(e.attribute))return W(Ye||(Ye=yn([""])),this._hass,t[null===(n=e.attribute)||void 0===n?void 0:n.replace("-","_")]);if(e.format&&mt.includes(e.format)){var i,o=e.attribute?null!==(i=t.attributes[e.attribute])&&void 0!==i?i:t[e.attribute]:t.state,r=new Date(o);return r instanceof Date&&!isNaN(r.getTime())?W(Qe||(Qe=yn([""])),this._hass,r,e.format):o}return qt(this._hass,t,e)}},{key:"renderIcon",value:function(t,e){var n,i=null!==(n=Wt(t,e))&&void 0!==n?n:!0===e.icon?t.attributes.icon||null:e.icon;return W(Xe||(Xe=yn([''])),Bt(e.icon_color),this._hass,t,i,e.state_color)}},{key:"renderWarning",value:function(){return W(tn||(tn=yn(["\n ","\n "])),this._hass.localize("ui.panel.lovelace.warning.entity_not_found","entity",this.config.entity))}},{key:"getGestureHandlers",value:function(t,e,n){var i,o,r,a,s,c,l,u=this;return!0===n.toggle?null:(this._actionHandlers.has(t)||this._actionHandlers.set(t,(i=function(t,i){return u.dispatchAction(e,n,t,i)},o={hasHold:!!n.hold_action,hasDoubleTap:!!n.double_tap_action},s=o.hasHold,c=o.hasDoubleTap,l=!1,{onDown:function(){l=!1,s&&(r=setTimeout(function(){l=!0},500))},onUp:function(){if(clearTimeout(r),l)return l=!1,void i(!0,!1);c?a?(clearTimeout(a),a=void 0,i(!1,!0)):a=setTimeout(function(){a=void 0,i(!1,!1)},250):i(!1,!1)},onCancel:function(){clearTimeout(r)}})),this._actionHandlers.get(t))}},{key:"dispatchAction",value:function(t,e,n,i){var o,r=i?e.double_tap_action:n?e.hold_action:null!==(o=e.tap_action)&&void 0!==o?o:{action:"more-info"};if(r&&"none"!==r.action){var a=i?"double_tap":n?"hold":"tap";xt(this,"hass-action",{config:gn({entity:r.entity||t},"".concat(a,"_action"),r),action:a})}}}],[{key:"getConfigElement",value:function(){return document.createElement("multiple-entity-row-editor")}},{key:"getStubConfig",value:function(t,e){var n,i,o=null!==(n=null!==(i=null==e?void 0:e.find(function(t){return t.startsWith("sensor.")}))&&void 0!==i?i:null==e?void 0:e[0])&&void 0!==n?n:"";return{entity:o}}},{key:"properties",get:function(){return{_hass:Object,config:Object,stateObj:Object}}},{key:"styles",get:function(){return r(Ft||(Ft=function(t,e){return e||(e=t.slice(0)),Object.freeze(Object.defineProperties(t,{raw:{value:Object.freeze(e)}}))}(["\n .icon-small {\n width: auto;\n }\n .entity {\n text-align: center;\n cursor: pointer;\n }\n .entity span {\n font-size: 10px;\n color: var(--multiple-entity-row-header-color, var(--secondary-text-color));\n }\n .entities-row {\n flex-direction: row;\n display: inline-flex;\n justify-content: space-between;\n align-items: center;\n }\n .entities-row .entity {\n margin-right: 16px;\n }\n .entities-row .entity:last-of-type {\n margin-right: 0;\n }\n .entities-column {\n flex-direction: column;\n display: flex;\n align-items: flex-end;\n justify-content: space-evenly;\n }\n .entities-column .entity div {\n display: inline-block;\n vertical-align: middle;\n }\n"])))}}])}(ut);customElements.define("multiple-entity-row",En),window.customCards=window.customCards||[],window.customCards.push({type:"multiple-entity-row",name:"Multiple Entity Row",description:"Show multiple entity states and attributes on a single entity row"})})(); \ No newline at end of file diff --git a/hass/settings/www/community/lovelace-multiple-entity-row/multiple-entity-row.js.gz b/hass/settings/www/community/lovelace-multiple-entity-row/multiple-entity-row.js.gz index c81639e..76682c2 100644 Binary files a/hass/settings/www/community/lovelace-multiple-entity-row/multiple-entity-row.js.gz and b/hass/settings/www/community/lovelace-multiple-entity-row/multiple-entity-row.js.gz differ