Compare commits

...

75 Commits

Author SHA1 Message Date
Johannes
d94d937d77 Update pages.py 2024-03-30 12:18:31 +01:00
Johannes
e5c1f0588a Update icons.py 2024-03-30 12:17:41 +01:00
Johannes
dd88ebe5da Update prepare_ha.md 2024-03-30 12:15:23 +01:00
Johannes
5536335ac9 Update prepare_ha.md 2024-03-29 21:47:36 +01:00
Johannes
df4fff6911 add docs for workaround script for appdaemon in ha 2024.04 2024-03-29 15:48:30 +01:00
Johannes
3dd83fde66 Update README.md 2024-03-27 21:27:59 +01:00
dependabot[bot]
f50b1ececa Bump docker/login-action from 3.0.0 to 3.1.0 (#1193)
Bumps [docker/login-action](https://github.com/docker/login-action) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3.0.0...v3.1.0)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-27 21:22:58 +01:00
dependabot[bot]
ebee7b379e Bump home-assistant/builder from 2024.01.0 to 2024.03.5 (#1198)
Bumps [home-assistant/builder](https://github.com/home-assistant/builder) from 2024.01.0 to 2024.03.5.
- [Release notes](https://github.com/home-assistant/builder/releases)
- [Commits](https://github.com/home-assistant/builder/compare/2024.01.0...2024.03.5)

---
updated-dependencies:
- dependency-name: home-assistant/builder
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-27 21:22:50 +01:00
Odianosen Ejale
255db25f58 Card show helper (#1187)
* Turn app into AD Base app

* Added the ability to keep the messages being sent quiet

* fix little conflict

* Allow other apps to have access to current app

* Fixed card access typing

* Added show card helper

* Added navigate helper
2024-03-21 21:56:26 +01:00
Thomas
19050079d4 Update NSPanelTs.ts
fix demomodus cardPower
2024-03-18 17:03:24 +01:00
Thomas
8d97f98a29 Update NsPanelTs.ts
fix demomodus cradPower
2024-03-18 17:01:57 +01:00
Armilar
137ca5855e Update NsPanelTs.ts - Fix Screensaver BG-Color 2024-03-06 16:25:03 +01:00
Armilar
7707b48622 Update NSPanelTs.ts - Fix Screensaver BG Color 2024-03-06 16:23:24 +01:00
joBr99
193546d1ed fixes #1179 (add nextion2text) 2024-02-25 11:03:17 +00:00
joBr99
6703bca1d0 fixes #1179 2024-02-25 11:59:50 +01:00
Johannes
5739947586 Update pages.py 2024-02-25 11:53:11 +01:00
Johannes
5e1a7f2102 workaround for #1190 2024-02-25 11:49:25 +01:00
joBr99
a0e574391b implemented #1178 (add nextion2text) 2024-02-25 10:48:07 +00:00
joBr99
bd107d930a implemented #1178 2024-02-25 11:44:46 +01:00
Odianosen Ejale
66f83732bb Fixed typing (#1186)
* Turn app into AD Base app

* Added the ability to keep the messages being sent quiet

* fix little conflict

* Allow other apps to have access to current app

* Fixed card access typing
2024-02-19 21:45:31 +01:00
Odianosen Ejale
e796891d8e Current Card access (#1184)
* Turn app into AD Base app

* Added the ability to keep the messages being sent quiet

* fix little conflict

* Allow other apps to have access to current app

* Access other cards from apps
2024-02-19 18:05:00 +01:00
Odianosen Ejale
ba46bc9189 Added ability to keep logs quiet for messages being sent (#1183)
* Turn app into AD Base app

* Added the ability to keep the messages being sent quiet

* fix little conflict
2024-02-19 12:52:18 +01:00
Odianosen Ejale
64ff369a90 Turn app into AD Base app (#1182) 2024-02-19 00:17:40 +01:00
Thomas
92616429ba Merge pull request #1177 from tt-tom17/patch-tt-tom17
v4.3.3.43 - Update NsPanelTs.ts
2024-02-12 13:26:20 +01:00
Thomas
377383d672 v4.3.3.43 - DEV Update NSPanelTs.ts
minor fixes
2024-02-12 13:18:55 +01:00
Thomas
52d405a6d6 v4.3.3.43 - Update NsPanelTs.ts
- Change pageId with Alias in Communication with HMI
- Media-Player: Dynamic loading of the speaker list, playlist, tracklist, fix repeat, add seek, add elapsed/duration
- Minor Fixes; Add miValue / maxValue to Volume-Slider
- Fix: cardGrid2 => 9 Entities for Layout 'us-p' issue #1167
- Fix VolumeSlider
2024-02-12 13:17:25 +01:00
Thomas
2e1492c4fa v4.3.3.43 - DEV Update NSPanelTs.ts
Description extended
2024-02-12 13:10:26 +01:00
Johannes
16673df8cf Update config.yaml 2024-02-11 21:23:50 +01:00
Johannes
cb4c26acfd Update requirements.txt 2024-02-11 21:23:29 +01:00
Johannes
fda7ca4574 Update config.yaml 2024-02-11 21:16:13 +01:00
Yves Schumann
8e2e8d1e82 Fixed typos on Github issue templates (#1170) 2024-02-11 21:15:31 +01:00
jacekowski
4e36f47774 fix obsolete call to get_forecast (#1173) 2024-02-11 21:15:07 +01:00
Armilar
858dac73d0 v4.3.3.43 - DEV Update NSPanelTs.ts
Fix VolumeSlider
2024-02-11 18:37:20 +01:00
Thomas
3cccefb715 Merge pull request #1169 from starwarsfan/bugfix/fixDuplicatedDefinitions
Fixed duplicated definition of 'ct'
2024-02-11 08:54:18 +01:00
Thomas
44640f33d2 Merge pull request #1171 from tt-tom17/patch-tt-tom17
v4.3.3.43 - DEV Update NSPanelTs.ts
2024-02-10 23:35:19 +01:00
Thomas
2ae3b9bd8e v4.3.3.43 - DEV Update NSPanelTs.ts
- Fix: cardGrid2 => 9 Entities for Layout 'us-p' issue #1167
2024-02-10 23:27:22 +01:00
Armilar
2db991a371 v4.3.3.42 - DEV Update NSPanelTs.ts
Add minValue / maxValue to Volume-Slider
2024-02-10 22:30:27 +01:00
Armilar
2e52abd76c v4.3.342 - DEV Update NSPanelTs.ts
Add minValue/maxValue to Volume-Slider
2024-02-10 22:28:52 +01:00
Yves Schumann
03c3acd214 Fixed duplicated definition of 'ct' 2024-02-10 20:43:47 +01:00
Armilar
c26b277c56 v4.3.3.42 - DEV Update NSPanelTs.ts
Spotify Minor Fixes
2024-02-10 11:09:42 +01:00
Armilar
3f7fd40d17 v4.3.3.42 - DEV Update NSPanelTs.ts
- Minor Fixes
- Change pageId with Alias in Communication with HMI (cardMedia)
- spotiffy Media-Player: Dynamic loading of the speaker list, playlist, tracklist, fix repeat, add seek, add elapsed/duration
2024-02-09 17:03:55 +01:00
Armilar
0b01c0d236 Merge pull request #1166 from Armilar/main
Able to merge. These branches can be automatically merged.
2024-02-07 23:22:35 +01:00
Armilar
3107b73430 Merge branch 'joBr99:main' into main 2024-02-07 23:21:27 +01:00
Armilar
5d421ae525 v4.3.3.42 - DEV Update NSPanelTs.ts
Fix Volumio in cardMedia
2024-02-07 22:53:57 +01:00
Johannes
56a8495787 Update config.yaml 2024-02-07 19:38:47 +01:00
Armilar
a12bc03dd7 v4.3.3.42 - DEVUpdate NSPanelTs.ts
Elapsed Fixes in cardMedia
2024-02-07 13:28:46 +01:00
Armilar
6b1a65f8f4 v4.3.3.42 - Update NSPanelTs.ts
Minor Fixes in cardMedia
2024-02-07 11:25:58 +01:00
Thomas
9d94155480 Update NSPanelTs.ts
Fix: bottomScreensaverEntity[i].ScreensaverEntityIconColor
Zeile 8899
2024-02-07 10:38:59 +01:00
joBr99
3b46759134 . 2024-02-06 22:15:57 +01:00
Thomas
8d21c653ae Merge pull request #1164 from tt-tom17/patch-tt-tom17
update CardLChart_Influx2.ts
2024-02-06 15:06:58 +01:00
Thomas
d983c44db7 update CardLChart_Influx2.ts
- codeanpassungen
2024-02-06 15:04:13 +01:00
Thomas
467a1d92bb Merge pull request #1163 from tt-tom17/patch-tt-tom17
v4.3.3.41 Update NSPanel.ts
2024-02-06 10:35:45 +01:00
Thomas
157d3e3e66 v4.3.3.41 Update NSPanel.ts
- Fix: activeBrightness -> null
- Fix: bHome -> corrected PageId
2024-02-06 10:32:06 +01:00
Armilar
51bb320dce Merge pull request #1162 from ticaki/main
Handle null in active*Brightness
2024-02-05 19:37:18 +01:00
ticaki
12c99c6857 Handle null in active*Brightness 2024-02-05 19:29:15 +01:00
Armilar
62e905f336 v4.3.3.40 - Update NsPanelTs.ts
- Fix maxColorTempValue for RGB
- Fix SqueezeboxRPC-Media-Player and add some Functions
2024-02-05 17:21:13 +01:00
Armilar
9b5964a758 v4.3.3.40 - Update NSPanelTs.ts
- Fix maxColorTempValue for RGB
- Fix SqueezeboxRPC-Media-Player and add some Functions
2024-02-05 17:06:01 +01:00
Armilar
9c49a9c67d v4.3.3.39 - Update NSPanelTs.ts
Fix: if (pageItem.minValueColorTemp !== undefined && pageItem.maxValueColorTemp !== undefined) {
2024-02-03 10:45:45 +01:00
Armilar
0a2461f4a5 v4.3.3.39 - Update NsPanelTs.ts
fix maxValueColorTemp
2024-02-03 10:44:24 +01:00
Thomas
49577ddbb6 Merge pull request #1159 from tt-tom17/main
v4.3.3.39 Update NSPanel.ts
2024-01-30 11:02:24 +01:00
Thomas
6172b0c35f v4.3.3.39 Update NSPanel.ts
- Add: Optional setOn & setOff for HW button with mode 'set'
- Fix: ack for read-only state
2024-01-30 10:55:19 +01:00
Thomas
e7cc10692b Update and Rename CardLChart_Influx2 2024-01-30 10:23:19 +01:00
Thomas
221d2c717d Merge pull request #1157 from tt-tom17/patch-tt-tom17
v4.3.3.39  Update NSPanel.ts
2024-01-30 08:55:30 +01:00
Thomas
2b54f742c5 v4.3.3.39 Update NSPanel.ts
- Add: Optional setOn & setOff for HW button with mode 'set'
- Fix: ack for read-only state
2024-01-30 08:50:21 +01:00
Armilar
f02eddcebe Merge branch 'joBr99:main' into main 2024-01-29 12:16:00 +01:00
Thomas
c25a5cef67 Merge pull request #1156 from tt-tom17/patch-tt-tom17
v4.3.3.39 Update NSPanel.ts
2024-01-29 12:14:25 +01:00
Thomas
0f69ee951c v4.3.3.39 Update NSPanel.ts
- Add: Optional setOn & setOff for HW button with mode 'set'
- Fix: ack for read-only state
2024-01-29 11:58:37 +01:00
Thomas
fd6650db50 v4.3.3.39 Update NSPanel.ts
- Add: Optional setOn & setOff for HW button with mode 'set'
- Fix: ack for read-only state
2024-01-29 10:17:37 +01:00
Thomas
f2ad80665a v4.3.3.39 Update NSPanel.ts
- Add: Optional setOn & setOff for HW button with mode 'set'
- Fix: ack for read-only state
2024-01-29 09:40:01 +01:00
Armilar
cff9c94c27 Merge pull request #1154 from ticaki/main
fix ack for read-only state
2024-01-28 02:49:58 +01:00
ticaki
b6fdc12820 fix ack for read-only state 2024-01-27 18:02:05 +01:00
Armilar
01265faef9 Merge pull request #1153 from tt-tom17/patch-tt-tom17
Script vom Wiki nach Github schieben
2024-01-26 18:56:58 +01:00
Thomas
a2feae891e Script vom Wiki nach Github schieben 2024-01-26 18:50:47 +01:00
Armilar
0efbd9e23c Merge branch 'joBr99:main' into main 2024-01-23 21:41:06 +01:00
Armilar
cd0c015fea v4.3.3.38 - Update NsPanelTs.ts (add nextion2text) 2024-01-20 23:31:37 +00:00
34 changed files with 1377 additions and 602 deletions

View File

@@ -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)_

View File

@@ -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)_

View File

@@ -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 }} \

View File

@@ -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
│ }

View File

@@ -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
│ }

View File

@@ -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
+ }

View File

@@ -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

View File

@@ -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

View File

@@ -1794,6 +1794,10 @@ Timer tmSerial
{ {
page cardChart page cardChart
} }
if(tId.txt=="cardLChart")
{
page cardLChart
}
} }
if(tInstruction.txt=="timeout") if(tInstruction.txt=="timeout")
{ {

View File

@@ -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

View File

@@ -956,6 +956,10 @@ Timer tmSerial
{ {
page cardChart page cardChart
} }
if(tId.txt=="cardLChart")
{
page cardLChart
}
} }
if(tInstruction.txt=="timeout") if(tInstruction.txt=="timeout")
{ {

Binary file not shown.

Binary file not shown.

View File

@@ -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

View File

@@ -1,2 +1,3 @@
ha_api = None ha_api = None
mqtt_api = None mqtt_api = None
ad_api = None

View File

@@ -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': "",

View File

@@ -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

View File

@@ -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)

View File

@@ -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:

View File

@@ -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":

View File

@@ -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

View File

@@ -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
```
![image](https://github.com/joBr99/nspanel-lovelace-ui/assets/29555657/41f21db3-a6e2-4e4f-8dab-b9351ecd23e5)
Adjust the entities in your apps.yaml that are accessing the forecast to the newly created trigger template:
![image](https://github.com/joBr99/nspanel-lovelace-ui/assets/29555657/1cfd913d-88be-4cb0-9a68-0e864ee1ad4f)

View File

@@ -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);
}
});

View 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 --------------------------------------------------------------------------

View 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);
}
});
});

View 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);
});
});

View 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);
}
}

View 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),
])
);
});

View File

@@ -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

View File

@@ -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:

View File

@@ -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", "")

View File

@@ -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):

View File

@@ -1,4 +1,4 @@
paho-mqtt paho-mqtt==1.6.1
pyyaml pyyaml
websockets websockets
websocket-client websocket-client