mirror of
https://github.com/joBr99/nspanel-lovelace-ui.git
synced 2026-02-21 21:54:46 +01:00
Compare commits
73 Commits
01265faef9
...
v4.4.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d94d937d77 | ||
|
|
e5c1f0588a | ||
|
|
dd88ebe5da | ||
|
|
5536335ac9 | ||
|
|
df4fff6911 | ||
|
|
3dd83fde66 | ||
|
|
f50b1ececa | ||
|
|
ebee7b379e | ||
|
|
255db25f58 | ||
|
|
19050079d4 | ||
|
|
8d97f98a29 | ||
|
|
137ca5855e | ||
|
|
7707b48622 | ||
|
|
193546d1ed | ||
|
|
6703bca1d0 | ||
|
|
5739947586 | ||
|
|
5e1a7f2102 | ||
|
|
a0e574391b | ||
|
|
bd107d930a | ||
|
|
66f83732bb | ||
|
|
e796891d8e | ||
|
|
ba46bc9189 | ||
|
|
64ff369a90 | ||
|
|
92616429ba | ||
|
|
377383d672 | ||
|
|
52d405a6d6 | ||
|
|
2e1492c4fa | ||
|
|
16673df8cf | ||
|
|
cb4c26acfd | ||
|
|
fda7ca4574 | ||
|
|
8e2e8d1e82 | ||
|
|
4e36f47774 | ||
|
|
858dac73d0 | ||
|
|
3cccefb715 | ||
|
|
44640f33d2 | ||
|
|
2ae3b9bd8e | ||
|
|
2db991a371 | ||
|
|
2e52abd76c | ||
|
|
03c3acd214 | ||
|
|
c26b277c56 | ||
|
|
3f7fd40d17 | ||
|
|
0b01c0d236 | ||
|
|
3107b73430 | ||
|
|
5d421ae525 | ||
|
|
56a8495787 | ||
|
|
a12bc03dd7 | ||
|
|
6b1a65f8f4 | ||
|
|
9d94155480 | ||
|
|
3b46759134 | ||
|
|
8d21c653ae | ||
|
|
d983c44db7 | ||
|
|
467a1d92bb | ||
|
|
157d3e3e66 | ||
|
|
51bb320dce | ||
|
|
12c99c6857 | ||
|
|
62e905f336 | ||
|
|
9b5964a758 | ||
|
|
9c49a9c67d | ||
|
|
0a2461f4a5 | ||
|
|
49577ddbb6 | ||
|
|
6172b0c35f | ||
|
|
e7cc10692b | ||
|
|
221d2c717d | ||
|
|
2b54f742c5 | ||
|
|
f02eddcebe | ||
|
|
c25a5cef67 | ||
|
|
0f69ee951c | ||
|
|
fd6650db50 | ||
|
|
f2ad80665a | ||
|
|
cff9c94c27 | ||
|
|
b6fdc12820 | ||
|
|
0efbd9e23c | ||
|
|
cd0c015fea |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -58,5 +58,5 @@ _If applicable, add screenshots/pictures to help explain your problem._
|
|||||||
_Add any other context about the problem here._
|
_Add any other context about the problem here._
|
||||||
_Please note here in case you are using ioBroker_
|
_Please note here in case you are using ioBroker_
|
||||||
|
|
||||||
### PANEL / FIRMWARE VERION
|
### PANEL / FIRMWARE VERSION
|
||||||
_Please add the Panel/Firmware Version you are using (EU, US-L or US-P)_
|
_Please add the Panel/Firmware Version you are using (EU, US-L or US-P)_
|
||||||
|
|||||||
2
.github/ISSUE_TEMPLATE/feature-request.md
vendored
2
.github/ISSUE_TEMPLATE/feature-request.md
vendored
@@ -24,5 +24,5 @@ _A clear and concise description of what the feature should do._
|
|||||||
### ADDITIONAL CONTEXT
|
### ADDITIONAL CONTEXT
|
||||||
_Add any other context about the problem here._
|
_Add any other context about the problem here._
|
||||||
|
|
||||||
### PANEL / FIRMWARE VERION
|
### PANEL / FIRMWARE VERSION
|
||||||
_Please add the Panel/Firmware Version you are using (EU, US-L or US-P)_
|
_Please add the Panel/Firmware Version you are using (EU, US-L or US-P)_
|
||||||
|
|||||||
4
.github/workflows/builder.yaml
vendored
4
.github/workflows/builder.yaml
vendored
@@ -92,7 +92,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
if: env.BUILD_ARGS != '--test'
|
if: env.BUILD_ARGS != '--test'
|
||||||
uses: docker/login-action@v3.0.0
|
uses: docker/login-action@v3.1.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
@@ -100,7 +100,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build ${{ matrix.addon }} add-on
|
- name: Build ${{ matrix.addon }} add-on
|
||||||
if: steps.check.outputs.build_arch == 'true'
|
if: steps.check.outputs.build_arch == 'true'
|
||||||
uses: home-assistant/builder@2024.01.0
|
uses: home-assistant/builder@2024.03.5
|
||||||
with:
|
with:
|
||||||
args: |
|
args: |
|
||||||
${{ env.BUILD_ARGS }} \
|
${{ env.BUILD_ARGS }} \
|
||||||
|
|||||||
@@ -102,6 +102,28 @@
|
|||||||
│ crcputs sys0,2
|
│ crcputs sys0,2
|
||||||
│ crcputs tSend.txt,0
|
│ crcputs tSend.txt,0
|
||||||
│ //send cmd
|
│ //send cmd
|
||||||
|
│ --- HMI/n2t-out/popupLight.txt
|
||||||
|
├── +++ HMI/US/landscape/n2t-out/popupLight.txt
|
||||||
|
│ @@ -453,19 +453,14 @@
|
||||||
|
│ 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
|
||||||
|
│ spstr strCommand.txt,tTmp.txt,"~",1
|
||||||
|
│ if(tInstruction.txt=="entityUpdateDetail"&&entn.txt==tTmp.txt)
|
||||||
|
│ {
|
||||||
|
│ // change icon
|
||||||
|
│ - spstr strCommand.txt,tTmp.txt,"~",2
|
||||||
|
│ - if(tTmp.txt!="")
|
||||||
|
│ - {
|
||||||
|
│ - tIcon1.txt=tTmp.txt
|
||||||
|
│ - }
|
||||||
|
│ //spstr strCommand.txt,tIcon1.txt,"~",2
|
||||||
|
│ vis tIcon1,1
|
||||||
|
│ // change icon color
|
||||||
|
│ spstr strCommand.txt,tTmp.txt,"~",3
|
||||||
|
│ covx tTmp.txt,sys0,0,0
|
||||||
|
│ tIcon1.pco=sys0
|
||||||
|
│ // get Button State
|
||||||
│ --- HMI/n2t-out/popupNotify.txt
|
│ --- HMI/n2t-out/popupNotify.txt
|
||||||
├── +++ HMI/US/landscape/n2t-out/popupNotify.txt
|
├── +++ HMI/US/landscape/n2t-out/popupNotify.txt
|
||||||
│ @@ -439,18 +439,14 @@
|
│ @@ -439,18 +439,14 @@
|
||||||
@@ -521,22 +543,3 @@
|
|||||||
│ spstr strCommand.txt,tNotifyText.txt,"~",2
|
│ spstr strCommand.txt,tNotifyText.txt,"~",2
|
||||||
│ if(tNotifyHead.txt!=""||tNotifyText.txt!="")
|
│ if(tNotifyHead.txt!=""||tNotifyText.txt!="")
|
||||||
│ {
|
│ {
|
||||||
│ @@ -952,14 +812,18 @@
|
|
||||||
│ {
|
|
||||||
│ page cardPower
|
|
||||||
│ }
|
|
||||||
│ if(tId.txt=="cardChart")
|
|
||||||
│ {
|
|
||||||
│ page cardChart
|
|
||||||
│ }
|
|
||||||
│ + if(tId.txt=="cardLChart")
|
|
||||||
│ + {
|
|
||||||
│ + page cardLChart
|
|
||||||
│ + }
|
|
||||||
│ }
|
|
||||||
│ if(tInstruction.txt=="timeout")
|
|
||||||
│ {
|
|
||||||
│ //set timeout to global var
|
|
||||||
│ spstr strCommand.txt,tTmp.txt,"~",1
|
|
||||||
│ covx tTmp.txt,sleepTimeout,0,0
|
|
||||||
│ }
|
|
||||||
|
|||||||
@@ -1985,6 +1985,26 @@
|
|||||||
│ Variable (string) entn
|
│ Variable (string) entn
|
||||||
│ Attributes
|
│ Attributes
|
||||||
│ Scope : local
|
│ Scope : local
|
||||||
|
│ @@ -453,19 +453,14 @@
|
||||||
|
│ 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
|
||||||
|
│ spstr strCommand.txt,tTmp.txt,"~",1
|
||||||
|
│ if(tInstruction.txt=="entityUpdateDetail"&&entn.txt==tTmp.txt)
|
||||||
|
│ {
|
||||||
|
│ // change icon
|
||||||
|
│ - spstr strCommand.txt,tTmp.txt,"~",2
|
||||||
|
│ - if(tTmp.txt!="")
|
||||||
|
│ - {
|
||||||
|
│ - tIcon1.txt=tTmp.txt
|
||||||
|
│ - }
|
||||||
|
│ //spstr strCommand.txt,tIcon1.txt,"~",2
|
||||||
|
│ vis tIcon1,1
|
||||||
|
│ // change icon color
|
||||||
|
│ spstr strCommand.txt,tTmp.txt,"~",3
|
||||||
|
│ covx tTmp.txt,sys0,0,0
|
||||||
|
│ tIcon1.pco=sys0
|
||||||
|
│ // get Button State
|
||||||
│ --- HMI/n2t-out/popupNotify.txt
|
│ --- HMI/n2t-out/popupNotify.txt
|
||||||
├── +++ HMI/US/portrait/n2t-out/popupNotify.txt
|
├── +++ HMI/US/portrait/n2t-out/popupNotify.txt
|
||||||
│ @@ -348,15 +348,15 @@
|
│ @@ -348,15 +348,15 @@
|
||||||
@@ -2466,22 +2486,3 @@
|
|||||||
│ spstr strCommand.txt,tNotifyText.txt,"~",2
|
│ spstr strCommand.txt,tNotifyText.txt,"~",2
|
||||||
│ if(tNotifyHead.txt!=""||tNotifyText.txt!="")
|
│ if(tNotifyHead.txt!=""||tNotifyText.txt!="")
|
||||||
│ {
|
│ {
|
||||||
│ @@ -952,14 +800,18 @@
|
|
||||||
│ {
|
|
||||||
│ page cardPower
|
|
||||||
│ }
|
|
||||||
│ if(tId.txt=="cardChart")
|
|
||||||
│ {
|
|
||||||
│ page cardChart
|
|
||||||
│ }
|
|
||||||
│ + if(tId.txt=="cardLChart")
|
|
||||||
│ + {
|
|
||||||
│ + page cardLChart
|
|
||||||
│ + }
|
|
||||||
│ }
|
|
||||||
│ if(tInstruction.txt=="timeout")
|
|
||||||
│ {
|
|
||||||
│ //set timeout to global var
|
|
||||||
│ spstr strCommand.txt,tTmp.txt,"~",1
|
|
||||||
│ covx tTmp.txt,sleepTimeout,0,0
|
|
||||||
│ }
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
+++ /dev/fd/62 2024-01-20 19:56:08.135834636 +0000
|
+++ /dev/fd/62 2024-02-25 11:03:09.634837907 +0000
|
||||||
+I/n2t-out/Program.s.txt
|
+I/n2t-out/Program.s.txt
|
||||||
++ HMI/US/portrait/n2t-out/Program.s.txt
|
++ HMI/US/portrait/n2t-out/Program.s.txt
|
||||||
+1 +12,11 @@
|
+1 +12,11 @@
|
||||||
@@ -686,6 +686,13 @@
|
|||||||
+ covx tTmp.txt,sys0,0,0
|
+ covx tTmp.txt,sys0,0,0
|
||||||
+ hSlider6.maxval=sys0
|
+ hSlider6.maxval=sys0
|
||||||
+ }
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if(tInstruction.txt=="pageType")
|
||||||
|
+ {
|
||||||
|
+ sleepValue=0
|
||||||
|
+ //command format pageType,specialPageName
|
||||||
|
+ //write name of speical page to tId
|
||||||
|
+ spstr strCommand.txt,tId.txt,"~",1
|
||||||
+I/n2t-out/cardGrid.txt
|
+I/n2t-out/cardGrid.txt
|
||||||
++ HMI/US/portrait/n2t-out/cardGrid.txt
|
++ HMI/US/portrait/n2t-out/cardGrid.txt
|
||||||
+ +7,14 @@
|
+ +7,14 @@
|
||||||
@@ -939,13 +946,6 @@
|
|||||||
+ spstr strCommand.txt,tEntity9.txt,"~",66
|
+ spstr strCommand.txt,tEntity9.txt,"~",66
|
||||||
+ vis tEntity9,1
|
+ vis tEntity9,1
|
||||||
+ }
|
+ }
|
||||||
+ }
|
|
||||||
+ if(tInstruction.txt=="pageType")
|
|
||||||
+ {
|
|
||||||
+ sleepValue=0
|
|
||||||
+ //command format pageType,specialPageName
|
|
||||||
+ //write name of speical page to tId
|
|
||||||
+ spstr strCommand.txt,tId.txt,"~",1
|
|
||||||
+I/n2t-out/cardLChart.txt
|
+I/n2t-out/cardLChart.txt
|
||||||
++ HMI/US/portrait/n2t-out/cardLChart.txt
|
++ HMI/US/portrait/n2t-out/cardLChart.txt
|
||||||
+ +7,14 @@
|
+ +7,14 @@
|
||||||
@@ -1527,6 +1527,26 @@
|
|||||||
+e (string) entn
|
+e (string) entn
|
||||||
+ributes
|
+ributes
|
||||||
+ Scope : local
|
+ Scope : local
|
||||||
|
+19 +453,14 @@
|
||||||
|
+ 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
|
||||||
|
+ spstr strCommand.txt,tTmp.txt,"~",1
|
||||||
|
+ if(tInstruction.txt=="entityUpdateDetail"&&entn.txt==tTmp.txt)
|
||||||
|
+ {
|
||||||
|
+ // change icon
|
||||||
|
+ spstr strCommand.txt,tTmp.txt,"~",2
|
||||||
|
+ if(tTmp.txt!="")
|
||||||
|
+ {
|
||||||
|
+ tIcon1.txt=tTmp.txt
|
||||||
|
+ }
|
||||||
|
+ //spstr strCommand.txt,tIcon1.txt,"~",2
|
||||||
|
+ vis tIcon1,1
|
||||||
|
+ // change icon color
|
||||||
|
+ spstr strCommand.txt,tTmp.txt,"~",3
|
||||||
|
+ covx tTmp.txt,sys0,0,0
|
||||||
|
+ tIcon1.pco=sys0
|
||||||
|
+ // get Button State
|
||||||
+I/n2t-out/popupNotify.txt
|
+I/n2t-out/popupNotify.txt
|
||||||
++ HMI/US/portrait/n2t-out/popupNotify.txt
|
++ HMI/US/portrait/n2t-out/popupNotify.txt
|
||||||
+15 +348,15 @@
|
+15 +348,15 @@
|
||||||
@@ -2008,22 +2028,3 @@
|
|||||||
+ spstr strCommand.txt,tNotifyText.txt,"~",2
|
+ spstr strCommand.txt,tNotifyText.txt,"~",2
|
||||||
+ if(tNotifyHead.txt!=""||tNotifyText.txt!="")
|
+ if(tNotifyHead.txt!=""||tNotifyText.txt!="")
|
||||||
+ {
|
+ {
|
||||||
+14 +800,18 @@
|
|
||||||
+ {
|
|
||||||
+ page cardPower
|
|
||||||
+ }
|
|
||||||
+ if(tId.txt=="cardChart")
|
|
||||||
+ {
|
|
||||||
+ page cardChart
|
|
||||||
+ }
|
|
||||||
+ if(tId.txt=="cardLChart")
|
|
||||||
+ {
|
|
||||||
+ page cardLChart
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ if(tInstruction.txt=="timeout")
|
|
||||||
+ {
|
|
||||||
+ //set timeout to global var
|
|
||||||
+ spstr strCommand.txt,tTmp.txt,"~",1
|
|
||||||
+ covx tTmp.txt,sleepTimeout,0,0
|
|
||||||
+ }
|
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ popupLightNew
|
|||||||
23 Component(s)
|
23 Component(s)
|
||||||
412 Line(s) of event code
|
412 Line(s) of event code
|
||||||
209 Unique line(s) of event code
|
209 Unique line(s) of event code
|
||||||
|
popupLight
|
||||||
|
28 Component(s)
|
||||||
|
417 Line(s) of event code
|
||||||
|
228 Unique line(s) of event code
|
||||||
cardGrid2
|
cardGrid2
|
||||||
52 Component(s)
|
52 Component(s)
|
||||||
703 Line(s) of event code
|
703 Line(s) of event code
|
||||||
@@ -54,10 +58,6 @@ cardLChart
|
|||||||
33 Component(s)
|
33 Component(s)
|
||||||
412 Line(s) of event code
|
412 Line(s) of event code
|
||||||
267 Unique line(s) of event code
|
267 Unique line(s) of event code
|
||||||
popupLight
|
|
||||||
28 Component(s)
|
|
||||||
412 Line(s) of event code
|
|
||||||
227 Unique line(s) of event code
|
|
||||||
cardPower
|
cardPower
|
||||||
54 Component(s)
|
54 Component(s)
|
||||||
541 Line(s) of event code
|
541 Line(s) of event code
|
||||||
@@ -66,10 +66,6 @@ cardThermo
|
|||||||
57 Component(s)
|
57 Component(s)
|
||||||
550 Line(s) of event code
|
550 Line(s) of event code
|
||||||
320 Unique line(s) of event code
|
320 Unique line(s) of event code
|
||||||
screensaver2
|
|
||||||
64 Component(s)
|
|
||||||
424 Line(s) of event code
|
|
||||||
264 Unique line(s) of event code
|
|
||||||
popupInSel
|
popupInSel
|
||||||
34 Component(s)
|
34 Component(s)
|
||||||
621 Line(s) of event code
|
621 Line(s) of event code
|
||||||
@@ -90,6 +86,10 @@ popupThermo
|
|||||||
44 Component(s)
|
44 Component(s)
|
||||||
523 Line(s) of event code
|
523 Line(s) of event code
|
||||||
276 Unique line(s) of event code
|
276 Unique line(s) of event code
|
||||||
|
screensaver2
|
||||||
|
64 Component(s)
|
||||||
|
428 Line(s) of event code
|
||||||
|
266 Unique line(s) of event code
|
||||||
cardEntities
|
cardEntities
|
||||||
67 Component(s)
|
67 Component(s)
|
||||||
1205 Line(s) of event code
|
1205 Line(s) of event code
|
||||||
@@ -98,5 +98,5 @@ cardEntities
|
|||||||
Total
|
Total
|
||||||
23 Page(s)
|
23 Page(s)
|
||||||
881 Component(s)
|
881 Component(s)
|
||||||
10769 Line(s) of event code
|
10778 Line(s) of event code
|
||||||
2466 Unique line(s) of event code
|
2466 Unique line(s) of event code
|
||||||
|
|||||||
@@ -806,6 +806,11 @@ Timer tmSerial
|
|||||||
if(tInstruction.txt=="entityUpdateDetail"&&entn.txt==tTmp.txt)
|
if(tInstruction.txt=="entityUpdateDetail"&&entn.txt==tTmp.txt)
|
||||||
{
|
{
|
||||||
// change icon
|
// change icon
|
||||||
|
spstr strCommand.txt,tTmp.txt,"~",2
|
||||||
|
if(tTmp.txt!="")
|
||||||
|
{
|
||||||
|
tIcon1.txt=tTmp.txt
|
||||||
|
}
|
||||||
//spstr strCommand.txt,tIcon1.txt,"~",2
|
//spstr strCommand.txt,tIcon1.txt,"~",2
|
||||||
vis tIcon1,1
|
vis tIcon1,1
|
||||||
// change icon color
|
// change icon color
|
||||||
|
|||||||
@@ -1794,6 +1794,10 @@ Timer tmSerial
|
|||||||
{
|
{
|
||||||
page cardChart
|
page cardChart
|
||||||
}
|
}
|
||||||
|
if(tId.txt=="cardLChart")
|
||||||
|
{
|
||||||
|
page cardLChart
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(tInstruction.txt=="timeout")
|
if(tInstruction.txt=="timeout")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -457,6 +457,11 @@ Timer tmSerial
|
|||||||
if(tInstruction.txt=="entityUpdateDetail"&&entn.txt==tTmp.txt)
|
if(tInstruction.txt=="entityUpdateDetail"&&entn.txt==tTmp.txt)
|
||||||
{
|
{
|
||||||
// change icon
|
// change icon
|
||||||
|
spstr strCommand.txt,tTmp.txt,"~",2
|
||||||
|
if(tTmp.txt!="")
|
||||||
|
{
|
||||||
|
tIcon1.txt=tTmp.txt
|
||||||
|
}
|
||||||
//spstr strCommand.txt,tIcon1.txt,"~",2
|
//spstr strCommand.txt,tIcon1.txt,"~",2
|
||||||
vis tIcon1,1
|
vis tIcon1,1
|
||||||
// change icon color
|
// change icon color
|
||||||
|
|||||||
@@ -956,6 +956,10 @@ Timer tmSerial
|
|||||||
{
|
{
|
||||||
page cardChart
|
page cardChart
|
||||||
}
|
}
|
||||||
|
if(tId.txt=="cardLChart")
|
||||||
|
{
|
||||||
|
page cardLChart
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(tInstruction.txt=="timeout")
|
if(tInstruction.txt=="timeout")
|
||||||
{
|
{
|
||||||
|
|||||||
BIN
HMI/nspanel.HMI
BIN
HMI/nspanel.HMI
Binary file not shown.
BIN
HMI/nspanel.tft
BIN
HMI/nspanel.tft
Binary file not shown.
@@ -65,3 +65,5 @@ SmartHomeNG: https://github.com/sisamiwe/shng-nspanel-plugin
|
|||||||
OpenHAB: https://github.com/donoo/o2n2l
|
OpenHAB: https://github.com/donoo/o2n2l
|
||||||
|
|
||||||
NodeRed: https://github.com/laluz742/node-red-contrib-nspanel-lui
|
NodeRed: https://github.com/laluz742/node-red-contrib-nspanel-lui
|
||||||
|
|
||||||
|
ESPHome without any Backend: https://github.com/olicooper/esphome-nspanel-lovelace-native
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
ha_api = None
|
ha_api = None
|
||||||
mqtt_api = None
|
mqtt_api = None
|
||||||
|
ad_api = None
|
||||||
@@ -132,6 +132,7 @@ class LuiBackendConfig(object):
|
|||||||
'sleepTrackingZones': ["not_home", "off"],
|
'sleepTrackingZones': ["not_home", "off"],
|
||||||
'sleepOverride': None,
|
'sleepOverride': None,
|
||||||
'locale': "en_US",
|
'locale': "en_US",
|
||||||
|
'quiet': True,
|
||||||
'timeFormat': "%H:%M",
|
'timeFormat': "%H:%M",
|
||||||
'dateFormatBabel': "full",
|
'dateFormatBabel': "full",
|
||||||
'dateAdditionalTemplate': "",
|
'dateAdditionalTemplate': "",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ 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
|
||||||
|
from luibackend.config import Card
|
||||||
|
|
||||||
class LuiController(object):
|
class LuiController(object):
|
||||||
|
|
||||||
@@ -458,3 +459,9 @@ class LuiController(object):
|
|||||||
apis.ha_api.get_entity(entity_id).call_service("pause")
|
apis.ha_api.get_entity(entity_id).call_service("pause")
|
||||||
if button_type == "timer-finish":
|
if button_type == "timer-finish":
|
||||||
apis.ha_api.get_entity(entity_id).call_service("finish")
|
apis.ha_api.get_entity(entity_id).call_service("finish")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_card(self) -> Card:
|
||||||
|
"""Used to get the current card"""
|
||||||
|
|
||||||
|
return self._current_card
|
||||||
|
|||||||
@@ -213,6 +213,9 @@ def get_icon_ha(entity_id, overwrite=None, stateOverwrite=None):
|
|||||||
entity = apis.ha_api.get_entity(entity_id)
|
entity = apis.ha_api.get_entity(entity_id)
|
||||||
state = entity.state if stateOverwrite is None else stateOverwrite
|
state = entity.state if stateOverwrite is None else stateOverwrite
|
||||||
|
|
||||||
|
if entity_id in ["sensor.weather_forecast_daily", "sensor.weather_forecast_hourly"]:
|
||||||
|
ha_type = "weather"
|
||||||
|
|
||||||
if overwrite is not None:
|
if overwrite is not None:
|
||||||
if type(overwrite) is str:
|
if type(overwrite) is str:
|
||||||
return get_icon_char(overwrite)
|
return get_icon_char(overwrite)
|
||||||
|
|||||||
@@ -77,12 +77,13 @@ 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, use_api, topic_send, api_panel_name):
|
def __init__(self, api, use_api, topic_send, api_panel_name, quiet):
|
||||||
self._ha_api = api
|
self._ha_api = api
|
||||||
self._use_api = use_api
|
self._use_api = use_api
|
||||||
self._topic_send = topic_send
|
self._topic_send = topic_send
|
||||||
self._api_panel_name = api_panel_name
|
self._api_panel_name = api_panel_name
|
||||||
self._prev_msg = ""
|
self._prev_msg = ""
|
||||||
|
self._quiet = quiet
|
||||||
|
|
||||||
def send_mqtt_msg(self, msg, topic=None, force=False):
|
def send_mqtt_msg(self, msg, topic=None, force=False):
|
||||||
if not force and self._prev_msg == msg:
|
if not force and self._prev_msg == msg:
|
||||||
@@ -90,7 +91,9 @@ class LuiMqttSender(object):
|
|||||||
return
|
return
|
||||||
self._prev_msg = msg
|
self._prev_msg = msg
|
||||||
|
|
||||||
apis.ha_api.log(f"Sending Message: {msg}")
|
if self._quiet is False:
|
||||||
|
apis.ha_api.log(f"Sending Message: {msg}")
|
||||||
|
|
||||||
if self._use_api:
|
if self._use_api:
|
||||||
apis.ha_api.call_service(service="esphome/" + self._api_panel_name + "_nspanelui_api_call", command=2, data=msg)
|
apis.ha_api.call_service(service="esphome/" + self._api_panel_name + "_nspanelui_api_call", command=2, data=msg)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -192,6 +192,9 @@ class LuiPagesGen(object):
|
|||||||
else:
|
else:
|
||||||
entityType = "delete"
|
entityType = "delete"
|
||||||
|
|
||||||
|
if entityId in ["sensor.weather_forecast_daily", "sensor.weather_forecast_hourly"]:
|
||||||
|
entityType = "weather"
|
||||||
|
|
||||||
apis.ha_api.log(f"Generating item for {entityId} with type {entityType}", level="DEBUG")
|
apis.ha_api.log(f"Generating item for {entityId} with type {entityType}", level="DEBUG")
|
||||||
|
|
||||||
status_entity = apis.ha_api.get_entity(item.status) if item.status and apis.ha_api.entity_exists(item.status) else None
|
status_entity = apis.ha_api.get_entity(item.status) if item.status and apis.ha_api.entity_exists(item.status) else None
|
||||||
@@ -221,7 +224,7 @@ class LuiPagesGen(object):
|
|||||||
if status_entity:
|
if status_entity:
|
||||||
icon_res = get_icon_ha(item.status, overwrite=icon)
|
icon_res = get_icon_ha(item.status, overwrite=icon)
|
||||||
icon_color = self.get_entity_color(status_entity, ha_type=item.status.split(".")[0], overwrite=colorOverride)
|
icon_color = self.get_entity_color(status_entity, ha_type=item.status.split(".")[0], overwrite=colorOverride)
|
||||||
if item.status.startswith("sensor") and (cardType == "cardGrid" or cardType == "cardGrid2") and item.iconOverride is None:
|
if item.status.startswith("sensor") and cardType in ["cardGrid", "cardGrid1", "cardGrid2"] and item.iconOverride is None:
|
||||||
icon_res = status_entity.state[:4]
|
icon_res = status_entity.state[:4]
|
||||||
if icon_res[-1] == ".":
|
if icon_res[-1] == ".":
|
||||||
icon_res = icon_res[:-1]
|
icon_res = icon_res[:-1]
|
||||||
@@ -245,7 +248,7 @@ class LuiPagesGen(object):
|
|||||||
if status_entity:
|
if status_entity:
|
||||||
icon_id = get_icon_ha(item.status, overwrite=icon)
|
icon_id = get_icon_ha(item.status, overwrite=icon)
|
||||||
icon_color = self.get_entity_color(status_entity, ha_type=item.status.split(".")[0], overwrite=colorOverride)
|
icon_color = self.get_entity_color(status_entity, ha_type=item.status.split(".")[0], overwrite=colorOverride)
|
||||||
if item.status.startswith("sensor") and (cardType == "cardGrid" or cardType == "cardGrid2") and item.iconOverride is None:
|
if item.status.startswith("sensor") and cardType in ["cardGrid", "cardGrid1", "cardGrid2"] and item.iconOverride is None:
|
||||||
icon_id = status_entity.state[:4]
|
icon_id = status_entity.state[:4]
|
||||||
if icon_id[-1] == ".":
|
if icon_id[-1] == ".":
|
||||||
icon_id = icon_id[:-1]
|
icon_id = icon_id[:-1]
|
||||||
@@ -318,7 +321,7 @@ class LuiPagesGen(object):
|
|||||||
value = value + unit_of_measurement
|
value = value + unit_of_measurement
|
||||||
if entityType == "binary_sensor":
|
if entityType == "binary_sensor":
|
||||||
value = get_translation(self._locale, f"backend.component.binary_sensor.state.{device_class}.{entity.state}")
|
value = get_translation(self._locale, f"backend.component.binary_sensor.state.{device_class}.{entity.state}")
|
||||||
if (cardType == "cardGrid" or cardType == "cardGrid2") and entityType == "sensor" and icon is None:
|
if cardType in ["cardGrid", "cardGrid1", "cardGrid2"] and entityType == "sensor" and icon is None:
|
||||||
icon_id = entity.state[:4]
|
icon_id = entity.state[:4]
|
||||||
if icon_id[-1] == ".":
|
if icon_id[-1] == ".":
|
||||||
icon_id = icon_id[:-1]
|
icon_id = icon_id[:-1]
|
||||||
@@ -779,6 +782,8 @@ class LuiPagesGen(object):
|
|||||||
if send_page_type:
|
if send_page_type:
|
||||||
if card.cardType == "cardGrid" and len(card.entities) > 6:
|
if card.cardType == "cardGrid" and len(card.entities) > 6:
|
||||||
card.cardType = "cardGrid2"
|
card.cardType = "cardGrid2"
|
||||||
|
if card.cardType == "cardGrid1":
|
||||||
|
card.cardType = "cardGrid"
|
||||||
self.page_type(card.cardType)
|
self.page_type(card.cardType)
|
||||||
|
|
||||||
# send sleep timeout if there is one configured for the current card
|
# send sleep timeout if there is one configured for the current card
|
||||||
@@ -788,7 +793,7 @@ class LuiPagesGen(object):
|
|||||||
self._send_mqtt_msg(f'timeout~{self._config.get("sleepTimeout")}')
|
self._send_mqtt_msg(f'timeout~{self._config.get("sleepTimeout")}')
|
||||||
|
|
||||||
temp_unit = card.raw_config.get("temperatureUnit", "celsius")
|
temp_unit = card.raw_config.get("temperatureUnit", "celsius")
|
||||||
if card.cardType in ["cardEntities", "cardGrid", "cardGrid2"]:
|
if card.cardType in ["cardEntities", "cardGrid", "cardGrid1","cardGrid2"]:
|
||||||
self.generate_entities_page(navigation, card.title, card.entities, card.cardType, temp_unit)
|
self.generate_entities_page(navigation, card.title, card.entities, card.cardType, temp_unit)
|
||||||
return
|
return
|
||||||
if card.cardType == "cardThermo":
|
if card.cardType == "cardThermo":
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import hassapi as hass
|
import adbase as ad
|
||||||
|
|
||||||
from luibackend.config import LuiBackendConfig
|
from luibackend.config import LuiBackendConfig
|
||||||
from luibackend.controller import LuiController
|
from luibackend.controller import LuiController
|
||||||
@@ -6,15 +6,19 @@ from luibackend.mqtt import LuiMqttListener, LuiMqttSender
|
|||||||
from luibackend.updater import Updater
|
from luibackend.updater import Updater
|
||||||
|
|
||||||
import apis
|
import apis
|
||||||
|
import json
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
class NsPanelLovelaceUIManager(hass.Hass):
|
class NsPanelLovelaceUIManager(ad.ADBase):
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.log('Starting')
|
self.adapi = self.get_ad_api()
|
||||||
apis.ha_api = self
|
self.adapi.log('Starting')
|
||||||
|
apis.ad_api = self.adapi
|
||||||
|
apis.ha_api = self.get_plugin_api("HASS")
|
||||||
apis.mqtt_api = self.get_plugin_api("MQTT")
|
apis.mqtt_api = self.get_plugin_api("MQTT")
|
||||||
|
|
||||||
cfg = self._cfg = LuiBackendConfig(self, self.args["config"])
|
cfg = self._cfg = LuiBackendConfig(apis.ha_api, self.args["config"])
|
||||||
|
|
||||||
use_api = cfg.get("use_api") == True
|
use_api = cfg.get("use_api") == True
|
||||||
|
|
||||||
@@ -22,10 +26,11 @@ class NsPanelLovelaceUIManager(hass.Hass):
|
|||||||
topic_recv = cfg.get("panelRecvTopic")
|
topic_recv = cfg.get("panelRecvTopic")
|
||||||
api_panel_name = cfg.get("panelName")
|
api_panel_name = cfg.get("panelName")
|
||||||
api_device_id = cfg.get("panelDeviceId")
|
api_device_id = cfg.get("panelDeviceId")
|
||||||
|
quiet = cfg.get("quiet")
|
||||||
|
|
||||||
mqttsend = LuiMqttSender(self, use_api, topic_send, api_panel_name)
|
mqttsender = self._mqttsender = LuiMqttSender(apis.ha_api, use_api, topic_send, api_panel_name, quiet)
|
||||||
|
|
||||||
controller = LuiController(cfg, mqttsend.send_mqtt_msg)
|
self._controller = LuiController(cfg, mqttsender.send_mqtt_msg)
|
||||||
|
|
||||||
desired_tasmota_driver_version = 8
|
desired_tasmota_driver_version = 8
|
||||||
desired_display_firmware_version = 53
|
desired_display_firmware_version = 53
|
||||||
@@ -41,11 +46,35 @@ class NsPanelLovelaceUIManager(hass.Hass):
|
|||||||
desired_tasmota_driver_url = cfg._config.get("berryURL", "https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be")
|
desired_tasmota_driver_url = cfg._config.get("berryURL", "https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be")
|
||||||
|
|
||||||
mode = cfg.get("updateMode")
|
mode = cfg.get("updateMode")
|
||||||
updater = Updater(self.log, mqttsend, topic_send, mode, desired_display_firmware_version, model, desired_display_firmware_url, desired_tasmota_driver_version, desired_tasmota_driver_url)
|
updater = Updater(self.adapi.log, mqttsender, topic_send, mode, desired_display_firmware_version, model, desired_display_firmware_url, desired_tasmota_driver_version, desired_tasmota_driver_url)
|
||||||
|
|
||||||
# Request Tasmota Driver Version
|
# Request Tasmota Driver Version
|
||||||
updater.request_berry_driver_version()
|
updater.request_berry_driver_version()
|
||||||
|
|
||||||
LuiMqttListener(use_api, topic_recv, api_panel_name, api_device_id, controller, updater)
|
LuiMqttListener(use_api, topic_recv, api_panel_name, api_device_id, self._controller, updater)
|
||||||
|
|
||||||
self.log(f'Started ({version})')
|
self.adapi.log(f'Started ({version})')
|
||||||
|
|
||||||
|
#
|
||||||
|
# helpers
|
||||||
|
#
|
||||||
|
|
||||||
|
def show_card(self, card_key: str) -> None:
|
||||||
|
"""Used to show card on panel"""
|
||||||
|
|
||||||
|
msg = json.dumps({"CustomRecv":f"event,buttonPress2,navigate.{card_key},button"})
|
||||||
|
topic = self._cfg.get("panelRecvTopic")
|
||||||
|
self._mqttsender.send_mqtt_msg(msg, topic)
|
||||||
|
|
||||||
|
def navigate(self, direction: Literal['up', 'prev', 'next']) -> None:
|
||||||
|
"""Used to navigate different directions on the panel"""
|
||||||
|
|
||||||
|
msg = json.dumps({"CustomRecv":f"event,buttonPress2,nav{direction.title()},button"})
|
||||||
|
topic = self._cfg.get("panelRecvTopic")
|
||||||
|
self._mqttsender.send_mqtt_msg(msg, topic)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_card(self) -> str:
|
||||||
|
"""Used to get the panel's current card"""
|
||||||
|
|
||||||
|
return self._controller.current_card.key
|
||||||
|
|||||||
@@ -93,3 +93,34 @@ Now, to install NSPanel Lovelace UI Backend with HACS, follow these steps:
|
|||||||
6. A confirmation panel will appear, click on `Download`, and wait for HACS to
|
6. A confirmation panel will appear, click on `Download`, and wait for HACS to
|
||||||
proceed with the download
|
proceed with the download
|
||||||
7. The Backend Application is now installed, and HACS will inform you when updates are available
|
7. The Backend Application is now installed, and HACS will inform you when updates are available
|
||||||
|
|
||||||
|
# Workaround for HomeAssistant 2024.04
|
||||||
|
AppDaemon is using the old REST API that until AppDaemon moved on the the websocket API this woraround is needed to get weather forecast data from homeassistant. (https://github.com/AppDaemon/appdaemon/issues/1837)
|
||||||
|
|
||||||
|
To get the forecast data in appdaemon, there is a script needed in homeassistant's configuration.yaml:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
template:
|
||||||
|
- trigger:
|
||||||
|
- platform: time_pattern
|
||||||
|
hours: /1
|
||||||
|
action:
|
||||||
|
- service: weather.get_forecasts
|
||||||
|
data:
|
||||||
|
type: daily
|
||||||
|
target:
|
||||||
|
entity_id: weather.k3ll3r # change to your weather entity in this line
|
||||||
|
response_variable: daily
|
||||||
|
sensor:
|
||||||
|
- name: Weather Forecast Daily
|
||||||
|
unique_id: weather_forecast_daily
|
||||||
|
state: "{{ now().isoformat() }}"
|
||||||
|
attributes:
|
||||||
|
forecast: "{{ daily['weather.k3ll3r'].forecast }}" # change to your weather entity in this line
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
Adjust the entities in your apps.yaml that are accessing the forecast to the newly created trigger template:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|||||||
130
ioBroker/Blockly/CardLChart_Influx2.ts
Normal file
130
ioBroker/Blockly/CardLChart_Influx2.ts
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/**
|
||||||
|
* Dieses Script fragt eine influxDb ab, um Daten für die cardLcart (Liniendiagramm) zuberechnen und im richtigen Format bereitzustellen.
|
||||||
|
* Es erstellt automatisch einen Datenpunkt.
|
||||||
|
* Die Abfrage muss ggf. angepasst werden. Aktuell ermittelt sie Werte der letzten 24h, zu Stundenwerten zusammengefasst.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const Debug = false; // true für erweiterte Ausgaben im Log
|
||||||
|
|
||||||
|
const NSPanel_Path = '0_userdata.0.NSPanel.';
|
||||||
|
const Path = NSPanel_Path + 'Influx2NSPanel.cardLChart.';
|
||||||
|
const InfluxInstance = 'influxdb.0';
|
||||||
|
const influxDbBucket = 'storage_short';
|
||||||
|
const numberOfHoursAgo = 24;
|
||||||
|
const xAxisTicksEveryM = 60;
|
||||||
|
const xAxisLabelEveryM = 240;
|
||||||
|
//
|
||||||
|
|
||||||
|
const sensors : Record<string, Record <string, string>> = {};
|
||||||
|
/**
|
||||||
|
* Hier werden die Sensoren festgelegt nach flogendem Schema
|
||||||
|
*
|
||||||
|
* sensors[‘Datenpunkt(kompletter Pfad) des Messwertes'] = {'taget': 'Name des Datenpunkt für die Chartwerte', 'measurement': 'genutzter Alias in der Influxdb für den Messwert'};
|
||||||
|
*
|
||||||
|
* Wenn der Wert in der Datenbank keinen Alias hat bleibt der Wert 'measurement': weg.
|
||||||
|
* Jeder Messwert bekommt einen eigenen sensors[...] = {'target':....}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
sensors['netatmo-crawler.0.stationData.1.temperature'] = {'target':'AussenTemp', 'measurement':'wetter.temperatur'};
|
||||||
|
|
||||||
|
// ##### ab hier keine Änderungen mehr nötig #####
|
||||||
|
|
||||||
|
// create data source for NsPanel on script startup
|
||||||
|
Object.keys(sensors).forEach(async id => {
|
||||||
|
await generateDateAsync(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// then listen to the sensors and update the data source states accordingly
|
||||||
|
on({ id: Object.keys(sensors), change: 'any' }, async function (obj) {
|
||||||
|
if (!obj.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await generateDateAsync(obj.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
//__________________________
|
||||||
|
// Beschreibe diese Funktion: Daten generieren
|
||||||
|
async function generateDateAsync(sensorId: string) {
|
||||||
|
let idMeasurement = sensors[sensorId].measurement;
|
||||||
|
if (idMeasurement =='' ||idMeasurement == undefined) {idMeasurement = sensorId};
|
||||||
|
const dataPointId:string = Path + sensors[sensorId].target +'.ACTUAL';
|
||||||
|
if (Debug) log(`(f) generateDateAsync: ${sensorId} ${dataPointId} > ${idMeasurement}`);
|
||||||
|
|
||||||
|
const query =[
|
||||||
|
'from(bucket: "' + influxDbBucket + '")',
|
||||||
|
'|> range(start: -' + numberOfHoursAgo + 'h)',
|
||||||
|
'|> filter(fn: (r) => r["_measurement"] == "' + idMeasurement + '")',
|
||||||
|
'|> filter(fn: (r) => r["_field"] == "value")',
|
||||||
|
'|> drop(columns: ["from", "ack", "q"])',
|
||||||
|
'|> aggregateWindow(every: 1h, fn: last, createEmpty: false)',
|
||||||
|
'|> map(fn: (r) => ({ r with _rtime: int(v: r._time) - int(v: r._start)}))',
|
||||||
|
'|> yield(name: "_result")'].join('');
|
||||||
|
|
||||||
|
if (Debug) console.log('Query: ' + query);
|
||||||
|
|
||||||
|
const result : any = await sendToAsync(InfluxInstance, 'query', query);
|
||||||
|
if (result.error) {
|
||||||
|
console.error(result.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Debug) console.log(JSON.stringify(result));
|
||||||
|
const numResults = result.result.length;
|
||||||
|
let coordinates : string = '';
|
||||||
|
for (let r = 0; r < numResults; r++)
|
||||||
|
{
|
||||||
|
const list : string[] = [];
|
||||||
|
const numValues = result.result[r].length;
|
||||||
|
|
||||||
|
for (let i = 0; i < numValues; i++)
|
||||||
|
{
|
||||||
|
const time = Math.round(result.result[r][i]._rtime/1000/1000/1000/60);
|
||||||
|
const value = Math.round(result.result[r][i]._value * 10);
|
||||||
|
list.push(time + ":" + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
coordinates = list.join("~");
|
||||||
|
if (Debug) console.log(coordinates);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ticksAndLabelsList : string[] = []
|
||||||
|
const date = new Date();
|
||||||
|
date.setMinutes(0, 0, 0);
|
||||||
|
const ts = Math.round(date.getTime() / 1000);
|
||||||
|
const tsYesterday = ts - (numberOfHoursAgo * 3600);
|
||||||
|
if (Debug) console.log('Iterate from ' + tsYesterday + ' to ' + ts + ' stepsize=' + (xAxisTicksEveryM * 60));
|
||||||
|
for (let x = tsYesterday, i = 0; x < ts; x += (xAxisTicksEveryM * 60), i += xAxisTicksEveryM)
|
||||||
|
{
|
||||||
|
if ((i % xAxisLabelEveryM))
|
||||||
|
ticksAndLabelsList.push('' + i);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const currentDate = new Date(x * 1000);
|
||||||
|
// Hours part from the timestamp
|
||||||
|
const hours = "0" + String(currentDate.getHours());
|
||||||
|
// Minutes part from the timestamp
|
||||||
|
const minutes = "0" + String(currentDate.getMinutes());
|
||||||
|
const formattedTime = hours.slice(-2) + ':' + minutes.slice(-2);
|
||||||
|
|
||||||
|
ticksAndLabelsList.push(String(i) + "^" + formattedTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Debug) console.log('Ticks & Label: ' + ticksAndLabelsList);
|
||||||
|
if (Debug) console.log('Coordinates: ' + coordinates);
|
||||||
|
await setOrCreate(dataPointId, ticksAndLabelsList.join("+") + '~' + coordinates, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//__________________________
|
||||||
|
// Beschreibe diese Funktion: Datenpunkte anlegen bzw. schreiben
|
||||||
|
async function setOrCreate(id : string, value : any, ack : boolean) {
|
||||||
|
if (!(await existsStateAsync(id))) {
|
||||||
|
await createStateAsync(id, value, {
|
||||||
|
name: id.split('.').reverse()[0],
|
||||||
|
desc: 'Sensor Values [~<time>:<value>]*',
|
||||||
|
type: 'string',
|
||||||
|
role: 'value',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await setStateAsync(id, value, ack);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
const Debug = false;
|
|
||||||
|
|
||||||
const NSPanel_Path = '0_userdata.0.NSPanel.1.';
|
|
||||||
const Path = NSPanel_Path + 'Influx2NSPanel.cardLChart.';
|
|
||||||
const InfluxInstance = 'influxdb.1';
|
|
||||||
const influxDbBucket = 'iobroker';
|
|
||||||
const numberOfHoursAgo = 24;
|
|
||||||
const xAxisTicksEveryM = 60;
|
|
||||||
const xAxisLabelEveryM = 240;
|
|
||||||
|
|
||||||
// this records holds all sensors and their corresponding states which act as the data source for the charts
|
|
||||||
// add all sensors which are to be displayed in this script, there is no need to use multiple scripts
|
|
||||||
const sensors : Record<string, string> = {};
|
|
||||||
/* ↓ Id of the sensor ↓ Id of the data source for the charts */
|
|
||||||
sensors['deconz.0.Sensors.65.temperature'] = Path + 'buero_temperature';
|
|
||||||
sensors['deconz.0.Sensors.65.humidity'] = Path + 'buero_luftfeuchte';
|
|
||||||
|
|
||||||
// create data source for NsPanel on script startup
|
|
||||||
Object.keys(sensors).forEach(async x => {
|
|
||||||
await generateDateAsync(x, sensors[x]);
|
|
||||||
});
|
|
||||||
|
|
||||||
// then listen to the sensors and update the data source states accordingly
|
|
||||||
on({ id: Object.keys(sensors), change: 'any' }, async function (obj) {
|
|
||||||
if (!obj.id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await generateDateAsync(obj.id, sensors[obj.id]);
|
|
||||||
});
|
|
||||||
|
|
||||||
async function generateDateAsync(sensorId: string, dataPointId: string) {
|
|
||||||
const query =[
|
|
||||||
'from(bucket: "' + influxDbBucket + '")',
|
|
||||||
'|> range(start: -' + numberOfHoursAgo + 'h)',
|
|
||||||
'|> filter(fn: (r) => r["_measurement"] == "' + sensorId + '")',
|
|
||||||
'|> filter(fn: (r) => r["_field"] == "value")',
|
|
||||||
'|> drop(columns: ["from", "ack", "q"])',
|
|
||||||
'|> aggregateWindow(every: 1h, fn: last, createEmpty: false)',
|
|
||||||
'|> map(fn: (r) => ({ r with _rtime: int(v: r._time) - int(v: r._start)}))',
|
|
||||||
'|> yield(name: "_result")'].join('');
|
|
||||||
|
|
||||||
if (Debug) console.log('Query: ' + query);
|
|
||||||
|
|
||||||
const result : any = await sendToAsync(InfluxInstance, 'query', query);
|
|
||||||
if (result.error) {
|
|
||||||
console.error(result.error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Debug) console.log(result);
|
|
||||||
const numResults = result.result.length;
|
|
||||||
let coordinates : string = '';
|
|
||||||
for (let r = 0; r < numResults; r++)
|
|
||||||
{
|
|
||||||
const list : string[] = []
|
|
||||||
const numValues = result.result[r].length;
|
|
||||||
|
|
||||||
for (let i = 0; i < numValues; i++)
|
|
||||||
{
|
|
||||||
const time = Math.round(result.result[r][i]._rtime/1000/1000/1000/60);
|
|
||||||
const value = Math.round(result.result[r][i]._value * 10);
|
|
||||||
list.push(time + ":" + value);
|
|
||||||
}
|
|
||||||
|
|
||||||
coordinates = list.join("~");
|
|
||||||
|
|
||||||
if (Debug) console.log(coordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ticksAndLabelsList : string[] = []
|
|
||||||
const date = new Date();
|
|
||||||
date.setMinutes(0, 0, 0);
|
|
||||||
const ts = Math.round(date.getTime() / 1000);
|
|
||||||
const tsYesterday = ts - (numberOfHoursAgo * 3600);
|
|
||||||
if (Debug) console.log('Iterate from ' + tsYesterday + ' to ' + ts + ' stepsize=' + (xAxisTicksEveryM * 60));
|
|
||||||
for (let x = tsYesterday, i = 0; x < ts; x += (xAxisTicksEveryM * 60), i += xAxisTicksEveryM)
|
|
||||||
{
|
|
||||||
if ((i % xAxisLabelEveryM))
|
|
||||||
ticksAndLabelsList.push('' + i);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const currentDate = new Date(x * 1000);
|
|
||||||
// Hours part from the timestamp
|
|
||||||
const hours = "0" + String(currentDate.getHours());
|
|
||||||
// Minutes part from the timestamp
|
|
||||||
const minutes = "0" + String(currentDate.getMinutes());
|
|
||||||
const formattedTime = hours.slice(-2) + ':' + minutes.slice(-2);
|
|
||||||
|
|
||||||
ticksAndLabelsList.push(String(i) + "^" + formattedTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Debug) console.log('Ticks & Label: ' + ticksAndLabelsList);
|
|
||||||
if (Debug) console.log('Coordinates: ' + coordinates);
|
|
||||||
await setOrCreate(dataPointId, ticksAndLabelsList.join("+") + '~' + coordinates, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setOrCreate(id : string, value : any, ack : boolean) {
|
|
||||||
if (!(await existsStateAsync(id))) {
|
|
||||||
await createStateAsync(id, value, {
|
|
||||||
name: id.split('.').reverse()[0],
|
|
||||||
desc: 'Sensor Values [~<time>:<value>]*',
|
|
||||||
type: 'string',
|
|
||||||
role: 'value',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await setStateAsync(id, value, ack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config
|
# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config
|
||||||
name: NSPanel Lovelace UI Addon
|
name: NSPanel Lovelace UI Addon
|
||||||
version: "4.7.74"
|
version: "4.7.80"
|
||||||
slug: nspanel-lovelace-ui
|
slug: nspanel-lovelace-ui
|
||||||
description: NSPanel Lovelace UI Addon
|
description: NSPanel Lovelace UI Addon
|
||||||
services:
|
services:
|
||||||
|
|||||||
@@ -209,11 +209,11 @@ class HAEntity(panel_cards.Entity):
|
|||||||
forecast = libs.home_assistant.execute_script(
|
forecast = libs.home_assistant.execute_script(
|
||||||
entity_name=self.entity_id,
|
entity_name=self.entity_id,
|
||||||
domain='weather',
|
domain='weather',
|
||||||
service="get_forecast",
|
service="get_forecasts",
|
||||||
service_data={
|
service_data={
|
||||||
'type': forecast_type
|
'type': forecast_type
|
||||||
}
|
}
|
||||||
).get("forecast", [])
|
).get(self.entity_id,{}).get("forecast", [])
|
||||||
if len(forecast) > pos:
|
if len(forecast) > pos:
|
||||||
forcast_pos = forecast[pos]
|
forcast_pos = forecast[pos]
|
||||||
forcast_condition = forcast_pos.get("condition", "")
|
forcast_condition = forcast_pos.get("condition", "")
|
||||||
|
|||||||
@@ -20,27 +20,32 @@ def calculate_dim_values(sleepTracking, sleepTrackingZones, sleepBrightness, scr
|
|||||||
dimmode = sleepBrightness
|
dimmode = sleepBrightness
|
||||||
elif isinstance(sleepBrightness, list):
|
elif isinstance(sleepBrightness, list):
|
||||||
logging.error("list style config for sleepBrightness no longer supported")
|
logging.error("list style config for sleepBrightness no longer supported")
|
||||||
elif sleepBrightness.startswith("ha:"):
|
#elif sleepBrightness.startswith("ha:"):
|
||||||
time.sleep(1)
|
# time.sleep(1)
|
||||||
dimmode = int(float(libs.home_assistant.get_template(sleepBrightness)[3:]))
|
# dimmode = int(float(libs.home_assistant.get_template(sleepBrightness)[3:]))
|
||||||
involved_entities.extend(libs.home_assistant.get_template_listener_entities(sleepBrightness))
|
# involved_entities.extend(libs.home_assistant.get_template_listener_entities(sleepBrightness))
|
||||||
elif libs.home_assistant.is_existent(sleepBrightness):
|
elif libs.home_assistant.is_existent(sleepBrightness):
|
||||||
involved_entities.append(sleepBrightness)
|
involved_entities.append(sleepBrightness)
|
||||||
dimmode = int(float(libs.home_assistant.get_entity_data(sleepBrightness).get('state', 10)))
|
try:
|
||||||
|
dimmode = int(float(libs.home_assistant.get_entity_data(sleepBrightness).get('state', 10)))
|
||||||
|
except ValueError:
|
||||||
|
print("sleepBrightness entity invalid")
|
||||||
|
|
||||||
if screenBrightness:
|
if screenBrightness:
|
||||||
if isinstance(screenBrightness, int):
|
if isinstance(screenBrightness, int):
|
||||||
dimValueNormal = screenBrightness
|
dimValueNormal = screenBrightness
|
||||||
elif isinstance(screenBrightness, list):
|
elif isinstance(screenBrightness, list):
|
||||||
logging.error("list style config for screenBrightness no longer supported")
|
logging.error("list style config for screenBrightness no longer supported")
|
||||||
elif screenBrightness.startswith("ha:"):
|
#elif screenBrightness.startswith("ha:"):
|
||||||
time.sleep(1)
|
# time.sleep(1)
|
||||||
dimValueNormal = int(float(libs.home_assistant.get_template(screenBrightness)[3:]))
|
# dimValueNormal = int(float(libs.home_assistant.get_template(screenBrightness)[3:]))
|
||||||
involved_entities.extend(libs.home_assistant.get_template_listener_entities(screenBrightness))
|
# involved_entities.extend(libs.home_assistant.get_template_listener_entities(screenBrightness))
|
||||||
elif libs.home_assistant.is_existent(screenBrightness):
|
elif libs.home_assistant.is_existent(screenBrightness):
|
||||||
involved_entities.append(screenBrightness)
|
involved_entities.append(screenBrightness)
|
||||||
dimValueNormal = int(float(libs.home_assistant.get_entity_data(screenBrightness).get('state', 100)))
|
try:
|
||||||
|
dimValueNormal = int(float(libs.home_assistant.get_entity_data(screenBrightness).get('state', 100)))
|
||||||
|
except ValueError:
|
||||||
|
print("screenBrightness entity invalid")
|
||||||
# force sleep brightness to zero in case sleepTracking is active
|
# force sleep brightness to zero in case sleepTracking is active
|
||||||
if sleepTracking:
|
if sleepTracking:
|
||||||
if libs.home_assistant.is_existent(sleepTracking):
|
if libs.home_assistant.is_existent(sleepTracking):
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
paho-mqtt
|
paho-mqtt==1.6.1
|
||||||
pyyaml
|
pyyaml
|
||||||
websockets
|
websockets
|
||||||
websocket-client
|
websocket-client
|
||||||
@@ -7,4 +7,4 @@ python-dateutil
|
|||||||
scheduler
|
scheduler
|
||||||
babel
|
babel
|
||||||
watchdog
|
watchdog
|
||||||
jinja2
|
jinja2
|
||||||
|
|||||||
Reference in New Issue
Block a user