mirror of
https://github.com/joBr99/nspanel-lovelace-ui.git
synced 2025-12-19 22:24:15 +01:00
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:
2059
HMI/README.md
2059
HMI/README.md
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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"""
|
||||
|
||||
@@ -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"""
|
||||
|
||||
@@ -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"""
|
||||
|
||||
@@ -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
360
HMI/code_gen/pages/out.txt
Normal 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++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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=""
|
||||
}
|
||||
"""
|
||||
BIN
HMI/nspanel.HMI
BIN
HMI/nspanel.HMI
Binary file not shown.
@@ -1 +1,2 @@
|
||||
ha_api = None
|
||||
ha_api = None
|
||||
mqtt_api = None
|
||||
@@ -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)
|
||||
@@ -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'):
|
||||
|
||||
@@ -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)
|
||||
@@ -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:
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user