mirror of
https://github.com/joBr99/nspanel-lovelace-ui.git
synced 2026-02-24 02:02:15 +01:00
Merge branch 'main' of https://github.com/joBr99/nspanel-lovelance-ui
This commit is contained in:
18
README.md
18
README.md
@@ -16,7 +16,7 @@ NsPanel Lovelace UI is a Firmware for the nextion screen inside of NSPanel in th
|
|||||||
- Screensaver Page with Time and Date
|
- Screensaver Page with Time and Date
|
||||||
|
|
||||||
It works with [Tasmota](https://tasmota.github.io/docs/) and MQTT.
|
It works with [Tasmota](https://tasmota.github.io/docs/) and MQTT.
|
||||||
To control the panel and update it with content from HomeAssistant there is an [AppDeamon](https://github.com/AppDaemon/appdaemon) App.
|
To control the panel and update it with content from HomeAssistant there is an [AppDaemon](https://github.com/AppDaemon/appdaemon) App.
|
||||||
|
|
||||||
See the following picture to get an idea of the look of this firmware for NSPanel.
|
See the following picture to get an idea of the look of this firmware for NSPanel.
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ See the following picture to get an idea of the look of this firmware for NSPane
|
|||||||
1. Install Tasmota to NSPanel
|
1. Install Tasmota to NSPanel
|
||||||
2. Install Berry Driver in Tasmota and setup MQTT
|
2. Install Berry Driver in Tasmota and setup MQTT
|
||||||
3. Flash Nextion Firmware
|
3. Flash Nextion Firmware
|
||||||
4. Install AppDeamon, setup MQTT and install Backend Application
|
4. Install AppDaemon, setup MQTT and install Backend Application
|
||||||
|
|
||||||
For more detailed Instructions see the following Sections:
|
For more detailed Instructions see the following Sections:
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ For more detailed Instructions see the following Sections:
|
|||||||
|
|
||||||
The NSPanel has two components an esp32 which runs Tasmota in this project and the nextion display, which is controlled by the esp32 via serial.
|
The NSPanel has two components an esp32 which runs Tasmota in this project and the nextion display, which is controlled by the esp32 via serial.
|
||||||
This project contains a display firmware, which can be controlled over serial/mqtt.
|
This project contains a display firmware, which can be controlled over serial/mqtt.
|
||||||
It's controlled by an AppDeamon Application, which crafts the required commands from your HomeAssistant Instance.
|
It's controlled by an AppDaemon Application, which crafts the required commands from your HomeAssistant Instance.
|
||||||
|
|
||||||
For more details on how the display firmware works see the [README File in the HMI Folder](HMI/README.md)
|
For more details on how the display firmware works see the [README File in the HMI Folder](HMI/README.md)
|
||||||
|
|
||||||
@@ -76,29 +76,29 @@ For more details on how the display firmware works see the [README File in the H
|
|||||||
|
|
||||||
### Installing AppDaemon
|
### Installing AppDaemon
|
||||||
|
|
||||||
The recommended backend application for this firmware is written in a python for [AppDeamon](https://github.com/AppDaemon/appdaemon).
|
The recommended backend application for this firmware is written in a python for [AppDaemon](https://github.com/AppDaemon/appdaemon).
|
||||||
This means it requires a working and running version of AppDaemon.
|
This means it requires a working and running version of AppDaemon.
|
||||||
|
|
||||||
The easiest way to install it is through HomeAssistant's Supervisor Add-on Store, it will be automaticly connected to your HomeAssistant Instance.
|
The easiest way to install it is through Home Assistant's Supervisor Add-on Store, it will be automaticly connected to your Home Assistant Instance.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Installing Studio Code Server (optional, recommended)
|
### Installing Studio Code Server (optional, recommended)
|
||||||
|
|
||||||
You will need a way a way to edit the `apps.yaml` config file in the appdeamon folder.
|
You will need a way to edit the `apps.yaml` config file in the Appdaemon folder.
|
||||||
Install Studio Code Server from Home Assistant's Supervisor Add-on Store to easily edit configuration Files on your HomeAssistant Instance.
|
Install Studio Code Server from Home Assistant's Supervisor Add-on Store to easily edit configuration Files on your HomeAssistant Instance.
|
||||||
|
|
||||||
### Installing HACS (optional, recommended)
|
### Installing HACS (optional, recommended)
|
||||||
|
|
||||||
HACS is the Home Assistant Community Store and allows for community integrations and
|
HACS is the Home Assistant Community Store and allows for community integrations and
|
||||||
automations to be updated cleanly and easily from the Home Assistant web user interface.
|
automations to be updated cleanly and easily from the Home Assistant web user interface.
|
||||||
It's simple to install the appdeamon app without HACS, but keeping up to date requires
|
It's simple to install the AppDaemon app without HACS, but keeping up to date requires
|
||||||
manual steps that HACS will handle for you: you will be notified of updates, and they
|
manual steps that HACS will handle for you: you will be notified of updates, and they
|
||||||
can be installed by a click on a button.
|
can be installed by a click on a button.
|
||||||
|
|
||||||
If you want to use HACS, you will have to follow [their documentation on how to install HACS](https://hacs.xyz/docs/setup/download).
|
If you want to use HACS, you will have to follow [their documentation on how to install HACS](https://hacs.xyz/docs/setup/download).
|
||||||
|
|
||||||
### Installing AppDeamon Backend Application
|
### Installing AppDaemon Backend Application
|
||||||
|
|
||||||
#### With HACS (recommended)
|
#### With HACS (recommended)
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ For the app to work you need a working MQTT Configuration in AppDaemon. Please c
|
|||||||
|
|
||||||
### Configure your NSPanel in AppDaemon
|
### Configure your NSPanel in AppDaemon
|
||||||
|
|
||||||
Confiure your NSPanel as you like, you need to edit the `apps.yaml` inside of your appdeamon config folder.
|
Confiure your NSPanel as you like, you need to edit the `apps.yaml` inside of your Appdaemon config folder.
|
||||||
You can have multiple nspanel sections.
|
You can have multiple nspanel sections.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import os
|
|||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
import appdaemon.plugins.hass.hassapi as hass
|
import hassapi as hass
|
||||||
|
|
||||||
class NsPanelLovelanceUIManager(hass.Hass):
|
class NsPanelLovelanceUIManager(hass.Hass):
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
@@ -42,11 +42,11 @@ class NsPanelLovelanceUI:
|
|||||||
found_current_dim_value = False
|
found_current_dim_value = False
|
||||||
for index, timeset in enumerate(sorted_timesets):
|
for index, timeset in enumerate(sorted_timesets):
|
||||||
self.api.run_daily(self.update_screensaver_brightness, timeset["time"], value=timeset["value"])
|
self.api.run_daily(self.update_screensaver_brightness, timeset["time"], value=timeset["value"])
|
||||||
self.api.log("current time %s", self.api.get_now().time())
|
self.api.log("Current time %s", self.api.get_now().time())
|
||||||
if self.api.parse_time(timeset["time"]) > self.api.get_now().time() and not found_current_dim_value:
|
if self.api.parse_time(timeset["time"]) > self.api.get_now().time() and not found_current_dim_value:
|
||||||
# first time after current time, set dim value
|
# first time after current time, set dim value
|
||||||
self.current_screensaver_brightness = sorted_timesets[index-1]["value"]
|
self.current_screensaver_brightness = sorted_timesets[index-1]["value"]
|
||||||
self.api.log("setting dim value to %s", sorted_timesets[index-1])
|
self.api.log("Setting dim value to %s", sorted_timesets[index-1])
|
||||||
found_current_dim_value = True
|
found_current_dim_value = True
|
||||||
# send screensaver brightness in case config has changed
|
# send screensaver brightness in case config has changed
|
||||||
self.update_screensaver_brightness(kwargs={"value": self.current_screensaver_brightness})
|
self.update_screensaver_brightness(kwargs={"value": self.current_screensaver_brightness})
|
||||||
@@ -62,10 +62,10 @@ class NsPanelLovelanceUI:
|
|||||||
# 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("CustomRecv" not in data):
|
if("CustomRecv" not in data):
|
||||||
self.api.log("Recived Message from Tasmota: %s", data, level="DEBUG")
|
self.api.log("Received Message from Tasmota: %s", data, level="DEBUG")
|
||||||
return
|
return
|
||||||
msg = data["CustomRecv"]
|
msg = data["CustomRecv"]
|
||||||
self.api.log("Recived Message from Tasmota: %s", msg, level="DEBUG")
|
self.api.log("Received Message from Tasmota: %s", msg, level="DEBUG")
|
||||||
|
|
||||||
# Split message into parts seperated by ","
|
# Split message into parts seperated by ","
|
||||||
msg = msg.split(",")
|
msg = msg.split(",")
|
||||||
@@ -75,7 +75,7 @@ class NsPanelLovelanceUI:
|
|||||||
if msg[0] == "event":
|
if msg[0] == "event":
|
||||||
|
|
||||||
if msg[1] == "startup":
|
if msg[1] == "startup":
|
||||||
self.api.log("handling startup event", level="DEBUG")
|
self.api.log("Handling startup event", level="DEBUG")
|
||||||
|
|
||||||
# send date and time
|
# send date and time
|
||||||
self.update_time("")
|
self.update_time("")
|
||||||
@@ -101,7 +101,7 @@ class NsPanelLovelanceUI:
|
|||||||
# Calculate current page
|
# Calculate current page
|
||||||
recv_page = int(msg[2])
|
recv_page = int(msg[2])
|
||||||
self.current_page_nr = recv_page % len(self.config["pages"])
|
self.current_page_nr = recv_page % len(self.config["pages"])
|
||||||
self.api.log("received pageOpen command, raw page: %i, calc page: %i", recv_page, self.current_page_nr, level="DEBUG")
|
self.api.log("Received pageOpen command, raw page: %i, calc page: %i", recv_page, self.current_page_nr, level="DEBUG")
|
||||||
# get type of current page
|
# get type of current page
|
||||||
page_type = self.config["pages"][self.current_page_nr]["type"]
|
page_type = self.config["pages"][self.current_page_nr]["type"]
|
||||||
# generate commands for current page
|
# generate commands for current page
|
||||||
@@ -117,7 +117,7 @@ class NsPanelLovelanceUI:
|
|||||||
self.handle_button_press(entity_id, btype, value)
|
self.handle_button_press(entity_id, btype, value)
|
||||||
|
|
||||||
if msg[1] == "pageOpenDetail":
|
if msg[1] == "pageOpenDetail":
|
||||||
self.api.log("received pageOpenDetail command", level="DEBUG")
|
self.api.log("Received pageOpenDetail command", level="DEBUG")
|
||||||
if(msg[2] == "popupLight"):
|
if(msg[2] == "popupLight"):
|
||||||
entity = self.api.get_entity(msg[3])
|
entity = self.api.get_entity(msg[3])
|
||||||
switch_val = 1 if entity.state == "on" else 0
|
switch_val = 1 if entity.state == "on" else 0
|
||||||
@@ -144,7 +144,7 @@ class NsPanelLovelanceUI:
|
|||||||
self.send_mqtt_msg("entityUpdateDetail,{0}".format(pos))
|
self.send_mqtt_msg("entityUpdateDetail,{0}".format(pos))
|
||||||
|
|
||||||
if msg[1] == "tempUpd":
|
if msg[1] == "tempUpd":
|
||||||
self.api.log("received tempUpd command", level="DEBUG")
|
self.api.log("Received tempUpd command", level="DEBUG")
|
||||||
temp = int(msg[4])/10
|
temp = int(msg[4])/10
|
||||||
self.api.get_entity(msg[3]).call_service("set_temperature", temperature=temp)
|
self.api.get_entity(msg[3]).call_service("set_temperature", temperature=temp)
|
||||||
|
|
||||||
@@ -228,9 +228,9 @@ class NsPanelLovelanceUI:
|
|||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
if self.api.entity_exists(item) or item == "delete":
|
if self.api.entity_exists(item) or item == "delete":
|
||||||
self.api.log("found configured item in homeassistant %s", item, level="DEBUG")
|
self.api.log("Found configured item in Home Assistant %s", item, level="DEBUG")
|
||||||
else:
|
else:
|
||||||
self.api.error("the following item does not exist in homeassistant, configuration error: %s", item)
|
self.api.error("The following item does not exist in Home Assistant, configuration error: %s", item)
|
||||||
raise Exception('Entity not found')
|
raise Exception('Entity not found')
|
||||||
|
|
||||||
def register_callbacks(self):
|
def register_callbacks(self):
|
||||||
@@ -242,7 +242,7 @@ class NsPanelLovelanceUI:
|
|||||||
items.extend(page["items"])
|
items.extend(page["items"])
|
||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
self.api.log("enable state callback for %s", item, level="DEBUG")
|
self.api.log("Enable state callback for %s", item, level="DEBUG")
|
||||||
self.api.handle = self.api.listen_state(self.state_change_callback, entity_id=item, attribute="all")
|
self.api.handle = self.api.listen_state(self.state_change_callback, entity_id=item, attribute="all")
|
||||||
|
|
||||||
def state_change_callback(self, entity, attribute, old, new, kwargs):
|
def state_change_callback(self, entity, attribute, old, new, kwargs):
|
||||||
@@ -250,9 +250,8 @@ class NsPanelLovelanceUI:
|
|||||||
|
|
||||||
page_type = current_page_config["type"]
|
page_type = current_page_config["type"]
|
||||||
|
|
||||||
self.api.log("got state_callback from {0}".format(entity), level="DEBUG")
|
self.api.log("Got state_callback from {0}".format(entity), level="DEBUG")
|
||||||
|
|
||||||
|
|
||||||
if page_type == "cardEntities":
|
if page_type == "cardEntities":
|
||||||
items = current_page_config["items"]
|
items = current_page_config["items"]
|
||||||
if entity in items:
|
if entity in items:
|
||||||
@@ -284,7 +283,7 @@ class NsPanelLovelanceUI:
|
|||||||
# type of item is the string before the "." in the item name
|
# type of item is the string before the "." in the item name
|
||||||
item_type = item.split(".")[0]
|
item_type = item.split(".")[0]
|
||||||
|
|
||||||
self.api.log("generating item command for %s with type %s", item, item_type, level="DEBUG")
|
self.api.log("Generating item command for %s with type %s", item, item_type, level="DEBUG")
|
||||||
|
|
||||||
if item_type == "delete":
|
if item_type == "delete":
|
||||||
return "entityUpd,{0},{1}".format(item_nr, item_type)
|
return "entityUpd,{0},{1}".format(item_nr, item_type)
|
||||||
@@ -368,7 +367,7 @@ class NsPanelLovelanceUI:
|
|||||||
|
|
||||||
|
|
||||||
def generate_page(self, page_number, page_type):
|
def generate_page(self, page_number, page_type):
|
||||||
self.api.log("generating page commands for page %i with type %s", self.current_page_nr, page_type, level="DEBUG")
|
self.api.log("Generating page commands for page %i with type %s", self.current_page_nr, page_type, level="DEBUG")
|
||||||
if page_type == "cardEntities":
|
if page_type == "cardEntities":
|
||||||
# Send page type
|
# Send page type
|
||||||
self.send_mqtt_msg("pageType,{0}".format(page_type))
|
self.send_mqtt_msg("pageType,{0}".format(page_type))
|
||||||
|
|||||||
Reference in New Issue
Block a user