diff --git a/HMI/nspanel.HMI b/HMI/nspanel.HMI index bc99b3c1..e051071e 100644 Binary files a/HMI/nspanel.HMI and b/HMI/nspanel.HMI differ diff --git a/HMI/nspanel.tft b/HMI/nspanel.tft index b936ab79..f531197e 100644 Binary files a/HMI/nspanel.tft and b/HMI/nspanel.tft differ diff --git a/apps/nspanel-lovelace-ui/luibackend/config.py b/apps/nspanel-lovelace-ui/luibackend/config.py index dcb163bf..d2aa16b2 100644 --- a/apps/nspanel-lovelace-ui/luibackend/config.py +++ b/apps/nspanel-lovelace-ui/luibackend/config.py @@ -115,7 +115,7 @@ class LuiBackendConfig(object): self._config[k] = v LOGGER.info(f"Loaded config: {self._config}") - root_page = {"items": self.get("pages")} + root_page = {"items": self.get("pages"), "name": "root"} self._page_config = PageNode(root_page) LOGGER.info(f"Parsed Page config to the following Tree: \n {self._page_config.dump()}") diff --git a/apps/nspanel-lovelace-ui/luibackend/controller.py b/apps/nspanel-lovelace-ui/luibackend/controller.py index 837edfba..97a550ec 100644 --- a/apps/nspanel-lovelace-ui/luibackend/controller.py +++ b/apps/nspanel-lovelace-ui/luibackend/controller.py @@ -12,7 +12,8 @@ class LuiController(object): self._config = config self._send_mqtt_msg = send_mqtt_msg - self._current_page = None + # first child of root page (default, after startup) + self._current_page = self._config._page_config.childs[0] self._pages_gen = LuiPagesGen(ha_api, config, send_mqtt_msg) @@ -28,8 +29,8 @@ class LuiController(object): # register callbacks self.register_callbacks() - def startup(self, display_firmware_version): - LOGGER.info(f"Startup Event; Display Firmware Version is {display_firmware_version}") + def startup(self): + LOGGER.info(f"Startup Event") # send time and date on startup self._pages_gen.update_time("") self._pages_gen.update_date("") @@ -53,6 +54,12 @@ class LuiController(object): LOGGER.info(f"Got callback for: {entity}") if entity in self._current_page.get_items(): self._pages_gen.render_page(self._current_page) + # send detail page update, just in case + if self._current_page.type in ["cardGrid", "cardEntities"]: + if entity.startswith("light"): + self._pages_gen.generate_light_detail_page(entity) + if entity.startswith("switch"): + self._pages_gen.generate_shutter_detail_page(entity) def detail_open(self, detail_type, entity_id): @@ -65,8 +72,8 @@ class LuiController(object): LOGGER.debug(f"Button Press Event; entity_id: {entity_id}; button_type: {button_type}; value: {value} ") # internal buttons if(entity_id == "screensaver" and button_type == "enter"): - # go to first child of root page (default, after startup) - self._current_page = self._config._page_config.childs[0] + self._pages_gen.render_page(self._current_page) + if(button_type == "bExit"): self._pages_gen.render_page(self._current_page) if(button_type == "bNext"): @@ -75,8 +82,6 @@ class LuiController(object): if(button_type == "bPrev"): self._current_page = self._current_page.prev() self._pages_gen.render_page(self._current_page) - if(button_type == "bExit"): - self._pages_gen.render_page(self._current_page) # buttons with actions on HA if button_type == "OnOff": diff --git a/apps/nspanel-lovelace-ui/luibackend/execptions.py b/apps/nspanel-lovelace-ui/luibackend/execptions.py deleted file mode 100644 index b5a8e217..00000000 --- a/apps/nspanel-lovelace-ui/luibackend/execptions.py +++ /dev/null @@ -1,8 +0,0 @@ -class LuiBackendException(Exception): - pass - -class LuiBackendConfigIncomplete(LuiBackendException): - pass - -class LuiBackendConfigError(LuiBackendException): - pass \ No newline at end of file diff --git a/apps/nspanel-lovelace-ui/luibackend/mqttListener.py b/apps/nspanel-lovelace-ui/luibackend/mqttListener.py index ad4a7133..24bf8d87 100644 --- a/apps/nspanel-lovelace-ui/luibackend/mqttListener.py +++ b/apps/nspanel-lovelace-ui/luibackend/mqttListener.py @@ -6,8 +6,9 @@ LOGGER = logging.getLogger(__name__) class LuiMqttListener(object): - def __init__(self, mqtt_api, topic, controller): + def __init__(self, mqtt_api, topic, controller, updater): self._controller = controller + self._updater = updater # Setup, mqtt subscription and callback mqtt_api.mqtt_subscribe(topic=topic) mqtt_api.listen_event(self.mqtt_event_callback, "MQTT_MESSAGE", topic=topic, namespace='mqtt') @@ -17,6 +18,9 @@ class LuiMqttListener(object): LOGGER.info(f'MQTT callback for: {data}') # Parse Json Message from Tasmota and strip out message from nextion display data = json.loads(data["payload"]) + if("nlui_driver_version" in data): + msg = data["nlui_driver_version"] + self._updater.set_tasmota_driver_version(int(msg)) if("CustomRecv" not in data): return msg = data["CustomRecv"] @@ -27,9 +31,14 @@ class LuiMqttListener(object): if msg[0] == "event": if msg[1] == "startup": display_firmware_version = int(msg[2]) - self._controller.startup(display_firmware_version) + self._updater.set_current_display_firmware_version(display_firmware_version) + # check for updates + msg_send = self._updater.check_updates() + # send messages for current page + if not msg_send: + self._controller.startup() if msg[1] == "screensaverOpen": - self._controller.screensaver_open() + self._controller.weather_update("") if msg[1] == "buttonPress2": entity_id = msg[2] btype = msg[3] diff --git a/apps/nspanel-lovelace-ui/luibackend/pages.py b/apps/nspanel-lovelace-ui/luibackend/pages.py index d75f26b2..0184f365 100644 --- a/apps/nspanel-lovelace-ui/luibackend/pages.py +++ b/apps/nspanel-lovelace-ui/luibackend/pages.py @@ -268,4 +268,8 @@ class LuiPagesGen(object): def generate_shutter_detail_page(self, entity): pos = 100-int(entity.attributes.get("current_position", 50)) - self.send_mqtt_msg(f"entityUpdateDetail,{pos}") + self._send_mqtt_msg(f"entityUpdateDetail,{pos}") + + def send_message_page(self, id, heading, msg, b1, b2): + self._send_mqtt_msg(f"pageType,popupNotify") + self._send_mqtt_msg(f"entityUpdateDetail,|{id}|{heading}|65535|{b1}|65535|{b2}|65535|{msg}|65535|0") \ No newline at end of file diff --git a/apps/nspanel-lovelace-ui/luibackend/updater.py b/apps/nspanel-lovelace-ui/luibackend/updater.py new file mode 100644 index 00000000..93d16652 --- /dev/null +++ b/apps/nspanel-lovelace-ui/luibackend/updater.py @@ -0,0 +1,72 @@ +import logging + +LOGGER = logging.getLogger(__name__) + +class Updater: + def __init__(self, controller, mode, desired_display_firmware_version, desired_display_firmware_url, desired_tasmota_driver_version, desired_tasmota_driver_url): + self.desired_display_firmware_version = desired_display_firmware_version + self.desired_display_firmware_url = desired_display_firmware_url + self.desired_tasmota_driver_version = desired_tasmota_driver_version + self.desired_tasmota_driver_url = desired_tasmota_driver_url + + self.mode = mode + self.controller = controller + self.current_tasmota_driver_version = None + self.current_display_firmware_version = None + + def set_tasmota_driver_version(self, driver_version): + self.current_tasmota_driver_version = driver_version + def set_current_display_firmware_version(self, panel_version): + self.current_display_firmware_version = panel_version + + def check_pre_req(self): + # we need to know both versions to continue + if self.current_tasmota_driver_version is not None and self.current_display_firmware_version is not None: + # tasmota driver has to be at least version 2 for Update command + # and panel has to be at version 11 for notify commands + # version 16 for new button cmd format + if self.current_tasmota_driver_version >= 2 and self.current_display_firmware_version >= 16: + return True + return False + + def check_updates(self): + # return's true if a notification was send to the panel + # run pre req check + if self.check_pre_req(): + LOGGER.info("Update Pre-Check sucessful Tasmota Driver Version: %s Panel Version: %s", self.current_tasmota_driver_version, self.current_display_firmware_version) + # check if tasmota driver needs update + if self.current_tasmota_driver_version < self.desired_tasmota_driver_version: + LOGGER.info("Update of Tasmota Driver needed") + # in auto mode just do the update + if self.mode == "auto": + self.update_berry_driver() + return False + # send notification about the update + if self.mode == "auto-notify": + update_msg = "There's an update avalible for the tasmota berry driver, do you want to start the update now? If you encounter issues after the update or this message appears frequently, please checkthe manual and repeat the installation steps for the tasmota berry driver. " + self.controller._pages_gen.send_message_page("updateBerryNoYes", "Driver Update available!", update_msg, "Dismiss", "Yes") + return True + return False + # check if display firmware needs an update + if self.current_display_firmware_version < self.desired_display_firmware_version: + LOGGER.info("Update of Display Firmware needed") + # in auto mode just do the update + if self.mode == "auto": + self.update_panel_driver() + return False + # send notification about the update + if self.mode == "auto-notify": + update_msg = "There's a firmware update avalible for the nextion sceen inside of nspanel, do you want to start the update now? If the update fails check the installation manual and flash again over the tasmota console. Be pationed the update will take a while." + self.controller._pages_gen.send_message_page("updateDisplayNoYes", "Display Update available!", update_msg, "Dismiss", "Yes") + return True + return False + else: + LOGGER.info("Update Pre-Check failed Tasmota Driver Version: %s Panel Version: %s", self.current_tasmota_driver_version, self.current_display_firmware_version) + return False + + def update_berry_driver(self): + topic = self.controller._config["panelSendTopic"].replace("CustomSend", "UpdateDriverVersion") + self.controller._send_mqtt_msg(topic, self.desired_tasmota_driver_url) + def update_panel_driver(self): + topic = self.controller._config["panelSendTopic"].replace("CustomSend", "FlashNextion") + self.controller._send_mqtt_msg(topic, self.desired_display_firmware_url) diff --git a/apps/nspanel-lovelace-ui/nspanel-lovelace-ui.py b/apps/nspanel-lovelace-ui/nspanel-lovelace-ui.py index 8245afc5..a82bb5c8 100644 --- a/apps/nspanel-lovelace-ui/nspanel-lovelace-ui.py +++ b/apps/nspanel-lovelace-ui/nspanel-lovelace-ui.py @@ -9,7 +9,7 @@ import hassapi as hass from luibackend.config import LuiBackendConfig from luibackend.controller import LuiController from luibackend.mqttListener import LuiMqttListener - +from luibackend.updater import Updater LOGGER = logging.getLogger(__name__) @@ -60,14 +60,21 @@ class NsPanelLovelaceUIManager(hass.Hass): LOGGER.info(f"Sending MQTT Message: {msg}") mqtt_api.mqtt_publish(topic_send, msg) + # Request Tasmota Driver Version + mqtt_api.mqtt_publish(topic_send.replace("CustomSend", "GetDriverVersion"), "x") + controller = LuiController(self, cfg, send_mqtt_msg) - topic_recv = cfg.get("panelRecvTopic") - mqtt_listener = LuiMqttListener(mqtt_api, topic_recv, controller) - + desired_display_firmware_version = 17 + desired_display_firmware_url = "http://nspanel.pky.eu/lovelace-ui/github/nspanel-v1.8.0.tft" + desired_tasmota_driver_version = 3 + desired_tasmota_driver_url = "https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be" + mode = cfg.get("updateMode") + updater = Updater(controller, mode, desired_display_firmware_version, desired_display_firmware_url, desired_tasmota_driver_version, desired_tasmota_driver_url) - + topic_recv = cfg.get("panelRecvTopic") + mqtt_listener = LuiMqttListener(mqtt_api, topic_recv, controller, updater) LOGGER.info('Started')