mirror of
https://github.com/joBr99/nspanel-lovelace-ui.git
synced 2026-02-21 13:44:45 +01:00
Compare commits
75 Commits
2103411de1
...
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 | ||
|
|
01265faef9 | ||
|
|
a2feae891e | ||
|
|
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:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
const idAbfalliCal = 'ical.1'; // iCal Instanz zum Abfallkalender
|
|
||||||
const idZeichenLoeschen = 14; // x Zeichen links vom String abziehen, wenn vor dem Eventname noch Text steht z.B. Strassenname; Standard = 0
|
|
||||||
const idRestmuellName ='Hausmüll'; // Schwarze Tonne
|
|
||||||
const idWertstoffName = 'Gelber Sack'; // Gelbe Tonne / Sack
|
|
||||||
const idPappePapierName = 'Papier'; // Blaue Tonne
|
|
||||||
const idBioabfaelleName = 'Biomüll'; // Braune Tonne
|
|
||||||
|
|
||||||
|
|
||||||
var i, Muell_JSON, Event2, Color = 0;
|
|
||||||
|
|
||||||
for (i = 1; i <= 4; i++) {
|
|
||||||
if (!existsState('0_userdata.0.Abfallkalender.' + parseFloat(i) + '.date')) {
|
|
||||||
log(i + '.date nicht vorhanden, wurde erstellt');
|
|
||||||
createState('0_userdata.0.Abfallkalender.' + parseFloat(i) + '.date', '',
|
|
||||||
{
|
|
||||||
name: parseFloat(i) + '.date',
|
|
||||||
role: 'state',
|
|
||||||
type: 'string',
|
|
||||||
read: true,
|
|
||||||
write: true,
|
|
||||||
def: ''
|
|
||||||
});
|
|
||||||
};
|
|
||||||
if (!existsState('0_userdata.0.Abfallkalender.' + parseFloat(i) + '.event')) {
|
|
||||||
log(i + '.event nicht vorhanden, wurde erstellt');
|
|
||||||
createState('0_userdata.0.Abfallkalender.' + parseFloat(i) + '.event', '',
|
|
||||||
{
|
|
||||||
name: parseFloat(i) + '.event',
|
|
||||||
role: 'state',
|
|
||||||
type: 'string',
|
|
||||||
read: true,
|
|
||||||
write: true,
|
|
||||||
def: ''
|
|
||||||
});
|
|
||||||
};
|
|
||||||
if (!existsState('0_userdata.0.Abfallkalender.' + parseFloat(i) + '.color')) {
|
|
||||||
log(i + '.color nicht vorhanden, wurde erstellt');
|
|
||||||
createState('0_userdata.0.Abfallkalender.' + parseFloat(i) + '.color', 0,
|
|
||||||
{
|
|
||||||
name: parseFloat(i) + '.color',
|
|
||||||
role: 'state',
|
|
||||||
type: 'number',
|
|
||||||
read: true,
|
|
||||||
write: true,
|
|
||||||
def: 0
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function subsequenceFromStartLast(sequence, at1) {
|
|
||||||
var start = at1;
|
|
||||||
var end = sequence.length;
|
|
||||||
return sequence.slice(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
on({ id: idAbfalliCal + '.data.table', change: "ne" }, async function () {
|
|
||||||
|
|
||||||
for (i = 0; i <= 3; i++) {
|
|
||||||
Muell_JSON = getState(idAbfalliCal + '.data.table').val;
|
|
||||||
setStateDelayed((['0_userdata.0.Abfallkalender.', parseFloat(i) + 1, '.date'].join('')), getAttr(Muell_JSON, (String(i) + '.date')), false, parseInt(((0) || "").toString(), 10), false);
|
|
||||||
Event2 = subsequenceFromStartLast(getAttr(Muell_JSON, (String(i) + '.event')), idZeichenLoeschen);
|
|
||||||
setStateDelayed((['0_userdata.0.Abfallkalender.', parseFloat(i) + 1, '.event'].join('')), Event2, false, parseInt(((0) || "").toString(), 10), false);
|
|
||||||
if (Event2 == idRestmuellName) {
|
|
||||||
Color = 33840;
|
|
||||||
} else if (Event2 == idBioabfaelleName) {
|
|
||||||
Color = 2016;
|
|
||||||
} else if (Event2 == idPappePapierName) {
|
|
||||||
Color = 31;
|
|
||||||
} else if (Event2 == idWertstoffName) {
|
|
||||||
Color = 65504;
|
|
||||||
}
|
|
||||||
setStateDelayed((['0_userdata.0.Abfallkalender.', parseFloat(i) + 1, '.color'].join('')), Color, false, parseInt(((0) || "").toString(), 10), false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
224
ioBroker/Blockly/Abfallkalender.ts
Normal file
224
ioBroker/Blockly/Abfallkalender.ts
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
/*
|
||||||
|
* @author 2023 @tt-tom
|
||||||
|
*
|
||||||
|
* Version 5.1.1
|
||||||
|
*
|
||||||
|
* Das Script erstellt die Datenpunkte und Alias für den Abfallkalender im Sonoff NSPanel
|
||||||
|
* Es wird der iCal Adapter benötigt und eine URL mit Terminen vom Entsorger bzw. eine .ics-Datei mit den Terminen.
|
||||||
|
* Das Script triggert auf dem bereitgestellten JSON im iCal adapter und füllt die 0_userdata.0 Datenpunkte
|
||||||
|
* Weitere Informationen findest du in der FAQ auf Github https://github.com/joBr99/nspanel-lovelace-ui/wiki
|
||||||
|
*
|
||||||
|
* changelog
|
||||||
|
* - 06.12.2023 - v5.0.2 add custom name for trashtype
|
||||||
|
* - 06.12.2023 - v5.1.0 Refactoring
|
||||||
|
* - 22.01.2024 - v5.1.1 Add tow Events more
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
const idTrashData: string = 'ical.0.data.table'; // Datenpunkt mit Daten im JSON Format
|
||||||
|
const idUserdataAbfallVerzeichnis: string = '0_userdata.0.Abfallkalender'; // Name des Datenpunktverzeichnis unter 0_userdata.0 -> Strandard = 0_userdata.0.Abfallkalender
|
||||||
|
const idAliasPanelVerzeichnis: string = 'alias.0.NSPanel.allgemein'; //Name PanelVerzeichnis unter alias.0. Standard = alias.0.NSPanel.1
|
||||||
|
const idAliasAbfallVerzeichnis: string = 'Abfall'; //Name Verzeichnis unterhalb der idPanelverzeichnis Standard = Abfall
|
||||||
|
|
||||||
|
const anzahlZeichenLoeschen: number = 14; // x Zeichen links vom String abziehen, wenn vor dem Eventname noch Text steht z.B. Strassenname; Standard = 0
|
||||||
|
const jsonEventName1: string = 'Hausmüll'; // Vergleichstring für Schwarze Tonne
|
||||||
|
const customEventName1: string = ''; // benutzerdefinierter Text für schwarze Tonne
|
||||||
|
const jsonEventName2: string = 'Gelber Sack'; // Vergleichstring für Gelbe Tonne / Sack
|
||||||
|
const customEventName2: string = ''; // benutzerdefinierter Text für gelbe Tonne
|
||||||
|
const jsonEventName3: string = 'Papier'; // Vergleichstring für Blaue Tonne
|
||||||
|
const customEventName3: string = ''; // benutzerdefinierter Text für blaue Tonne
|
||||||
|
const jsonEventName4: string = 'Biomüll'; // Vergleichstring für Braune Tonne
|
||||||
|
const customEventName4: string = ''; // benutzerdefinierter Text für braune Tonne
|
||||||
|
const jsonEventName5: string = 'Treppe'; // Vergleichstring für Event 5
|
||||||
|
const customEventName5: string = 'Besen schwingen'; // benutzerdefinierter Text für Event 5
|
||||||
|
const jsonEventName6: string = ''; // Vergleichstring für Event 6
|
||||||
|
const customEventName6: string = ''; // benutzerdefinierter Text für Event 6
|
||||||
|
|
||||||
|
const Debug: boolean = false;
|
||||||
|
|
||||||
|
// ------------------------- Trigger zum füllen der 0_userdata Datenpunkte aus dem json vom ical Adapter -------------------------------
|
||||||
|
|
||||||
|
// Trigger auf JSON Datenpunkt
|
||||||
|
on({ id: idTrashData, change: 'ne' }, async function () {
|
||||||
|
JSON_auswerten();
|
||||||
|
});
|
||||||
|
|
||||||
|
// ------------------------------------- Ende Trigger ------------------------------------
|
||||||
|
|
||||||
|
// ------------------------------------- Funktion JSON auswerten und DP füllen -------------------------------
|
||||||
|
async function JSON_auswerten() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
let trashJSON: any;
|
||||||
|
let instanzName: any;
|
||||||
|
let eventName: string;
|
||||||
|
let eventDatum: string;
|
||||||
|
let eventStartdatum: string;
|
||||||
|
let farbNummer: number = 0;
|
||||||
|
let farbString: string;
|
||||||
|
let abfallNummer: number = 1;
|
||||||
|
|
||||||
|
trashJSON = getState(idTrashData).val;
|
||||||
|
instanzName = idTrashData.split('.');
|
||||||
|
|
||||||
|
if (Debug) log('Rohdaten von Instanz ' + instanzName[0] + ': ' + JSON.stringify(trashJSON), 'info')
|
||||||
|
|
||||||
|
|
||||||
|
if (Debug) log('Anzahl Trash - Daten: ' + trashJSON.length, 'info');
|
||||||
|
|
||||||
|
for (let i = 0; i < trashJSON.length; i++) {
|
||||||
|
if (abfallNummer === 7) {
|
||||||
|
if (Debug) log('Alle Abfall-Datenpunkte gefüllt', 'warn');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
log('Daten vom ical Adapter werden ausgewertet', 'info');
|
||||||
|
eventName = getAttr(trashJSON, (String(i) + '.event')).slice(anzahlZeichenLoeschen, getAttr(trashJSON, (String(i) + '.event')).length);
|
||||||
|
// Leerzeichen vorne und hinten löschen
|
||||||
|
eventName = eventName.trimEnd();
|
||||||
|
eventName = eventName.trimStart();
|
||||||
|
eventDatum = getAttr(trashJSON, (String(i) + '.date'));
|
||||||
|
eventStartdatum = getAttr(trashJSON, (String(i) + '._date'));
|
||||||
|
|
||||||
|
let d: Date = currentDate();
|
||||||
|
let d1: Date = new Date(eventStartdatum);
|
||||||
|
|
||||||
|
if (Debug) log('--------- Nächster Termin wird geprüft ---------', 'info');
|
||||||
|
//if (Debug) log(d + ' ' + d1, 'info');
|
||||||
|
if (Debug) log('Startdatum UTC: ' + eventStartdatum, 'info');
|
||||||
|
if (Debug) log('Datum: ' + eventDatum, 'info');
|
||||||
|
if (Debug) log('Event: ' + eventName, 'info');
|
||||||
|
if (Debug) log('Kontrolle Leerzeichen %' + eventName + '%', 'info');
|
||||||
|
|
||||||
|
if (d.getTime() <= d1.getTime()) {
|
||||||
|
if ((eventName == jsonEventName1) || (eventName == jsonEventName2) || (eventName == jsonEventName3) || (eventName == jsonEventName4) || (eventName == jsonEventName5) || (eventName == jsonEventName6)) {
|
||||||
|
|
||||||
|
switch (eventName) {
|
||||||
|
case jsonEventName1:
|
||||||
|
farbNummer = 33840;
|
||||||
|
if (customEventName1 != '') {
|
||||||
|
eventName = customEventName1;
|
||||||
|
if (Debug) log('Event customName: ' + eventName, 'info');
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case jsonEventName2:
|
||||||
|
farbNummer = 65504;
|
||||||
|
if (customEventName2 != '') {
|
||||||
|
eventName = customEventName2;
|
||||||
|
if (Debug) log('Event customName: ' + eventName, 'info');
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case jsonEventName3:
|
||||||
|
farbNummer = 31;
|
||||||
|
if (customEventName3 != '') {
|
||||||
|
eventName = customEventName3
|
||||||
|
if (Debug) log('Event customName: ' + eventName, 'info');
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case jsonEventName4:
|
||||||
|
farbNummer = 2016;
|
||||||
|
if (customEventName4 != '') {
|
||||||
|
eventName = customEventName4;
|
||||||
|
if (Debug) log('Event customName: ' + eventName, 'info');
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case jsonEventName5:
|
||||||
|
farbNummer = 2016;
|
||||||
|
if (customEventName5 != '') {
|
||||||
|
eventName = customEventName5;
|
||||||
|
if (Debug) log('Event customName: ' + eventName, 'info');
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case jsonEventName6:
|
||||||
|
farbNummer = 2016;
|
||||||
|
if (customEventName6 != '') {
|
||||||
|
eventName = customEventName6
|
||||||
|
if (Debug) log('Event customName: ' + eventName, 'info');
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (farbString != undefined) farbNummer = rgb_dec565(hex_rgb(farbString));
|
||||||
|
|
||||||
|
|
||||||
|
setState(idUserdataAbfallVerzeichnis + '.' + String(abfallNummer) + '.date', eventDatum);
|
||||||
|
setState(idUserdataAbfallVerzeichnis + '.' + String(abfallNummer) + '.event', eventName);
|
||||||
|
setState(idUserdataAbfallVerzeichnis + '.' + String(abfallNummer) + '.color', farbNummer);
|
||||||
|
|
||||||
|
|
||||||
|
//if (Debug) log('farbString: ' + farbString + ' farbNummer: ' + farbNummer, 'info');
|
||||||
|
if (Debug) log('Abfallnummer: ' + abfallNummer, 'info');
|
||||||
|
|
||||||
|
abfallNummer += 1
|
||||||
|
} else {
|
||||||
|
if (Debug) log('Kein Abfalltermin => Event passt mit keinem Abfallnamen überein.', 'warn');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Debug) log('Termin liegt vor dem heutigen Tag', 'warn');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
log('error at subscrption: ' + err.message, 'warn');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------- Ende Funktion JSON ------------------------------
|
||||||
|
|
||||||
|
// ------------------------------------- Funktion zur Prüfung und Erstellung der Datenpunkte in 0_userdata.0 und alias.0 -----------------------
|
||||||
|
|
||||||
|
async function Init_Datenpunkte() {
|
||||||
|
try {
|
||||||
|
for (let i = 1; i <= 6; i++) {
|
||||||
|
if (existsObject(idUserdataAbfallVerzeichnis + '.' + String(i)) == false) {
|
||||||
|
log('Datenpunkt ' + idUserdataAbfallVerzeichnis + '.' + String(i) + ' werden angelegt', 'info')
|
||||||
|
await createStateAsync(idUserdataAbfallVerzeichnis + '.' + String(i) + '.date', '', { type: 'string' });
|
||||||
|
await createStateAsync(idUserdataAbfallVerzeichnis + '.' + String(i) + '.event', '', { type: 'string' });
|
||||||
|
await createStateAsync(idUserdataAbfallVerzeichnis + '.' + String(i) + '.color', 0, { type: 'number' });
|
||||||
|
setObject(idAliasPanelVerzeichnis + '.' + idAliasAbfallVerzeichnis, { type: 'device', common: { name: { de: 'Abfall', en: 'Trash' } }, native: {} });
|
||||||
|
setObject(idAliasPanelVerzeichnis + '.' + idAliasAbfallVerzeichnis + '.event' + String(i), { type: 'channel', common: { role: 'warning', name: { de: 'Ereignis ' + String(i), en: 'Event' + String(i) } }, native: {} });
|
||||||
|
await createAliasAsync(idAliasPanelVerzeichnis + '.' + idAliasAbfallVerzeichnis + '.event' + String(i) + '.TITLE', idUserdataAbfallVerzeichnis + '.' + String(i) + '.event', true, <iobJS.StateCommon>{ type: 'string', role: 'weather.title.short', name: { de: 'TITEL', en: 'TITLE' } });
|
||||||
|
await createAliasAsync(idAliasPanelVerzeichnis + '.' + idAliasAbfallVerzeichnis + '.event' + String(i) + '.LEVEL', idUserdataAbfallVerzeichnis + '.' + String(i) + '.color', true, <iobJS.StateCommon>{ type: 'number', role: 'value.warning', name: { de: 'LEVEL', en: 'LEVEL' } });
|
||||||
|
await createAliasAsync(idAliasPanelVerzeichnis + '.' + idAliasAbfallVerzeichnis + '.event' + String(i) + '.INFO', idUserdataAbfallVerzeichnis + '.' + String(i) + '.date', true, <iobJS.StateCommon>{ type: 'string', role: 'weather.title', name: { de: 'INFO', en: 'INFO' } });
|
||||||
|
log('Fertig', 'info')
|
||||||
|
} else {
|
||||||
|
log('Datenpunkt ' + idUserdataAbfallVerzeichnis + '.' + String(i) + ' vorhanden', 'info')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log('Startabfrage der Daten', 'info');
|
||||||
|
JSON_auswerten();
|
||||||
|
} catch (err) {
|
||||||
|
log('error at function Init_Datenpunkte: ' + err.message, 'warn');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Init_Datenpunkte();
|
||||||
|
|
||||||
|
// --------------------------- Ende Funktion Datenpunkte ------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------- Zusatzfuktionen -------------------------------------------------------------
|
||||||
|
function currentDate() {
|
||||||
|
let d: Date = new Date();
|
||||||
|
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
function rgb_dec565(rgb: RGB): number {
|
||||||
|
//return ((Math.floor(rgb.red / 255 * 31) << 11) | (Math.floor(rgb.green / 255 * 63) << 5) | (Math.floor(rgb.blue / 255 * 31)));
|
||||||
|
return ((rgb.red >> 3) << 11) | ((rgb.green >> 2)) << 5 | ((rgb.blue) >> 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hex_rgb(colorhex: string): RGB {
|
||||||
|
let r = parseInt(colorhex.substring(1, 3), 16);
|
||||||
|
let g = parseInt(colorhex.substring(3, 5), 16);
|
||||||
|
let b = parseInt(colorhex.substring(5, 7), 16);
|
||||||
|
return { red: r, green: g, blue: b };
|
||||||
|
}
|
||||||
|
|
||||||
|
type RGB = {
|
||||||
|
red: number,
|
||||||
|
green: number,
|
||||||
|
blue: number
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------- Ende Zudatzfunktionen --------------------------------------------------------------------------
|
||||||
50
ioBroker/Blockly/CardChart_History.js
Normal file
50
ioBroker/Blockly/CardChart_History.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
var sourceDP = 'alias.0.Wohnzimmer.Heizung.ACTUAL';
|
||||||
|
var targetDP = '0_userdata.0.Test.chartTest';
|
||||||
|
var rangeHours = 24;
|
||||||
|
var maxXAchsisTicks = 6;
|
||||||
|
var historyInstance = 'history.0';
|
||||||
|
|
||||||
|
on({id: sourceDP, change: "any"}, async function (obj) {
|
||||||
|
sendTo(historyInstance, 'getHistory', {
|
||||||
|
id: sourceDP,
|
||||||
|
options: {
|
||||||
|
start: Date.now() - (60 * 60 * 1000 * rangeHours),
|
||||||
|
end: Date.now(),
|
||||||
|
count: rangeHours,
|
||||||
|
limit: rangeHours,
|
||||||
|
aggregate: 'average'
|
||||||
|
}
|
||||||
|
}, function (result) {
|
||||||
|
var cardChartString = "";
|
||||||
|
var stepXAchsis = rangeHours / maxXAchsisTicks;
|
||||||
|
|
||||||
|
for (var i = 0; i < rangeHours; i++){
|
||||||
|
var deltaHour = rangeHours - i;
|
||||||
|
var targetDate = new Date(Date.now() - (deltaHour * 60 * 60 * 1000));
|
||||||
|
|
||||||
|
//Check history items for requested hours
|
||||||
|
for (var j = 0, targetValue = 0; j < result.result.length; j++) {
|
||||||
|
var valueDate = new Date(result.result[j].ts);
|
||||||
|
var value = (Math.round(result.result[j].val * 10) / 10);
|
||||||
|
|
||||||
|
if (valueDate > targetDate){
|
||||||
|
if ((targetDate.getHours() % stepXAchsis) == 0){
|
||||||
|
cardChartString += targetValue + '^' + targetDate.getHours() + ':00' + '~';
|
||||||
|
} else {
|
||||||
|
cardChartString += targetValue + '~';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
targetValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cardChartString = cardChartString.substring(0,cardChartString.length-1);
|
||||||
|
if (existsState(targetDP) == false ) {
|
||||||
|
createState(targetDP, cardChartString, true, { type: 'string' });
|
||||||
|
} else {
|
||||||
|
setState(targetDP, cardChartString, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
78
ioBroker/Blockly/CardLChart_History.js
Normal file
78
ioBroker/Blockly/CardLChart_History.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
const sourceDP = 'alias.0.Wohnzimmer.Heizung.ACTUAL';
|
||||||
|
const targetDP = '0_userdata.0.Test.chartTest';
|
||||||
|
const numberOfHoursAgo = 24; // Period of time in hours which shall be visualized
|
||||||
|
const xAxisTicksEveryM = 60; // Time after x axis gets a tick in minutes
|
||||||
|
const xAxisLabelEveryM = 240; // Time after x axis is labeled in minutes
|
||||||
|
const historyInstance = 'history.0';
|
||||||
|
|
||||||
|
const Debug = false;
|
||||||
|
const maxX = 1420;
|
||||||
|
const limitMeasurements = 35;
|
||||||
|
|
||||||
|
createState(targetDP, "", {
|
||||||
|
name: 'SensorGrid',
|
||||||
|
desc: 'Sensor Values [~<time>:<value>]*',
|
||||||
|
type: 'string',
|
||||||
|
role: 'value',
|
||||||
|
});
|
||||||
|
|
||||||
|
on({id: sourceDP, change: "any"}, async function (obj) {
|
||||||
|
sendTo(historyInstance, 'getHistory', {
|
||||||
|
id: sourceDP,
|
||||||
|
options: {
|
||||||
|
start: Date.now() - (numberOfHoursAgo * 60 * 60 * 1000 ), //Time in ms: hours * 60m * 60s * 1000ms
|
||||||
|
end: Date.now(),
|
||||||
|
count: limitMeasurements,
|
||||||
|
limit: limitMeasurements,
|
||||||
|
aggregate: 'average'
|
||||||
|
}
|
||||||
|
}, function (result) {
|
||||||
|
var ticksAndLabels = ""
|
||||||
|
var coordinates = "";
|
||||||
|
var cardLChartString = "";
|
||||||
|
|
||||||
|
let ticksAndLabelsList = []
|
||||||
|
var date = new Date();
|
||||||
|
date.setMinutes(0, 0, 0);
|
||||||
|
var ts = Math.round(date.getTime() / 1000);
|
||||||
|
var tsYesterday = ts - (numberOfHoursAgo * 3600);
|
||||||
|
|
||||||
|
for (var x = tsYesterday, i = 0; x < ts; x += (xAxisTicksEveryM * 60), i += xAxisTicksEveryM)
|
||||||
|
{
|
||||||
|
if (i % xAxisLabelEveryM)
|
||||||
|
{
|
||||||
|
ticksAndLabelsList.push(i);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
var currentDate = new Date(x * 1000);
|
||||||
|
// Hours part from the timestamp
|
||||||
|
var hours = "0" + currentDate.getHours();
|
||||||
|
// Minutes part from the timestamp
|
||||||
|
var minutes = "0" + currentDate.getMinutes();
|
||||||
|
// Seconds part from the timestamp
|
||||||
|
var seconds = "0" + currentDate.getSeconds();
|
||||||
|
var formattedTime = hours.slice(-2) + ':' + minutes.slice(-2);
|
||||||
|
ticksAndLabelsList.push(String(i) + "^" + formattedTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ticksAndLabels = ticksAndLabelsList.join("+");
|
||||||
|
|
||||||
|
let list = [];
|
||||||
|
let offSetTime = Math.round(result.result[0].ts / 1000);
|
||||||
|
let counter = Math.round((result.result[result.result.length -1 ].ts / 1000 - offSetTime) / maxX);
|
||||||
|
for (var i = 0; i < result.result.length; i++)
|
||||||
|
{
|
||||||
|
var time = Math.round(((result.result[i].ts / 1000) - offSetTime) / counter);
|
||||||
|
var value = Math.round(result.result[i].val * 10);
|
||||||
|
if ((value != null) && (value != 0)){
|
||||||
|
list.push(time + ":" + value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coordinates = list.join("~");
|
||||||
|
cardLChartString = ticksAndLabels + '~' + coordinates
|
||||||
|
setState(targetDP, cardLChartString, true);
|
||||||
|
|
||||||
|
if (Debug) console.log(cardLChartString);
|
||||||
|
});
|
||||||
|
});
|
||||||
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
54
ioBroker/Blockly/CardPower.js
Normal file
54
ioBroker/Blockly/CardPower.js
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* generate an JSON for display Power-Card on NSPanel
|
||||||
|
* Source: https://github.com/joBr99/nspanel-lovelace-ui/wiki/ioBroker-Card-Definitionen-(Seiten)#cardpower-ab-ts-script-v341
|
||||||
|
* Version: 0.1 - L4rs
|
||||||
|
*/
|
||||||
|
schedule("* * * * *", function () {
|
||||||
|
|
||||||
|
// Definition der Datenpunkte für das JSON der POWER-Card und der anzuzeigenden Leistungswerte
|
||||||
|
var powerCardJson = "0_userdata.0.NSPanel.Energie.PowerCard",
|
||||||
|
pwr1 = "", // Batterie
|
||||||
|
pwr2 = Math.round(getState("mqtt.0.SmartHome.Energie.PV.openDTU.114180710360.0.power").val), // Solar
|
||||||
|
pwr3 = "", // Wind
|
||||||
|
pwr4 = "", // Verbraucher
|
||||||
|
pwr5 = Math.round(getState("hm-rpc.0.MEQ0706303.1.POWER").val), // Stromnetz
|
||||||
|
pwr6 = 0, // Auto
|
||||||
|
pwrHome = Math.round(pwr5 - pwr2); // Berechnung des Energiefluss anstelle eines Datenpunktes
|
||||||
|
|
||||||
|
// Definition der Keys im JSON
|
||||||
|
var keys = ["id", "value", "unit", "icon", "iconColor", "speed"];
|
||||||
|
|
||||||
|
// Definition der "Kacheln", inkl. StandardIcon. Es können alle Icon aus dem Iconmapping genutzt werden.
|
||||||
|
// Kacheln die nicht genutzt werden sollen, müssen wie z.b. item1 formatiert sein
|
||||||
|
var home = [0, pwrHome, "W", "home-lightning-bolt-outline", 0]; // Icon home
|
||||||
|
var item1 = [1, pwr1, "", "", 0, ""]; // Icon battery-charging-60
|
||||||
|
var item2 = [2, pwr2, "W", "solar-power-variant-outline", 3, pwr2 > 0 ? -2 : 0]; // Icon solar-power-variant
|
||||||
|
var item3 = [3, pwr3, "", "", 0, ""]; // Icon wind-turbine
|
||||||
|
var item4 = [4, pwr4, "", "", 0, ""]; // Icon shape
|
||||||
|
var item5 = [5, pwr5, "W", "transmission-tower", 10, 10]; // Icon transmission-tower
|
||||||
|
var item6 = [6, pwr6, "kW", "car-electric-outline", 5, 0]; // Icon car
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON generieren und in den Datenpunkt schreiben,
|
||||||
|
*
|
||||||
|
* --- ab hier keine Änderungen mehr ---
|
||||||
|
*/
|
||||||
|
function func(tags, values) {
|
||||||
|
return Object.assign(
|
||||||
|
...tags.map((element, index) => ({ [element]: values[index] }))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(
|
||||||
|
powerCardJson,
|
||||||
|
JSON.stringify([
|
||||||
|
func(keys, home),
|
||||||
|
func(keys, item1),
|
||||||
|
func(keys, item2),
|
||||||
|
func(keys, item3),
|
||||||
|
func(keys, item4),
|
||||||
|
func(keys, item5),
|
||||||
|
func(keys, item6),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*-----------------------------------------------------------------------
|
/*-----------------------------------------------------------------------
|
||||||
TypeScript v4.3.3.39 zur Steuerung des SONOFF NSPanel mit dem ioBroker by @Armilar / @TT-Tom / @ticaki / @Britzelpuf / @Sternmiere / @ravenS0ne
|
TypeScript v4.3.3.43 zur Steuerung des SONOFF NSPanel mit dem ioBroker by @Armilar / @TT-Tom / @ticaki / @Britzelpuf / @Sternmiere / @ravenS0ne
|
||||||
- abgestimmt auf TFT 53 / v4.3.3 / BerryDriver 9 / Tasmota 13.3.0
|
- abgestimmt auf TFT 53 / v4.3.3 / BerryDriver 9 / Tasmota 13.3.0
|
||||||
@joBr99 Projekt: https://github.com/joBr99/nspanel-lovelace-ui/tree/main/ioBroker
|
@joBr99 Projekt: https://github.com/joBr99/nspanel-lovelace-ui/tree/main/ioBroker
|
||||||
NsPanelTs.ts (dieses TypeScript in ioBroker) Stable: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/NsPanelTs.ts
|
NsPanelTs.ts (dieses TypeScript in ioBroker) Stable: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/NsPanelTs.ts
|
||||||
@@ -103,10 +103,20 @@ ReleaseNotes:
|
|||||||
- 16.01.2024 - v4.3.3.38 Optimate: function SendTime()
|
- 16.01.2024 - v4.3.3.38 Optimate: function SendTime()
|
||||||
- 17.01.2024 - v4.3.3.38 Add: ScreensaverEntityIconSelect for MRIcons is like common.states for states.
|
- 17.01.2024 - v4.3.3.38 Add: ScreensaverEntityIconSelect for MRIcons is like common.states for states.
|
||||||
- 17.01.2024 - v4.3.3.38 Add: Changing the ScreensaverEntityValue value updates the screensaver.
|
- 17.01.2024 - v4.3.3.38 Add: Changing the ScreensaverEntityValue value updates the screensaver.
|
||||||
- 19.01.2024 - v4.3.3.38 Change: yAxisTicks parameter is not required in cardLChart PageItem
|
- 19.01.2024 - v4.3.3.38 Change: yAxisTicks parameter is not required in cardLChart PageItem
|
||||||
- 20.01.2024 - v4.3.3.38 Add: click on indicatorIcon navigate to Page
|
- 20.01.2024 - v4.3.3.38 Add: click on indicatorIcon navigate to Page
|
||||||
- 23.01.2024 - v4.3.3.39 Add: Optional setOn & setOff for HW button with mode 'set'
|
- 23.01.2024 - v4.3.3.39 Add: Optional setOn & setOff for HW button with mode 'set'
|
||||||
|
- 28.01.2024 - v4.3.3.39 Fix: ack for read-only state
|
||||||
|
- 03.02.2024 - v4.3.3.40 Fix: RGB maxValueColorTemp
|
||||||
|
- 05.02.2024 - v4.3.3.40 Fix: SqueezeboxRPC-Media-Player and add some Functions
|
||||||
|
- 06.02.2024 - v4.3.3.41 Fix: activeBrightness -> null
|
||||||
|
- 06.02.2024 - v4.3.3.41 Fix: bHome -> corrected PageId
|
||||||
|
- 07.02.2024 - v4.3.3.42 Minor Fixes
|
||||||
|
- 09.02.2024 - v4.3.3.42 Change pageId with Alias in Communication with HMI
|
||||||
|
- 09.02.2024 - v4.3.3.42 Spotify Media-Player: Dynamic loading of the speaker list, playlist, tracklist, fix repeat, add seek, add elapsed/duration
|
||||||
|
- 10.02.2024 - v4.3.3.42 Spotify Minor Fixes; Add miValue / maxValue to Volume-Slider
|
||||||
|
- 10.02.2024 - v4.3.3.43 Fix: cardGrid2 => 9 Entities for Layout 'us-p' issue #1167
|
||||||
|
- 11.02.2024 - v4.3.3.43 Fix VolumeSlider
|
||||||
|
|
||||||
Todo:
|
Todo:
|
||||||
- XX.XX.XXXX - v5.0.0 Change the bottomScreensaverEntity (rolling) if more than 6 entries are defined
|
- XX.XX.XXXX - v5.0.0 Change the bottomScreensaverEntity (rolling) if more than 6 entries are defined
|
||||||
@@ -128,7 +138,8 @@ Mögliche Seiten-Ansichten:
|
|||||||
(die 4 kleineren Icons können als Wetter-Vorschau + 4Tage (Symbol + Höchsttemperatur) oder zur Anzeige definierter Infos konfiguriert werden)
|
(die 4 kleineren Icons können als Wetter-Vorschau + 4Tage (Symbol + Höchsttemperatur) oder zur Anzeige definierter Infos konfiguriert werden)
|
||||||
cardEntities Page - 4 vertikale angeordnete Steuerelemente - auch als Subpage
|
cardEntities Page - 4 vertikale angeordnete Steuerelemente - auch als Subpage
|
||||||
cardGrid Page - 6 horizontal angeordnete Steuerelemente in 2 Reihen a 3 Steuerelemente - auch als Subpage
|
cardGrid Page - 6 horizontal angeordnete Steuerelemente in 2 Reihen a 3 Steuerelemente - auch als Subpage
|
||||||
cardGrid2 Page - 8 horizontal angeordnete Steuerelemente in 2 Reihen a 4 Steuerelemente - auch als Subpage
|
cardGrid2 Page - 8 horizontal angeordnete Steuerelemente in 2 Reihen a 4 Steuerelemente bzw. beim US-Modell im Portrait-Modus
|
||||||
|
9 horizontal angeordnete Steuerelemente in 3 Reihen a 3 Steuerelemente - auch als Subpage
|
||||||
cardThermo Page - Thermostat mit Solltemperatur, Isttemperatur, Mode - Weitere Eigenschaften können im Alias definiert werden
|
cardThermo Page - Thermostat mit Solltemperatur, Isttemperatur, Mode - Weitere Eigenschaften können im Alias definiert werden
|
||||||
cardMedia Page - Mediaplayer - Ausnahme: Alias sollte mit Alias-Manager automatisch über Alexa-Verzeichnis Player angelegt werden
|
cardMedia Page - Mediaplayer - Ausnahme: Alias sollte mit Alias-Manager automatisch über Alexa-Verzeichnis Player angelegt werden
|
||||||
cardAlarm Page - Alarmseite mit Zustand und Tastenfeld
|
cardAlarm Page - Alarmseite mit Zustand und Tastenfeld
|
||||||
@@ -204,6 +215,7 @@ Upgrades in Konsole:
|
|||||||
---------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/******************************* Begin CONFIG Parameter *******************************/
|
/******************************* Begin CONFIG Parameter *******************************/
|
||||||
|
|
||||||
// DE: liefert bei true detailliertere Meldundgen im Log.
|
// DE: liefert bei true detailliertere Meldundgen im Log.
|
||||||
@@ -973,7 +985,7 @@ export const config: Config = {
|
|||||||
// _________________________________ DE: Ab hier keine Konfiguration mehr _____________________________________
|
// _________________________________ DE: Ab hier keine Konfiguration mehr _____________________________________
|
||||||
// _________________________________ EN: No more configuration from here _____________________________________
|
// _________________________________ EN: No more configuration from here _____________________________________
|
||||||
|
|
||||||
const scriptVersion: string = 'v4.3.3.39';
|
const scriptVersion: string = 'v4.3.3.43';
|
||||||
const tft_version: string = 'v4.3.3';
|
const tft_version: string = 'v4.3.3';
|
||||||
const desired_display_firmware_version = 53;
|
const desired_display_firmware_version = 53;
|
||||||
const berry_driver_version = 9;
|
const berry_driver_version = 9;
|
||||||
@@ -1086,8 +1098,8 @@ async function CheckConfigParameters() {
|
|||||||
let common = getObject(id).common;
|
let common = getObject(id).common;
|
||||||
if (common.name == 'javascript') {
|
if (common.name == 'javascript') {
|
||||||
javaScriptVersion = common.version;
|
javaScriptVersion = common.version;
|
||||||
setIfExists(NSPanel_Path + 'IoBroker.JavaScriptVersion', 'v' + javaScriptVersion);
|
setIfExists(NSPanel_Path + 'IoBroker.JavaScriptVersion', 'v' + javaScriptVersion, null, true);
|
||||||
setIfExists(NSPanel_Path + 'IoBroker.ScriptName', (name as unknown as string).split('.').slice(2).join('.'));
|
setIfExists(NSPanel_Path + 'IoBroker.ScriptName', (name as unknown as string).split('.').slice(2).join('.'), null, true);
|
||||||
let jsVersion = common.version.split('.');
|
let jsVersion = common.version.split('.');
|
||||||
let jsV = 10*parseInt(jsVersion[0]) + parseInt(jsVersion[1]);
|
let jsV = 10*parseInt(jsVersion[0]) + parseInt(jsVersion[1]);
|
||||||
if (jsV<61) log('JS-Adapter: ' + common.name + ' must be at least v6.1.3. Currently: v' + common.version, 'error');
|
if (jsV<61) log('JS-Adapter: ' + common.name + ' must be at least v6.1.3. Currently: v' + common.version, 'error');
|
||||||
@@ -1098,7 +1110,7 @@ async function CheckConfigParameters() {
|
|||||||
const hostList = $('system.host.*.nodeCurrent');
|
const hostList = $('system.host.*.nodeCurrent');
|
||||||
hostList.each(function(id, i) {
|
hostList.each(function(id, i) {
|
||||||
nodeVersion = getState(id).val;
|
nodeVersion = getState(id).val;
|
||||||
setIfExists(NSPanel_Path + 'IoBroker.NodeJSVersion', 'v' + nodeVersion);
|
setIfExists(NSPanel_Path + 'IoBroker.NodeJSVersion', 'v' + nodeVersion, null , true);
|
||||||
let nodeJSVersion = (getState(id).val).split('.');
|
let nodeJSVersion = (getState(id).val).split('.');
|
||||||
if (parseInt(nodeJSVersion[0]) < 18) {
|
if (parseInt(nodeJSVersion[0]) < 18) {
|
||||||
log('nodeJS must be at least v18.X.X. Currently: v' + getState(id).val + '! Please Update your System! --> iob nodejs-update 18', );
|
log('nodeJS must be at least v18.X.X. Currently: v' + getState(id).val + '! Please Update your System! --> iob nodejs-update 18', );
|
||||||
@@ -1145,7 +1157,7 @@ async function InitIoBrokerInfo() {
|
|||||||
setObject(AliasPath + 'IoBroker.ScriptName', {type: 'channel', common: {role: 'info', name:'Scriptname'}, native: {}});
|
setObject(AliasPath + 'IoBroker.ScriptName', {type: 'channel', common: {role: 'info', name:'Scriptname'}, native: {}});
|
||||||
await createAliasAsync(AliasPath + 'IoBroker.ScriptName.ACTUAL', NSPanel_Path + 'IoBroker.ScriptName', true, <iobJS.StateCommon>{ type: 'string', role: 'state', name: 'ACTUAL' });
|
await createAliasAsync(AliasPath + 'IoBroker.ScriptName.ACTUAL', NSPanel_Path + 'IoBroker.ScriptName', true, <iobJS.StateCommon>{ type: 'string', role: 'state', name: 'ACTUAL' });
|
||||||
}
|
}
|
||||||
setIfExists(NSPanel_Path + 'IoBroker.ScriptVersion', scriptVersion);
|
setIfExists(NSPanel_Path + 'IoBroker.ScriptVersion', scriptVersion, null, true);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
log('error at funktion InitIoBrokerInfo ' + err.message, 'warn');
|
log('error at funktion InitIoBrokerInfo ' + err.message, 'warn');
|
||||||
}
|
}
|
||||||
@@ -1240,13 +1252,13 @@ async function Init_Release() {
|
|||||||
if (existsObject(NSPanel_Path + 'Display_Firmware.desiredVersion') == false) {
|
if (existsObject(NSPanel_Path + 'Display_Firmware.desiredVersion') == false) {
|
||||||
await createStateAsync(NSPanel_Path + 'Display_Firmware.desiredVersion', desired_display_firmware_version, { type: 'number', write: false });
|
await createStateAsync(NSPanel_Path + 'Display_Firmware.desiredVersion', desired_display_firmware_version, { type: 'number', write: false });
|
||||||
} else {
|
} else {
|
||||||
await setStateAsync(NSPanel_Path + 'Display_Firmware.desiredVersion', desired_display_firmware_version);
|
await setStateAsync(NSPanel_Path + 'Display_Firmware.desiredVersion', desired_display_firmware_version, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existsObject(NSPanel_Path + 'Config.Update.activ') == false) {
|
if (existsObject(NSPanel_Path + 'Config.Update.activ') == false) {
|
||||||
await createStateAsync(NSPanel_Path + 'Config.Update.activ', 1, { type: 'number', write: false });
|
await createStateAsync(NSPanel_Path + 'Config.Update.activ', 1, { type: 'number', write: false });
|
||||||
} else {
|
} else {
|
||||||
await setStateAsync(NSPanel_Path + 'Config.Update.activ', 0);
|
await setStateAsync(NSPanel_Path + 'Config.Update.activ', 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentFW = 0;
|
let currentFW = 0;
|
||||||
@@ -1270,8 +1282,8 @@ async function Init_Release() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Create TFT DP's
|
//Create TFT DP's
|
||||||
await setStateAsync(NSPanel_Path + 'Display_Firmware.TFT.currentVersion', currentFW + ' / v' + FWRelease[findFWIndex]);
|
await setStateAsync(NSPanel_Path + 'Display_Firmware.TFT.currentVersion', currentFW + ' / v' + FWRelease[findFWIndex], true);
|
||||||
await setStateAsync(NSPanel_Path + 'Display_Firmware.TFT.desiredVersion', desired_display_firmware_version + ' / ' + tft_version);
|
await setStateAsync(NSPanel_Path + 'Display_Firmware.TFT.desiredVersion', desired_display_firmware_version + ' / ' + tft_version, true);
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
log('error at function Init_Release: ' + err.message, 'warn');
|
log('error at function Init_Release: ' + err.message, 'warn');
|
||||||
@@ -1513,11 +1525,11 @@ InitActiveBrightness();
|
|||||||
|
|
||||||
on({id: [NSPanel_Path + 'ScreensaverInfo.activeBrightness'], change: 'ne'}, async function (obj) {
|
on({id: [NSPanel_Path + 'ScreensaverInfo.activeBrightness'], change: 'ne'}, async function (obj) {
|
||||||
try {
|
try {
|
||||||
let active = getState(NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness').val;
|
let active = getState(NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness').val ?? -1;
|
||||||
if (obj.state.val >= 0 || obj.state.val <= 100) {
|
if (obj.state.val >= 0 || obj.state.val <= 100) {
|
||||||
log('action at trigger activeBrightness: ' + obj.state.val + ' - activeDimmodeBrightness: ' + active, 'info');
|
log('action at trigger activeBrightness: ' + obj.state.val + ' - activeDimmodeBrightness: ' + active, 'info');
|
||||||
SendToPanel({ payload: 'dimmode~' + active + '~' + obj.state.val + '~' + rgb_dec565(config.defaultBackgroundColor) + '~' + rgb_dec565(globalTextColor) + '~' + Sliders2 });
|
SendToPanel({ payload: 'dimmode~' + active + '~' + obj.state.val + '~' + rgb_dec565(config.defaultBackgroundColor) + '~' + rgb_dec565(globalTextColor) + '~' + Sliders2 });
|
||||||
InitDimmode();
|
InitDimmode();
|
||||||
}
|
}
|
||||||
} catch (err:any) {
|
} catch (err:any) {
|
||||||
log('error at trigger activeBrightness: ' + err.message, 'warn');
|
log('error at trigger activeBrightness: ' + err.message, 'warn');
|
||||||
@@ -1526,7 +1538,7 @@ on({id: [NSPanel_Path + 'ScreensaverInfo.activeBrightness'], change: 'ne'}, asyn
|
|||||||
|
|
||||||
on({id: [NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness'], change: "ne"}, async function (obj) {
|
on({id: [NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness'], change: "ne"}, async function (obj) {
|
||||||
try {
|
try {
|
||||||
let active = getState(NSPanel_Path + 'ScreensaverInfo.activeBrightness').val;
|
let active = getState(NSPanel_Path + 'ScreensaverInfo.activeBrightness').val ?? 80;
|
||||||
if (obj.state.val != null && obj.state.val != -1) {
|
if (obj.state.val != null && obj.state.val != -1) {
|
||||||
if (obj.state.val < -1 || obj.state.val > 100) {
|
if (obj.state.val < -1 || obj.state.val > 100) {
|
||||||
log('activeDimmodeBrightness value only between -1 and 100', 'info');
|
log('activeDimmodeBrightness value only between -1 and 100', 'info');
|
||||||
@@ -1556,7 +1568,7 @@ on({id: [NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness'], change: "ne"
|
|||||||
|
|
||||||
on({id: String(NSPanel_Path) + 'ScreensaverInfo.Trigger_Dimmode', change: "ne"}, async function (obj) {
|
on({id: String(NSPanel_Path) + 'ScreensaverInfo.Trigger_Dimmode', change: "ne"}, async function (obj) {
|
||||||
try {
|
try {
|
||||||
let active = getState(NSPanel_Path + 'ScreensaverInfo.activeBrightness').val;
|
let active = getState(NSPanel_Path + 'ScreensaverInfo.activeBrightness').val ?? 80;
|
||||||
if (obj.state.val) {
|
if (obj.state.val) {
|
||||||
SendToPanel({ payload: 'dimmode~' + 100 + '~' + active + '~' + rgb_dec565(config.defaultBackgroundColor) + '~' + rgb_dec565(globalTextColor) + '~' + Sliders2 });
|
SendToPanel({ payload: 'dimmode~' + 100 + '~' + active + '~' + rgb_dec565(config.defaultBackgroundColor) + '~' + rgb_dec565(globalTextColor) + '~' + Sliders2 });
|
||||||
} else {
|
} else {
|
||||||
@@ -1907,8 +1919,8 @@ on({id: [NSPanel_Path + 'PageNavi'], change: "any"}, async function (obj) {
|
|||||||
//----------------------Begin Dimmode
|
//----------------------Begin Dimmode
|
||||||
function ScreensaverDimmode(timeDimMode:NSPanel.DimMode) {
|
function ScreensaverDimmode(timeDimMode:NSPanel.DimMode) {
|
||||||
try {
|
try {
|
||||||
let active = getState(NSPanel_Path + 'ScreensaverInfo.activeBrightness').val
|
let active = getState(NSPanel_Path + 'ScreensaverInfo.activeBrightness').val ?? 80
|
||||||
let dimmode = getState(NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness').val
|
let dimmode = getState(NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness').val ?? -1
|
||||||
if (Debug) {
|
if (Debug) {
|
||||||
log('function ScreensaverDimmode RGB-Wert HMIDark' + rgb_dec565(HMIDark), 'info');
|
log('function ScreensaverDimmode RGB-Wert HMIDark' + rgb_dec565(HMIDark), 'info');
|
||||||
}
|
}
|
||||||
@@ -2015,12 +2027,12 @@ async function InitDimmode() {
|
|||||||
ScreensaverDimmode(timeDimMode);
|
ScreensaverDimmode(timeDimMode);
|
||||||
});
|
});
|
||||||
if (getState(NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness').val != null && getState(NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness').val != -1) {
|
if (getState(NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness').val != null && getState(NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness').val != -1) {
|
||||||
SendToPanel({ payload: 'dimmode~' + getState(NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness').val + '~' + getState(NSPanel_Path + 'ScreensaverInfo.activeBrightness').val + '~' + rgb_dec565(config.defaultBackgroundColor) + '~' + rgb_dec565(globalTextColor) + '~' + Sliders2 });
|
SendToPanel({ payload: 'dimmode~' + getState(NSPanel_Path + 'ScreensaverInfo.activeDimmodeBrightness').val + '~' + getState(NSPanel_Path + 'ScreensaverInfo.activeBrightness').val ?? 80 + '~' + rgb_dec565(config.defaultBackgroundColor) + '~' + rgb_dec565(globalTextColor) + '~' + Sliders2 });
|
||||||
} else {
|
} else {
|
||||||
if (isDimTimeInRange(timeDimMode.timeDay,timeDimMode.timeNight)) {
|
if (isDimTimeInRange(timeDimMode.timeDay,timeDimMode.timeNight)) {
|
||||||
SendToPanel({ payload: 'dimmode~' + timeDimMode.brightnessDay + '~' + getState(NSPanel_Path + 'ScreensaverInfo.activeBrightness').val + '~' + rgb_dec565(config.defaultBackgroundColor) + '~' + rgb_dec565(globalTextColor) + '~' + Sliders2 });
|
SendToPanel({ payload: 'dimmode~' + timeDimMode.brightnessDay + '~' + getState(NSPanel_Path + 'ScreensaverInfo.activeBrightness').val?? 80 + '~' + rgb_dec565(config.defaultBackgroundColor) + '~' + rgb_dec565(globalTextColor) + '~' + Sliders2 });
|
||||||
} else {
|
} else {
|
||||||
SendToPanel({ payload: 'dimmode~' + timeDimMode.brightnessNight + '~' + getState(NSPanel_Path + 'ScreensaverInfo.activeBrightness').val + '~' + rgb_dec565(config.defaultBackgroundColor) + '~' + rgb_dec565(globalTextColor) + '~' + Sliders2 });
|
SendToPanel({ payload: 'dimmode~' + timeDimMode.brightnessNight + '~' + getState(NSPanel_Path + 'ScreensaverInfo.activeBrightness').val ?? 80 + '~' + rgb_dec565(config.defaultBackgroundColor) + '~' + rgb_dec565(globalTextColor) + '~' + Sliders2 });
|
||||||
}
|
}
|
||||||
ScreensaverDimmode(timeDimMode);
|
ScreensaverDimmode(timeDimMode);
|
||||||
}
|
}
|
||||||
@@ -3169,9 +3181,9 @@ function findPageItem(searching: String): PageItem {
|
|||||||
function GeneratePage(page: PageType): void {
|
function GeneratePage(page: PageType): void {
|
||||||
try {
|
try {
|
||||||
activePage = page;
|
activePage = page;
|
||||||
setIfExists(NSPanel_Path + 'ActivePage.type', activePage.type);
|
setIfExists(NSPanel_Path + 'ActivePage.type', activePage.type, null, true);
|
||||||
setIfExists(NSPanel_Path + 'ActivePage.heading', activePage.heading);
|
setIfExists(NSPanel_Path + 'ActivePage.heading', activePage.heading, null, true);
|
||||||
setIfExists(NSPanel_Path + 'ActivePage.id0', activePage.items[0] !== undefined ? activePage.items[0].id : '');
|
setIfExists(NSPanel_Path + 'ActivePage.id0', activePage.items[0] !== undefined ? activePage.items[0].id : '', null, true);
|
||||||
switch (page.type) {
|
switch (page.type) {
|
||||||
case 'cardEntities':
|
case 'cardEntities':
|
||||||
SendToPanel(GenerateEntitiesPage(page));
|
SendToPanel(GenerateEntitiesPage(page));
|
||||||
@@ -3374,7 +3386,11 @@ function GeneratePageElements(page: PageType): string {
|
|||||||
maxItems = 6;
|
maxItems = 6;
|
||||||
break;
|
break;
|
||||||
case 'cardGrid2':
|
case 'cardGrid2':
|
||||||
maxItems = 8;
|
if (getState(NSPanel_Path + 'NSPanel_Version').val == 'us-p') {
|
||||||
|
maxItems = 9;
|
||||||
|
} else {
|
||||||
|
maxItems = 8;
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4753,67 +4769,25 @@ function unsubscribeMediaSubscriptions(): void {
|
|||||||
|
|
||||||
function subscribeMediaSubscriptions(id: string): void {
|
function subscribeMediaSubscriptions(id: string): void {
|
||||||
on({id: [id + '.STATE',
|
on({id: [id + '.STATE',
|
||||||
id + '.VOLUME',
|
id + '.ARTIST',
|
||||||
id + '.ARTIST',
|
id + '.TITLE',
|
||||||
id + '.ALBUM',
|
id + '.ALBUM',
|
||||||
id + '.TITLE',
|
id + '.VOLUME',
|
||||||
id + '.REPEAT',
|
id + '.REPEAT',
|
||||||
id + '.SHUFFLE'], change: "any"}, async function () {
|
id + '.SHUFFLE',
|
||||||
(function () { if (timeoutMedia) { clearTimeout(timeoutMedia); timeoutMedia = null; } })();
|
id + '.DURATION',
|
||||||
timeoutMedia = setTimeout(async function () {
|
id + '.ELAPSED'], change: "any", ack: true}, async function () {
|
||||||
if (useMediaEvents) {
|
if (useMediaEvents && pageCounter == 1) {
|
||||||
GeneratePage(activePage!);
|
GeneratePage(activePage!);
|
||||||
setTimeout(async function () {
|
}
|
||||||
GeneratePage(activePage!);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
},50)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function subscribeMediaSubscriptionsSonosAdd(id: string): void {
|
function subscribeMediaSubscriptionsSonosAdd(id: string): void {
|
||||||
on({id: [id + '.QUEUE',
|
on({id: [id + '.QUEUE'], change: "any", ack: true}, async function () {
|
||||||
id + '.DURATION',
|
if (useMediaEvents && pageCounter == 1) {
|
||||||
id + '.ELAPSED'], change: "any"}, async function () {
|
GeneratePage(activePage!);
|
||||||
(function () { if (timeoutMedia) { clearTimeout(timeoutMedia); timeoutMedia = null; } })();
|
}
|
||||||
timeoutMedia = setTimeout(async function () {
|
|
||||||
if (useMediaEvents) {
|
|
||||||
GeneratePage(activePage!);
|
|
||||||
setTimeout(async function () {
|
|
||||||
GeneratePage(activePage!);
|
|
||||||
}, 50);
|
|
||||||
}
|
|
||||||
},50)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function subscribeMediaSubscriptionsAlexaAdd(id: string): void {
|
|
||||||
on({id: [id + '.DURATION',
|
|
||||||
id + '.ELAPSED'], change: "any"}, async function () {
|
|
||||||
(function () { if (timeoutMedia) { clearTimeout(timeoutMedia); timeoutMedia = null; } })();
|
|
||||||
timeoutMedia = setTimeout(async function () {
|
|
||||||
if (useMediaEvents) {
|
|
||||||
GeneratePage(activePage!);
|
|
||||||
setTimeout(async function () {
|
|
||||||
GeneratePage(activePage!);
|
|
||||||
}, 50);
|
|
||||||
}
|
|
||||||
},50)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function subscribeMediaSubscriptionsBoseAdd(id: string): void {
|
|
||||||
on({id: [id + '.DURATION',
|
|
||||||
id + '.ELAPSED'], change: "any"}, async function () {
|
|
||||||
(function () { if (timeoutMedia) { clearTimeout(timeoutMedia); timeoutMedia = null; } })();
|
|
||||||
timeoutMedia = setTimeout(async function () {
|
|
||||||
if (useMediaEvents) {
|
|
||||||
GeneratePage(activePage!);
|
|
||||||
setTimeout(async function () {
|
|
||||||
GeneratePage(activePage!);
|
|
||||||
}, 50);
|
|
||||||
}
|
|
||||||
},50)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4942,6 +4916,13 @@ async function createAutoMediaAlias (id: string, mediaDevice: string, adapterPla
|
|||||||
log('error at function createAutoMediaAlias Adapter spotify-premium: ' + err.message, 'warn');
|
log('error at function createAutoMediaAlias Adapter spotify-premium: ' + err.message, 'warn');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//Add Spotify Datapoints > v4.3.3.42
|
||||||
|
//Spotify-Premium has Role value and a known Bug in player.progress
|
||||||
|
if (existsObject(id + '.DURATION') == false) {
|
||||||
|
const dpPath: string = adapterPlayerInstance;
|
||||||
|
await createAliasAsync(id + '.DURATION', dpPath + 'player.duration', true, <iobJS.StateCommon> {type: 'string', role: 'media.duration.text', name: 'DURATION'});
|
||||||
|
await createAliasAsync(id + '.ELAPSED', dpPath + 'player.progress', true, <iobJS.StateCommon> {type: 'string', role: 'media.elapsed.text', name: 'ELAPSED'});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -4979,7 +4960,12 @@ async function createAutoMediaAlias (id: string, mediaDevice: string, adapterPla
|
|||||||
log('error function createAutoMediaAlias Adapter volumio: ' + err.message, 'warn');
|
log('error function createAutoMediaAlias Adapter volumio: ' + err.message, 'warn');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//Add Volumio Datapoints > v4.3.3.42
|
||||||
|
if (existsObject(id + '.DURATION') == false) {
|
||||||
|
const dpPath: string = adapterPlayerInstance;
|
||||||
|
await createAliasAsync(id + '.DURATION', dpPath + 'playbackInfo.duration', true, <iobJS.StateCommon> {type: 'string', role: 'media.duration', name: 'DURATION'});
|
||||||
|
//await createAliasAsync(id + '.ELAPSED', dpPath + 'player.progress', true, <iobJS.StateCommon> {type: 'string', role: 'media.elapsed.text', name: 'ELAPSED'});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "squeezeboxrpc.0.":
|
case "squeezeboxrpc.0.":
|
||||||
@@ -5009,13 +4995,14 @@ async function createAutoMediaAlias (id: string, mediaDevice: string, adapterPla
|
|||||||
await createAliasAsync(id + '.STATE', dpPath + '.Power', true, <iobJS.StateCommon> {type: 'number', role: 'switch', name: 'STATE'});
|
await createAliasAsync(id + '.STATE', dpPath + '.Power', true, <iobJS.StateCommon> {type: 'number', role: 'switch', name: 'STATE'});
|
||||||
await createAliasAsync(id + '.VOLUME', dpPath + '.Volume', true, <iobJS.StateCommon> {type: 'number', role: 'level.volume', name: 'VOLUME'});
|
await createAliasAsync(id + '.VOLUME', dpPath + '.Volume', true, <iobJS.StateCommon> {type: 'number', role: 'level.volume', name: 'VOLUME'});
|
||||||
await createAliasAsync(id + '.VOLUME_ACTUAL', dpPath + '.Volume', true, <iobJS.StateCommon> {type: 'number', role: 'value.volume', name: 'VOLUME_ACTUAL'});
|
await createAliasAsync(id + '.VOLUME_ACTUAL', dpPath + '.Volume', true, <iobJS.StateCommon> {type: 'number', role: 'value.volume', name: 'VOLUME_ACTUAL'});
|
||||||
await createAliasAsync(id + '.SHUFFLE', dpPath + '.PlaylistShuffle', true, <iobJS.StateCommon> {type: 'string', role: 'media.mode.shuffle', name: 'SHUFFLE', alias: {id: dpPath + '.PlaylistShuffle', read: 'val !== 0 ? \'on\' : \'off\'', write: 'val === \'off\' ? 0 : 1'}});
|
await createAliasAsync(id + '.SHUFFLE', dpPath + '.PlaylistShuffle', true, <iobJS.StateCommon> {type: 'string', role: 'media.mode.shuffle', name: 'SHUFFLE'});
|
||||||
await createAliasAsync(id + '.REPEAT', dpPath + '.PlaylistRepeat', true, <iobJS.StateCommon> {type: 'number', role: 'media.mode.repeat', name: 'REPEAT'});
|
await createAliasAsync(id + '.REPEAT', dpPath + '.PlaylistRepeat', true, <iobJS.StateCommon> {type: 'number', role: 'media.mode.repeat', name: 'REPEAT'});
|
||||||
|
await createAliasAsync(id + '.DURATION', dpPath + '.Duration', true, <iobJS.StateCommon> {type: 'string', role: 'media.duration', name: 'DURATION'});
|
||||||
|
await createAliasAsync(id + '.ELAPSED', dpPath + '.Time', true, <iobJS.StateCommon> {type: 'string', role: 'media.elapsed', name: 'ELAPSED'});
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
log('error at function createAutoMediaAlias Adapter Squeezebox: ' + err.message, 'warn');
|
log('error at function createAutoMediaAlias Adapter Squeezebox: ' + err.message, 'warn');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "bosesoundtouch.0.":
|
case "bosesoundtouch.0.":
|
||||||
@@ -5074,6 +5061,7 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
if (!page.items[0].id) throw new Error ('Missing page id for cardMedia!');
|
if (!page.items[0].id) throw new Error ('Missing page id for cardMedia!');
|
||||||
|
|
||||||
let id = page.items[0].id;
|
let id = page.items[0].id;
|
||||||
|
let tid = 0;
|
||||||
let out_msgs: NSPanel.Payload[] = [];
|
let out_msgs: NSPanel.Payload[] = [];
|
||||||
|
|
||||||
if (!page.items[0].adapterPlayerInstance!) throw new Error('page.items[0].adapterPlayerInstance is undefined!')
|
if (!page.items[0].adapterPlayerInstance!) throw new Error('page.items[0].adapterPlayerInstance is undefined!')
|
||||||
@@ -5081,23 +5069,6 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
let v1Adapter = vInstance.split('.');
|
let v1Adapter = vInstance.split('.');
|
||||||
let v2Adapter:NSPanel.PlayerType = v1Adapter[0] as NSPanel.PlayerType;
|
let v2Adapter:NSPanel.PlayerType = v1Adapter[0] as NSPanel.PlayerType;
|
||||||
|
|
||||||
// Some magic to change the ID of the alias, since speakers are not a property but separate objects
|
|
||||||
if(v2Adapter == 'squeezeboxrpc') {
|
|
||||||
if(id && getObject(id).type != 'channel') {
|
|
||||||
id = id + '.' + page.items[0].mediaDevice;
|
|
||||||
page.items[0].id = id;
|
|
||||||
page.heading = page.items[0].mediaDevice ?? '';
|
|
||||||
} else {
|
|
||||||
let idParts = id.split('.');
|
|
||||||
if(idParts[idParts.length-1] !== page.items[0].mediaDevice) {
|
|
||||||
idParts[idParts.length-1] = page.items[0].mediaDevice ?? '';
|
|
||||||
id = idParts.join('.');
|
|
||||||
page.items[0].id = id;
|
|
||||||
page.heading = page.items[0].mediaDevice ?? '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let vMediaDevice = (page.items[0].mediaDevice != undefined) ? page.items[0].mediaDevice : '';
|
let vMediaDevice = (page.items[0].mediaDevice != undefined) ? page.items[0].mediaDevice : '';
|
||||||
|
|
||||||
if (isPlayerWithMediaDevice(v2Adapter)) {
|
if (isPlayerWithMediaDevice(v2Adapter)) {
|
||||||
@@ -5117,10 +5088,10 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
subscribeMediaSubscriptions(page.items[0].id);
|
subscribeMediaSubscriptions(page.items[0].id);
|
||||||
if (v2Adapter == 'sonos') {
|
if (v2Adapter == 'sonos') {
|
||||||
subscribeMediaSubscriptionsSonosAdd(page.items[0].id);
|
subscribeMediaSubscriptionsSonosAdd(page.items[0].id);
|
||||||
} else if (v2Adapter == 'alexa2') {
|
} else if (v2Adapter == 'spotify-premium') {
|
||||||
subscribeMediaSubscriptionsAlexaAdd(page.items[0].id);
|
setState(vInstance + 'getDevices', true);
|
||||||
} else if (v2Adapter == 'bosesoundtouch') {
|
setState(vInstance + 'getPlaybackInfo', true);
|
||||||
subscribeMediaSubscriptionsBoseAdd(page.items[0].id);
|
setState(vInstance + 'getPlaylists', true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5130,10 +5101,6 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
subscribeMediaSubscriptions(page.items[0].id);
|
subscribeMediaSubscriptions(page.items[0].id);
|
||||||
if (v2Adapter == 'sonos') {
|
if (v2Adapter == 'sonos') {
|
||||||
subscribeMediaSubscriptionsSonosAdd(page.items[0].id);
|
subscribeMediaSubscriptionsSonosAdd(page.items[0].id);
|
||||||
} else if (v2Adapter == 'alexa2') {
|
|
||||||
subscribeMediaSubscriptionsAlexaAdd(page.items[0].id);
|
|
||||||
} else if (v2Adapter == 'bosesoundtouch') {
|
|
||||||
subscribeMediaSubscriptionsBoseAdd(page.items[0].id);
|
|
||||||
}
|
}
|
||||||
} else if (page.type == 'cardMedia' && pageCounter == -1) {
|
} else if (page.type == 'cardMedia' && pageCounter == -1) {
|
||||||
//Do Nothing
|
//Do Nothing
|
||||||
@@ -5144,8 +5111,8 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
if (existsObject(id)) {
|
if (existsObject(id)) {
|
||||||
let name = getState(id + '.ALBUM').val;
|
let name = getState(id + '.ALBUM').val;
|
||||||
let title = getState(id + '.TITLE').val;
|
let title = getState(id + '.TITLE').val;
|
||||||
if (title.length > 27) {
|
if (title.length > 26) {
|
||||||
title = title.slice(0, 27) + '...';
|
title = title.slice(0, 26) + '...';
|
||||||
}
|
}
|
||||||
if (existsObject(id + '.DURATION') && existsObject(id + '.ELAPSED')) {
|
if (existsObject(id + '.DURATION') && existsObject(id + '.ELAPSED')) {
|
||||||
if (v2Adapter == 'alexa2') {
|
if (v2Adapter == 'alexa2') {
|
||||||
@@ -5167,7 +5134,14 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
vDuration = vDuration.slice(1);
|
vDuration = vDuration.slice(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
title = title + ' (' + vElapsed + '|' + vDuration + ')';
|
if (vDuration != '0:00') {
|
||||||
|
title = title + ' (' + vElapsed + '|' + vDuration + ')';
|
||||||
|
} else {
|
||||||
|
title = title + ' (' + vElapsed + ')';
|
||||||
|
}
|
||||||
|
if (title == ' (0:00)') {
|
||||||
|
title = '';
|
||||||
|
}
|
||||||
} else if (v2Adapter == 'sonos' && getState(page.items[0].adapterPlayerInstance + 'root.' + page.items[0].mediaDevice + '.current_type').val == 0) {
|
} else if (v2Adapter == 'sonos' && getState(page.items[0].adapterPlayerInstance + 'root.' + page.items[0].mediaDevice + '.current_type').val == 0) {
|
||||||
let vElapsed = getState(id + '.ELAPSED').val;
|
let vElapsed = getState(id + '.ELAPSED').val;
|
||||||
if (vElapsed.length == 5) {
|
if (vElapsed.length == 5) {
|
||||||
@@ -5196,7 +5170,51 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
title = title + ' (' + vElapsed + '|' + vDuration + ')';
|
title = title + ' (' + vElapsed + '|' + vDuration + ')';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let author = getState(id + '.ARTIST').val;
|
let author = getState(id + '.ARTIST').val;
|
||||||
|
|
||||||
|
if (v2Adapter == 'squeezeboxrpc' && author.length == 0) {
|
||||||
|
if(existsObject(([page.items[0].adapterPlayerInstance, 'Players.', page.items[0].mediaDevice, '.Playlist'].join('')))) {
|
||||||
|
if(existsObject(([page.items[0].adapterPlayerInstance, 'Players.', page.items[0].mediaDevice, '.Playlist'].join('')))) {
|
||||||
|
let lmstracklist = JSON.parse(getState(([page.items[0].adapterPlayerInstance, 'Players.', page.items[0].mediaDevice, '.Playlist'].join(''))).val);
|
||||||
|
let currentIndex: number = parseInt(getState([page.items[0].adapterPlayerInstance, 'Players.', page.items[0].mediaDevice, '.PlaylistCurrentIndex'].join('')).val);
|
||||||
|
author = lmstracklist[currentIndex].Artist + '|' + lmstracklist[currentIndex].Album;
|
||||||
|
if (author.length > 37) {
|
||||||
|
author = author.slice(0, 37) + '...';
|
||||||
|
}
|
||||||
|
let elapsedTime: number = parseInt(getState([page.items[0].adapterPlayerInstance, 'Players.', page.items[0].mediaDevice, '.Time'].join('')).val);
|
||||||
|
let elapsedSeconds = elapsedTime%60 < 10 ? '0' : '';
|
||||||
|
let vElapsed = Math.floor(elapsedTime/60) + ":" + elapsedSeconds + elapsedTime%60;
|
||||||
|
|
||||||
|
let durationSeconds = parseInt(lmstracklist[currentIndex].Duration)%60 < 10 ? '0' : '';
|
||||||
|
let vDuration = Math.floor(parseInt(lmstracklist[currentIndex].Duration)/60) + ":" + durationSeconds + parseInt(lmstracklist[currentIndex].Duration)%60;
|
||||||
|
title = lmstracklist[currentIndex].title;
|
||||||
|
if (title.length > 25) {
|
||||||
|
title = title.slice(0, 25) + '...';
|
||||||
|
}
|
||||||
|
title = title + ' (' + vElapsed + '|' + vDuration + ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Settings >>Aktualisierungsintervall für Statusinformationen<< = 1 !
|
||||||
|
// If the refresh time is set to 1 second in the spotify-premium.X instance,
|
||||||
|
// the elapsed refresh bug '00:00' is not visible
|
||||||
|
if (v2Adapter == 'spotify-premium') {
|
||||||
|
let vElapsed: string = getState(id + '.ELAPSED').val;
|
||||||
|
if (vElapsed.substring(0,1) == '0') {
|
||||||
|
vElapsed = vElapsed.slice(1)
|
||||||
|
}
|
||||||
|
let vDuration: string = getState(id + '.DURATION').val;
|
||||||
|
if (vDuration.substring(0,1) == '0') {
|
||||||
|
vDuration = vDuration.slice(1)
|
||||||
|
}
|
||||||
|
title = title + ' (' + vElapsed + '|' + vDuration + ')';
|
||||||
|
if (title == ' (0:00|0:00)') {
|
||||||
|
title = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let shuffle = getState(id + '.SHUFFLE').val;
|
let shuffle = getState(id + '.SHUFFLE').val;
|
||||||
|
|
||||||
//New Adapter/Player
|
//New Adapter/Player
|
||||||
@@ -5207,19 +5225,23 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
media_icon = Icons.GetIcon('spotify');
|
media_icon = Icons.GetIcon('spotify');
|
||||||
name = getState(id + '.CONTEXT_DESCRIPTION').val;
|
name = getState(id + '.CONTEXT_DESCRIPTION').val;
|
||||||
let nameLength = name.length;
|
let nameLength = name.length;
|
||||||
if (name.substring(0,9) == 'Playlist:') {
|
if (name.substring(0,17) == 'Playlist: This Is') {
|
||||||
|
name = name.slice(18, 34) + '...';
|
||||||
|
} else if (name.substring(0,9) == 'Playlist:') {
|
||||||
name = name.slice(10, 26) + '...';
|
name = name.slice(10, 26) + '...';
|
||||||
} else if (name.substring(0,6) == 'Album:') {
|
} else if (name.substring(0,6) == 'Album:') {
|
||||||
name = name.slice(7, 23) + '...';
|
name = name.slice(7, 23) + '...';
|
||||||
} else if (name.substring(0,6) == 'Track') {
|
} else if (name.substring(0,6) == 'Track:') {
|
||||||
name = 'Spotify-Premium';
|
name = name.slice(7, 23) + '...';
|
||||||
|
} else if (name.substring(0,7) == 'Artist:') {
|
||||||
|
name = name.slice(8, 24) + '...';
|
||||||
}
|
}
|
||||||
if (nameLength == 0) {
|
if (nameLength == 0) {
|
||||||
name = 'Spotify-Premium';
|
name = 'Spotify-Premium';
|
||||||
}
|
}
|
||||||
author = getState(id + '.ARTIST').val + ' | ' + getState(id + '.ALBUM').val;
|
author = getState(id + '.ARTIST').val + ' | ' + getState(id + '.ALBUM').val;
|
||||||
if (author.length > 30) {
|
if (author.length > 37) {
|
||||||
author = getState(id + '.ARTIST').val;
|
author = author.slice(0,37) + '...';
|
||||||
}
|
}
|
||||||
if ((getState(id + '.ARTIST').val).length == 0) {
|
if ((getState(id + '.ARTIST').val).length == 0) {
|
||||||
author = findLocale('media','no_music_to_control');
|
author = findLocale('media','no_music_to_control');
|
||||||
@@ -5270,9 +5292,10 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
//Logitech Squeezebox RPC
|
//Logitech Squeezebox RPC
|
||||||
if (v2Adapter == 'squeezeboxrpc') {
|
if (v2Adapter == 'squeezeboxrpc') {
|
||||||
media_icon = Icons.GetIcon('dlna');
|
media_icon = Icons.GetIcon('dlna');
|
||||||
let nameLength = name.length;
|
if (name.length == 0) {
|
||||||
if (nameLength == 0) {
|
name = page.heading;
|
||||||
name = page.items[0].mediaDevice;
|
} else if (name.length > 16) {
|
||||||
|
name = name.slice(0,16) + '...'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5290,6 +5313,8 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
}
|
}
|
||||||
if (nameLength == 0) {
|
if (nameLength == 0) {
|
||||||
name = 'Alexa Player';
|
name = 'Alexa Player';
|
||||||
|
} else {
|
||||||
|
name = name.slice(0,16) + '...';
|
||||||
}
|
}
|
||||||
author = getState(id + '.ARTIST').val + ' | ' + getState(id + '.ALBUM').val;
|
author = getState(id + '.ARTIST').val + ' | ' + getState(id + '.ALBUM').val;
|
||||||
if (author.length > 30) {
|
if (author.length > 30) {
|
||||||
@@ -5302,12 +5327,12 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
|
|
||||||
//Volumio
|
//Volumio
|
||||||
if (v2Adapter == 'volumio') {
|
if (v2Adapter == 'volumio') {
|
||||||
if (name != undefined) { author = author + " [" + name + "]"; }
|
media_icon = Icons.GetIcon('clock-time-twelve-outline');
|
||||||
name = getState(vInstance + 'info.name').val; /* page.heading;
|
if (name != undefined) { author = author + " | " + name; }
|
||||||
getState(id + '.TRACK').val; */
|
name = page.heading;
|
||||||
}
|
}
|
||||||
|
|
||||||
let volume = getState(id + '.VOLUME').val;
|
let volume = scale(getState(id + '.VOLUME').val, activePage!.items[0]!.minValue ?? 0, activePage!.items[0]!.maxValue ?? 100, 100, 0);
|
||||||
let iconplaypause = Icons.GetIcon('pause'); //pause
|
let iconplaypause = Icons.GetIcon('pause'); //pause
|
||||||
let shuffle_icon = Icons.GetIcon('shuffle-variant'); //shuffle
|
let shuffle_icon = Icons.GetIcon('shuffle-variant'); //shuffle
|
||||||
let onoffbutton = 1374;
|
let onoffbutton = 1374;
|
||||||
@@ -5315,7 +5340,9 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
if (shuffle == 'off' || shuffle == false || shuffle == 0 || shuffle == 'false') {
|
if (shuffle == 'off' || shuffle == false || shuffle == 0 || shuffle == 'false') {
|
||||||
shuffle_icon = Icons.GetIcon('shuffle-disabled'); //shuffle
|
shuffle_icon = Icons.GetIcon('shuffle-disabled'); //shuffle
|
||||||
}
|
}
|
||||||
if (v2Adapter == 'volumio') { shuffle_icon = Icons.GetIcon('refresh'); } //Volumio: refresh playlist
|
|
||||||
|
// Todo: Refresh automatisieren und dafür wieder Shuffle nutzen
|
||||||
|
//if (v2Adapter == 'volumio') { shuffle_icon = Icons.GetIcon('shuffle-disabled'); } //Volumio: refresh playlist
|
||||||
|
|
||||||
|
|
||||||
//For all players
|
//For all players
|
||||||
@@ -5346,7 +5373,7 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentSpeaker = findLocale('media','no_speaker_found');
|
let currentSpeaker: string = findLocale('media','no_speaker_found');
|
||||||
|
|
||||||
if (v2Adapter == 'alexa2') {
|
if (v2Adapter == 'alexa2') {
|
||||||
currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'Echo-Devices.', page.items[0].mediaDevice, '.Info.name'].join(''))).val;
|
currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'Echo-Devices.', page.items[0].mediaDevice, '.Info.name'].join(''))).val;
|
||||||
@@ -5358,6 +5385,8 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'Players.', page.items[0].mediaDevice, '.Playername'].join(''))).val;
|
currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'Players.', page.items[0].mediaDevice, '.Playername'].join(''))).val;
|
||||||
} else if (v2Adapter == 'bosesoundtouch') {
|
} else if (v2Adapter == 'bosesoundtouch') {
|
||||||
currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'deviceInfo.name'].join(''))).val;
|
currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'deviceInfo.name'].join(''))).val;
|
||||||
|
} else if (v2Adapter == 'volumio') {
|
||||||
|
currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'info.name'].join(''))).val;
|
||||||
}
|
}
|
||||||
//-------------------------------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------------------------------
|
||||||
// All Alexa devices (the online / player and commands directory is available) are listed and linked below
|
// All Alexa devices (the online / player and commands directory is available) are listed and linked below
|
||||||
@@ -5374,6 +5403,11 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
speakerListArray.push(getState(playerId).val);
|
speakerListArray.push(getState(playerId).val);
|
||||||
page.items[0].speakerList = speakerListArray;
|
page.items[0].speakerList = speakerListArray;
|
||||||
});
|
});
|
||||||
|
} else if (v2Adapter == 'spotify-premium') {
|
||||||
|
// All possible Devices if page.items[0].speakerList empty
|
||||||
|
if (Debug) log(getState(page.items[0].adapterPlayerInstance + 'devices.availableDeviceListString').val);
|
||||||
|
speakerListArray = (getState(page.items[0].adapterPlayerInstance + 'devices.availableDeviceListString').val).split(';');
|
||||||
|
page.items[0].speakerList = speakerListArray;
|
||||||
} else {
|
} else {
|
||||||
let i_list = Array.prototype.slice.apply($('[state.id="' + page.items[0].adapterPlayerInstance + 'Echo-Devices.*.Info.name"]'));
|
let i_list = Array.prototype.slice.apply($('[state.id="' + page.items[0].adapterPlayerInstance + 'Echo-Devices.*.Info.name"]'));
|
||||||
for (let i_index in i_list) {
|
for (let i_index in i_list) {
|
||||||
@@ -5399,7 +5433,7 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
if (speakerListArray.length > 0) {
|
if (speakerListArray.length > 0) {
|
||||||
speakerListIconCol = rgb_dec565(HMIOn);
|
speakerListIconCol = rgb_dec565(HMIOn);
|
||||||
speakerListString = 'input_sel' + '~' +
|
speakerListString = 'input_sel' + '~' +
|
||||||
id + '?speakerlist' + '~' +
|
tid + '?speakerlist' + '~' +
|
||||||
Icons.GetIcon('speaker') + '~' +
|
Icons.GetIcon('speaker') + '~' +
|
||||||
speakerListIconCol + '~' +
|
speakerListIconCol + '~' +
|
||||||
findLocale('media','speaker') + '~' +
|
findLocale('media','speaker') + '~' +
|
||||||
@@ -5433,10 +5467,13 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/* Spotify: get all playlists if empty */
|
||||||
|
} else if (v2Adapter == 'spotify-premium') {
|
||||||
|
page.items[0].playList = (getState(page.items[0].adapterPlayerInstance + 'playlists.playlistListString').val).split(';');
|
||||||
}
|
}
|
||||||
playListIconCol = rgb_dec565(HMIOn);
|
playListIconCol = rgb_dec565(HMIOn);
|
||||||
playListString = 'input_sel' + '~' +
|
playListString = 'input_sel' + '~' +
|
||||||
id + '?playlist' + '~' +
|
tid + '?playlist' + '~' +
|
||||||
Icons.GetIcon('playlist-play') + '~' +
|
Icons.GetIcon('playlist-play') + '~' +
|
||||||
playListIconCol + '~' +
|
playListIconCol + '~' +
|
||||||
//'PlayL ' + page.heading + '~' +
|
//'PlayL ' + page.heading + '~' +
|
||||||
@@ -5446,9 +5483,7 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
|
|
||||||
//InSel Tracklist
|
//InSel Tracklist
|
||||||
globalTracklist = ''
|
globalTracklist = ''
|
||||||
if (v2Adapter == 'spotify-premium') {
|
|
||||||
globalTracklist = ' ' //Todo
|
|
||||||
}
|
|
||||||
let trackListString: string = '~~~~~~'
|
let trackListString: string = '~~~~~~'
|
||||||
let trackListIconCol = rgb_dec565(HMIOff);
|
let trackListIconCol = rgb_dec565(HMIOff);
|
||||||
if (v2Adapter == 'volumio') { /* Volumio: get queue */
|
if (v2Adapter == 'volumio') { /* Volumio: get queue */
|
||||||
@@ -5479,8 +5514,8 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
|
|
||||||
}, 2000);
|
}, 2000);
|
||||||
globalTracklist = page.items[0].globalTracklist;
|
globalTracklist = page.items[0].globalTracklist;
|
||||||
} else if(v2Adapter == 'squeezeboxrpc' && existsObject(([page.items[0].adapterPlayerInstance, '.Players.', page.items[0].mediaDevice, '.Playlist'].join('')))) {
|
} else if(v2Adapter == 'squeezeboxrpc' && existsObject(([page.items[0].adapterPlayerInstance, 'Players.', page.items[0].mediaDevice, '.Playlist'].join('')))) {
|
||||||
let lmstracklist = JSON.parse(getState(([page.items[0].adapterPlayerInstance, '.Players.', page.items[0].mediaDevice, '.Playlist'].join(''))).val);
|
let lmstracklist = JSON.parse(getState(([page.items[0].adapterPlayerInstance, 'Players.', page.items[0].mediaDevice, '.Playlist'].join(''))).val);
|
||||||
globalTracklist = lmstracklist;
|
globalTracklist = lmstracklist;
|
||||||
} else if(v2Adapter == 'sonos' && existsObject(([page.items[0].adapterPlayerInstance, 'root.', page.items[0].mediaDevice, '.playlist_set'].join('')))) {
|
} else if(v2Adapter == 'sonos' && existsObject(([page.items[0].adapterPlayerInstance, 'root.', page.items[0].mediaDevice, '.playlist_set'].join('')))) {
|
||||||
let lmstracklist = getState(([page.items[0].adapterPlayerInstance, 'root.', page.items[0].mediaDevice, '.queue'].join(''))).val;
|
let lmstracklist = getState(([page.items[0].adapterPlayerInstance, 'root.', page.items[0].mediaDevice, '.queue'].join(''))).val;
|
||||||
@@ -5499,12 +5534,19 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
trackList = trackList + ']';
|
trackList = trackList + ']';
|
||||||
if (Debug) log(trackList, 'info');
|
if (Debug) log(trackList, 'info');
|
||||||
globalTracklist = trackList;
|
globalTracklist = trackList;
|
||||||
|
} else if (v2Adapter == 'spotify-premium') {
|
||||||
|
try {
|
||||||
|
let tempTrackList = JSON.parse(getState(page.items[0].adapterPlayerInstance + 'player.playlist.trackListArray').val);
|
||||||
|
globalTracklist = tempTrackList;
|
||||||
|
} catch {
|
||||||
|
log('Hello Mr. Developer something went wrong in tracklist!', 'debug')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (globalTracklist != null && globalTracklist.length != 0) {
|
if (globalTracklist != null && globalTracklist.length != 0) {
|
||||||
trackListIconCol = rgb_dec565(HMIOn);
|
trackListIconCol = rgb_dec565(HMIOn);
|
||||||
trackListString = 'input_sel' + '~' +
|
trackListString = 'input_sel' + '~' +
|
||||||
id + '?tracklist' + '~' +
|
tid + '?tracklist' + '~' +
|
||||||
Icons.GetIcon('animation-play-outline') + '~' +
|
Icons.GetIcon('animation-play-outline') + '~' +
|
||||||
trackListIconCol + '~' +
|
trackListIconCol + '~' +
|
||||||
findLocale('media','tracklist') + '~' +
|
findLocale('media','tracklist') + '~' +
|
||||||
@@ -5517,7 +5559,7 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
if (page.items[0].equalizerList != undefined) {
|
if (page.items[0].equalizerList != undefined) {
|
||||||
equalizerListIconCol = rgb_dec565(HMIOn);
|
equalizerListIconCol = rgb_dec565(HMIOn);
|
||||||
equalizerListString = 'input_sel' + '~' +
|
equalizerListString = 'input_sel' + '~' +
|
||||||
id + '?equalizer' + '~' +
|
tid + '?equalizer' + '~' +
|
||||||
Icons.GetIcon('equalizer-outline') + '~' +
|
Icons.GetIcon('equalizer-outline') + '~' +
|
||||||
equalizerListIconCol + '~' +
|
equalizerListIconCol + '~' +
|
||||||
findLocale('media','equalizer') + '~' +
|
findLocale('media','equalizer') + '~' +
|
||||||
@@ -5526,7 +5568,7 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
let equalizerListIconCol = rgb_dec565(HMIOn);
|
let equalizerListIconCol = rgb_dec565(HMIOn);
|
||||||
//equalizerListString is used for favariteList
|
//equalizerListString is used for favariteList
|
||||||
equalizerListString = 'input_sel' + '~' +
|
equalizerListString = 'input_sel' + '~' +
|
||||||
id + '?favorites' + '~' +
|
tid + '?favorites' + '~' +
|
||||||
Icons.GetIcon('playlist-star') + '~' +
|
Icons.GetIcon('playlist-star') + '~' +
|
||||||
equalizerListIconCol + '~' +
|
equalizerListIconCol + '~' +
|
||||||
findLocale('media','favorites') + '~' +
|
findLocale('media','favorites') + '~' +
|
||||||
@@ -5575,13 +5617,10 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
repeatIcon = Icons.GetIcon('repeat');
|
repeatIcon = Icons.GetIcon('repeat');
|
||||||
repeatIconCol = rgb_dec565(HMIOn);
|
repeatIconCol = rgb_dec565(HMIOn);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
repeatIcon = Icons.GetIcon('repeat-off');
|
|
||||||
}
|
|
||||||
} else if (v2Adapter == 'volumio') { /* Volumio: only Repeat true/false with API */
|
} else if (v2Adapter == 'volumio') { /* Volumio: only Repeat true/false with API */
|
||||||
if (getState(id + '.REPEAT').val == true) {
|
if (getState(id + '.REPEAT').val == true) {
|
||||||
repeatIcon = Icons.GetIcon('repeat-variant');
|
repeatIcon = Icons.GetIcon('repeat-variant');
|
||||||
repeatIconCol = rgb_dec565(colMediaIcon);
|
repeatIconCol = rgb_dec565(HMIOn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5592,7 +5631,7 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
v2Adapter == 'volumio' ||
|
v2Adapter == 'volumio' ||
|
||||||
v2Adapter == 'squeezeboxrpc') {
|
v2Adapter == 'squeezeboxrpc') {
|
||||||
repeatButtonString = 'button' + '~' +
|
repeatButtonString = 'button' + '~' +
|
||||||
id + '?repeat' + '~' +
|
tid + '?repeat' + '~' +
|
||||||
repeatIcon + '~' +
|
repeatIcon + '~' +
|
||||||
repeatIconCol + '~' +
|
repeatIconCol + '~' +
|
||||||
'Repeat' + '~' +
|
'Repeat' + '~' +
|
||||||
@@ -5605,22 +5644,40 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
if (v2Adapter == 'sonos') {
|
if (v2Adapter == 'sonos') {
|
||||||
if (page.items[0].crossfade == undefined || page.items[0].crossfade == false) {
|
if (page.items[0].crossfade == undefined || page.items[0].crossfade == false) {
|
||||||
toolsString = 'input_sel' + '~' +
|
toolsString = 'input_sel' + '~' +
|
||||||
id + '?seek' + '~' +
|
tid + '?seek' + '~' +
|
||||||
media_icon + '~' +
|
media_icon + '~' +
|
||||||
toolsIconCol + '~' +
|
toolsIconCol + '~' +
|
||||||
findLocale('media','seek') + '~' +
|
findLocale('media','seek') + '~' +
|
||||||
'media5~'
|
'media5~'
|
||||||
} else {
|
} else {
|
||||||
toolsString = 'input_sel' + '~' +
|
toolsString = 'input_sel' + '~' +
|
||||||
id + '?crossfade' + '~' +
|
tid + '?crossfade' + '~' +
|
||||||
media_icon + '~' +
|
media_icon + '~' +
|
||||||
toolsIconCol + '~' +
|
toolsIconCol + '~' +
|
||||||
findLocale('media','crossfade') + '~' +
|
findLocale('media','crossfade') + '~' +
|
||||||
'media5~'
|
'media5~'
|
||||||
}
|
}
|
||||||
|
} else if (v2Adapter == 'squeezeboxrpc') {
|
||||||
|
if (page.items[0].crossfade == undefined || page.items[0].crossfade == false) {
|
||||||
|
toolsString = 'input_sel' + '~' +
|
||||||
|
tid + '?seek' + '~' +
|
||||||
|
media_icon + '~' +
|
||||||
|
toolsIconCol + '~' +
|
||||||
|
findLocale('media','seek') + '~' +
|
||||||
|
'media5~'
|
||||||
|
}
|
||||||
|
} else if (v2Adapter == 'spotify-premium') {
|
||||||
|
if (page.items[0].crossfade == undefined || page.items[0].crossfade == false) {
|
||||||
|
toolsString = 'input_sel' + '~' +
|
||||||
|
tid + '?seek' + '~' +
|
||||||
|
media_icon + '~' +
|
||||||
|
toolsIconCol + '~' +
|
||||||
|
findLocale('media','seek') + '~' +
|
||||||
|
'media5~'
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
toolsString = 'button' + '~' +
|
toolsString = 'button' + '~' +
|
||||||
id + '' + '~' +
|
tid + '' + '~' +
|
||||||
media_icon + '~' +
|
media_icon + '~' +
|
||||||
toolsIconCol + '~' +
|
toolsIconCol + '~' +
|
||||||
findLocale('media','tools') + '~' +
|
findLocale('media','tools') + '~' +
|
||||||
@@ -5631,7 +5688,7 @@ function GenerateMediaPage(page: NSPanel.PageMedia): NSPanel.Payload[] {
|
|||||||
payload: 'entityUpd~' + //entityUpd
|
payload: 'entityUpd~' + //entityUpd
|
||||||
name + '~' + //heading
|
name + '~' + //heading
|
||||||
GetNavigationString(pageId) + '~' + //navigation
|
GetNavigationString(pageId) + '~' + //navigation
|
||||||
id + '~' + //internalNameEntiy
|
tid + '~' + //internalNameEntiy
|
||||||
title + '~' + //title
|
title + '~' + //title
|
||||||
rgb_dec565(colMediaTitle) + '~' + //titleColor
|
rgb_dec565(colMediaTitle) + '~' + //titleColor
|
||||||
author + '~' + //author
|
author + '~' + //author
|
||||||
@@ -6050,8 +6107,6 @@ function subscribePowerSubscriptions(id: string): void {
|
|||||||
function GeneratePowerPage(page: NSPanel.PagePower): NSPanel.Payload[] {
|
function GeneratePowerPage(page: NSPanel.PagePower): NSPanel.Payload[] {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!page.items[0].id) throw new Error ('Missing pageItem.id for PowerPage!');
|
|
||||||
|
|
||||||
let obj:object = {};
|
let obj:object = {};
|
||||||
let demoMode = false;
|
let demoMode = false;
|
||||||
if (page.items[0].id == undefined){
|
if (page.items[0].id == undefined){
|
||||||
@@ -6233,17 +6288,17 @@ function GenerateChartPage(page: NSPanel.PageChart): NSPanel.Payload[] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setIfExists(id: string, value: any, type: string | null = null): boolean {
|
function setIfExists(id: string, value: any, type: string | null = null, ack: boolean = false): boolean {
|
||||||
try {
|
try {
|
||||||
if (type === null) {
|
if (type === null) {
|
||||||
if (existsState(id)) {
|
if (existsState(id)) {
|
||||||
setState(id, value);
|
setState(id, value, ack);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const obj = getObject(id);
|
const obj = getObject(id);
|
||||||
if (existsState(id) && obj.common.type !== undefined && obj.common.type === type) {
|
if (existsState(id) && obj.common.type !== undefined && obj.common.type === type) {
|
||||||
setState(id, value);
|
setState(id, value, ack);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6443,17 +6498,21 @@ function HandleButtonEvent(words: any): void {
|
|||||||
GeneratePage(activePage!);
|
GeneratePage(activePage!);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'bHome':
|
case 'bHome':
|
||||||
if (Debug) {
|
if (Debug) {
|
||||||
log('HandleButtonEvent -> bHome: ' + words[4] + ' - ' + pageId, 'info');
|
log('HandleButtonEvent -> bHome: ' + words[4] + ' - ' + pageId, 'info');
|
||||||
}
|
}
|
||||||
UnsubscribeWatcher();
|
UnsubscribeWatcher();
|
||||||
if (activePage!.home != undefined) {
|
const home = activePage!.home;
|
||||||
GeneratePage(eval(activePage!.home));
|
if (home !== undefined) {
|
||||||
} else {
|
pageId = config.pages.findIndex(a => a == eval(home))
|
||||||
GeneratePage(config.pages[0]);
|
pageId = pageId === -1 ? 0 : pageId;
|
||||||
}
|
GeneratePage(eval(home));
|
||||||
break;
|
} else {
|
||||||
|
pageId = 0;
|
||||||
|
GeneratePage(config.pages[0]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'notifyAction':
|
case 'notifyAction':
|
||||||
if (words[4] == 'yes') {
|
if (words[4] == 'yes') {
|
||||||
setState(popupNotifyInternalName, <iobJS.State>{ val: words[2], ack: true });
|
setState(popupNotifyInternalName, <iobJS.State>{ val: words[2], ack: true });
|
||||||
@@ -6514,7 +6573,7 @@ function HandleButtonEvent(words: any): void {
|
|||||||
if (Debug) log('NaviToPage: ' + words[2]);
|
if (Debug) log('NaviToPage: ' + words[2]);
|
||||||
GeneratePage(indicatorScreensaverEntity.ScreensaverEntityNaviToPage);
|
GeneratePage(indicatorScreensaverEntity.ScreensaverEntityNaviToPage);
|
||||||
} else {
|
} else {
|
||||||
const value = ['event','buttonPress2','screensaver','bExit',2];
|
const value = ['event','buttonPress2','screensaver','bExit','2'];
|
||||||
HandleButtonEvent(value);
|
HandleButtonEvent(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6555,6 +6614,7 @@ function HandleButtonEvent(words: any): void {
|
|||||||
case 'rgbSingle':
|
case 'rgbSingle':
|
||||||
case 'hue':
|
case 'hue':
|
||||||
toggleState(id + '.ON_ACTUAL');
|
toggleState(id + '.ON_ACTUAL');
|
||||||
|
break;
|
||||||
case 'media':
|
case 'media':
|
||||||
if (!activePage || activePage.type != 'cardMedia') {
|
if (!activePage || activePage.type != 'cardMedia') {
|
||||||
if (activePage) throw new Error(`Found channel role media for card: ${activePage.type} not allowed`)
|
if (activePage) throw new Error(`Found channel role media for card: ${activePage.type} not allowed`)
|
||||||
@@ -6573,19 +6633,20 @@ function HandleButtonEvent(words: any): void {
|
|||||||
|
|
||||||
switch (deviceAdapterRP) {
|
switch (deviceAdapterRP) {
|
||||||
case 'spotify-premium':
|
case 'spotify-premium':
|
||||||
let stateSpotifyRepeat = getState(id + '.REPEAT').val
|
if (Debug) log(getState(id + '.REPEAT').val);
|
||||||
if (stateSpotifyRepeat == 'none') {
|
let stateSpotifyRepeat = getState(id + '.REPEAT').val;
|
||||||
setIfExists(id + '.REPEAT', 'all');
|
if (stateSpotifyRepeat == 'off') {
|
||||||
} else if (stateSpotifyRepeat == 'all') {
|
setIfExists(id + '.REPEAT', 'context');
|
||||||
setIfExists(id + '.REPEAT', 'one');
|
} else if (stateSpotifyRepeat == 'context') {
|
||||||
} else if (stateSpotifyRepeat == 'one') {
|
setIfExists(id + '.REPEAT', 'track');
|
||||||
setIfExists(id + '.REPEAT', 'none');
|
} else if (stateSpotifyRepeat == 'track') {
|
||||||
|
setIfExists(id + '.REPEAT', 'off');
|
||||||
}
|
}
|
||||||
GeneratePage(activePage!);
|
GeneratePage(activePage!);
|
||||||
break;
|
break;
|
||||||
case 'bosesoundtouch':
|
case 'bosesoundtouch':
|
||||||
if (Debug) log(adapterInstanceRepeat);
|
if (Debug) log(adapterInstanceRepeat);
|
||||||
let stateBoseRepeat = getState(id + '.REPEAT').val
|
let stateBoseRepeat = getState(id + '.REPEAT').val;
|
||||||
if (stateBoseRepeat == 'REPEAT_OFF') {
|
if (stateBoseRepeat == 'REPEAT_OFF') {
|
||||||
setIfExists(adapterInstanceRepeat + 'key', 'REPEAT_ALL');
|
setIfExists(adapterInstanceRepeat + 'key', 'REPEAT_ALL');
|
||||||
} else if (stateBoseRepeat == 'REPEAT_ALL') {
|
} else if (stateBoseRepeat == 'REPEAT_ALL') {
|
||||||
@@ -6596,7 +6657,7 @@ function HandleButtonEvent(words: any): void {
|
|||||||
GeneratePage(activePage!);
|
GeneratePage(activePage!);
|
||||||
break;
|
break;
|
||||||
case 'sonos':
|
case 'sonos':
|
||||||
let stateSonosRepeat = getState(id + '.REPEAT').val
|
let stateSonosRepeat = getState(id + '.REPEAT').val;
|
||||||
if (stateSonosRepeat == 0) {
|
if (stateSonosRepeat == 0) {
|
||||||
setIfExists(id + '.REPEAT', 1);
|
setIfExists(id + '.REPEAT', 1);
|
||||||
} else if (stateSonosRepeat == 1) {
|
} else if (stateSonosRepeat == 1) {
|
||||||
@@ -6811,7 +6872,7 @@ function HandleButtonEvent(words: any): void {
|
|||||||
if (isPageMediaItem(pageItemTemp)) {
|
if (isPageMediaItem(pageItemTemp)) {
|
||||||
let adaInstanceSplit = pageItemTemp.adapterPlayerInstance!.split('.');
|
let adaInstanceSplit = pageItemTemp.adapterPlayerInstance!.split('.');
|
||||||
if (adaInstanceSplit[0] == 'squeezeboxrpc') {
|
if (adaInstanceSplit[0] == 'squeezeboxrpc') {
|
||||||
let adapterPlayerInstanceStateSeceltor: string = [pageItemTemp.adapterPlayerInstance, 'Players', pageItemTemp.mediaDevice, 'state'].join('.');
|
let adapterPlayerInstanceStateSeceltor: string = pageItemTemp.adapterPlayerInstance + 'Players.' + pageItemTemp.mediaDevice + '.state';
|
||||||
if (Debug) log('HandleButtonEvent media-pause Squeezebox-> adapterPlayerInstanceStateSeceltor: ' + adapterPlayerInstanceStateSeceltor, 'info');
|
if (Debug) log('HandleButtonEvent media-pause Squeezebox-> adapterPlayerInstanceStateSeceltor: ' + adapterPlayerInstanceStateSeceltor, 'info');
|
||||||
let stateVal = getState(adapterPlayerInstanceStateSeceltor).val;
|
let stateVal = getState(adapterPlayerInstanceStateSeceltor).val;
|
||||||
if (stateVal == 0) {
|
if (stateVal == 0) {
|
||||||
@@ -6875,6 +6936,13 @@ function HandleButtonEvent(words: any): void {
|
|||||||
setIfExists(id + '.SHUFFLE', false);
|
setIfExists(id + '.SHUFFLE', false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ((tempPage.adapterPlayerInstance).startsWith("squeezeboxrpc")) {
|
||||||
|
if (getState(tempPage.adapterPlayerInstance + 'Players.' + tempPage.mediaDevice + '.PlaylistShuffle').val == 1) {
|
||||||
|
setIfExists(tempPage.adapterPlayerInstance + 'Players.' + tempPage.mediaDevice + '.PlaylistShuffle', 0);
|
||||||
|
} else {
|
||||||
|
setIfExists(tempPage.adapterPlayerInstance + 'Players.' + tempPage.mediaDevice + '.PlaylistShuffle', 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
if ((tempPage.adapterPlayerInstance).startsWith("bosesoundtouch")) {
|
if ((tempPage.adapterPlayerInstance).startsWith("bosesoundtouch")) {
|
||||||
if (Debug) log(tempPage.adapterPlayerInstance + 'nowPlaying.shuffle');
|
if (Debug) log(tempPage.adapterPlayerInstance + 'nowPlaying.shuffle');
|
||||||
if (getState(tempPage.adapterPlayerInstance + 'nowPlaying.shuffle').val == 'false') {
|
if (getState(tempPage.adapterPlayerInstance + 'nowPlaying.shuffle').val == 'false') {
|
||||||
@@ -6888,15 +6956,11 @@ function HandleButtonEvent(words: any): void {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'volumeSlider':
|
case 'volumeSlider':
|
||||||
pageCounter = -1;
|
subscribeMediaSubscriptions(id);
|
||||||
(function () { if (timeoutSlider) { clearTimeout(timeoutSlider); timeoutSlider = null; } })();
|
useMediaEvents = true;
|
||||||
timeoutSlider = setTimeout(async function () {
|
pageCounter = 1;
|
||||||
setIfExists(id + '.VOLUME', parseInt(words[4]));
|
let vVolume = scale(parseInt(words[4]), 100, 0, activePage!.items[0]!.minValue ?? 0, activePage!.items[0]!.maxValue ?? 100);
|
||||||
setTimeout(async function () {
|
setIfExists(id + '.VOLUME', Math.floor(vVolume));
|
||||||
pageCounter = 1;
|
|
||||||
GeneratePage(activePage!);
|
|
||||||
}, 3000);
|
|
||||||
}, 20);
|
|
||||||
break;
|
break;
|
||||||
case 'mode-speakerlist':
|
case 'mode-speakerlist':
|
||||||
let pageItem = findPageItem(id);
|
let pageItem = findPageItem(id);
|
||||||
@@ -6990,7 +7054,7 @@ function HandleButtonEvent(words: any): void {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'squeezeboxrpc':
|
case 'squeezeboxrpc':
|
||||||
setState([pageItemPL.adapterPlayerInstance, 'Players', pageItemPL.mediaDevice, 'cmdPlayFavorite'].join('.'), words[4]);
|
setState([adapterInstancePL, 'Players.', pageItemPL.mediaDevice, '.cmdPlayFavorite'].join(''), words[4]);
|
||||||
break;
|
break;
|
||||||
case "bosesoundtouch":
|
case "bosesoundtouch":
|
||||||
if (Debug) log('bosesoundtouch - playlist ' + pageItemPL.adapterPlayerInstance + ' - ' + words[4]);
|
if (Debug) log('bosesoundtouch - playlist ' + pageItemPL.adapterPlayerInstance + ' - ' + words[4]);
|
||||||
@@ -7020,8 +7084,9 @@ function HandleButtonEvent(words: any): void {
|
|||||||
|
|
||||||
switch (deviceAdapterTL) {
|
switch (deviceAdapterTL) {
|
||||||
case 'spotify-premium':
|
case 'spotify-premium':
|
||||||
let trackArray = (function () { try {return JSON.parse(getState(pageItemTL.adapterPlayerInstance + 'player.playlist.trackListArray').val);} catch(e) {return {};}})();
|
//let trackArray = (function () { try {return JSON.parse(getState(pageItemTL.adapterPlayerInstance + 'player.playlist.trackListArray').val);} catch(e) {return {};}})();
|
||||||
setState(adapterInstanceTL + 'player.trackId', getAttr(trackArray, words[4] + '.id'));
|
//setState(adapterInstanceTL + 'player.trackId', getAttr(trackArray, words[4] + '.id'));
|
||||||
|
setState(adapterInstanceTL + 'player.playlist.trackNo', parseInt(words[4]) + 1);
|
||||||
break;
|
break;
|
||||||
case 'sonos':
|
case 'sonos':
|
||||||
setState(adapterInstanceTL + 'root.' + pageItemTL.mediaDevice + '.current_track_number', parseInt(words[4]) + 1);
|
setState(adapterInstanceTL + 'root.' + pageItemTL.mediaDevice + '.current_track_number', parseInt(words[4]) + 1);
|
||||||
@@ -7046,7 +7111,7 @@ function HandleButtonEvent(words: any): void {
|
|||||||
break;
|
break;
|
||||||
case 'squeezeboxrpc':
|
case 'squeezeboxrpc':
|
||||||
//@ts-ignore Fehler kommt von findPageItem in vscode
|
//@ts-ignore Fehler kommt von findPageItem in vscode
|
||||||
setState([pageItemPL.adapterPlayerInstance, 'Players', pageItemPL.mediaDevice, 'PlaylistCurrentIndex'].join('.'), words[4]);
|
setState([adapterInstanceTL, 'Players.', pageItemTL.mediaDevice, '.PlaylistCurrentIndex'].join(''), words[4]);
|
||||||
break;
|
break;
|
||||||
case "bosesoundtouch":
|
case "bosesoundtouch":
|
||||||
break;
|
break;
|
||||||
@@ -7099,6 +7164,14 @@ function HandleButtonEvent(words: any): void {
|
|||||||
let deviceAdapterSK: NSPanel.PlayerType = adapterSK[0] as NSPanel.PlayerType;
|
let deviceAdapterSK: NSPanel.PlayerType = adapterSK[0] as NSPanel.PlayerType;
|
||||||
switch (deviceAdapterSK) {
|
switch (deviceAdapterSK) {
|
||||||
case 'spotify-premium':
|
case 'spotify-premium':
|
||||||
|
setState(adapterInstanceSK + 'player.progressPercentage', parseInt(words[4]) * 10);
|
||||||
|
break;
|
||||||
|
case 'squeezeboxrpc':
|
||||||
|
const vDuration: number = getState(adapterInstanceSK + 'Players.' + pageItemSeek.mediaDevice + '.Duration').val;
|
||||||
|
const vSeekPercentage : number = words[4] * 10;
|
||||||
|
const setSeekSeconds: number = vSeekPercentage * vDuration / 100;
|
||||||
|
if (Debug) log(adapterInstanceSK + 'Players.' + pageItemSeek.mediaDevice + '.cmdGoTime' + ': ' + setSeekSeconds + ' sec.');
|
||||||
|
setState(adapterInstanceSK + 'Players.' + pageItemSeek.mediaDevice + '.cmdGoTime', String(setSeekSeconds.toFixed(0)));
|
||||||
break;
|
break;
|
||||||
case 'sonos':
|
case 'sonos':
|
||||||
if (Debug) log('HandleButtonEvent mode-seek -> id: ' + id, 'info');
|
if (Debug) log('HandleButtonEvent mode-seek -> id: ' + id, 'info');
|
||||||
@@ -7158,7 +7231,7 @@ function HandleButtonEvent(words: any): void {
|
|||||||
if (!isPageMediaItem(pageItemTemp)) break;
|
if (!isPageMediaItem(pageItemTemp)) break;
|
||||||
let adapterInstance = pageItemTemp.adapterPlayerInstance.split('.');
|
let adapterInstance = pageItemTemp.adapterPlayerInstance.split('.');
|
||||||
if (adapterInstance[0] == 'squeezeboxrpc') {
|
if (adapterInstance[0] == 'squeezeboxrpc') {
|
||||||
let adapterPlayerInstancePowerSelector: string = [pageItemTemp.adapterPlayerInstance, 'Players', pageItemTemp.mediaDevice, 'Power'].join('.');
|
let adapterPlayerInstancePowerSelector: string = [pageItemTemp.adapterPlayerInstance, 'Players.', pageItemTemp.mediaDevice, '.Power'].join('');
|
||||||
let stateVal = getState(adapterPlayerInstancePowerSelector).val;
|
let stateVal = getState(adapterPlayerInstancePowerSelector).val;
|
||||||
if (stateVal === 0) {
|
if (stateVal === 0) {
|
||||||
setState(adapterPlayerInstancePowerSelector, 1);
|
setState(adapterPlayerInstancePowerSelector, 1);
|
||||||
@@ -7720,7 +7793,7 @@ function GenerateDetailPage(type: NSPanel.PopupType, optional: NSPanel.mediaOpti
|
|||||||
if (existsState(id + '.TEMPERATURE')) {
|
if (existsState(id + '.TEMPERATURE')) {
|
||||||
colorTemp = 0;
|
colorTemp = 0;
|
||||||
if (getState(id + '.TEMPERATURE').val != null) {
|
if (getState(id + '.TEMPERATURE').val != null) {
|
||||||
if (pageItem.minValueColorTemp !== undefined && pageItem.minValueColorTemp !== undefined) {
|
if (pageItem.minValueColorTemp !== undefined && pageItem.maxValueColorTemp !== undefined) {
|
||||||
colorTemp = Math.trunc(scale(getState(id + '.TEMPERATURE').val, pageItem.minValueColorTemp, pageItem.maxValueColorTemp!, 100, 0));
|
colorTemp = Math.trunc(scale(getState(id + '.TEMPERATURE').val, pageItem.minValueColorTemp, pageItem.maxValueColorTemp!, 100, 0));
|
||||||
} else {
|
} else {
|
||||||
colorTemp = getState(id + '.TEMPERATURE').val;
|
colorTemp = getState(id + '.TEMPERATURE').val;
|
||||||
@@ -8184,9 +8257,21 @@ function GenerateDetailPage(type: NSPanel.PopupType, optional: NSPanel.mediaOpti
|
|||||||
const vTempAdapter = (pageItem.adapterPlayerInstance!).split('.');
|
const vTempAdapter = (pageItem.adapterPlayerInstance!).split('.');
|
||||||
const vAdapter: NSPanel.PlayerType = vTempAdapter[0] as NSPanel.PlayerType;
|
const vAdapter: NSPanel.PlayerType = vTempAdapter[0] as NSPanel.PlayerType;
|
||||||
if (optional == 'seek') {
|
if (optional == 'seek') {
|
||||||
const actualStateTemp: number = getState(pageItem.adapterPlayerInstance + 'root.' + pageItem.mediaDevice + '.seek').val;
|
|
||||||
actualState = Math.round(actualStateTemp / 10) * 10 + '%';
|
|
||||||
if (vAdapter == 'sonos') {
|
if (vAdapter == 'sonos') {
|
||||||
|
const actualStateTemp: number = getState(pageItem.adapterPlayerInstance + 'root.' + pageItem.mediaDevice + '.seek').val;
|
||||||
|
actualState = Math.round(actualStateTemp / 10) * 10 + '%';
|
||||||
|
optionalString = '0%?10%?20%?30%?40%?50%?60%?70%?80%?90%?100%';
|
||||||
|
}
|
||||||
|
if (vAdapter == 'spotify-premium') {
|
||||||
|
const actualStateTemp: number = getState(pageItem.adapterPlayerInstance + 'player.progressPercentage').val;
|
||||||
|
actualState = Math.round(actualStateTemp / 10) * 10 + '%';
|
||||||
|
optionalString = '0%?10%?20%?30%?40%?50%?60%?70%?80%?90%?100%';
|
||||||
|
}
|
||||||
|
if (vAdapter == 'squeezeboxrpc') {
|
||||||
|
const actualStateTime: number = parseInt(getState(pageItem.adapterPlayerInstance + 'Players.' + pageItem.mediaDevice + '.Time').val);
|
||||||
|
const actualStateDuration: number = parseInt(getState(pageItem.adapterPlayerInstance + 'Players.' + pageItem.mediaDevice + '.Duration').val);
|
||||||
|
const actualStateTemp: number = actualStateTime * 100 / actualStateDuration;
|
||||||
|
actualState = Math.round(actualStateTemp / 10) * 10 + '%';
|
||||||
optionalString = '0%?10%?20%?30%?40%?50%?60%?70%?80%?90%?100%';
|
optionalString = '0%?10%?20%?30%?40%?50%?60%?70%?80%?90%?100%';
|
||||||
}
|
}
|
||||||
mode = 'seek';
|
mode = 'seek';
|
||||||
@@ -8324,7 +8409,7 @@ function GenerateDetailPage(type: NSPanel.PopupType, optional: NSPanel.mediaOpti
|
|||||||
//Limit 900 characters, then memory overflow --> Shorten as much as possible
|
//Limit 900 characters, then memory overflow --> Shorten as much as possible
|
||||||
let temp_array: any[] = [];
|
let temp_array: any[] = [];
|
||||||
//let trackArray = (function () { try {return JSON.parse(getState(pageItem.adapterPlayerInstance + 'player.playlist.trackListArray').val);} catch(e) {return {};}})();
|
//let trackArray = (function () { try {return JSON.parse(getState(pageItem.adapterPlayerInstance + 'player.playlist.trackListArray').val);} catch(e) {return {};}})();
|
||||||
for (let track_index = 0; track_index < 45; track_index++) {
|
for (let track_index = 0; track_index < 48; track_index++) {
|
||||||
let temp_cut_array = getAttr(globalTracklist, track_index + '.title');
|
let temp_cut_array = getAttr(globalTracklist, track_index + '.title');
|
||||||
/* Volumio: @local/NAS no title -> name */
|
/* Volumio: @local/NAS no title -> name */
|
||||||
if (temp_cut_array == undefined) {
|
if (temp_cut_array == undefined) {
|
||||||
@@ -8499,9 +8584,9 @@ function UnsubscribeWatcher(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function HandleScreensaver(): void {
|
function HandleScreensaver(): void {
|
||||||
setIfExists(NSPanel_Path + 'ActivePage.type', 'screensaver');
|
setIfExists(NSPanel_Path + 'ActivePage.type', 'screensaver', null, true);
|
||||||
setIfExists(NSPanel_Path + 'ActivePage.id0', 'screensaver');
|
setIfExists(NSPanel_Path + 'ActivePage.id0', 'screensaver', null, true);
|
||||||
setIfExists(NSPanel_Path + 'ActivePage.heading', 'Screensaver');
|
setIfExists(NSPanel_Path + 'ActivePage.heading', 'Screensaver', null, true);
|
||||||
if (existsObject(NSPanel_Path + 'Config.Screensaver.ScreensaverAdvanced')) {
|
if (existsObject(NSPanel_Path + 'Config.Screensaver.ScreensaverAdvanced')) {
|
||||||
if (getState(NSPanel_Path + 'Config.Screensaver.ScreensaverAdvanced').val) {
|
if (getState(NSPanel_Path + 'Config.Screensaver.ScreensaverAdvanced').val) {
|
||||||
SendToPanel({ payload: 'pageType~screensaver2' });
|
SendToPanel({ payload: 'pageType~screensaver2' });
|
||||||
@@ -8769,9 +8854,10 @@ function HandleScreensaverUpdate(): void {
|
|||||||
iconColor + '~' +
|
iconColor + '~' +
|
||||||
config.bottomScreensaverEntity[4].ScreensaverEntityText + '~' +
|
config.bottomScreensaverEntity[4].ScreensaverEntityText + '~' +
|
||||||
val
|
val
|
||||||
}
|
} // Ende zusätzlichen Status Alternativ Layout
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// USER definierte Bottom Entities
|
||||||
let checkpoint = true;
|
let checkpoint = true;
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for (i = 0; i < maxEntities - 1 && i < config.bottomScreensaverEntity.length; i++) {
|
for (i = 0; i < maxEntities - 1 && i < config.bottomScreensaverEntity.length; i++) {
|
||||||
@@ -8825,7 +8911,7 @@ function HandleScreensaverUpdate(): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const temp = config.bottomScreensaverEntity[4].ScreensaverEntityIconColor
|
const temp = config.bottomScreensaverEntity[i].ScreensaverEntityIconColor
|
||||||
if (temp && typeof temp == 'string' && existsObject(temp)) {
|
if (temp && typeof temp == 'string' && existsObject(temp)) {
|
||||||
iconColor = getState(temp).val;
|
iconColor = getState(temp).val;
|
||||||
}
|
}
|
||||||
@@ -8896,6 +8982,8 @@ function HandleScreensaverUpdate(): void {
|
|||||||
SendToPanel({ payload: 'weatherUpdate~' + payloadString });
|
SendToPanel({ payload: 'weatherUpdate~' + payloadString });
|
||||||
|
|
||||||
HandleScreensaverStatusIcons();
|
HandleScreensaverStatusIcons();
|
||||||
|
|
||||||
|
HandleScreensaverColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
@@ -9889,8 +9977,8 @@ namespace NSPanel {
|
|||||||
|
|
||||||
export type SerialType = 'button' | 'light' | 'shutter' | 'text' | 'input_sel' | 'timer' | 'number' | 'fan'
|
export type SerialType = 'button' | 'light' | 'shutter' | 'text' | 'input_sel' | 'timer' | 'number' | 'fan'
|
||||||
|
|
||||||
export type roles = 'light' |'socket'|'dimmer'| 'hue' | 'rgb' | 'rgbSingle' | 'cd' | 'blind' | 'door' | 'window' | 'volumeGroup' | 'volume'
|
export type roles = 'light' |'socket'|'dimmer'| 'hue' | 'rgb' | 'rgbSingle' | 'ct' | 'blind' | 'door' | 'window' | 'volumeGroup' | 'volume'
|
||||||
| 'info' | 'humidity' | 'temperature' | 'value.temperature' | 'value.humidity' | 'sensor.door' | 'sensor.window' | 'thermostat' | 'warning' | 'ct'
|
| 'info' | 'humidity' | 'temperature' | 'value.temperature' | 'value.humidity' | 'sensor.door' | 'sensor.window' | 'thermostat' | 'warning'
|
||||||
| 'cie' | 'gate' | 'motion' | 'buttonSensor' | 'button' | 'value.time' | 'level.timer' | 'value.alarmtime' | 'level.mode.fan' | 'lock' | 'slider'
|
| 'cie' | 'gate' | 'motion' | 'buttonSensor' | 'button' | 'value.time' | 'level.timer' | 'value.alarmtime' | 'level.mode.fan' | 'lock' | 'slider'
|
||||||
| 'switch.mode.wlan' | 'media' | 'timeTable' | 'airCondition'
|
| 'switch.mode.wlan' | 'media' | 'timeTable' | 'airCondition'
|
||||||
|
|
||||||
@@ -9950,7 +10038,7 @@ namespace NSPanel {
|
|||||||
|
|
||||||
export type PageGrid2 = {
|
export type PageGrid2 = {
|
||||||
type: 'cardGrid2',
|
type: 'cardGrid2',
|
||||||
items: [PageItem?, PageItem?, PageItem?, PageItem?, PageItem?, PageItem?, PageItem?, PageItem?],
|
items: [PageItem?, PageItem?, PageItem?, PageItem?, PageItem?, PageItem?, PageItem?, PageItem?, PageItem?],
|
||||||
} & PageBaseType
|
} & PageBaseType
|
||||||
|
|
||||||
export type PageThermo = {
|
export type PageThermo = {
|
||||||
@@ -10054,7 +10142,6 @@ namespace NSPanel {
|
|||||||
navigate?: boolean,
|
navigate?: boolean,
|
||||||
colormode?: string,
|
colormode?: string,
|
||||||
colorScale?: IconScaleElement,
|
colorScale?: IconScaleElement,
|
||||||
//adapterPlayerInstance?: adapterPlayerInstanceType,
|
|
||||||
targetPage?: string,
|
targetPage?: string,
|
||||||
modeList?: string[],
|
modeList?: string[],
|
||||||
hidePassword?: boolean,
|
hidePassword?: boolean,
|
||||||
|
|||||||
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
|
||||||
|
|||||||
Reference in New Issue
Block a user