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 spstr strCommand.txt,tHeading.txt,"~",1
""" + navigation """ + navigation
print(head) print(head)
start = 3 start = 14
for i in range(1,7): for i in range(1,5):
idxstart = start + (i-1)*6 idxstart = start + (i-1)*6
item = f""" item = f"""
// get Type // get Type

View File

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

View File

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

View File

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

View File

@@ -8,23 +8,23 @@ text = sharedhead + """
text += """ text += """
//entity name //entity name
spstr strCommand.txt,entn.txt,"~",3 spstr strCommand.txt,entn.txt,"~",14
//currentTemp //currentTemp
spstr strCommand.txt,tCurTemp.txt,"~",4 spstr strCommand.txt,tCurTemp.txt,"~",15
//dstTemp //dstTemp
spstr strCommand.txt,tTmp.txt,"~",5 spstr strCommand.txt,tTmp.txt,"~",16
covx tTmp.txt,xTempDest1.val,0,0 covx tTmp.txt,xTempDest1.val,0,0
xTempDest.val=xTempDest1.val xTempDest.val=xTempDest1.val
//status //status
spstr strCommand.txt,tStatus.txt,"~",6 spstr strCommand.txt,tStatus.txt,"~",17
//minTemp //minTemp
spstr strCommand.txt,tTmp.txt,"~",7 spstr strCommand.txt,tTmp.txt,"~",18
covx tTmp.txt,xTempMin1.val,0,0 covx tTmp.txt,xTempMin1.val,0,0
//maxTemp //maxTemp
spstr strCommand.txt,tTmp.txt,"~",8 spstr strCommand.txt,tTmp.txt,"~",19
covx tTmp.txt,xTempMax1.val,0,0 covx tTmp.txt,xTempMax1.val,0,0
//tempStep //tempStep
spstr strCommand.txt,tTmp.txt,"~",9 spstr strCommand.txt,tTmp.txt,"~",20
covx tTmp.txt,xTempStep1.val,0,0 covx tTmp.txt,xTempStep1.val,0,0
// disable all buttons // disable all buttons
vis bt0,0 vis bt0,0
@@ -37,7 +37,7 @@ text += """
vis bt7,0 vis bt7,0
""" """
start = 10 start = 21
for i in range(0,8): for i in range(0,8):
idxstart = start + i*4 idxstart = start + i*4
text += f""" text += f"""
@@ -59,17 +59,17 @@ for i in range(0,8):
text += """ text += """
//Text tCurTempLbl //Text tCurTempLbl
spstr strCommand.txt,tCurTempLbl.txt,"~",42 spstr strCommand.txt,tCurTempLbl.txt,"~",53
//Text tStateLbl //Text tStateLbl
spstr strCommand.txt,tStateLbl.txt,"~",43 spstr strCommand.txt,tStateLbl.txt,"~",54
//Text tALbl //Text tALbl
spstr strCommand.txt,tALbl.txt,"~",44 spstr strCommand.txt,tALbl.txt,"~",55
//Text tCF //Text tCF
spstr strCommand.txt,tCF.txt,"~",45 spstr strCommand.txt,tCF.txt,"~",56
tCF1.txt=tCF.txt tCF1.txt=tCF.txt
tCF2.txt=tCF.txt tCF2.txt=tCF.txt
//Second Temperature //Second Temperature
spstr strCommand.txt,tTmp.txt,"~",46 spstr strCommand.txt,tTmp.txt,"~",57
if(tTmp.txt!="") if(tTmp.txt!="")
{ {
covx tTmp.txt,xTempDest2.val,0,0 covx tTmp.txt,xTempDest2.val,0,0
@@ -87,7 +87,7 @@ text += """
vis tCF2,1 vis tCF2,1
} }
//Show btDetail //Show btDetail
spstr strCommand.txt,tTmp.txt,"~",47 spstr strCommand.txt,tTmp.txt,"~",58
if(tTmp.txt!="1") if(tTmp.txt!="1")
{ {
vis btDetail,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 = """
// navigation icons // navigation icon left
spstr strCommand.txt,tId.txt,"~",2 spstr strCommand.txt,tTmp.txt,"~",2 //type
spstr tId.txt,tTmp.txt,"|",0 if(tTmp.txt=="delete"||tTmp.txt=="")
if(tTmp.txt=="0")
{ {
vis bPrev,0 vis bPrev,0
tsw mSwipePrev,0 }else
tsw mSwipeUp,0
}
if(tTmp.txt=="1")
{ {
// 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 vis bPrev,1
tsw mSwipePrev,1
tsw mSwipeUp,0
bPrev.txt=""
} }
if(tTmp.txt=="2")
{ // navigation icon right
vis bPrev,1 spstr strCommand.txt,tTmp.txt,"~",8 //type
tsw mSwipePrev,0 if(tTmp.txt=="delete"||tTmp.txt=="")
tsw mSwipeUp,1
bPrev.txt=""
}
spstr tId.txt,tTmp.txt,"|",1
if(tTmp.txt=="0")
{ {
vis bNext,0 vis bNext,0
tsw mSwipeNext,0 }else
}
if(tTmp.txt=="1")
{ {
// 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 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 uuid
import apis import apis
class Entity(object): class Entity(object):
@@ -20,8 +22,11 @@ class Entity(object):
self.entity_input_config = entity_input_config self.entity_input_config = entity_input_config
class Card(object): class Card(object):
def __init__(self, card_input_config, pos=None): def __init__(self, card_input_config, hidden=False):
self.pos = pos 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.raw_config = card_input_config
self.cardType = card_input_config.get("type", "unknown") self.cardType = card_input_config.get("type", "unknown")
self.title = card_input_config.get("title", "unknown") self.title = card_input_config.get("title", "unknown")
@@ -35,7 +40,7 @@ class Card(object):
for e in card_input_config.get("entities", []): for e in card_input_config.get("entities", []):
self.entities.append(Entity(e)) self.entities.append(Entity(e))
self.id = f"{self.cardType}_{self.key}".replace(".","_").replace("~","_").replace(" ","_") 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): def get_entity_names(self):
entityIds = [] entityIds = []
@@ -81,7 +86,6 @@ class LuiBackendConfig(object):
self._config = {} self._config = {}
self._config_cards = [] self._config_cards = []
self._config_screensaver = None self._config_screensaver = None
self._config_hidden_cards = []
self._DEFAULT_CONFIG = { self._DEFAULT_CONFIG = {
'panelRecvTopic': "tele/tasmota_your_mqtt_topic/RESULT", 'panelRecvTopic': "tele/tasmota_your_mqtt_topic/RESULT",
@@ -148,20 +152,33 @@ class LuiBackendConfig(object):
self._config = self.dict_recursive_update(inconfig, self._DEFAULT_CONFIG) self._config = self.dict_recursive_update(inconfig, self._DEFAULT_CONFIG)
apis.ha_api.log("Loaded config: %s", self._config) apis.ha_api.log("Loaded config: %s", self._config)
# parse cards displayed on panel # parse cards
pos = 0
for card in self.get("cards"): for card in self.get("cards"):
self._config_cards.append(Card(card, pos)) self._config_cards.append(Card(card))
pos = pos + 1
# 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 # parse screensaver
self._config_screensaver = Card(self.get("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"): 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 # 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_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): def get(self, name):
path = name.split(".") path = name.split(".")
@@ -182,8 +199,6 @@ class LuiBackendConfig(object):
entities = [] entities = []
for card in self._config_cards: for card in self._config_cards:
entities.extend(card.get_entity_names()) 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()) entities.extend(self._config_screensaver.get_entity_names())
return entities return entities
@@ -191,21 +206,35 @@ class LuiBackendConfig(object):
entities = [] entities = []
for card in self._config_cards: for card in self._config_cards:
entities.extend(card.get_entity_list()) entities.extend(card.get_entity_list())
for card in self._config_hidden_cards:
entities.extend(card.get_entity_list())
return entities return entities
def getCard(self, pos):
card = self._config_cards[pos%len(self._config_cards)]
return card
def searchCard(self, id): def searchCard(self, id):
id = id.replace("navigate.", "") id = id.replace("navigate.", "")
if id.startswith("uuid"):
return self.get_card_by_uuid(id)
# legacy type_key
for card in self._config_cards: for card in self._config_cards:
if card.id == id: if card.id == id:
return card return card
if self._config_screensaver.id == id: if self._config_screensaver.id == id:
return self._config_screensaver 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 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 datetime
import apis import apis
from helper import scale, pos_to_color, rgb_dec565 from helper import scale, pos_to_color, rgb_dec565
from pages import LuiPagesGen from pages import LuiPagesGen
class LuiController(object): class LuiController(object):
@@ -15,7 +13,7 @@ class LuiController(object):
self._current_card = self._config._config_screensaver self._current_card = self._config._config_screensaver
self._previous_cards = [] self._previous_cards = []
# first card (default, after startup) # 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) self._pages_gen = LuiPagesGen(config, send_mqtt_msg)
@@ -207,9 +205,9 @@ class LuiController(object):
if dstCard is not None: if dstCard is not None:
self._previous_cards = [] self._previous_cards = []
self._previous_cards.append(dstCard) 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: 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 # check for double tap if configured and render current page
if self._config.get("screensaver.doubleTapToUnlock") and int(value) >= 2: if self._config.get("screensaver.doubleTapToUnlock") and int(value) >= 2:
self._current_card = self._previous_cards.pop() self._current_card = self._previous_cards.pop()
@@ -227,28 +225,14 @@ class LuiController(object):
if button_type == "bExit": if button_type == "bExit":
self._pages_gen.render_card(self._current_card) self._pages_gen.render_card(self._current_card)
if button_type == "bUp": #if button_type == "bHome":
if self._previous_cards: # if self._previous_cards:
self._current_card = self._previous_cards.pop() # self._current_card = self._previous_cards[0]
else: # self._previous_cards.clear()
self._current_card = self._config.getCard(0) # else:
self._pages_gen.render_card(self._current_card) # self._current_card = self._config.getCard(0)
if button_type == "bHome": # self._pages_gen.render_card(self._current_card)
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)
elif entity_id == "updateDisplayNoYes" and value == "no": elif entity_id == "updateDisplayNoYes" and value == "no":
self._pages_gen.render_card(self._current_card) self._pages_gen.render_card(self._current_card)
@@ -295,14 +279,25 @@ class LuiController(object):
entity_id = le.entityId entity_id = le.entityId
if entity_id.startswith('navigate'): 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 # internal for navigation to nested pages
dstCard = self._config.searchCard(entity_id) else:
dstCard = self._config.searchCard(entity_id)
if dstCard is not None: 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._current_card = dstCard
self._pages_gen.render_card(self._current_card) self._pages_gen.render_card(self._current_card)
else: else:
apis.ha_api.log(f"No page with key {entity_id} found") 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'): elif entity_id.startswith('scene'):
apis.ha_api.get_entity(entity_id).call_service("turn_on") apis.ha_api.get_entity(entity_id).call_service("turn_on")
elif entity_id.startswith('script'): elif entity_id.startswith('script'):

View File

@@ -1,18 +1,19 @@
import json import json
import apis
class LuiMqttListener(object): class LuiMqttListener(object):
def __init__(self, mqtt_api, topic, controller, updater): def __init__(self, topic, controller, updater):
self._controller = controller self._controller = controller
self._updater = updater self._updater = updater
self._mqtt_api = mqtt_api
# Setup, mqtt subscription and callback # Setup, mqtt subscription and callback
mqtt_api.mqtt_subscribe(topic=topic) apis.mqtt_api.mqtt_subscribe(topic=topic)
mqtt_api.listen_event(self.mqtt_event_callback, "MQTT_MESSAGE", topic=topic, namespace='mqtt') apis.mqtt_api.listen_event(self.mqtt_event_callback, "MQTT_MESSAGE", topic=topic, namespace='mqtt')
def mqtt_event_callback(self, event_name, data, kwargs): 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 # 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): if("nlui_driver_version" in data):
@@ -22,7 +23,7 @@ class LuiMqttListener(object):
if("CustomRecv" not in data): if("CustomRecv" not in data):
return return
msg = data["CustomRecv"] 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 "," # Split message into parts seperated by ","
msg = msg.split(",") msg = msg.split(",")
# run action based on received command # run action based on received command
@@ -30,9 +31,7 @@ class LuiMqttListener(object):
if msg[1] == "startup": if msg[1] == "startup":
self._updater.request_berry_driver_version() self._updater.request_berry_driver_version()
display_firmware_version = int(msg[2]) display_firmware_version = int(msg[2])
model = None model = msg[3]
if display_firmware_version >= 23:
model = msg[3]
self._updater.set_current_display_firmware_version(display_firmware_version, model) self._updater.set_current_display_firmware_version(display_firmware_version, model)
# check for updates # check for updates
msg_send = self._updater.check_updates() msg_send = self._updater.check_updates()
@@ -60,9 +59,8 @@ class LuiMqttListener(object):
self._controller.detail_open(msg[2], msg[3]) self._controller.detail_open(msg[2], msg[3])
class LuiMqttSender(object): class LuiMqttSender(object):
def __init__(self, api, mqttapi, topic_send): def __init__(self, api, topic_send):
self._ha_api = api self._ha_api = api
self._mqtt_api = mqttapi
self._topic_send = topic_send self._topic_send = topic_send
self._prev_msg = "" self._prev_msg = ""
@@ -73,4 +71,4 @@ class LuiMqttSender(object):
if topic is None: if topic is None:
topic = self._topic_send topic = self._topic_send
self._ha_api.log(f"Sending MQTT Message: {msg}") 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 icons import get_action_icon
from helper import scale, rgb_dec565, rgb_brightness, get_attr_safe, convert_temperature from helper import scale, rgb_dec565, rgb_brightness, get_attr_safe, convert_temperature
from localization import get_translation from localization import get_translation
from config import Entity
# check Babel # check Babel
import importlib import importlib
@@ -32,43 +33,46 @@ class LuiPagesGen(object):
for overwrite_state, overwrite_val in overwrite.items(): for overwrite_state, overwrite_val in overwrite.items():
if overwrite_state == state: if overwrite_state == state:
return rgb_dec565(overwrite_val) 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 if ha_type == "alarm_control_panel":
default_color_on = rgb_dec565([253, 216, 53]) if entity.state == "disarmed":
default_color_off = rgb_dec565([68, 115, 158]) icon_color = rgb_dec565([13,160,53])
icon_color = default_color_on if entity.state in ["on", "unlocked", "above_horizon", "home", "active"] else default_color_off 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 ha_type == "climate":
if entity.state == "disarmed": if entity.state in ["auto", "heat_cool"]:
icon_color = rgb_dec565([13,160,53]) icon_color = 1024
if entity.state == "arming": if entity.state == "heat":
icon_color = rgb_dec565([244,180,0]) icon_color = 64512
if entity.state in ["armed_home", "armed_away", "armed_night", "armed_vacation", "pending", "triggered"]: if entity.state == "off":
icon_color = rgb_dec565([223,76,30]) 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 "rgb_color" in attr:
if entity.state in ["auto", "heat_cool"]: color = attr.rgb_color
icon_color = 1024 if "brightness" in attr:
if entity.state == "heat": color = rgb_brightness(color, attr.brightness)
icon_color = 64512 icon_color = rgb_dec565(color)
if entity.state == "off": elif "brightness" in attr:
icon_color = 35921 color = rgb_brightness([253, 216, 53], attr.brightness)
if entity.state == "cool": icon_color = rgb_dec565(color)
icon_color = 11487 return icon_color
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
def update_time(self, kwargs): def update_time(self, kwargs):
time = datetime.datetime.now().strftime(self._config.get("timeFormat")) time = datetime.datetime.now().strftime(self._config.get("timeFormat"))
@@ -201,7 +205,7 @@ class LuiPagesGen(object):
state = None state = None
self._send_mqtt_msg(get_screensaver_color_output(theme=theme, state=state)) 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 entityId = item.entityId
icon = item.iconOverride icon = item.iconOverride
colorOverride = item.colorOverride colorOverride = item.colorOverride
@@ -230,7 +234,8 @@ class LuiPagesGen(object):
if icon_res[-1] == ".": if icon_res[-1] == ".":
icon_res = icon_res[:-1] icon_res = icon_res[:-1]
else: 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}" return f"~button~{entityId}~{icon_res}~{icon_color}~{name}~{text}"
else: else:
return f"~text~{entityId}~{get_icon_id('alert-circle-outline')}~17299~page not found~" return f"~text~{entityId}~{get_icon_id('alert-circle-outline')}~17299~page not found~"
@@ -632,19 +637,33 @@ class LuiPagesGen(object):
self._send_mqtt_msg(command) self._send_mqtt_msg(command)
def render_card(self, card, send_page_type=True): 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 l = self.generate_entities_item(Entity(
r = 1 {
'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: if len(self._config._config_cards) == 1:
l = 0 l = "delete~~~~~"
r = 0 r = "delete~~~~~"
if card.pos is None:
l = 2 if card.hidden:
r = 0 l = f"x~navUp~{get_icon_id('mdi:arrow-up-bold')}~65535~~"
if self._config.get("homeButton"): r = "delete~~~~~"
r = 2 # r = 0
navigation = f"{l}|{r}" # if self._config.get("homeButton"):
# r = 2
navigation = f"{l}~{r}"
# Switch to page # Switch to page
if send_page_type: if send_page_type:

View File

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

View File

@@ -1,9 +1,9 @@
# Subpages # 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 ```yaml
- entity: navigate.cardGrid_testKey - entity: navigate.testKey
``` ```
will allow you to navigate to a cardGrid page with the configured key 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. You can override the status of navigation items, to make them look like different entities.
```yaml ```yaml
- entity: navigate.cardThermo_test - entity: navigate.test
status: climate.test status: climate.test
``` ```