What about habpanelviewer app?
Hey Mark,
Amazing job! What kind of device do you show your Dashboard on? Is it a tablet / computer or?
I would like to know the size of the screen / resolution in order to achieve so many information on one screen :).
Hi Yoinkz
Thanks - I use a 23" Dell touchscreen (full hd - 1920x1080) hooked up to an Intel Compute Stick. I just run Chrome in kiosk mode.
Here are some other photos of the physical installation:
Wow, this is a high-end solution
Which Compute stick are you using? Is it fast and snappy using HABPanel?
Continuing the discussion from Examples of HABPanel Solutions:
I love the model, can you share the code?:sorrindo:
Wow, I love this too (and would love to have the code). But I hope that I wouldnât have an energy consumption of 3,6kW⊠were you heating up tea water and starting the dishwasher and washing machine at the same time?
Hi, Iâm pretty new to OH and HABPanel (thank you for that great software!), but Iâd like to show you the current status of my dashboardâŠ
My house will be built next year (planned with KNX and 1-wire) - so until now I integrated the things I donât need a the house for
The 2 graphs are only for testing - the one in the lower rigth corner will be replaced by a graph showing used and generated power, the graph on the left side will be replaced by âknx-scenesâ or important buttons for the living room.
On the right, you see outdoor temperature forecasts. If the change is more than +/- 2 K from today to tomorrow, it will be shown (at the moment the minus 4 K for the night).
Below that, we see the garbage dates and how many days until then. It is sorted by date. If tomorrow is a date, at 17:00 the icons starts blinking until I click it. If it is still blinking 21:00, I get a notification on my phone.
Then, we see birthdays (and also how many days until that date). Nothing special here
And finally, I show the missed calls from my Fritzbox. If there is a recorded call, I see a blinking icon, a click plays the call und marks as âoldâ. Therefore I modified a script I found here in the community (thanks for that!).
The green checkmark on the left shows that there are no weather warnings from DWD (deutscher Wetterdienst). If there are warnings, it looks like this (with a blinking warning symbol):
Ah, and in the midde I calculate if itâs good to ventilate the âbasementâ - when I have a sensor there in the future, this will be changed, but at the moment I calulate if the humidity inside will be below 65% after ventilating.
The circle shows how the sun will shine on our future house so we can already see at what time we will have sun/shaddow on which side.
Sorry for the long post - next one will be shorter. If someone wants to use a part of it, I will post the code.
Cheers, Jochen
This is awesome habpanels⊠keep up the good work.
WowâŠthat looks great! How did you implement the calender-infos? And how you are able to interact with them (for example clicking to deactivate/confirm)
Maybe you have same code snipets for us?
Hi Robert, sure, you can have all the snippets you want
I will explain the garbage stuff as itâs the more cpmplex one. I imported the dates to a google calendar and read them via caldavPersonal binding. In my case itâs called âMuellkalenderâ.
First, I only worked with a filter for each item, but then they are not sorted by date in my widget. If I just display the next 4 events, I have the ones with a weekly plan double and maybe âpaperâ with a monthly plan not shown in the list. Both is not what I want, I want each kind of garbage displaded once, but sorted by date. Thatâs why I introduced a âsecond layerâ of items:
/* Abfall-Kalender */
DateTime Restmuell "RestmĂŒll [%1$td.%1$tm.%1$tY]" <calendar> (gAbfall) { caldavPersonal="calendar:Muellkalender type:EVENT eventNr:1 value:START filter-name:'Restmuelltonne'" }
DateTime Biomuell "BiomĂŒll [%1$td.%1$tm.%1$tY]" <calendar> (gAbfall) { caldavPersonal="calendar:Muellkalender type:EVENT eventNr:1 value:START filter-name:'Biotonne'" }
DateTime Papiermuell "Papier [%1$td.%1$tm.%1$tY]" <calendar> (gAbfall) { caldavPersonal="calendar:Muellkalender type:EVENT eventNr:1 value:START filter-name:'Papiertonne'" }
DateTime RaWeg "RaWeg [%1$td.%1$tm.%1$tY]" <calendar> (gAbfall) { caldavPersonal="calendar:Muellkalender type:EVENT eventNr:1 value:START filter-name:'RaWeg'" }
DateTime Abfall_1_Datum "Abfall 1 Datum [%1$td.%1$tm.%1$tY]" <calendar> (gAbfall)
DateTime Abfall_2_Datum "Abfall 2 Datum [%1$td.%1$tm.%1$tY]" <calendar> (gAbfall)
DateTime Abfall_3_Datum "Abfall 3 Datum [%1$td.%1$tm.%1$tY]" <calendar> (gAbfall)
DateTime Abfall_4_Datum "Abfall 4 Datum [%1$td.%1$tm.%1$tY]" <calendar> (gAbfall)
String Abfall_1_Art "Abfall 1 Art [%s]" (gAbfall)
String Abfall_2_Art "Abfall 2 Art [%s]" (gAbfall)
String Abfall_3_Art "Abfall 3 Art [%s]" (gAbfall)
String Abfall_4_Art "Abfall 4 Art [%s]" (gAbfall)
String RestmuellTage "RestmĂŒll [%s]" (gAbfall)
String BiomuellTage "BiomĂŒll [%s]" (gAbfall)
String PapiermuellTage "Papier [%s]" (gAbfall)
String RaWegTage "RaWeg [%s]" (gAbfall)
String Abfall_1_Tage "Abfall 1 Tage [%s]" (gAbfall)
String Abfall_2_Tage "Abfall 2 Tage [%s]" (gAbfall)
String Abfall_3_Tage "Abfall 3 Tage [%s]" (gAbfall)
String Abfall_4_Tage "Abfall 4 Tage [%s]" (gAbfall)
Switch Abfall_Steht_An "Abfall steht an" (gAbfall)
As you see, the last one is a switch (âAbfall steht anâ means âgarbage is pendingâ). I use this for the confirmation.
Of course, I need some rules. The first one is for calculating the days from today to the date (if itâs today it shows âheuteâ, if itâs tomorrow it shows âmorgenâ, otherwise the number of days).
Second one is my sorting algorithm - Itâs maybe not the smartest algorithm, but itâs the one I think I understand
3rd rule is switching the switch on at 17:00 if garbage is tomorrow (called âmorgenâ). This is set to off by a click on the icon in the widget.
4th rule is informing me, if switch is still on at 20:30.
5th rule is ultimative escalation level informing my wife and me again. Never used up to now
rule "Tage bis Abfall berechnen"
when
Time cron "0 5 * 1/1 * ? *" or
Item Restmuell changed or
Item Biomuell changed or
Item Papiermuell changed or
Item RaWeg changed or
Item DelayedStartup changed from OFF to ON
then
logInfo("all.rules", "Tage bis Abfall berechnen")
//Restmuell
val DateTime varRestmuellDatum = new DateTime((Restmuell.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli).withTimeAtStartOfDay
val Long varRestmuellDiff = Math::round((varRestmuellDatum.millis - now.withTimeAtStartOfDay.millis) / (86400000.0))
if ( varRestmuellDiff == 0 ) {
RestmuellTage.postUpdate("heute")
} else if ( varRestmuellDiff == 1 ) {
RestmuellTage.postUpdate("morgen")
} else {
RestmuellTage.postUpdate(String::format("(%1$d T.)", varRestmuellDiff))
}
//Biomuell
val DateTime varBiomuellDatum = new DateTime((Biomuell.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli).withTimeAtStartOfDay
val Long varBiomuellDiff = Math::round((varBiomuellDatum.millis - now.withTimeAtStartOfDay.millis) / (86400000.0))
if ( varBiomuellDiff == 0 ) {
BiomuellTage.postUpdate("heute")
} else if ( varBiomuellDiff == 1 ) {
BiomuellTage.postUpdate("morgen")
} else {
BiomuellTage.postUpdate(String::format("(%1$d T.)", varBiomuellDiff))
}
//Papiermuell
val DateTime varPapiermuellDatum = new DateTime((Papiermuell.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli).withTimeAtStartOfDay
val Long varPapiermuellDiff = Math::round((varPapiermuellDatum.millis - now.withTimeAtStartOfDay.millis) / (86400000.0))
if ( varPapiermuellDiff == 0 ) {
PapiermuellTage.postUpdate("heute")
} else if ( varPapiermuellDiff == 1 ) {
PapiermuellTage.postUpdate("morgen")
} else {
PapiermuellTage.postUpdate(String::format("(%1$d T.)", varPapiermuellDiff))
}
//RaWeg
val DateTime varRaWegDatum = new DateTime((RaWeg.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli).withTimeAtStartOfDay
val Long varRaWegDiff = Math::round((varRaWegDatum.millis - now.withTimeAtStartOfDay.millis) / (86400000.0))
if ( varRaWegDiff == 0 ) {
RaWegTage.postUpdate("heute")
} else if ( varRaWegDiff == 1 ) {
RaWegTage.postUpdate("morgen")
} else {
RaWegTage.postUpdate(String::format("(%1$d T.)", varRaWegDiff))
}
end
rule "Abfalltermine sortieren"
when
Item Restmuell received update or
Item Biomuell received update or
Item Papiermuell received update or
Item RaWeg received update or
Item RestmuellTage changed or
Item PapiermuellTage changed or
Item BiomuellTage changed or
Item RaWegTage changed or
//Time cron "0 8 0 1/1 * ? *" or
Item DelayedStartup changed from OFF to ON
then
Thread::sleep(3000)
var DateTime varTempDatum
var DateTime varAbfall1Datum = new DateTime((Restmuell.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)
var DateTime varAbfall2Datum = new DateTime((Biomuell.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)
var DateTime varAbfall3Datum = new DateTime((Papiermuell.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)
var DateTime varAbfall4Datum = new DateTime((RaWeg.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)
var String varTempArt
var String varAbfall1Art = "Restmuell"
var String varAbfall2Art = "Biomuell"
var String varAbfall3Art = "Papiermuell"
var String varAbfall4Art = "RaWeg"
var String varTempTage
var String varAbfall1Tage = RestmuellTage.state.toString
var String varAbfall2Tage = BiomuellTage.state.toString
var String varAbfall3Tage = PapiermuellTage.state.toString
var String varAbfall4Tage = RaWegTage.state.toString
var i = 1
while ((i=i+1) < 6) {
if (varAbfall1Datum > varAbfall2Datum) {
varTempDatum = varAbfall1Datum
varAbfall1Datum = varAbfall2Datum
varAbfall2Datum = varTempDatum
varTempArt = varAbfall1Art
varAbfall1Art = varAbfall2Art
varAbfall2Art = varTempArt
varTempTage = varAbfall1Tage
varAbfall1Tage = varAbfall2Tage
varAbfall2Tage = varTempTage
if (varAbfall2Datum > varAbfall3Datum) {
varTempDatum = varAbfall2Datum
varAbfall2Datum = varAbfall3Datum
varAbfall3Datum = varTempDatum
varTempArt = varAbfall2Art
varAbfall2Art = varAbfall3Art
varAbfall3Art = varTempArt
varTempTage = varAbfall2Tage
varAbfall2Tage = varAbfall3Tage
varAbfall3Tage = varTempTage
if (varAbfall3Datum > varAbfall4Datum) {
varTempDatum = varAbfall3Datum
varAbfall3Datum = varAbfall4Datum
varAbfall4Datum = varTempDatum
varTempArt = varAbfall3Art
varAbfall3Art = varAbfall4Art
varAbfall4Art = varTempArt
varTempTage = varAbfall3Tage
varAbfall3Tage = varAbfall4Tage
varAbfall4Tage = varTempTage
}
}
}
if (varAbfall2Datum > varAbfall3Datum) {
varTempDatum = varAbfall2Datum
varAbfall2Datum = varAbfall3Datum
varAbfall3Datum = varTempDatum
varTempArt = varAbfall2Art
varAbfall2Art = varAbfall3Art
varAbfall3Art = varTempArt
varTempTage = varAbfall2Tage
varAbfall2Tage = varAbfall3Tage
varAbfall3Tage = varTempTage
if (varAbfall3Datum > varAbfall4Datum) {
varTempDatum = varAbfall3Datum
varAbfall3Datum = varAbfall4Datum
varAbfall4Datum = varTempDatum
varTempArt = varAbfall3Art
varAbfall3Art = varAbfall4Art
varAbfall4Art = varTempArt
varTempTage = varAbfall3Tage
varAbfall3Tage = varAbfall4Tage
varAbfall4Tage = varTempTage
}
}
if (varAbfall3Datum > varAbfall4Datum) {
varTempDatum = varAbfall3Datum
varAbfall3Datum = varAbfall4Datum
varAbfall4Datum = varTempDatum
varTempArt = varAbfall3Art
varAbfall3Art = varAbfall4Art
varAbfall4Art = varTempArt
varTempTage = varAbfall3Tage
varAbfall3Tage = varAbfall4Tage
varAbfall4Tage = varTempTage
}
}
Abfall_1_Datum.postUpdate(varAbfall1Datum.toString)
Abfall_2_Datum.postUpdate(varAbfall2Datum.toString)
Abfall_3_Datum.postUpdate(varAbfall3Datum.toString)
Abfall_4_Datum.postUpdate(varAbfall4Datum.toString)
Abfall_1_Art.postUpdate(varAbfall1Art)
Abfall_2_Art.postUpdate(varAbfall2Art)
Abfall_3_Art.postUpdate(varAbfall3Art)
Abfall_4_Art.postUpdate(varAbfall4Art)
Abfall_1_Tage.postUpdate(varAbfall1Tage)
Abfall_2_Tage.postUpdate(varAbfall2Tage)
Abfall_3_Tage.postUpdate(varAbfall3Tage)
Abfall_4_Tage.postUpdate(varAbfall4Tage)
end
rule "Abfall steht an - Blinkeding"
when
Time cron "0 0 17 1/1 * ? *"
then
if (Abfall_1_Tage.state.toString == "morgen") {
Abfall_Steht_An.postUpdate(ON)
}
end
rule "Abfall steht an - Informiere Jochen"
when
Time cron "0 30 20 1/1 * ? *"
then
if ((Abfall_Steht_An.state == ON) && (Abfall_1_Art != "RaWeg")) {
sendTelegram("haus_an_mich_bot", "%s solltest du noch raus stellen", Abfall_1_Art.state.toString)
}
end
rule "Abfall steht an - Informiere -Frau- und Jochen"
when
Time cron "0 30 21 1/1 * ? *"
then
if ((Abfall_Steht_An.state == ON) && (Abfall_1_Art != "RaWeg")) {
sendTelegram("haus_an_mich_bot", "Oh je, jetzt gibt's Ărger... %s steht wohl immer noch nicht drauĂen und -Frau- tritt dir gleich in den Hintern!", Abfall_1_Art.state.toString)
sendTelegram("haus_an_frau_bot", "%s steht wohl immer noch nicht drauĂen... So ein Schlumpf, der Jochen", Abfall_1_Art.state.toString)
}
end
An finally, the sorted items are displayed in a widget, with the blinking icon and confirmation click:
abfall.widget.json (8.8 KB)
Itâs working, but there still is some work to do, reducing the repeating style stuff by better usage of css e.g. But thatâs cosmetic stuff
Have fun
Is it possible to share your sun position code? Iâve got the same widget but for some reason mine wonât ever update (just displays correctly when first loaded and then never updates). Hoping to copy someone elseâs directly and see if I can get that to work.
Hi Ewan, I think thatâs the only widget where I only copy-pasted the code from this great community
I use this version:
And the code for the template widget is:
<object data="/static/shaddow.svg?{{itemValue('Sun_Azimuth')}}" type="image/svg+xml"></object>
I think the important part for the update is the â?{{âŠ}}â => do have that one in your widget? And is the name of the item correct?
I think, if we need futher debugging, we should switch to the Sun-Position-SVG-ThreadâŠ
Hi Jochen,
looks very impressive. Is this using a Theme like the Matrix Theme?
What widgets did you use for the top bar(s)? Did you create them yourself?
Would be possible to share your config and widgets?
Hi Garrett,
itâs a modified Orange Tree Theme, I got the idea from here:
This is my css file:
orange-tree-overrides.css (3.8 KB)
But most of it is not used in my case as I do not use the widgets from that post. So I could clean up that file, in theoryâŠ
The 2 top widgets I created after searching some code snippets here. I post them, but be carefull, they are not responsive or something (to be honest, Iâm sure itâs bad code) but for me they only have to look good on my wall monitor.
mainmenu.widget.json (3.4 KB)
uhrtemp.widget.json (1.1 KB)
Thanks.
How do you change the background color of the icons? or are they custom icons? css? When I use the widgets they display as white?
Regards
Hi Garrett,
I use the icons from the german âknx-user-forumâ. You find the files here:
I did not use css, but hard coded color not the best way, but the easiest one for the moment.
You can do that for all icons at once e.g. with Notepad++ by replacing all #FFFFFF by #FF9C27 in all files.
Ah⊠ok thanks.
The weather graph, is that a iframe from a website or are you generating that with the weather plugin?