mirror of
https://github.com/joBr99/nspanel-lovelace-ui.git
synced 2025-12-22 07:24:24 +01:00
added updater
This commit is contained in:
BIN
HMI/nspanel.HMI
BIN
HMI/nspanel.HMI
Binary file not shown.
BIN
HMI/nspanel.tft
BIN
HMI/nspanel.tft
Binary file not shown.
@@ -115,7 +115,7 @@ class LuiBackendConfig(object):
|
|||||||
self._config[k] = v
|
self._config[k] = v
|
||||||
LOGGER.info(f"Loaded config: {self._config}")
|
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)
|
self._page_config = PageNode(root_page)
|
||||||
|
|
||||||
LOGGER.info(f"Parsed Page config to the following Tree: \n {self._page_config.dump()}")
|
LOGGER.info(f"Parsed Page config to the following Tree: \n {self._page_config.dump()}")
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ class LuiController(object):
|
|||||||
self._config = config
|
self._config = config
|
||||||
self._send_mqtt_msg = send_mqtt_msg
|
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)
|
self._pages_gen = LuiPagesGen(ha_api, config, send_mqtt_msg)
|
||||||
|
|
||||||
@@ -28,8 +29,8 @@ class LuiController(object):
|
|||||||
# register callbacks
|
# register callbacks
|
||||||
self.register_callbacks()
|
self.register_callbacks()
|
||||||
|
|
||||||
def startup(self, display_firmware_version):
|
def startup(self):
|
||||||
LOGGER.info(f"Startup Event; Display Firmware Version is {display_firmware_version}")
|
LOGGER.info(f"Startup Event")
|
||||||
# send time and date on startup
|
# send time and date on startup
|
||||||
self._pages_gen.update_time("")
|
self._pages_gen.update_time("")
|
||||||
self._pages_gen.update_date("")
|
self._pages_gen.update_date("")
|
||||||
@@ -53,6 +54,12 @@ class LuiController(object):
|
|||||||
LOGGER.info(f"Got callback for: {entity}")
|
LOGGER.info(f"Got callback for: {entity}")
|
||||||
if entity in self._current_page.get_items():
|
if entity in self._current_page.get_items():
|
||||||
self._pages_gen.render_page(self._current_page)
|
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):
|
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} ")
|
LOGGER.debug(f"Button Press Event; entity_id: {entity_id}; button_type: {button_type}; value: {value} ")
|
||||||
# internal buttons
|
# internal buttons
|
||||||
if(entity_id == "screensaver" and button_type == "enter"):
|
if(entity_id == "screensaver" and button_type == "enter"):
|
||||||
# go to first child of root page (default, after startup)
|
self._pages_gen.render_page(self._current_page)
|
||||||
self._current_page = self._config._page_config.childs[0]
|
if(button_type == "bExit"):
|
||||||
self._pages_gen.render_page(self._current_page)
|
self._pages_gen.render_page(self._current_page)
|
||||||
|
|
||||||
if(button_type == "bNext"):
|
if(button_type == "bNext"):
|
||||||
@@ -75,8 +82,6 @@ class LuiController(object):
|
|||||||
if(button_type == "bPrev"):
|
if(button_type == "bPrev"):
|
||||||
self._current_page = self._current_page.prev()
|
self._current_page = self._current_page.prev()
|
||||||
self._pages_gen.render_page(self._current_page)
|
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
|
# buttons with actions on HA
|
||||||
if button_type == "OnOff":
|
if button_type == "OnOff":
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
class LuiBackendException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class LuiBackendConfigIncomplete(LuiBackendException):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class LuiBackendConfigError(LuiBackendException):
|
|
||||||
pass
|
|
||||||
@@ -6,8 +6,9 @@ LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class LuiMqttListener(object):
|
class LuiMqttListener(object):
|
||||||
|
|
||||||
def __init__(self, mqtt_api, topic, controller):
|
def __init__(self, mqtt_api, topic, controller, updater):
|
||||||
self._controller = controller
|
self._controller = controller
|
||||||
|
self._updater = updater
|
||||||
# Setup, mqtt subscription and callback
|
# Setup, mqtt subscription and callback
|
||||||
mqtt_api.mqtt_subscribe(topic=topic)
|
mqtt_api.mqtt_subscribe(topic=topic)
|
||||||
mqtt_api.listen_event(self.mqtt_event_callback, "MQTT_MESSAGE", topic=topic, namespace='mqtt')
|
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}')
|
LOGGER.info(f'MQTT callback for: {data}')
|
||||||
# Parse Json Message from Tasmota and strip out message from nextion display
|
# Parse Json Message from Tasmota and strip out message from nextion display
|
||||||
data = json.loads(data["payload"])
|
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):
|
if("CustomRecv" not in data):
|
||||||
return
|
return
|
||||||
msg = data["CustomRecv"]
|
msg = data["CustomRecv"]
|
||||||
@@ -27,9 +31,14 @@ class LuiMqttListener(object):
|
|||||||
if msg[0] == "event":
|
if msg[0] == "event":
|
||||||
if msg[1] == "startup":
|
if msg[1] == "startup":
|
||||||
display_firmware_version = int(msg[2])
|
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":
|
if msg[1] == "screensaverOpen":
|
||||||
self._controller.screensaver_open()
|
self._controller.weather_update("")
|
||||||
if msg[1] == "buttonPress2":
|
if msg[1] == "buttonPress2":
|
||||||
entity_id = msg[2]
|
entity_id = msg[2]
|
||||||
btype = msg[3]
|
btype = msg[3]
|
||||||
|
|||||||
@@ -268,4 +268,8 @@ class LuiPagesGen(object):
|
|||||||
|
|
||||||
def generate_shutter_detail_page(self, entity):
|
def generate_shutter_detail_page(self, entity):
|
||||||
pos = 100-int(entity.attributes.get("current_position", 50))
|
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")
|
||||||
72
apps/nspanel-lovelace-ui/luibackend/updater.py
Normal file
72
apps/nspanel-lovelace-ui/luibackend/updater.py
Normal file
@@ -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)
|
||||||
@@ -9,7 +9,7 @@ import hassapi as hass
|
|||||||
from luibackend.config import LuiBackendConfig
|
from luibackend.config import LuiBackendConfig
|
||||||
from luibackend.controller import LuiController
|
from luibackend.controller import LuiController
|
||||||
from luibackend.mqttListener import LuiMqttListener
|
from luibackend.mqttListener import LuiMqttListener
|
||||||
|
from luibackend.updater import Updater
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -60,14 +60,21 @@ class NsPanelLovelaceUIManager(hass.Hass):
|
|||||||
LOGGER.info(f"Sending MQTT Message: {msg}")
|
LOGGER.info(f"Sending MQTT Message: {msg}")
|
||||||
mqtt_api.mqtt_publish(topic_send, 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)
|
controller = LuiController(self, cfg, send_mqtt_msg)
|
||||||
|
|
||||||
topic_recv = cfg.get("panelRecvTopic")
|
desired_display_firmware_version = 17
|
||||||
mqtt_listener = LuiMqttListener(mqtt_api, topic_recv, controller)
|
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')
|
LOGGER.info('Started')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user