271 lines
10 KiB
Python
271 lines
10 KiB
Python
import secrets
|
|
import string
|
|
|
|
import apis
|
|
|
|
def uuid():
|
|
alphabet = string.ascii_letters + string.digits
|
|
return ''.join(secrets.choice(alphabet) for _ in range(10))
|
|
|
|
class Entity(object):
|
|
def __init__(self, entity_input_config):
|
|
self.uuid = f"uuid.{uuid()}"
|
|
if type(entity_input_config) is not dict:
|
|
self.entityId = "error"
|
|
else:
|
|
self.entityId = entity_input_config.get("entity", "unknown")
|
|
self.nameOverride = entity_input_config.get("name")
|
|
self.iconOverride = entity_input_config.get("icon")
|
|
self.colorOverride = entity_input_config.get("color")
|
|
self.status = entity_input_config.get("status")
|
|
self.condState = entity_input_config.get("state")
|
|
self.condStateNot = entity_input_config.get("state_not")
|
|
self.condTemplate = entity_input_config.get("state_template")
|
|
self.assumedState = entity_input_config.get("assumed_state", False)
|
|
self.stype = entity_input_config.get("type")
|
|
self.value = entity_input_config.get("value")
|
|
self.font = entity_input_config.get("font")
|
|
self.data = entity_input_config.get("data", {})
|
|
self.entity_input_config = entity_input_config
|
|
|
|
class Card(object):
|
|
def __init__(self, card_input_config, hidden=False):
|
|
self.uuid = f"uuid.{uuid()}"
|
|
self.uuid_prev = None
|
|
self.uuid_next = None
|
|
self.hidden = hidden
|
|
self.raw_config = card_input_config
|
|
self.cardType = card_input_config.get("type", "unknown")
|
|
self.title = card_input_config.get("title", "unknown")
|
|
self.key = card_input_config.get("key", "unknown")
|
|
self.nav1Override = None
|
|
if card_input_config.get("navItem1"):
|
|
self.nav1Override = Entity(card_input_config.get("navItem1"))
|
|
self.nav2Override = None
|
|
if card_input_config.get("navItem2"):
|
|
self.nav2Override = Entity(card_input_config.get("navItem2"))
|
|
self.sleepTimeout = card_input_config.get("sleepTimeout")
|
|
self.last_update = 0
|
|
self.cooldown = card_input_config.get("cooldown", 0)
|
|
# for single entity card like climate or media
|
|
self.entity = None
|
|
if card_input_config.get("entity") is not None:
|
|
self.entity = Entity(card_input_config)
|
|
# for pages like grid or entities
|
|
self.entities = []
|
|
for e in card_input_config.get("entities", []):
|
|
self.entities.append(Entity(e))
|
|
self.id = f"{self.cardType}_{self.key}".replace(".","_").replace("~","_").replace(" ","_")
|
|
|
|
def get_entity_names(self, uuid=False):
|
|
entityIds = {}
|
|
#apis.ha_api.log(f"test123 {self.entity.entityId}")
|
|
if self.entity is not None:
|
|
#entityIds[self.entity.uuid] = self.entity.entityId
|
|
entityIds.setdefault(self.entity.uuid, []).append(self.entity.entityId)
|
|
if self.entity.status is not None:
|
|
#entityIds[self.entity.uuid] = self.entity.status
|
|
entityIds.setdefault(self.entity.uuid, []).append(self.entity.status)
|
|
for e in self.entities:
|
|
#entityIds[e.uuid] = e.entityId
|
|
entityIds.setdefault(e.uuid, []).append(e.entityId)
|
|
if e.status is not None:
|
|
#entityIds[e.uuid] = e.status
|
|
entityIds.setdefault(e.uuid, []).append(e.status)
|
|
|
|
# additional keys to check
|
|
add_ent_keys = ['statusIcon1', 'statusIcon2', 'alarmControl']
|
|
for ent_key in add_ent_keys:
|
|
val = self.raw_config.get(ent_key)
|
|
if val is not None:
|
|
#entityIds[f"{ent_key}."] = val.get("entity")
|
|
entityIds.setdefault(self.entity.uuid, []).append(val.get("entity"))
|
|
if uuid:
|
|
return entityIds
|
|
else:
|
|
out = []
|
|
for l in entityIds.values():
|
|
out.extend(l)
|
|
return out
|
|
|
|
def get_entity_list(self):
|
|
entitys = []
|
|
if self.entity is not None:
|
|
entitys.append(self.entity)
|
|
if self.entities:
|
|
for e in self.entities:
|
|
entitys.append(e)
|
|
if self.nav1Override:
|
|
entitys.append(self.nav1Override)
|
|
if self.nav2Override:
|
|
entitys.append(self.nav2Override)
|
|
return entitys
|
|
|
|
|
|
class LuiBackendConfig(object):
|
|
|
|
def dict_recursive_update(self, source: dict, target: dict) -> dict:
|
|
for sk, sv in source.items():
|
|
if sk in target and isinstance(target[sk], dict):
|
|
target[sk] = self.dict_recursive_update(sv, target[sk])
|
|
else:
|
|
target[sk] = sv
|
|
return target
|
|
|
|
def __init__(self, ha_api, config_in):
|
|
apis.ha_api = ha_api
|
|
self._config = {}
|
|
self._config_cards = []
|
|
self._config_screensaver = None
|
|
|
|
self._DEFAULT_CONFIG = {
|
|
'panelRecvTopic': "tele/tasmota_your_mqtt_topic/RESULT",
|
|
'panelSendTopic': "cmnd/tasmota_your_mqtt_topic/CustomSend",
|
|
'updateMode': "auto-notify",
|
|
'model': "eu",
|
|
'sleepTimeout': 20,
|
|
'sleepBrightness': 20,
|
|
'screenBrightness': 100,
|
|
'defaultBackgroundColor': "ha-dark",
|
|
'featureExperimentalSliders': False,
|
|
'sleepTracking': None,
|
|
'sleepTrackingZones': ["not_home", "off"],
|
|
'sleepOverride': None,
|
|
'locale': "en_US",
|
|
'quiet': True,
|
|
'timeFormat': "%H:%M",
|
|
'dateFormatBabel': "full",
|
|
'dateAdditionalTemplate': "",
|
|
'timeAdditionalTemplate': "",
|
|
'dateFormat': "%A, %d. %B %Y",
|
|
'cards': [{
|
|
'type': 'cardEntities',
|
|
'entities': [{
|
|
'entity': 'iText.',
|
|
'name': 'MQTT Config successful',
|
|
'icon': 'mdi:check',
|
|
'color:': [0, 255, 0],
|
|
},{
|
|
'entity': 'iText.',
|
|
'name': 'Continue adding',
|
|
'icon': 'mdi:arrow-right-bold',
|
|
},{
|
|
'entity': 'iText.',
|
|
'name': 'cards to your',
|
|
'icon': 'mdi:card',
|
|
},{
|
|
'entity': 'iText.',
|
|
'name': 'apps.yaml',
|
|
'icon': 'mdi:cog',
|
|
}],
|
|
'title': 'Setup successful'
|
|
}],
|
|
'screensaver': {
|
|
'type': 'screensaver',
|
|
'entity': 'weather.example',
|
|
'weatherUnit': 'celsius',
|
|
'forecastSkip': 0,
|
|
'weatherOverrideForecast1': None,
|
|
'weatherOverrideForecast2': None,
|
|
'weatherOverrideForecast3': None,
|
|
'weatherOverrideForecast4': None,
|
|
'doubleTapToUnlock': False,
|
|
'alternativeLayout': False,
|
|
'defaultCard': None,
|
|
'key': 'screensaver'
|
|
},
|
|
'hiddenCards': []
|
|
}
|
|
|
|
self.load(config_in)
|
|
|
|
def load(self, inconfig):
|
|
apis.ha_api.log("Input config: %s", inconfig)
|
|
self._config = self.dict_recursive_update(inconfig, self._DEFAULT_CONFIG)
|
|
apis.ha_api.log("Loaded config: %s", self._config)
|
|
|
|
# parse cards
|
|
for card in self.get("cards"):
|
|
self._config_cards.append(Card(card))
|
|
|
|
# setup prev and next uuids
|
|
top_level_cards = list(filter(lambda card: not card.hidden, self._config_cards))
|
|
card_uuids = [card.uuid for card in top_level_cards]
|
|
|
|
prev_uuids = card_uuids[-1:] + card_uuids[:-1]
|
|
next_uuids = card_uuids[ 1:] + card_uuids[: 1]
|
|
|
|
if len(card_uuids) > 1:
|
|
for prev_uuids, card, next_uuids in zip(prev_uuids, top_level_cards, next_uuids):
|
|
(card.uuid_prev, card.uuid_next) = (prev_uuids, next_uuids)
|
|
|
|
# parse screensaver
|
|
self._config_screensaver = Card(self.get("screensaver"))
|
|
|
|
# parse hidden cards
|
|
for card in self.get("hiddenCards"):
|
|
self._config_cards.append(Card(card, hidden=True))
|
|
# all entites sorted by generated key, to be able to use short identifiers
|
|
self._config_entites_table = {x.uuid: x for x in self.get_all_entitys()}
|
|
self._config_card_table = {x.uuid: x for x in self._config_cards}
|
|
|
|
def get(self, name):
|
|
path = name.split(".")
|
|
value = self._config
|
|
for p in path:
|
|
if value is not None:
|
|
value = value.get(p, None)
|
|
if value is not None:
|
|
return value
|
|
# try to get a value from default config
|
|
value = self._DEFAULT_CONFIG
|
|
for p in path:
|
|
if value is not None:
|
|
value = value.get(p, None)
|
|
return value
|
|
|
|
def get_all_entity_names(self):
|
|
entities = []
|
|
for card in self._config_cards:
|
|
entities.extend(card.get_entity_names())
|
|
entities.extend(self._config_screensaver.get_entity_names())
|
|
return entities
|
|
|
|
def get_all_entitys(self):
|
|
entities = []
|
|
for card in self._config_cards:
|
|
entities.extend(card.get_entity_list())
|
|
return entities
|
|
|
|
def search_card(self, id):
|
|
id = id.replace("navigate.", "")
|
|
if id.startswith("uuid"):
|
|
return self.get_card_by_uuid(id)
|
|
# legacy type_key
|
|
for card in self._config_cards:
|
|
if card.id == id:
|
|
return card
|
|
if self._config_screensaver.id == id:
|
|
return self._config_screensaver
|
|
|
|
# just search for key
|
|
for card in self._config_cards:
|
|
if card.key == id:
|
|
return card
|
|
if self._config_screensaver.key == id:
|
|
return self._config_screensaver
|
|
|
|
def get_default_card(self):
|
|
defaultCard = self._config.get("screensaver.defaultCard")
|
|
if defaultCard is not None:
|
|
defaultCard = apis.ha_api.render_template(defaultCard)
|
|
defaultCard = self.search_card(defaultCard)
|
|
if defaultCard is not None:
|
|
return defaultCard
|
|
else:
|
|
return self._config_cards[0]
|
|
|
|
def get_card_by_uuid(self, uuid):
|
|
return self._config_card_table.get(uuid)
|
|
|