start reworking navigation paramters (#644)

* modify cardGrid/cardEntities nav

* rework backend nav for new style

* fix some bugs

* update other pages with new nav paramters

* readd readme part
This commit is contained in:
joBr99
2022-12-28 20:00:44 +01:00
committed by GitHub
parent ff792a0bb3
commit f0c5b5b429
16 changed files with 2567 additions and 278 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -6,8 +6,8 @@ head = sharedhead + """
spstr strCommand.txt,tHeading.txt,"~",1
""" + navigation
print(head)
start = 3
for i in range(1,7):
start = 14
for i in range(1,5):
idxstart = start + (i-1)*6
item = f"""
// get Type

View File

@@ -6,7 +6,7 @@ head = sharedhead + """
spstr strCommand.txt,tHeading.txt,"~",1
""" + navigation
print(head)
start = 3
start = 14
for i in range(1,7):
idxstart = start + (i-1)*6
item = f"""

View File

@@ -8,31 +8,31 @@ head = sharedhead + """
print(head)
print("""
//entity name
spstr strCommand.txt,entn.txt,"~",3
spstr strCommand.txt,entn.txt,"~",14
//title
spstr strCommand.txt,tTitle.txt,"~",4
spstr strCommand.txt,tTitle.txt,"~",15
//title farbe
spstr strCommand.txt,tTmp.txt,"~",5
spstr strCommand.txt,tTmp.txt,"~",16
if(tTmp.txt!="")
{
covx tTmp.txt,tTitle.pco,0,0
}
//author
spstr strCommand.txt,tAuthor.txt,"~",6
spstr strCommand.txt,tAuthor.txt,"~",17
//author farbe
spstr strCommand.txt,tTmp.txt,"~",7
spstr strCommand.txt,tTmp.txt,"~",18
if(tTmp.txt!="")
{
covx tTmp.txt,tAuthor.pco,0,0
}
//volume
spstr strCommand.txt,tTmp.txt,"~",8
spstr strCommand.txt,tTmp.txt,"~",19
covx tTmp.txt,sys0,0,0
hVolume.val=sys0
//icon
spstr strCommand.txt,tPlayPause.txt,"~",9
spstr strCommand.txt,tPlayPause.txt,"~",20
// on off button
spstr strCommand.txt,tTmp.txt,"~",10
spstr strCommand.txt,tTmp.txt,"~",21
if(tTmp.txt=="disable")
{
vis t5,0
@@ -42,7 +42,7 @@ print("""
covx tTmp.txt,t5.pco,0,0
}
// shuffel btn
spstr strCommand.txt,tTmp.txt,"~",11
spstr strCommand.txt,tTmp.txt,"~",22
if(tTmp.txt=="disable")
{
vis tShuffle,0
@@ -54,7 +54,7 @@ print("""
""")
start = 12
start = 23
for i in range(1,7):
idxstart = start + (i-1)*6
item = f"""

View File

@@ -5,16 +5,16 @@ head = sharedhead + """
// command format: entityUpd,heading,navigation,colorHome,iconHome[,iconColor,icon,speed,valueUp,valueDown]x6
spstr strCommand.txt,tHeading.txt,"~",1
""" + navigation + """
// icon color home
spstr strCommand.txt,tTmp.txt,"~",3
// icon color home
spstr strCommand.txt,tTmp.txt,"~",14
covx tTmp.txt,t1.pco,0,0
// icon home
spstr strCommand.txt,t1.txt,"~",4
spstr strCommand.txt,t1.txt,"~",15
// text home
spstr strCommand.txt,tHome.txt,"~",5
spstr strCommand.txt,tHome.txt,"~",16
"""
print(head)
start = 6
start = 17
for i in range(0,6):
idxstart = start + (i)*4
item = f"""

View File

@@ -8,23 +8,23 @@ text = sharedhead + """
text += """
//entity name
spstr strCommand.txt,entn.txt,"~",3
spstr strCommand.txt,entn.txt,"~",14
//currentTemp
spstr strCommand.txt,tCurTemp.txt,"~",4
spstr strCommand.txt,tCurTemp.txt,"~",15
//dstTemp
spstr strCommand.txt,tTmp.txt,"~",5
spstr strCommand.txt,tTmp.txt,"~",16
covx tTmp.txt,xTempDest1.val,0,0
xTempDest.val=xTempDest1.val
//status
spstr strCommand.txt,tStatus.txt,"~",6
spstr strCommand.txt,tStatus.txt,"~",17
//minTemp
spstr strCommand.txt,tTmp.txt,"~",7
spstr strCommand.txt,tTmp.txt,"~",18
covx tTmp.txt,xTempMin1.val,0,0
//maxTemp
spstr strCommand.txt,tTmp.txt,"~",8
spstr strCommand.txt,tTmp.txt,"~",19
covx tTmp.txt,xTempMax1.val,0,0
//tempStep
spstr strCommand.txt,tTmp.txt,"~",9
spstr strCommand.txt,tTmp.txt,"~",20
covx tTmp.txt,xTempStep1.val,0,0
// disable all buttons
vis bt0,0
@@ -37,7 +37,7 @@ text += """
vis bt7,0
"""
start = 10
start = 21
for i in range(0,8):
idxstart = start + i*4
text += f"""
@@ -59,17 +59,17 @@ for i in range(0,8):
text += """
//Text tCurTempLbl
spstr strCommand.txt,tCurTempLbl.txt,"~",42
spstr strCommand.txt,tCurTempLbl.txt,"~",53
//Text tStateLbl
spstr strCommand.txt,tStateLbl.txt,"~",43
spstr strCommand.txt,tStateLbl.txt,"~",54
//Text tALbl
spstr strCommand.txt,tALbl.txt,"~",44
spstr strCommand.txt,tALbl.txt,"~",55
//Text tCF
spstr strCommand.txt,tCF.txt,"~",45
spstr strCommand.txt,tCF.txt,"~",56
tCF1.txt=tCF.txt
tCF2.txt=tCF.txt
//Second Temperature
spstr strCommand.txt,tTmp.txt,"~",46
spstr strCommand.txt,tTmp.txt,"~",57
if(tTmp.txt!="")
{
covx tTmp.txt,xTempDest2.val,0,0
@@ -87,7 +87,7 @@ text += """
vis tCF2,1
}
//Show btDetail
spstr strCommand.txt,tTmp.txt,"~",47
spstr strCommand.txt,tTmp.txt,"~",58
if(tTmp.txt!="1")
{
vis btDetail,1

360
HMI/code_gen/pages/out.txt Normal file
View File

@@ -0,0 +1,360 @@
// data available
if(usize>1)
{
bufferPos=0
while(bufferPos<usize)
{
// check for 0x55 0xBB - Command Init Secuence
if(u[bufferPos]==187&&u[bufferPos-1]==85)
{
//remove garbage at the start of the buffer if there's any to free buffer for command
if(u[bufferPos]!=1)
{
udelete bufferPos-1
}
//instruction is now aligned with buffer, because we deleted garbage before instrcution
//get length after init sequence (check if there are more than to bytes in buffer)
if(3<usize)
{
// check if serial buffer has reached the announced length
ucopy payloadLength,2,2,0
// we are only checking payload length so we have to skip first 3 bytes (init+payload length) (-1 because of < instead of <=)
payloadLength+=3
// payload length does also not contain crc, so we are adding another 2 bytes for crc
payloadLength+=2
if(payloadLength<usize)
{
// calculate crc
crcrest 1,0xFFFF
// u[2] contains payload legth at 3rd pos in buffer, we are calculating crc from 3rd pos with number of bytes from payload length
//crcputu 3,u[2]
// u[2] cotnains payload length, we are calculating a crc over the whole message, so we have to add 3 to the length from u[2]
crcputu 0,payloadLength-1
// get recived crc to be able to compare it
ucopy recvCrc,payloadLength-1,2,0
// compare crc with recived value
if(crcval==recvCrc)
{
// crc is okay
// here is the location where acual code should be
// write command to variable strCommand
ucopy strCommand.txt,4,payloadLength-5,0
// write instruction to tInstuction (debug output, but used as variable here, ui elements will be disabled by default)
spstr strCommand.txt,tInstruction.txt,"~",0
if(tInstruction.txt=="entityUpd")
{
// command format: entityUpd,heading,navigation,colorHome,iconHome[,iconColor,icon,speed,valueUp,valueDown]x6
spstr strCommand.txt,tHeading.txt,"~",1
// navigation icon left
spstr strCommand.txt,tTmp.txt,"~",2 //type
if(tTmp.txt=="delete"||tTmp.txt=="")
{
vis bPrev,0
}else
{
// get internal name
spstr strCommand.txt,nent1.txt,"~",3
// change icon
spstr strCommand.txt,bPrev.txt,"~",4
// change icon color
spstr strCommand.txt,tTmp.txt,"~",5
covx tTmp.txt,sys0,0,0
bPrev.pco=sys0
vis bPrev,1
}
// navigation icon right
spstr strCommand.txt,tTmp.txt,"~",8 //type
if(tTmp.txt=="delete"||tTmp.txt=="")
{
vis bNext,0
}else
{
// get internal name
spstr strCommand.txt,nent2.txt,"~",9
// change icon
spstr strCommand.txt,bNext.txt,"~",10
// change icon color
spstr strCommand.txt,tTmp.txt,"~",11
covx tTmp.txt,sys0,0,0
bNext.pco=sys0
vis bNext,1
}
// icon color home
spstr strCommand.txt,tTmp.txt,"~",14
covx tTmp.txt,t1.pco,0,0
// icon home
spstr strCommand.txt,t1.txt,"~",15
// text home
spstr strCommand.txt,tHome.txt,"~",16
// iconColor
spstr strCommand.txt,tTmp.txt,"~",17
covx tTmp.txt,t0Icon.pco,0,0
// icon
spstr strCommand.txt,t0Icon.txt,"~",18
// speed
spstr strCommand.txt,tTmp.txt,"~",19
covx tTmp.txt,t0Speed.val,0,0
// lower text
spstr strCommand.txt,t0u.txt,"~",20
if(t0Icon.txt!="")
{
vis t0Icon,1
vis t0u,1
vis h0,1
}else
{
vis t0Icon,0
vis t0u,0
vis h0,0
}
// iconColor
spstr strCommand.txt,tTmp.txt,"~",21
covx tTmp.txt,t1Icon.pco,0,0
// icon
spstr strCommand.txt,t1Icon.txt,"~",22
// speed
spstr strCommand.txt,tTmp.txt,"~",23
covx tTmp.txt,t1Speed.val,0,0
// lower text
spstr strCommand.txt,t1u.txt,"~",24
if(t1Icon.txt!="")
{
vis t1Icon,1
vis t1u,1
vis h1,1
}else
{
vis t1Icon,0
vis t1u,0
vis h1,0
}
// iconColor
spstr strCommand.txt,tTmp.txt,"~",25
covx tTmp.txt,t2Icon.pco,0,0
// icon
spstr strCommand.txt,t2Icon.txt,"~",26
// speed
spstr strCommand.txt,tTmp.txt,"~",27
covx tTmp.txt,t2Speed.val,0,0
// lower text
spstr strCommand.txt,t2u.txt,"~",28
if(t2Icon.txt!="")
{
vis t2Icon,1
vis t2u,1
vis h2,1
}else
{
vis t2Icon,0
vis t2u,0
vis h2,0
}
// iconColor
spstr strCommand.txt,tTmp.txt,"~",29
covx tTmp.txt,t3Icon.pco,0,0
// icon
spstr strCommand.txt,t3Icon.txt,"~",30
// speed
spstr strCommand.txt,tTmp.txt,"~",31
covx tTmp.txt,t3Speed.val,0,0
// lower text
spstr strCommand.txt,t3u.txt,"~",32
if(t3Icon.txt!="")
{
vis t3Icon,1
vis t3u,1
vis h3,1
}else
{
vis t3Icon,0
vis t3u,0
vis h3,0
}
// iconColor
spstr strCommand.txt,tTmp.txt,"~",33
covx tTmp.txt,t4Icon.pco,0,0
// icon
spstr strCommand.txt,t4Icon.txt,"~",34
// speed
spstr strCommand.txt,tTmp.txt,"~",35
covx tTmp.txt,t4Speed.val,0,0
// lower text
spstr strCommand.txt,t4u.txt,"~",36
if(t4Icon.txt!="")
{
vis t4Icon,1
vis t4u,1
vis h4,1
}else
{
vis t4Icon,0
vis t4u,0
vis h4,0
}
// iconColor
spstr strCommand.txt,tTmp.txt,"~",37
covx tTmp.txt,t5Icon.pco,0,0
// icon
spstr strCommand.txt,t5Icon.txt,"~",38
// speed
spstr strCommand.txt,tTmp.txt,"~",39
covx tTmp.txt,t5Speed.val,0,0
// lower text
spstr strCommand.txt,t5u.txt,"~",40
if(t5Icon.txt!="")
{
vis t5Icon,1
vis t5u,1
vis h5,1
}else
{
vis t5Icon,0
vis t5u,0
vis h5,0
}
}
if(tInstruction.txt=="pageType")
{
sleepValue=0
//command format pageType,specialPageName
//write name of speical page to tId
spstr strCommand.txt,tId.txt,"~",1
//save second arg if there's one
spstr strCommand.txt,tTmp.txt,"~",2
//save third arg if there's one
spstr strCommand.txt,pageIcons.tTmp2.txt,"~",3
spstr strCommand.txt,pageIcons.tTmp3.txt,"~",4
//we are going to exit this page with this command, so we have to clear the buffer, so we are not getting into a stupid loop ...
udelete payloadLength-1
bufferPos=0
if(tId.txt=="pageStartup")
{
page pageStartup
}
if(tId.txt=="screensaver")
{
page screensaver
}
if(tId.txt=="cardEntities")
{
page cardEntities
}
if(tId.txt=="cardGrid")
{
page cardGrid
}
if(tId.txt=="popupLight")
{
pageIcons.tTmp1.txt=tTmp.txt
page popupLight
}
if(tId.txt=="popupShutter")
{
pageIcons.tTmp1.txt=tTmp.txt
page popupShutter
}
if(tId.txt=="popupNotify")
{
page popupNotify
}
if(tId.txt=="cardThermo")
{
page cardThermo
}
if(tId.txt=="cardMedia")
{
page cardMedia
}
if(tId.txt=="cardAlarm")
{
page cardAlarm
}
if(tId.txt=="cardQR")
{
page cardQR
}
if(tId.txt=="cardPower")
{
page cardPower
}
if(tId.txt=="cardChart")
{
page cardChart
}
}
if(tInstruction.txt=="time")
{
// get set time to global variable
spstr strCommand.txt,pageIcons.vaTime.txt,"~",1
}
if(tInstruction.txt=="date")
{
// get set date to global variable
spstr strCommand.txt,pageIcons.vaDate.txt,"~",1
}
if(tInstruction.txt=="dimmode")
{
// get value
spstr strCommand.txt,tTmp.txt,"~",1
covx tTmp.txt,dimValue,0,0
// get value normal
spstr strCommand.txt,tTmp.txt,"~",2
covx tTmp.txt,dimValueNormal,0,0
dim=dimValueNormal
// get background color
spstr strCommand.txt,tTmp.txt,"~",3
if(tTmp.txt!="")
{
covx tTmp.txt,defaultBcoColor,0,0
}
// get font color
spstr strCommand.txt,tTmp.txt,"~",4
if(tTmp.txt!="")
{
covx tTmp.txt,defaultFontColor,0,0
}
}
if(tInstruction.txt=="timeout")
{
//set timeout to global var
spstr strCommand.txt,tTmp.txt,"~",1
covx tTmp.txt,sleepTimeout,0,0
}
// end of user code
udelete payloadLength-1
bufferPos=0
}
}
}
}
// next character
bufferPos++
}
}

View File

@@ -166,44 +166,39 @@ sharedfoot = """
"""
navigation = """
// navigation icons
spstr strCommand.txt,tId.txt,"~",2
spstr tId.txt,tTmp.txt,"|",0
if(tTmp.txt=="0")
// navigation icon left
spstr strCommand.txt,tTmp.txt,"~",2 //type
if(tTmp.txt=="delete"||tTmp.txt=="")
{
vis bPrev,0
tsw mSwipePrev,0
tsw mSwipeUp,0
}
if(tTmp.txt=="1")
}else
{
// get internal name
spstr strCommand.txt,nent1.txt,"~",3
// change icon
spstr strCommand.txt,bPrev.txt,"~",4
// change icon color
spstr strCommand.txt,tTmp.txt,"~",5
covx tTmp.txt,sys0,0,0
bPrev.pco=sys0
vis bPrev,1
tsw mSwipePrev,1
tsw mSwipeUp,0
bPrev.txt=""
}
if(tTmp.txt=="2")
{
vis bPrev,1
tsw mSwipePrev,0
tsw mSwipeUp,1
bPrev.txt=""
}
spstr tId.txt,tTmp.txt,"|",1
if(tTmp.txt=="0")
// navigation icon right
spstr strCommand.txt,tTmp.txt,"~",8 //type
if(tTmp.txt=="delete"||tTmp.txt=="")
{
vis bNext,0
tsw mSwipeNext,0
}
if(tTmp.txt=="1")
}else
{
// get internal name
spstr strCommand.txt,nent2.txt,"~",9
// change icon
spstr strCommand.txt,bNext.txt,"~",10
// change icon color
spstr strCommand.txt,tTmp.txt,"~",11
covx tTmp.txt,sys0,0,0
bNext.pco=sys0
vis bNext,1
tsw mSwipeNext,1
bNext.txt=""
}
if(tTmp.txt=="2")
{
vis bNext,1
bNext.txt=""
}
"""

Binary file not shown.

View File

@@ -1 +1,2 @@
ha_api = None
ha_api = None
mqtt_api = None

View File

@@ -1,4 +1,6 @@
from itertools import pairwise
import uuid
import apis
class Entity(object):
@@ -20,8 +22,11 @@ class Entity(object):
self.entity_input_config = entity_input_config
class Card(object):
def __init__(self, card_input_config, pos=None):
self.pos = pos
def __init__(self, card_input_config, hidden=False):
self.uuid = f"uuid.{uuid.uuid4().hex}"
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")
@@ -35,7 +40,7 @@ class Card(object):
for e in card_input_config.get("entities", []):
self.entities.append(Entity(e))
self.id = f"{self.cardType}_{self.key}".replace(".","_").replace("~","_").replace(" ","_")
#self._ha_api.log(f"Created Card {self.cardType} with pos {pos} and id {self.id}")
#self._ha_api.log(f"Created Card {self.cardType} and id {self.id}")
def get_entity_names(self):
entityIds = []
@@ -81,7 +86,6 @@ class LuiBackendConfig(object):
self._config = {}
self._config_cards = []
self._config_screensaver = None
self._config_hidden_cards = []
self._DEFAULT_CONFIG = {
'panelRecvTopic': "tele/tasmota_your_mqtt_topic/RESULT",
@@ -148,20 +152,33 @@ class LuiBackendConfig(object):
self._config = self.dict_recursive_update(inconfig, self._DEFAULT_CONFIG)
apis.ha_api.log("Loaded config: %s", self._config)
# parse cards displayed on panel
pos = 0
# parse cards
for card in self.get("cards"):
self._config_cards.append(Card(card, pos))
pos = pos + 1
self._config_cards.append(Card(card))
# setup prev and next uuids
top_level_cards = filter(lambda card: not card.hidden, self._config_cards)
first_card = None
last_card = None
for cur, next in pairwise(top_level_cards):
if first_card is None:
first_card = cur
last_card = next
cur.uuid_next = next.uuid
next.uuid_prev = cur.uuid
first_card.uuid_prev = last_card.uuid
last_card.uuid_next = first_card.uuid
# parse screensaver
self._config_screensaver = Card(self.get("screensaver"))
# parse hidden pages that can be accessed through navigate
# parse hidden cards
for card in self.get("hiddenCards"):
self._config_hidden_cards.append(Card(card))
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(".")
@@ -182,8 +199,6 @@ class LuiBackendConfig(object):
entities = []
for card in self._config_cards:
entities.extend(card.get_entity_names())
for card in self._config_hidden_cards:
entities.extend(card.get_entity_names())
entities.extend(self._config_screensaver.get_entity_names())
return entities
@@ -191,21 +206,35 @@ class LuiBackendConfig(object):
entities = []
for card in self._config_cards:
entities.extend(card.get_entity_list())
for card in self._config_hidden_cards:
entities.extend(card.get_entity_list())
return entities
def getCard(self, pos):
card = self._config_cards[pos%len(self._config_cards)]
return card
def searchCard(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
for card in self._config_hidden_cards:
if card.id == id:
# 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")
defaultCard = apis.ha_api.render_template(defaultCard)
if defaultCard is not None:
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)

View File

@@ -1,9 +1,7 @@
import datetime
import apis
from helper import scale, pos_to_color, rgb_dec565
from pages import LuiPagesGen
class LuiController(object):
@@ -15,7 +13,7 @@ class LuiController(object):
self._current_card = self._config._config_screensaver
self._previous_cards = []
# first card (default, after startup)
self._previous_cards.append(self._config.getCard(0))
self._previous_cards.append(self._config.get_default_card())
self._pages_gen = LuiPagesGen(config, send_mqtt_msg)
@@ -207,9 +205,9 @@ class LuiController(object):
if dstCard is not None:
self._previous_cards = []
self._previous_cards.append(dstCard)
# set _previous_cards to first page in case it's empty
# set _previous_cards to default page in case it's empty
if len(self._previous_cards) == 0:
self._previous_cards.append(self._config.getCard(0))
self._previous_cards.append(self._config.get_default_card())
# check for double tap if configured and render current page
if self._config.get("screensaver.doubleTapToUnlock") and int(value) >= 2:
self._current_card = self._previous_cards.pop()
@@ -227,28 +225,14 @@ class LuiController(object):
if button_type == "bExit":
self._pages_gen.render_card(self._current_card)
if button_type == "bUp":
if self._previous_cards:
self._current_card = self._previous_cards.pop()
else:
self._current_card = self._config.getCard(0)
self._pages_gen.render_card(self._current_card)
if button_type == "bHome":
if self._previous_cards:
self._current_card = self._previous_cards[0]
self._previous_cards.clear()
else:
self._current_card = self._config.getCard(0)
self._pages_gen.render_card(self._current_card)
if button_type == "bNext":
card = self._config.getCard(self._current_card.pos+1)
self._current_card = card
self._pages_gen.render_card(card)
if button_type == "bPrev":
card = self._config.getCard(self._current_card.pos-1)
self._current_card = card
self._pages_gen.render_card(card)
#if button_type == "bHome":
# if self._previous_cards:
# self._current_card = self._previous_cards[0]
# self._previous_cards.clear()
# else:
# self._current_card = self._config.getCard(0)
# self._pages_gen.render_card(self._current_card)
elif entity_id == "updateDisplayNoYes" and value == "no":
self._pages_gen.render_card(self._current_card)
@@ -295,14 +279,25 @@ class LuiController(object):
entity_id = le.entityId
if entity_id.startswith('navigate'):
# internal navigation for next/prev
if entity_id.startswith('navigate.uuid'):
dstCard = self._config.get_card_by_uuid(entity_id.replace('navigate.',''))
# internal for navigation to nested pages
dstCard = self._config.searchCard(entity_id)
else:
dstCard = self._config.searchCard(entity_id)
if dstCard is not None:
self._previous_cards.append(self._current_card)
if dstCard.hidden:
self._previous_cards.append(self._current_card)
self._current_card = dstCard
self._pages_gen.render_card(self._current_card)
else:
apis.ha_api.log(f"No page with key {entity_id} found")
if entity_id.startswith('navUp'):
if self._previous_cards:
self._current_card = self._previous_cards.pop()
else:
self._current_card = self._config.get_default_card()
self._pages_gen.render_card(self._current_card)
elif entity_id.startswith('scene'):
apis.ha_api.get_entity(entity_id).call_service("turn_on")
elif entity_id.startswith('script'):

View File

@@ -1,18 +1,19 @@
import json
import apis
class LuiMqttListener(object):
def __init__(self, mqtt_api, topic, controller, updater):
def __init__(self, topic, controller, updater):
self._controller = controller
self._updater = updater
self._mqtt_api = mqtt_api
# 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')
apis.mqtt_api.mqtt_subscribe(topic=topic)
apis.mqtt_api.listen_event(self.mqtt_event_callback, "MQTT_MESSAGE", topic=topic, namespace='mqtt')
def mqtt_event_callback(self, event_name, data, kwargs):
self._mqtt_api.log(f'MQTT callback for: {data}')
apis.mqtt_api.log(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):
@@ -22,7 +23,7 @@ class LuiMqttListener(object):
if("CustomRecv" not in data):
return
msg = data["CustomRecv"]
self._mqtt_api.log(f"Received Message from Screen: {msg}")
apis.mqtt_api.log(f"Received Message from Screen: {msg}")
# Split message into parts seperated by ","
msg = msg.split(",")
# run action based on received command
@@ -30,9 +31,7 @@ class LuiMqttListener(object):
if msg[1] == "startup":
self._updater.request_berry_driver_version()
display_firmware_version = int(msg[2])
model = None
if display_firmware_version >= 23:
model = msg[3]
model = msg[3]
self._updater.set_current_display_firmware_version(display_firmware_version, model)
# check for updates
msg_send = self._updater.check_updates()
@@ -60,9 +59,8 @@ class LuiMqttListener(object):
self._controller.detail_open(msg[2], msg[3])
class LuiMqttSender(object):
def __init__(self, api, mqttapi, topic_send):
def __init__(self, api, topic_send):
self._ha_api = api
self._mqtt_api = mqttapi
self._topic_send = topic_send
self._prev_msg = ""
@@ -73,4 +71,4 @@ class LuiMqttSender(object):
if topic is None:
topic = self._topic_send
self._ha_api.log(f"Sending MQTT Message: {msg}")
self._mqtt_api.mqtt_publish(topic, msg)
apis.mqtt_api.mqtt_publish(topic, msg)

View File

@@ -9,6 +9,7 @@ from icons import get_icon, get_icon_ha
from icons import get_action_icon
from helper import scale, rgb_dec565, rgb_brightness, get_attr_safe, convert_temperature
from localization import get_translation
from config import Entity
# check Babel
import importlib
@@ -32,43 +33,46 @@ class LuiPagesGen(object):
for overwrite_state, overwrite_val in overwrite.items():
if overwrite_state == state:
return rgb_dec565(overwrite_val)
if isinstance(entity, str):
default_color = rgb_dec565([68, 115, 158])
return default_color
else:
attr = entity.attributes
default_color_on = rgb_dec565([253, 216, 53])
default_color_off = rgb_dec565([68, 115, 158])
icon_color = default_color_on if entity.state in ["on", "unlocked", "above_horizon", "home", "active"] else default_color_off
attr = entity.attributes
default_color_on = rgb_dec565([253, 216, 53])
default_color_off = rgb_dec565([68, 115, 158])
icon_color = default_color_on if entity.state in ["on", "unlocked", "above_horizon", "home", "active"] else default_color_off
if ha_type == "alarm_control_panel":
if entity.state == "disarmed":
icon_color = rgb_dec565([13,160,53])
if entity.state == "arming":
icon_color = rgb_dec565([244,180,0])
if entity.state in ["armed_home", "armed_away", "armed_night", "armed_vacation", "pending", "triggered"]:
icon_color = rgb_dec565([223,76,30])
if ha_type == "alarm_control_panel":
if entity.state == "disarmed":
icon_color = rgb_dec565([13,160,53])
if entity.state == "arming":
icon_color = rgb_dec565([244,180,0])
if entity.state in ["armed_home", "armed_away", "armed_night", "armed_vacation", "pending", "triggered"]:
icon_color = rgb_dec565([223,76,30])
if ha_type == "climate":
if entity.state in ["auto", "heat_cool"]:
icon_color = 1024
if entity.state == "heat":
icon_color = 64512
if entity.state == "off":
icon_color = 35921
if entity.state == "cool":
icon_color = 11487
if entity.state == "dry":
icon_color = 60897
if entity.state == "fan_only":
icon_color = 35921
if ha_type == "climate":
if entity.state in ["auto", "heat_cool"]:
icon_color = 1024
if entity.state == "heat":
icon_color = 64512
if entity.state == "off":
icon_color = 35921
if entity.state == "cool":
icon_color = 11487
if entity.state == "dry":
icon_color = 60897
if entity.state == "fan_only":
icon_color = 35921
if "rgb_color" in attr:
color = attr.rgb_color
if "brightness" in attr:
color = rgb_brightness(color, attr.brightness)
icon_color = rgb_dec565(color)
elif "brightness" in attr:
color = rgb_brightness([253, 216, 53], attr.brightness)
icon_color = rgb_dec565(color)
return icon_color
if "rgb_color" in attr:
color = attr.rgb_color
if "brightness" in attr:
color = rgb_brightness(color, attr.brightness)
icon_color = rgb_dec565(color)
elif "brightness" in attr:
color = rgb_brightness([253, 216, 53], attr.brightness)
icon_color = rgb_dec565(color)
return icon_color
def update_time(self, kwargs):
time = datetime.datetime.now().strftime(self._config.get("timeFormat"))
@@ -201,7 +205,7 @@ class LuiPagesGen(object):
state = None
self._send_mqtt_msg(get_screensaver_color_output(theme=theme, state=state))
def generate_entities_item(self, item, cardType, temp_unit=""):
def generate_entities_item(self, item, cardType="cardGrid", temp_unit=""):
entityId = item.entityId
icon = item.iconOverride
colorOverride = item.colorOverride
@@ -230,7 +234,8 @@ class LuiPagesGen(object):
if icon_res[-1] == ".":
icon_res = icon_res[:-1]
else:
icon_color = rgb_dec565(colorOverride) if colorOverride is not None and type(colorOverride) is list else 17299
#icon_color = rgb_dec565(colorOverride) if colorOverride is not None and type(colorOverride) is list else 17299
icon_color = self.get_entity_color(entityId, overwrite=colorOverride)
return f"~button~{entityId}~{icon_res}~{icon_color}~{name}~{text}"
else:
return f"~text~{entityId}~{get_icon_id('alert-circle-outline')}~17299~page not found~"
@@ -631,20 +636,34 @@ class LuiPagesGen(object):
command += f"~{icon_color}~{icon}~{speed}~{entity.state}"
self._send_mqtt_msg(command)
def render_card(self, card, send_page_type=True):
apis.ha_api.log(f"Started rendering of page {card.pos} with type {card.cardType}")
l = 1
r = 1
def render_card(self, card, send_page_type=True):
l = self.generate_entities_item(Entity(
{
'entity': f'navigate.{card.uuid_prev}',
'icon': 'mdi:arrow-left-bold',
'color': [255, 255, 255],
}
))[1:]
r = self.generate_entities_item(Entity(
{
'entity': f'navigate.{card.uuid_next}',
'icon': 'mdi:arrow-right-bold',
'color': [255, 255, 255],
}
))[1:]
if len(self._config._config_cards) == 1:
l = 0
r = 0
if card.pos is None:
l = 2
r = 0
if self._config.get("homeButton"):
r = 2
navigation = f"{l}|{r}"
l = "delete~~~~~"
r = "delete~~~~~"
if card.hidden:
l = f"x~navUp~{get_icon_id('mdi:arrow-up-bold')}~65535~~"
r = "delete~~~~~"
# r = 0
# if self._config.get("homeButton"):
# r = 2
navigation = f"{l}~{r}"
# Switch to page
if send_page_type:

View File

@@ -5,43 +5,44 @@ from luibackend.controller import LuiController
from luibackend.mqtt import LuiMqttListener, LuiMqttSender
from luibackend.updater import Updater
import apis
class NsPanelLovelaceUIManager(hass.Hass):
def initialize(self):
self.log('Starting')
mqtt_api = self._mqtt_api = self.get_plugin_api("MQTT")
apis.ha_api = self
apis.mqtt_api = self.get_plugin_api("MQTT")
cfg = self._cfg = LuiBackendConfig(self, self.args["config"])
topic_send = cfg.get("panelSendTopic")
mqttsend = LuiMqttSender(self, mqtt_api, topic_send)
topic_recv = cfg.get("panelRecvTopic")
mqttsend = LuiMqttSender(self, topic_send)
# Request Tasmota Driver Version
mqtt_api.mqtt_publish(topic_send.replace("CustomSend", "GetDriverVersion"), "x")
apis.mqtt_api.mqtt_publish(topic_send.replace("CustomSend", "GetDriverVersion"), "x")
controller = LuiController(cfg, mqttsend.send_mqtt_msg)
desired_tasmota_driver_version = 8
desired_display_firmware_version = 46
version = "v3.7.0"
model = cfg.get("model")
if model == "us-l":
# us landscape version
desired_display_firmware_url = f"http://nspanel.pky.eu/lovelace-ui/github/nspanel-us-l-{version}.tft"
elif model == "us-p":
# us portrait version
desired_display_firmware_url = f"http://nspanel.pky.eu/lovelace-ui/github/nspanel-us-p-{version}.tft"
else:
# eu version
desired_display_firmware_url = f"http://nspanel.pky.eu/lovelace-ui/github/nspanel-{version}.tft"
desired_tasmota_driver_version = 8
match model:
case "us-l":
desired_display_firmware_url = f"http://nspanel.pky.eu/lovelace-ui/github/nspanel-us-l-{version}.tft"
case "us-p":
desired_display_firmware_url = f"http://nspanel.pky.eu/lovelace-ui/github/nspanel-us-p-{version}.tft"
case _:
desired_display_firmware_url = f"http://nspanel.pky.eu/lovelace-ui/github/nspanel-{version}.tft"
desired_tasmota_driver_url = "https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be"
mode = cfg.get("updateMode")
topic_send = cfg.get("panelSendTopic")
updater = Updater(self.log, mqttsend.send_mqtt_msg, topic_send, mode, desired_display_firmware_version, model, desired_display_firmware_url, desired_tasmota_driver_version, desired_tasmota_driver_url)
topic_recv = cfg.get("panelRecvTopic")
LuiMqttListener(mqtt_api, topic_recv, controller, updater)
LuiMqttListener(topic_recv, controller, updater)
self.log('Started')

View File

@@ -1,9 +1,9 @@
# Subpages
You can configure entities with with the prefix `navigate`, that are navigating to cards, in case it's hidden card, the navigation items will change and the arrow is bringing you back to the privious page.
You can configure entities with with the prefix `navigate`, that are navigating to cards, in case it's hidden card, the navigation items will change and the arrow is bringing you back to the previous page.
```yaml
- entity: navigate.cardGrid_testKey
- entity: navigate.testKey
```
will allow you to navigate to a cardGrid page with the configured key testKey
@@ -22,6 +22,6 @@ will allow you to navigate to a cardGrid page with the configured key testKey
You can override the status of navigation items, to make them look like different entities.
```yaml
- entity: navigate.cardThermo_test
- entity: navigate.test
status: climate.test
```