mirror of
https://github.com/joBr99/nspanel-lovelace-ui.git
synced 2025-12-20 14:37:01 +01:00
Compare commits
306 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d94d937d77 | ||
|
|
e5c1f0588a | ||
|
|
dd88ebe5da | ||
|
|
5536335ac9 | ||
|
|
df4fff6911 | ||
|
|
3dd83fde66 | ||
|
|
f50b1ececa | ||
|
|
ebee7b379e | ||
|
|
255db25f58 | ||
|
|
19050079d4 | ||
|
|
8d97f98a29 | ||
|
|
137ca5855e | ||
|
|
7707b48622 | ||
|
|
193546d1ed | ||
|
|
6703bca1d0 | ||
|
|
5739947586 | ||
|
|
5e1a7f2102 | ||
|
|
a0e574391b | ||
|
|
bd107d930a | ||
|
|
66f83732bb | ||
|
|
e796891d8e | ||
|
|
ba46bc9189 | ||
|
|
64ff369a90 | ||
|
|
92616429ba | ||
|
|
377383d672 | ||
|
|
52d405a6d6 | ||
|
|
2e1492c4fa | ||
|
|
16673df8cf | ||
|
|
cb4c26acfd | ||
|
|
fda7ca4574 | ||
|
|
8e2e8d1e82 | ||
|
|
4e36f47774 | ||
|
|
858dac73d0 | ||
|
|
3cccefb715 | ||
|
|
44640f33d2 | ||
|
|
2ae3b9bd8e | ||
|
|
2db991a371 | ||
|
|
2e52abd76c | ||
|
|
03c3acd214 | ||
|
|
c26b277c56 | ||
|
|
3f7fd40d17 | ||
|
|
0b01c0d236 | ||
|
|
3107b73430 | ||
|
|
5d421ae525 | ||
|
|
56a8495787 | ||
|
|
a12bc03dd7 | ||
|
|
6b1a65f8f4 | ||
|
|
9d94155480 | ||
|
|
3b46759134 | ||
|
|
8d21c653ae | ||
|
|
d983c44db7 | ||
|
|
467a1d92bb | ||
|
|
157d3e3e66 | ||
|
|
51bb320dce | ||
|
|
12c99c6857 | ||
|
|
62e905f336 | ||
|
|
9b5964a758 | ||
|
|
9c49a9c67d | ||
|
|
0a2461f4a5 | ||
|
|
49577ddbb6 | ||
|
|
6172b0c35f | ||
|
|
e7cc10692b | ||
|
|
221d2c717d | ||
|
|
2b54f742c5 | ||
|
|
f02eddcebe | ||
|
|
c25a5cef67 | ||
|
|
0f69ee951c | ||
|
|
fd6650db50 | ||
|
|
f2ad80665a | ||
|
|
cff9c94c27 | ||
|
|
b6fdc12820 | ||
|
|
01265faef9 | ||
|
|
a2feae891e | ||
|
|
bd24d4bcd1 | ||
|
|
0efbd9e23c | ||
|
|
4aab72fb10 | ||
|
|
aa266da5ac | ||
|
|
49987d55ce | ||
|
|
c6939efd70 | ||
|
|
f7f853f05e | ||
|
|
1faa540a70 | ||
|
|
1746c876bd | ||
|
|
cd0c015fea | ||
|
|
760b25b7a2 | ||
|
|
eccfad5615 | ||
|
|
27034e4bae | ||
|
|
99376c8fc2 | ||
|
|
17e7ba1ef2 | ||
|
|
38526890cc | ||
|
|
ae9b33d5f0 | ||
|
|
ff96812d26 | ||
|
|
0359a4b3dc | ||
|
|
f75dd3a800 | ||
|
|
a992dc56c5 | ||
|
|
576176e1cc | ||
|
|
1d3914ce86 | ||
|
|
b2f338cad8 | ||
|
|
74a329ca29 | ||
|
|
29ae1b4034 | ||
|
|
ae5cab9830 | ||
|
|
a986e588b5 | ||
|
|
8c84c1050f | ||
|
|
c3ded4d817 | ||
|
|
db32de68e3 | ||
|
|
f76f2ca393 | ||
|
|
8449257628 | ||
|
|
2bd3d0d290 | ||
|
|
117798a3f5 | ||
|
|
01392bcbf8 | ||
|
|
5a3478d916 | ||
|
|
f3b545fd90 | ||
|
|
e7a6a05a1b | ||
|
|
f65ff57a95 | ||
|
|
9a8f53e890 | ||
|
|
e94c711f12 | ||
|
|
4cc8455fff | ||
|
|
943bb93398 | ||
|
|
0a1eb8c2e5 | ||
|
|
b7fd06413d | ||
|
|
a2b805f4e1 | ||
|
|
bc69af7b6b | ||
|
|
c36202878f | ||
|
|
60f31595d4 | ||
|
|
7194d7f613 | ||
|
|
af02a70600 | ||
|
|
77d8e0607d | ||
|
|
d6d12bc93c | ||
|
|
ead1def4bb | ||
|
|
14e944885f | ||
|
|
a075e0cba8 | ||
|
|
dd14e66f10 | ||
|
|
ce0892b986 | ||
|
|
71b84cc8d3 | ||
|
|
fd3ce243a6 | ||
|
|
aa3e90ef98 | ||
|
|
2621b22ffd | ||
|
|
6460f5f4ff | ||
|
|
e45560c27f | ||
|
|
0c6cd158dd | ||
|
|
f11de05eb3 | ||
|
|
ef47efb9aa | ||
|
|
54422eccaa | ||
|
|
02004f4b6d | ||
|
|
58278c5388 | ||
|
|
ff7d2020f7 | ||
|
|
160420fe82 | ||
|
|
56703ec458 | ||
|
|
9947664ae8 | ||
|
|
4d3f54439e | ||
|
|
6254f369f4 | ||
|
|
9b98cac4c8 | ||
|
|
71f3b75ab2 | ||
|
|
1a5cf8a2f7 | ||
|
|
33712b198d | ||
|
|
1fd5784a54 | ||
|
|
3904ca2343 | ||
|
|
8ebd0f5193 | ||
|
|
8c9bca3f25 | ||
|
|
6908744669 | ||
|
|
d0e463de98 | ||
|
|
f4c7287dfd | ||
|
|
a33df14761 | ||
|
|
3afc41269c | ||
|
|
11add2bfcc | ||
|
|
dd84fa16e5 | ||
|
|
e823c0f1ec | ||
|
|
56c104a5bc | ||
|
|
bfb2c2eaab | ||
|
|
7d57205ac2 | ||
|
|
4b81b1794d | ||
|
|
f5019b494f | ||
|
|
5102b8b955 | ||
|
|
089e553944 | ||
|
|
dfc07a6d76 | ||
|
|
b7687e006c | ||
|
|
10cf15bebd | ||
|
|
fc3d4adc72 | ||
|
|
bc330d5aaf | ||
|
|
c8a8feace2 | ||
|
|
9afdaa4cbc | ||
|
|
18c7f2eb9c | ||
|
|
de237171ef | ||
|
|
a4b90944e8 | ||
|
|
cb44fcc8c9 | ||
|
|
03bae9e9bd | ||
|
|
1ec463f6c7 | ||
|
|
5420abcfaa | ||
|
|
e2530cdf62 | ||
|
|
b14687cb30 | ||
|
|
360fb881f1 | ||
|
|
90d35a8574 | ||
|
|
73a0ba468e | ||
|
|
4e7119768b | ||
|
|
8bfa6deb76 | ||
|
|
e87febc54a | ||
|
|
43df10e823 | ||
|
|
e2acb70a1c | ||
|
|
f8774af675 | ||
|
|
9ddb6c7834 | ||
|
|
330e5fecdf | ||
|
|
6cc41bf510 | ||
|
|
956bd23a56 | ||
|
|
f1ce806ded | ||
|
|
7748c22292 | ||
|
|
131aa491b9 | ||
|
|
dbc5ff7ccd | ||
|
|
5c3f366e53 | ||
|
|
b1b679701e | ||
|
|
c489f07c0a | ||
|
|
14bc7dedec | ||
|
|
d4067c5ddb | ||
|
|
50209418d7 | ||
|
|
8f3c74165d | ||
|
|
b7b8f389eb | ||
|
|
9082ed20f3 | ||
|
|
f807406a97 | ||
|
|
93aafe259b | ||
|
|
b96fc6e6bd | ||
|
|
1996b29c60 | ||
|
|
c8eb476ca8 | ||
|
|
aeaa995a0a | ||
|
|
b35122868f | ||
|
|
1cb974494f | ||
|
|
723ecde4cd | ||
|
|
f29e5c4978 | ||
|
|
46ffff7eea | ||
|
|
774c920591 | ||
|
|
f27eb07827 | ||
|
|
da8362d81d | ||
|
|
6e38d4f38d | ||
|
|
2344c9a9ed | ||
|
|
5180f0f869 | ||
|
|
b4f2789834 | ||
|
|
78c6029200 | ||
|
|
dca112e42b | ||
|
|
5ad16dd735 | ||
|
|
723be0735e | ||
|
|
a5bfb9388f | ||
|
|
9c6f24f984 | ||
|
|
59843ffea5 | ||
|
|
4de9c4a12f | ||
|
|
3eb05e5a84 | ||
|
|
5d7a7ed1a4 | ||
|
|
7124a22c38 | ||
|
|
fa4d65a383 | ||
|
|
d26306f892 | ||
|
|
9c0bb037fb | ||
|
|
4b73e20b9b | ||
|
|
3940a0c2e9 | ||
|
|
8f57d4a642 | ||
|
|
3979fdf6a0 | ||
|
|
4cd47126eb | ||
|
|
eb0dd79c80 | ||
|
|
3a39a8ca0e | ||
|
|
b5c4a2128b | ||
|
|
41f43fe5d0 | ||
|
|
f3f93b7136 | ||
|
|
2fb1855842 | ||
|
|
9a3627427f | ||
|
|
94fbf0a5f7 | ||
|
|
caddec1190 | ||
|
|
03367ea27d | ||
|
|
8e792ae8fc | ||
|
|
0a03f736ce | ||
|
|
8d7f6ffea5 | ||
|
|
93a6a7a88a | ||
|
|
3913b17596 | ||
|
|
d08e8eb40c | ||
|
|
c2d281658e | ||
|
|
108582cbfb | ||
|
|
b17db265f4 | ||
|
|
206739dcc5 | ||
|
|
adcb618a11 | ||
|
|
dfba3b6e84 | ||
|
|
2726859135 | ||
|
|
c0e20e6f25 | ||
|
|
148c2fc5a2 | ||
|
|
526f5e8946 | ||
|
|
8cd17b9d9a | ||
|
|
70ff46ab4b | ||
|
|
770348b07b | ||
|
|
4795cc23ad | ||
|
|
bae64dcee5 | ||
|
|
953a8d7110 | ||
|
|
3b5eaac976 | ||
|
|
6e28237ec5 | ||
|
|
b8c47948c3 | ||
|
|
0e8f9ad220 | ||
|
|
79e43e2740 | ||
|
|
c32d2958a6 | ||
|
|
3b7c934972 | ||
|
|
40f29d09c1 | ||
|
|
b601f2d860 | ||
|
|
5953d7c8dd | ||
|
|
e9859c0d32 | ||
|
|
4ad997515f | ||
|
|
ba637cf11e | ||
|
|
a4abcd1734 | ||
|
|
86bbd36813 | ||
|
|
c9dffc431c | ||
|
|
04ffd6257e | ||
|
|
4102f56cee | ||
|
|
6a62a6206a | ||
|
|
0bddceccfa | ||
|
|
09156fbc89 | ||
|
|
76d0075c7d |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -58,5 +58,5 @@ _If applicable, add screenshots/pictures to help explain your problem._
|
||||
_Add any other context about the problem here._
|
||||
_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)_
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature-request.md
vendored
2
.github/ISSUE_TEMPLATE/feature-request.md
vendored
@@ -24,5 +24,5 @@ _A clear and concise description of what the feature should do._
|
||||
### ADDITIONAL CONTEXT
|
||||
_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)_
|
||||
|
||||
4
.github/workflows/builder.yaml
vendored
4
.github/workflows/builder.yaml
vendored
@@ -92,7 +92,7 @@ jobs:
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: env.BUILD_ARGS != '--test'
|
||||
uses: docker/login-action@v3.0.0
|
||||
uses: docker/login-action@v3.1.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
|
||||
- name: Build ${{ matrix.addon }} add-on
|
||||
if: steps.check.outputs.build_arch == 'true'
|
||||
uses: home-assistant/builder@2023.09.0
|
||||
uses: home-assistant/builder@2024.03.5
|
||||
with:
|
||||
args: |
|
||||
${{ env.BUILD_ARGS }} \
|
||||
|
||||
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -72,4 +72,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
paths:
|
||||
- docs/*
|
||||
- .github/workflows/docs.yml
|
||||
@@ -18,18 +18,11 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
- run: pip install mkdocs-material mkdocs-video markdown-include mike
|
||||
- run: cp HMI/README.md docs/hmi-serial-protocol.md
|
||||
#- run: mkdocs gh-deploy --force
|
||||
- run: git config --global user.name Docs deploy
|
||||
- run: git config --global user.email docs@dummy.bot.com
|
||||
- run: mike deploy --push --update-aliases dev
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
29
.github/workflows/docs-release.yml
vendored
Normal file
29
.github/workflows/docs-release.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: docs-ci
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- docs/*
|
||||
- .github/workflows/docs-release.yml
|
||||
- mkdocs.yml
|
||||
- HMI/README.md
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
- run: pip install mkdocs-material mkdocs-video markdown-include mike
|
||||
- run: cp HMI/README.md docs/hmi-serial-protocol.md
|
||||
- run: git config --global user.name Docs deploy
|
||||
- run: git config --global user.email docs@dummy.bot.com
|
||||
- run: mike set-default stable
|
||||
- run: mike deploy --push --update-aliases stable
|
||||
@@ -1,17 +1,5 @@
|
||||
--- HMI/n2t-out
|
||||
+++ HMI/US/landscape/n2t-out
|
||||
├── file list
|
||||
│ @@ -1,10 +1,9 @@
|
||||
│ Program.s.txt
|
||||
│ cardAlarm.txt
|
||||
│ -cardBurnRec.txt
|
||||
│ cardChart.txt
|
||||
│ cardEntities.txt
|
||||
│ cardGrid.txt
|
||||
│ cardGrid2.txt
|
||||
│ cardLChart.txt
|
||||
│ cardMedia.txt
|
||||
│ cardPower.txt
|
||||
│ --- HMI/n2t-out/Program.s.txt
|
||||
├── +++ HMI/US/landscape/n2t-out/Program.s.txt
|
||||
│ @@ -13,10 +13,10 @@
|
||||
@@ -114,6 +102,49 @@
|
||||
│ crcputs sys0,2
|
||||
│ crcputs tSend.txt,0
|
||||
│ //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/US/landscape/n2t-out/popupNotify.txt
|
||||
│ @@ -439,18 +439,14 @@
|
||||
│ {
|
||||
│ page cardPower
|
||||
│ }
|
||||
│ if(tId.txt=="cardChart")
|
||||
│ {
|
||||
│ page cardChart
|
||||
│ }
|
||||
│ - if(tId.txt=="cardLChart")
|
||||
│ - {
|
||||
│ - page cardLChart
|
||||
│ - }
|
||||
│ }
|
||||
│ // end of user code
|
||||
│ udelete payloadLength-1
|
||||
│ bufferPos=0
|
||||
│ }
|
||||
│ }
|
||||
│ }
|
||||
│ --- HMI/n2t-out/screensaver.txt
|
||||
├── +++ HMI/US/landscape/n2t-out/screensaver.txt
|
||||
│ @@ -19,15 +19,14 @@
|
||||
@@ -221,7 +252,7 @@
|
||||
│ vis p0,0
|
||||
│ vis tNotifyHead,0
|
||||
│ vis tNotifyText,0
|
||||
│ @@ -41,17 +40,14 @@
|
||||
│ @@ -41,52 +40,19 @@
|
||||
│ }
|
||||
│ tDate.txt=pageIcons.vaDate.txt
|
||||
│ dim=dimValue
|
||||
@@ -232,14 +263,80 @@
|
||||
│ - Postinitialize Event
|
||||
│ - click m0,1
|
||||
│ -
|
||||
│ -Variable (string) entn1
|
||||
│ - Attributes
|
||||
│ - Scope : local
|
||||
│ - Text :
|
||||
│ - Max. Text Size: 14
|
||||
│ -
|
||||
│ -Variable (string) entn2
|
||||
│ - Attributes
|
||||
│ - Scope : local
|
||||
│ - Text :
|
||||
│ - Max. Text Size: 14
|
||||
│ -
|
||||
│ -Variable (string) entn3
|
||||
│ - Attributes
|
||||
│ - Scope : local
|
||||
│ - Text :
|
||||
│ - Max. Text Size: 14
|
||||
│ -
|
||||
│ -Variable (string) entn4
|
||||
│ - Attributes
|
||||
│ - Scope : local
|
||||
│ - Text :
|
||||
│ - Max. Text Size: 14
|
||||
│ -
|
||||
│ -Variable (string) entn5
|
||||
│ - Attributes
|
||||
│ - Scope : local
|
||||
│ - Text :
|
||||
│ - Max. Text Size: 14
|
||||
│ -
|
||||
│ Variable (string) strCommand
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Text :
|
||||
│ Max. Text Size: 1979
|
||||
│ - Max. Text Size: 1935
|
||||
│ + Max. Text Size: 1979
|
||||
│
|
||||
│ Variable (string) strTmp
|
||||
│ @@ -376,34 +372,14 @@
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Text :
|
||||
│ Max. Text Size: 2
|
||||
│
|
||||
│ @@ -96,27 +62,27 @@
|
||||
│ Text :
|
||||
│ Max. Text Size: 25
|
||||
│
|
||||
│ Variable (string) tInstruction
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Text :
|
||||
│ - Max. Text Size: 15
|
||||
│ + Max. Text Size: 50
|
||||
│
|
||||
│ Variable (string) tSend
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Text :
|
||||
│ Max. Text Size: 50
|
||||
│
|
||||
│ Variable (string) tTmp
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Text :
|
||||
│ - Max. Text Size: 30
|
||||
│ + Max. Text Size: 50
|
||||
│
|
||||
│ Variable (int32) vaTap
|
||||
│ Attributes
|
||||
│ Scope: local
|
||||
│ Value: 0
|
||||
│
|
||||
│ Variable (int32) xc1
|
||||
│ @@ -370,145 +336,50 @@
|
||||
│ Scope : local
|
||||
│ Dragging : 0
|
||||
│ Send Component ID : disabled
|
||||
@@ -247,6 +344,117 @@
|
||||
│ Text :
|
||||
│ Max. Text Size : 4
|
||||
│
|
||||
│ - Events
|
||||
│ - Touch Press Event
|
||||
│ - tSend.txt="event,buttonPress2,"+entn1.txt+",button"
|
||||
│ - //send calc crc
|
||||
│ - btlen tSend.txt,sys0
|
||||
│ - crcrest 1,0xffff // reset CRC
|
||||
│ - crcputh 55 bb
|
||||
│ - crcputs sys0,2
|
||||
│ - crcputs tSend.txt,0
|
||||
│ - //send cmd
|
||||
│ - printh 55 bb
|
||||
│ - prints sys0,2
|
||||
│ - prints tSend.txt,0
|
||||
│ - prints crcval,2
|
||||
│ -
|
||||
│ Text f2Icon
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Dragging : 0
|
||||
│ Send Component ID : disabled
|
||||
│ Associated Keyboard: none
|
||||
│ Text :
|
||||
│ Max. Text Size : 4
|
||||
│
|
||||
│ - Events
|
||||
│ - Touch Press Event
|
||||
│ - tSend.txt="event,buttonPress2,"+entn2.txt+",button"
|
||||
│ - //send calc crc
|
||||
│ - btlen tSend.txt,sys0
|
||||
│ - crcrest 1,0xffff // reset CRC
|
||||
│ - crcputh 55 bb
|
||||
│ - crcputs sys0,2
|
||||
│ - crcputs tSend.txt,0
|
||||
│ - //send cmd
|
||||
│ - printh 55 bb
|
||||
│ - prints sys0,2
|
||||
│ - prints tSend.txt,0
|
||||
│ - prints crcval,2
|
||||
│ -
|
||||
│ Text f3Icon
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Dragging : 0
|
||||
│ Send Component ID : disabled
|
||||
│ Associated Keyboard: none
|
||||
│ Text :
|
||||
│ Max. Text Size : 4
|
||||
│
|
||||
│ - Events
|
||||
│ - Touch Press Event
|
||||
│ - tSend.txt="event,buttonPress2,"+entn3.txt+",button"
|
||||
│ - //send calc crc
|
||||
│ - btlen tSend.txt,sys0
|
||||
│ - crcrest 1,0xffff // reset CRC
|
||||
│ - crcputh 55 bb
|
||||
│ - crcputs sys0,2
|
||||
│ - crcputs tSend.txt,0
|
||||
│ - //send cmd
|
||||
│ - printh 55 bb
|
||||
│ - prints sys0,2
|
||||
│ - prints tSend.txt,0
|
||||
│ - prints crcval,2
|
||||
│ -
|
||||
│ Text f4Icon
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Dragging : 0
|
||||
│ Send Component ID : disabled
|
||||
│ Associated Keyboard: none
|
||||
│ Text :
|
||||
│ Max. Text Size : 4
|
||||
│
|
||||
│ - Events
|
||||
│ - Touch Press Event
|
||||
│ - tSend.txt="event,buttonPress2,"+entn4.txt+",button"
|
||||
│ - //send calc crc
|
||||
│ - btlen tSend.txt,sys0
|
||||
│ - crcrest 1,0xffff // reset CRC
|
||||
│ - crcputh 55 bb
|
||||
│ - crcputs sys0,2
|
||||
│ - crcputs tSend.txt,0
|
||||
│ - //send cmd
|
||||
│ - printh 55 bb
|
||||
│ - prints sys0,2
|
||||
│ - prints tSend.txt,0
|
||||
│ - prints crcval,2
|
||||
│ -
|
||||
│ Text f5Icon
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Dragging : 0
|
||||
│ Send Component ID : disabled
|
||||
│ Associated Keyboard: none
|
||||
│ Text :
|
||||
│ Max. Text Size : 4
|
||||
│
|
||||
│ - Events
|
||||
│ - Touch Press Event
|
||||
│ - tSend.txt="event,buttonPress2,"+entn5.txt+",button"
|
||||
│ - //send calc crc
|
||||
│ - btlen tSend.txt,sys0
|
||||
│ - crcrest 1,0xffff // reset CRC
|
||||
│ - crcputh 55 bb
|
||||
│ - crcputs sys0,2
|
||||
│ - crcputs tSend.txt,0
|
||||
│ - //send cmd
|
||||
│ - printh 55 bb
|
||||
│ - prints sys0,2
|
||||
│ - prints tSend.txt,0
|
||||
│ - prints crcval,2
|
||||
│ -
|
||||
│ -Text m0
|
||||
│ - Attributes
|
||||
│ - Scope : local
|
||||
@@ -274,7 +482,7 @@
|
||||
│ Send Component ID : disabled
|
||||
│ Associated Keyboard: none
|
||||
│ Text : PM
|
||||
│ @@ -585,15 +561,14 @@
|
||||
│ @@ -690,15 +561,14 @@
|
||||
│ if(tTmp.txt!="")
|
||||
│ {
|
||||
│ covx tTmp.txt,defaultFontColor,0,0
|
||||
@@ -290,3 +498,48 @@
|
||||
│ if(tAMPM.txt=="")
|
||||
│ {
|
||||
│ vis tAMPM,0
|
||||
│ @@ -819,44 +689,34 @@
|
||||
│ //e6Val
|
||||
│ spstr strCommand.txt,e6Val.txt,"~",60
|
||||
│ //f1Icon
|
||||
│ spstr strCommand.txt,f1Icon.txt,"~",63
|
||||
│ //f1Icon Color
|
||||
│ spstr strCommand.txt,tTmp.txt,"~",64
|
||||
│ covx tTmp.txt,f1Icon.pco,0,0
|
||||
│ - //f1Icon intNameEntity
|
||||
│ - spstr strCommand.txt,entn1.txt,"~",62
|
||||
│ //f2Icon
|
||||
│ spstr strCommand.txt,f2Icon.txt,"~",69
|
||||
│ //f2Icon Color
|
||||
│ spstr strCommand.txt,tTmp.txt,"~",70
|
||||
│ covx tTmp.txt,f2Icon.pco,0,0
|
||||
│ - //f2Icon intNameEntity
|
||||
│ - spstr strCommand.txt,entn2.txt,"~",68
|
||||
│ //f3Icon
|
||||
│ spstr strCommand.txt,f3Icon.txt,"~",75
|
||||
│ //f3Icon Color
|
||||
│ spstr strCommand.txt,tTmp.txt,"~",76
|
||||
│ covx tTmp.txt,f3Icon.pco,0,0
|
||||
│ - //f3Icon intNameEntity
|
||||
│ - spstr strCommand.txt,entn3.txt,"~",74
|
||||
│ //f4Icon
|
||||
│ spstr strCommand.txt,f4Icon.txt,"~",81
|
||||
│ //f4Icon Color
|
||||
│ spstr strCommand.txt,tTmp.txt,"~",82
|
||||
│ covx tTmp.txt,f4Icon.pco,0,0
|
||||
│ - //f4Icon intNameEntity
|
||||
│ - spstr strCommand.txt,entn4.txt,"~",80
|
||||
│ //f5Icon
|
||||
│ spstr strCommand.txt,f5Icon.txt,"~",87
|
||||
│ //f5Icon Color
|
||||
│ spstr strCommand.txt,tTmp.txt,"~",88
|
||||
│ covx tTmp.txt,f5Icon.pco,0,0
|
||||
│ - //f5Icon intNameEntity
|
||||
│ - spstr strCommand.txt,entn5.txt,"~",86
|
||||
│ }
|
||||
│ if(tInstruction.txt=="notify")
|
||||
│ {
|
||||
│ spstr strCommand.txt,tNotifyHead.txt,"~",1
|
||||
│ spstr strCommand.txt,tNotifyText.txt,"~",2
|
||||
│ if(tNotifyHead.txt!=""||tNotifyText.txt!="")
|
||||
│ {
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
--- HMI/n2t-out
|
||||
+++ HMI/US/portrait/n2t-out
|
||||
├── file list
|
||||
│ @@ -1,10 +1,9 @@
|
||||
│ Program.s.txt
|
||||
│ cardAlarm.txt
|
||||
│ -cardBurnRec.txt
|
||||
│ cardChart.txt
|
||||
│ cardEntities.txt
|
||||
│ cardGrid.txt
|
||||
│ cardGrid2.txt
|
||||
│ cardLChart.txt
|
||||
│ cardMedia.txt
|
||||
│ cardPower.txt
|
||||
│ --- HMI/n2t-out/Program.s.txt
|
||||
├── +++ HMI/US/portrait/n2t-out/Program.s.txt
|
||||
│ @@ -12,11 +12,11 @@
|
||||
@@ -1997,6 +1985,26 @@
|
||||
│ Variable (string) entn
|
||||
│ Attributes
|
||||
│ 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/US/portrait/n2t-out/popupNotify.txt
|
||||
│ @@ -348,15 +348,15 @@
|
||||
@@ -2016,6 +2024,25 @@
|
||||
│ }
|
||||
│ if(tInstruction.txt=="exitPopup")
|
||||
│ {
|
||||
│ @@ -439,18 +439,14 @@
|
||||
│ {
|
||||
│ page cardPower
|
||||
│ }
|
||||
│ if(tId.txt=="cardChart")
|
||||
│ {
|
||||
│ page cardChart
|
||||
│ }
|
||||
│ - if(tId.txt=="cardLChart")
|
||||
│ - {
|
||||
│ - page cardLChart
|
||||
│ - }
|
||||
│ }
|
||||
│ // end of user code
|
||||
│ udelete payloadLength-1
|
||||
│ bufferPos=0
|
||||
│ }
|
||||
│ }
|
||||
│ }
|
||||
│ --- HMI/n2t-out/screensaver.txt
|
||||
├── +++ HMI/US/portrait/n2t-out/screensaver.txt
|
||||
│ @@ -7,27 +7,14 @@
|
||||
@@ -2168,7 +2195,7 @@
|
||||
│ vis p0,0
|
||||
│ vis tNotifyHead,0
|
||||
│ vis tNotifyText,0
|
||||
│ @@ -41,17 +28,14 @@
|
||||
│ @@ -41,52 +28,19 @@
|
||||
│ }
|
||||
│ tDate.txt=pageIcons.vaDate.txt
|
||||
│ dim=dimValue
|
||||
@@ -2179,14 +2206,80 @@
|
||||
│ - Postinitialize Event
|
||||
│ - click m0,1
|
||||
│ -
|
||||
│ -Variable (string) entn1
|
||||
│ - Attributes
|
||||
│ - Scope : local
|
||||
│ - Text :
|
||||
│ - Max. Text Size: 14
|
||||
│ -
|
||||
│ -Variable (string) entn2
|
||||
│ - Attributes
|
||||
│ - Scope : local
|
||||
│ - Text :
|
||||
│ - Max. Text Size: 14
|
||||
│ -
|
||||
│ -Variable (string) entn3
|
||||
│ - Attributes
|
||||
│ - Scope : local
|
||||
│ - Text :
|
||||
│ - Max. Text Size: 14
|
||||
│ -
|
||||
│ -Variable (string) entn4
|
||||
│ - Attributes
|
||||
│ - Scope : local
|
||||
│ - Text :
|
||||
│ - Max. Text Size: 14
|
||||
│ -
|
||||
│ -Variable (string) entn5
|
||||
│ - Attributes
|
||||
│ - Scope : local
|
||||
│ - Text :
|
||||
│ - Max. Text Size: 14
|
||||
│ -
|
||||
│ Variable (string) strCommand
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Text :
|
||||
│ Max. Text Size: 1979
|
||||
│ - Max. Text Size: 1935
|
||||
│ + Max. Text Size: 1979
|
||||
│
|
||||
│ Variable (string) strTmp
|
||||
│ @@ -376,34 +360,14 @@
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Text :
|
||||
│ Max. Text Size: 2
|
||||
│
|
||||
│ @@ -96,27 +50,27 @@
|
||||
│ Text :
|
||||
│ Max. Text Size: 25
|
||||
│
|
||||
│ Variable (string) tInstruction
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Text :
|
||||
│ - Max. Text Size: 15
|
||||
│ + Max. Text Size: 50
|
||||
│
|
||||
│ Variable (string) tSend
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Text :
|
||||
│ Max. Text Size: 50
|
||||
│
|
||||
│ Variable (string) tTmp
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Text :
|
||||
│ - Max. Text Size: 30
|
||||
│ + Max. Text Size: 50
|
||||
│
|
||||
│ Variable (int32) vaTap
|
||||
│ Attributes
|
||||
│ Scope: local
|
||||
│ Value: 0
|
||||
│
|
||||
│ Variable (int32) xc1
|
||||
│ @@ -370,145 +324,50 @@
|
||||
│ Scope : local
|
||||
│ Dragging : 0
|
||||
│ Send Component ID : disabled
|
||||
@@ -2194,6 +2287,117 @@
|
||||
│ Text :
|
||||
│ Max. Text Size : 4
|
||||
│
|
||||
│ - Events
|
||||
│ - Touch Press Event
|
||||
│ - tSend.txt="event,buttonPress2,"+entn1.txt+",button"
|
||||
│ - //send calc crc
|
||||
│ - btlen tSend.txt,sys0
|
||||
│ - crcrest 1,0xffff // reset CRC
|
||||
│ - crcputh 55 bb
|
||||
│ - crcputs sys0,2
|
||||
│ - crcputs tSend.txt,0
|
||||
│ - //send cmd
|
||||
│ - printh 55 bb
|
||||
│ - prints sys0,2
|
||||
│ - prints tSend.txt,0
|
||||
│ - prints crcval,2
|
||||
│ -
|
||||
│ Text f2Icon
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Dragging : 0
|
||||
│ Send Component ID : disabled
|
||||
│ Associated Keyboard: none
|
||||
│ Text :
|
||||
│ Max. Text Size : 4
|
||||
│
|
||||
│ - Events
|
||||
│ - Touch Press Event
|
||||
│ - tSend.txt="event,buttonPress2,"+entn2.txt+",button"
|
||||
│ - //send calc crc
|
||||
│ - btlen tSend.txt,sys0
|
||||
│ - crcrest 1,0xffff // reset CRC
|
||||
│ - crcputh 55 bb
|
||||
│ - crcputs sys0,2
|
||||
│ - crcputs tSend.txt,0
|
||||
│ - //send cmd
|
||||
│ - printh 55 bb
|
||||
│ - prints sys0,2
|
||||
│ - prints tSend.txt,0
|
||||
│ - prints crcval,2
|
||||
│ -
|
||||
│ Text f3Icon
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Dragging : 0
|
||||
│ Send Component ID : disabled
|
||||
│ Associated Keyboard: none
|
||||
│ Text :
|
||||
│ Max. Text Size : 4
|
||||
│
|
||||
│ - Events
|
||||
│ - Touch Press Event
|
||||
│ - tSend.txt="event,buttonPress2,"+entn3.txt+",button"
|
||||
│ - //send calc crc
|
||||
│ - btlen tSend.txt,sys0
|
||||
│ - crcrest 1,0xffff // reset CRC
|
||||
│ - crcputh 55 bb
|
||||
│ - crcputs sys0,2
|
||||
│ - crcputs tSend.txt,0
|
||||
│ - //send cmd
|
||||
│ - printh 55 bb
|
||||
│ - prints sys0,2
|
||||
│ - prints tSend.txt,0
|
||||
│ - prints crcval,2
|
||||
│ -
|
||||
│ Text f4Icon
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Dragging : 0
|
||||
│ Send Component ID : disabled
|
||||
│ Associated Keyboard: none
|
||||
│ Text :
|
||||
│ Max. Text Size : 4
|
||||
│
|
||||
│ - Events
|
||||
│ - Touch Press Event
|
||||
│ - tSend.txt="event,buttonPress2,"+entn4.txt+",button"
|
||||
│ - //send calc crc
|
||||
│ - btlen tSend.txt,sys0
|
||||
│ - crcrest 1,0xffff // reset CRC
|
||||
│ - crcputh 55 bb
|
||||
│ - crcputs sys0,2
|
||||
│ - crcputs tSend.txt,0
|
||||
│ - //send cmd
|
||||
│ - printh 55 bb
|
||||
│ - prints sys0,2
|
||||
│ - prints tSend.txt,0
|
||||
│ - prints crcval,2
|
||||
│ -
|
||||
│ Text f5Icon
|
||||
│ Attributes
|
||||
│ Scope : local
|
||||
│ Dragging : 0
|
||||
│ Send Component ID : disabled
|
||||
│ Associated Keyboard: none
|
||||
│ Text :
|
||||
│ Max. Text Size : 4
|
||||
│
|
||||
│ - Events
|
||||
│ - Touch Press Event
|
||||
│ - tSend.txt="event,buttonPress2,"+entn5.txt+",button"
|
||||
│ - //send calc crc
|
||||
│ - btlen tSend.txt,sys0
|
||||
│ - crcrest 1,0xffff // reset CRC
|
||||
│ - crcputh 55 bb
|
||||
│ - crcputs sys0,2
|
||||
│ - crcputs tSend.txt,0
|
||||
│ - //send cmd
|
||||
│ - printh 55 bb
|
||||
│ - prints sys0,2
|
||||
│ - prints tSend.txt,0
|
||||
│ - prints crcval,2
|
||||
│ -
|
||||
│ -Text m0
|
||||
│ - Attributes
|
||||
│ - Scope : local
|
||||
@@ -2221,7 +2425,7 @@
|
||||
│ Send Component ID : disabled
|
||||
│ Associated Keyboard: none
|
||||
│ Text : PM
|
||||
│ @@ -585,15 +549,14 @@
|
||||
│ @@ -690,15 +549,14 @@
|
||||
│ if(tTmp.txt!="")
|
||||
│ {
|
||||
│ covx tTmp.txt,defaultFontColor,0,0
|
||||
@@ -2237,3 +2441,48 @@
|
||||
│ if(tAMPM.txt=="")
|
||||
│ {
|
||||
│ vis tAMPM,0
|
||||
│ @@ -819,44 +677,34 @@
|
||||
│ //e6Val
|
||||
│ spstr strCommand.txt,e6Val.txt,"~",60
|
||||
│ //f1Icon
|
||||
│ spstr strCommand.txt,f1Icon.txt,"~",63
|
||||
│ //f1Icon Color
|
||||
│ spstr strCommand.txt,tTmp.txt,"~",64
|
||||
│ covx tTmp.txt,f1Icon.pco,0,0
|
||||
│ - //f1Icon intNameEntity
|
||||
│ - spstr strCommand.txt,entn1.txt,"~",62
|
||||
│ //f2Icon
|
||||
│ spstr strCommand.txt,f2Icon.txt,"~",69
|
||||
│ //f2Icon Color
|
||||
│ spstr strCommand.txt,tTmp.txt,"~",70
|
||||
│ covx tTmp.txt,f2Icon.pco,0,0
|
||||
│ - //f2Icon intNameEntity
|
||||
│ - spstr strCommand.txt,entn2.txt,"~",68
|
||||
│ //f3Icon
|
||||
│ spstr strCommand.txt,f3Icon.txt,"~",75
|
||||
│ //f3Icon Color
|
||||
│ spstr strCommand.txt,tTmp.txt,"~",76
|
||||
│ covx tTmp.txt,f3Icon.pco,0,0
|
||||
│ - //f3Icon intNameEntity
|
||||
│ - spstr strCommand.txt,entn3.txt,"~",74
|
||||
│ //f4Icon
|
||||
│ spstr strCommand.txt,f4Icon.txt,"~",81
|
||||
│ //f4Icon Color
|
||||
│ spstr strCommand.txt,tTmp.txt,"~",82
|
||||
│ covx tTmp.txt,f4Icon.pco,0,0
|
||||
│ - //f4Icon intNameEntity
|
||||
│ - spstr strCommand.txt,entn4.txt,"~",80
|
||||
│ //f5Icon
|
||||
│ spstr strCommand.txt,f5Icon.txt,"~",87
|
||||
│ //f5Icon Color
|
||||
│ spstr strCommand.txt,tTmp.txt,"~",88
|
||||
│ covx tTmp.txt,f5Icon.pco,0,0
|
||||
│ - //f5Icon intNameEntity
|
||||
│ - spstr strCommand.txt,entn5.txt,"~",86
|
||||
│ }
|
||||
│ if(tInstruction.txt=="notify")
|
||||
│ {
|
||||
│ spstr strCommand.txt,tNotifyHead.txt,"~",1
|
||||
│ spstr strCommand.txt,tNotifyText.txt,"~",2
|
||||
│ if(tNotifyHead.txt!=""||tNotifyText.txt!="")
|
||||
│ {
|
||||
|
||||
@@ -1,16 +1,4 @@
|
||||
+++ /dev/fd/62 2023-11-27 23:28:52.512823638 +0000
|
||||
+le list
|
||||
+ +1,9 @@
|
||||
+.s.txt
|
||||
+rm.txt
|
||||
+nRec.txt
|
||||
+rt.txt
|
||||
+ities.txt
|
||||
+d.txt
|
||||
+d2.txt
|
||||
+art.txt
|
||||
+ia.txt
|
||||
+er.txt
|
||||
+++ /dev/fd/62 2024-02-25 11:03:09.634837907 +0000
|
||||
+I/n2t-out/Program.s.txt
|
||||
++ HMI/US/portrait/n2t-out/Program.s.txt
|
||||
+1 +12,11 @@
|
||||
@@ -1539,6 +1527,26 @@
|
||||
+e (string) entn
|
||||
+ributes
|
||||
+ 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
|
||||
++ HMI/US/portrait/n2t-out/popupNotify.txt
|
||||
+15 +348,15 @@
|
||||
@@ -1558,6 +1566,25 @@
|
||||
+ }
|
||||
+ if(tInstruction.txt=="exitPopup")
|
||||
+ {
|
||||
+18 +439,14 @@
|
||||
+ {
|
||||
+ page cardPower
|
||||
+ }
|
||||
+ if(tId.txt=="cardChart")
|
||||
+ {
|
||||
+ page cardChart
|
||||
+ }
|
||||
+ if(tId.txt=="cardLChart")
|
||||
+ {
|
||||
+ page cardLChart
|
||||
+ }
|
||||
+ }
|
||||
+ // end of user code
|
||||
+ udelete payloadLength-1
|
||||
+ bufferPos=0
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+I/n2t-out/screensaver.txt
|
||||
++ HMI/US/portrait/n2t-out/screensaver.txt
|
||||
+ +7,14 @@
|
||||
@@ -1710,7 +1737,7 @@
|
||||
+ vis p0,0
|
||||
+ vis tNotifyHead,0
|
||||
+ vis tNotifyText,0
|
||||
+7 +28,14 @@
|
||||
+2 +28,19 @@
|
||||
+ }
|
||||
+ tDate.txt=pageIcons.vaDate.txt
|
||||
+ dim=dimValue
|
||||
@@ -1721,14 +1748,80 @@
|
||||
+ Postinitialize Event
|
||||
+ click m0,1
|
||||
+
|
||||
+e (string) entn1
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Text :
|
||||
+ Max. Text Size: 14
|
||||
+
|
||||
+e (string) entn2
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Text :
|
||||
+ Max. Text Size: 14
|
||||
+
|
||||
+e (string) entn3
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Text :
|
||||
+ Max. Text Size: 14
|
||||
+
|
||||
+e (string) entn4
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Text :
|
||||
+ Max. Text Size: 14
|
||||
+
|
||||
+e (string) entn5
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Text :
|
||||
+ Max. Text Size: 14
|
||||
+
|
||||
+e (string) strCommand
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Text :
|
||||
+ Max. Text Size: 1935
|
||||
+ Max. Text Size: 1979
|
||||
+
|
||||
+e (string) strTmp
|
||||
+34 +360,14 @@
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Text :
|
||||
+ Max. Text Size: 2
|
||||
+
|
||||
+7 +50,27 @@
|
||||
+ Text :
|
||||
+ Max. Text Size: 25
|
||||
+
|
||||
+e (string) tInstruction
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Text :
|
||||
+ Max. Text Size: 15
|
||||
+ Max. Text Size: 50
|
||||
+
|
||||
+e (string) tSend
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Text :
|
||||
+ Max. Text Size: 50
|
||||
+
|
||||
+e (string) tTmp
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Text :
|
||||
+ Max. Text Size: 30
|
||||
+ Max. Text Size: 50
|
||||
+
|
||||
+e (int32) vaTap
|
||||
+ributes
|
||||
+ Scope: local
|
||||
+ Value: 0
|
||||
+
|
||||
+e (int32) xc1
|
||||
+145 +324,50 @@
|
||||
+ Scope : local
|
||||
+ Dragging : 0
|
||||
+ Send Component ID : disabled
|
||||
@@ -1736,6 +1829,117 @@
|
||||
+ Text :
|
||||
+ Max. Text Size : 4
|
||||
+
|
||||
+nts
|
||||
+ Touch Press Event
|
||||
+ tSend.txt="event,buttonPress2,"+entn1.txt+",button"
|
||||
+ //send calc crc
|
||||
+ btlen tSend.txt,sys0
|
||||
+ crcrest 1,0xffff // reset CRC
|
||||
+ crcputh 55 bb
|
||||
+ crcputs sys0,2
|
||||
+ crcputs tSend.txt,0
|
||||
+ //send cmd
|
||||
+ printh 55 bb
|
||||
+ prints sys0,2
|
||||
+ prints tSend.txt,0
|
||||
+ prints crcval,2
|
||||
+
|
||||
+Icon
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Dragging : 0
|
||||
+ Send Component ID : disabled
|
||||
+ Associated Keyboard: none
|
||||
+ Text :
|
||||
+ Max. Text Size : 4
|
||||
+
|
||||
+nts
|
||||
+ Touch Press Event
|
||||
+ tSend.txt="event,buttonPress2,"+entn2.txt+",button"
|
||||
+ //send calc crc
|
||||
+ btlen tSend.txt,sys0
|
||||
+ crcrest 1,0xffff // reset CRC
|
||||
+ crcputh 55 bb
|
||||
+ crcputs sys0,2
|
||||
+ crcputs tSend.txt,0
|
||||
+ //send cmd
|
||||
+ printh 55 bb
|
||||
+ prints sys0,2
|
||||
+ prints tSend.txt,0
|
||||
+ prints crcval,2
|
||||
+
|
||||
+Icon
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Dragging : 0
|
||||
+ Send Component ID : disabled
|
||||
+ Associated Keyboard: none
|
||||
+ Text :
|
||||
+ Max. Text Size : 4
|
||||
+
|
||||
+nts
|
||||
+ Touch Press Event
|
||||
+ tSend.txt="event,buttonPress2,"+entn3.txt+",button"
|
||||
+ //send calc crc
|
||||
+ btlen tSend.txt,sys0
|
||||
+ crcrest 1,0xffff // reset CRC
|
||||
+ crcputh 55 bb
|
||||
+ crcputs sys0,2
|
||||
+ crcputs tSend.txt,0
|
||||
+ //send cmd
|
||||
+ printh 55 bb
|
||||
+ prints sys0,2
|
||||
+ prints tSend.txt,0
|
||||
+ prints crcval,2
|
||||
+
|
||||
+Icon
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Dragging : 0
|
||||
+ Send Component ID : disabled
|
||||
+ Associated Keyboard: none
|
||||
+ Text :
|
||||
+ Max. Text Size : 4
|
||||
+
|
||||
+nts
|
||||
+ Touch Press Event
|
||||
+ tSend.txt="event,buttonPress2,"+entn4.txt+",button"
|
||||
+ //send calc crc
|
||||
+ btlen tSend.txt,sys0
|
||||
+ crcrest 1,0xffff // reset CRC
|
||||
+ crcputh 55 bb
|
||||
+ crcputs sys0,2
|
||||
+ crcputs tSend.txt,0
|
||||
+ //send cmd
|
||||
+ printh 55 bb
|
||||
+ prints sys0,2
|
||||
+ prints tSend.txt,0
|
||||
+ prints crcval,2
|
||||
+
|
||||
+Icon
|
||||
+ributes
|
||||
+ Scope : local
|
||||
+ Dragging : 0
|
||||
+ Send Component ID : disabled
|
||||
+ Associated Keyboard: none
|
||||
+ Text :
|
||||
+ Max. Text Size : 4
|
||||
+
|
||||
+nts
|
||||
+ Touch Press Event
|
||||
+ tSend.txt="event,buttonPress2,"+entn5.txt+",button"
|
||||
+ //send calc crc
|
||||
+ btlen tSend.txt,sys0
|
||||
+ crcrest 1,0xffff // reset CRC
|
||||
+ crcputh 55 bb
|
||||
+ crcputs sys0,2
|
||||
+ crcputs tSend.txt,0
|
||||
+ //send cmd
|
||||
+ printh 55 bb
|
||||
+ prints sys0,2
|
||||
+ prints tSend.txt,0
|
||||
+ prints crcval,2
|
||||
+
|
||||
+
|
||||
+ributes
|
||||
+ Scope : local
|
||||
@@ -1779,3 +1983,48 @@
|
||||
+ if(tAMPM.txt=="")
|
||||
+ {
|
||||
+ vis tAMPM,0
|
||||
+44 +677,34 @@
|
||||
+ //e6Val
|
||||
+ spstr strCommand.txt,e6Val.txt,"~",60
|
||||
+ //f1Icon
|
||||
+ spstr strCommand.txt,f1Icon.txt,"~",63
|
||||
+ //f1Icon Color
|
||||
+ spstr strCommand.txt,tTmp.txt,"~",64
|
||||
+ covx tTmp.txt,f1Icon.pco,0,0
|
||||
+ //f1Icon intNameEntity
|
||||
+ spstr strCommand.txt,entn1.txt,"~",62
|
||||
+ //f2Icon
|
||||
+ spstr strCommand.txt,f2Icon.txt,"~",69
|
||||
+ //f2Icon Color
|
||||
+ spstr strCommand.txt,tTmp.txt,"~",70
|
||||
+ covx tTmp.txt,f2Icon.pco,0,0
|
||||
+ //f2Icon intNameEntity
|
||||
+ spstr strCommand.txt,entn2.txt,"~",68
|
||||
+ //f3Icon
|
||||
+ spstr strCommand.txt,f3Icon.txt,"~",75
|
||||
+ //f3Icon Color
|
||||
+ spstr strCommand.txt,tTmp.txt,"~",76
|
||||
+ covx tTmp.txt,f3Icon.pco,0,0
|
||||
+ //f3Icon intNameEntity
|
||||
+ spstr strCommand.txt,entn3.txt,"~",74
|
||||
+ //f4Icon
|
||||
+ spstr strCommand.txt,f4Icon.txt,"~",81
|
||||
+ //f4Icon Color
|
||||
+ spstr strCommand.txt,tTmp.txt,"~",82
|
||||
+ covx tTmp.txt,f4Icon.pco,0,0
|
||||
+ //f4Icon intNameEntity
|
||||
+ spstr strCommand.txt,entn4.txt,"~",80
|
||||
+ //f5Icon
|
||||
+ spstr strCommand.txt,f5Icon.txt,"~",87
|
||||
+ //f5Icon Color
|
||||
+ spstr strCommand.txt,tTmp.txt,"~",88
|
||||
+ covx tTmp.txt,f5Icon.pco,0,0
|
||||
+ //f5Icon intNameEntity
|
||||
+ spstr strCommand.txt,entn5.txt,"~",86
|
||||
+ }
|
||||
+ if(tInstruction.txt=="notify")
|
||||
+ {
|
||||
+ spstr strCommand.txt,tNotifyHead.txt,"~",1
|
||||
+ spstr strCommand.txt,tNotifyText.txt,"~",2
|
||||
+ if(tNotifyHead.txt!=""||tNotifyText.txt!="")
|
||||
+ {
|
||||
|
||||
@@ -121,6 +121,8 @@ for i in range(1,6):
|
||||
//f{i}Icon Color
|
||||
spstr strCommand.txt,tTmp.txt,"~",{idxstart+3}
|
||||
covx tTmp.txt,f{i}Icon.pco,0,0
|
||||
//f{i}Icon intNameEntity
|
||||
spstr strCommand.txt,entn{i}.txt,"~",{idxstart+1}
|
||||
"""
|
||||
head = head + item
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
Page cardBurnRec
|
||||
Attributes
|
||||
ID : 0
|
||||
Scope : local
|
||||
Dragging : 0
|
||||
Send Component ID : disabled
|
||||
Opacity : 127
|
||||
Width : 480
|
||||
Effect : load
|
||||
Effect Priority : 0
|
||||
Effect Time : 300
|
||||
Locked : no
|
||||
Swide up page ID : disabled
|
||||
Swide down page ID : disabled
|
||||
Swide left page ID : disabled
|
||||
Swide right page ID: disabled
|
||||
Fill : solid color
|
||||
Back. Color : 65535
|
||||
|
||||
Timer tm0
|
||||
Attributes
|
||||
ID : 1
|
||||
Scope : local
|
||||
Period (ms): 1001
|
||||
Enabled : yes
|
||||
|
||||
Events
|
||||
Timer Event
|
||||
dim=100
|
||||
sys0=0
|
||||
sys1=0
|
||||
if(sys2==WHITE)
|
||||
{
|
||||
sys2=BLACK
|
||||
}else
|
||||
{
|
||||
sys2=WHITE
|
||||
}
|
||||
sya1=sys2
|
||||
while(sys0<8)
|
||||
{
|
||||
sya0=sys0%2
|
||||
if(sya1==WHITE)
|
||||
{
|
||||
sya1=BLACK
|
||||
}else
|
||||
{
|
||||
sya1=WHITE
|
||||
}
|
||||
fill 0,40*sys0,480,40,sya1
|
||||
sys0++
|
||||
}
|
||||
|
||||
TouchCap tc0
|
||||
Attributes
|
||||
ID : 2
|
||||
Scope: local
|
||||
Value: 0
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
page pageStartup
|
||||
|
||||
@@ -6,10 +6,14 @@ pageIcons
|
||||
7 Component(s)
|
||||
0 Line(s) of event code
|
||||
0 Unique line(s) of event code
|
||||
cardBurnRec
|
||||
3 Component(s)
|
||||
25 Line(s) of event code
|
||||
21 Unique line(s) of event code
|
||||
pageTest
|
||||
25 Component(s)
|
||||
68 Line(s) of event code
|
||||
66 Unique line(s) of event code
|
||||
popupNotify
|
||||
19 Component(s)
|
||||
271 Line(s) of event code
|
||||
174 Unique line(s) of event code
|
||||
popupFan
|
||||
27 Component(s)
|
||||
355 Line(s) of event code
|
||||
@@ -26,14 +30,10 @@ popupLightNew
|
||||
23 Component(s)
|
||||
412 Line(s) of event code
|
||||
209 Unique line(s) of event code
|
||||
popupNotify
|
||||
19 Component(s)
|
||||
267 Line(s) of event code
|
||||
172 Unique line(s) of event code
|
||||
pageTest
|
||||
26 Component(s)
|
||||
69 Line(s) of event code
|
||||
67 Unique line(s) of event code
|
||||
popupLight
|
||||
28 Component(s)
|
||||
417 Line(s) of event code
|
||||
228 Unique line(s) of event code
|
||||
cardGrid2
|
||||
52 Component(s)
|
||||
703 Line(s) of event code
|
||||
@@ -46,6 +46,10 @@ cardChart
|
||||
33 Component(s)
|
||||
447 Line(s) of event code
|
||||
297 Unique line(s) of event code
|
||||
cardGrid
|
||||
44 Component(s)
|
||||
593 Line(s) of event code
|
||||
333 Unique line(s) of event code
|
||||
cardQR
|
||||
34 Component(s)
|
||||
420 Line(s) of event code
|
||||
@@ -54,10 +58,6 @@ cardLChart
|
||||
33 Component(s)
|
||||
412 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
|
||||
54 Component(s)
|
||||
541 Line(s) of event code
|
||||
@@ -66,10 +66,6 @@ cardThermo
|
||||
57 Component(s)
|
||||
550 Line(s) of event code
|
||||
320 Unique line(s) of event code
|
||||
cardGrid
|
||||
44 Component(s)
|
||||
593 Line(s) of event code
|
||||
333 Unique line(s) of event code
|
||||
popupInSel
|
||||
34 Component(s)
|
||||
621 Line(s) of event code
|
||||
@@ -91,16 +87,16 @@ popupThermo
|
||||
523 Line(s) of event code
|
||||
276 Unique line(s) of event code
|
||||
screensaver2
|
||||
59 Component(s)
|
||||
373 Line(s) of event code
|
||||
256 Unique line(s) of event code
|
||||
64 Component(s)
|
||||
428 Line(s) of event code
|
||||
266 Unique line(s) of event code
|
||||
cardEntities
|
||||
67 Component(s)
|
||||
1205 Line(s) of event code
|
||||
536 Unique line(s) of event code
|
||||
|
||||
Total
|
||||
24 Page(s)
|
||||
880 Component(s)
|
||||
10740 Line(s) of event code
|
||||
2475 Unique line(s) of event code
|
||||
23 Page(s)
|
||||
881 Component(s)
|
||||
10778 Line(s) of event code
|
||||
2466 Unique line(s) of event code
|
||||
|
||||
@@ -335,41 +335,6 @@ Button b13
|
||||
Touch Press Event
|
||||
showqq
|
||||
|
||||
Button b14
|
||||
Attributes
|
||||
ID : 25
|
||||
Scope : local
|
||||
Dragging : 0
|
||||
Send Component ID : disabled
|
||||
Opacity : 127
|
||||
x coordinate : 229
|
||||
y coordinate : 188
|
||||
Width : 106
|
||||
Height : 40
|
||||
Effect : load
|
||||
Effect Priority : 0
|
||||
Effect Time : 300
|
||||
Fill : solid color
|
||||
Style : 3D auto
|
||||
Font ID : 1
|
||||
Back. Color : 50712
|
||||
Back. Picture ID (Pressed): 65535
|
||||
Back. Color (Pressed) : 1024
|
||||
Font Color (Unpressed) : 0
|
||||
Font Color (Pressed) : 65535
|
||||
Horizontal Alignment : center
|
||||
Vertical Alignment : center
|
||||
State : unpressed
|
||||
Text : burntest
|
||||
Max. Text Size : 10
|
||||
Word wrap : disabled
|
||||
Horizontal Spacing : 0
|
||||
Vertical Spacing : 0
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
page cardBurnRec
|
||||
|
||||
Button b15
|
||||
Attributes
|
||||
ID : 21
|
||||
|
||||
@@ -806,6 +806,11 @@ Timer tmSerial
|
||||
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
|
||||
|
||||
@@ -672,6 +672,10 @@ Timer tmSerial
|
||||
{
|
||||
page cardChart
|
||||
}
|
||||
if(tId.txt=="cardLChart")
|
||||
{
|
||||
page cardLChart
|
||||
}
|
||||
}
|
||||
// end of user code
|
||||
udelete payloadLength-1
|
||||
|
||||
@@ -56,12 +56,47 @@ Page screensaver2
|
||||
Postinitialize Event
|
||||
click m0,1
|
||||
|
||||
Variable (string) entn1
|
||||
Attributes
|
||||
ID : 59
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 14
|
||||
|
||||
Variable (string) entn2
|
||||
Attributes
|
||||
ID : 60
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 14
|
||||
|
||||
Variable (string) entn3
|
||||
Attributes
|
||||
ID : 61
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 14
|
||||
|
||||
Variable (string) entn4
|
||||
Attributes
|
||||
ID : 62
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 14
|
||||
|
||||
Variable (string) entn5
|
||||
Attributes
|
||||
ID : 63
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 14
|
||||
|
||||
Variable (string) strCommand
|
||||
Attributes
|
||||
ID : 4
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 1979
|
||||
Max. Text Size: 1935
|
||||
|
||||
Variable (string) strTmp
|
||||
Attributes
|
||||
@@ -82,7 +117,7 @@ Variable (string) tInstruction
|
||||
ID : 18
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 50
|
||||
Max. Text Size: 15
|
||||
|
||||
Variable (string) tSend
|
||||
Attributes
|
||||
@@ -96,7 +131,7 @@ Variable (string) tTmp
|
||||
ID : 19
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 50
|
||||
Max. Text Size: 30
|
||||
|
||||
Variable (int32) vaTap
|
||||
Attributes
|
||||
@@ -865,6 +900,21 @@ Text f1Icon
|
||||
Horizontal Spacing : 0
|
||||
Vertical Spacing : 0
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
tSend.txt="event,buttonPress2,"+entn1.txt+",button"
|
||||
//send calc crc
|
||||
btlen tSend.txt,sys0
|
||||
crcrest 1,0xffff // reset CRC
|
||||
crcputh 55 bb
|
||||
crcputs sys0,2
|
||||
crcputs tSend.txt,0
|
||||
//send cmd
|
||||
printh 55 bb
|
||||
prints sys0,2
|
||||
prints tSend.txt,0
|
||||
prints crcval,2
|
||||
|
||||
Text f2Icon
|
||||
Attributes
|
||||
ID : 54
|
||||
@@ -894,6 +944,21 @@ Text f2Icon
|
||||
Horizontal Spacing : 0
|
||||
Vertical Spacing : 0
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
tSend.txt="event,buttonPress2,"+entn2.txt+",button"
|
||||
//send calc crc
|
||||
btlen tSend.txt,sys0
|
||||
crcrest 1,0xffff // reset CRC
|
||||
crcputh 55 bb
|
||||
crcputs sys0,2
|
||||
crcputs tSend.txt,0
|
||||
//send cmd
|
||||
printh 55 bb
|
||||
prints sys0,2
|
||||
prints tSend.txt,0
|
||||
prints crcval,2
|
||||
|
||||
Text f3Icon
|
||||
Attributes
|
||||
ID : 55
|
||||
@@ -923,6 +988,21 @@ Text f3Icon
|
||||
Horizontal Spacing : 0
|
||||
Vertical Spacing : 0
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
tSend.txt="event,buttonPress2,"+entn3.txt+",button"
|
||||
//send calc crc
|
||||
btlen tSend.txt,sys0
|
||||
crcrest 1,0xffff // reset CRC
|
||||
crcputh 55 bb
|
||||
crcputs sys0,2
|
||||
crcputs tSend.txt,0
|
||||
//send cmd
|
||||
printh 55 bb
|
||||
prints sys0,2
|
||||
prints tSend.txt,0
|
||||
prints crcval,2
|
||||
|
||||
Text f4Icon
|
||||
Attributes
|
||||
ID : 53
|
||||
@@ -952,6 +1032,21 @@ Text f4Icon
|
||||
Horizontal Spacing : 0
|
||||
Vertical Spacing : 0
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
tSend.txt="event,buttonPress2,"+entn4.txt+",button"
|
||||
//send calc crc
|
||||
btlen tSend.txt,sys0
|
||||
crcrest 1,0xffff // reset CRC
|
||||
crcputh 55 bb
|
||||
crcputs sys0,2
|
||||
crcputs tSend.txt,0
|
||||
//send cmd
|
||||
printh 55 bb
|
||||
prints sys0,2
|
||||
prints tSend.txt,0
|
||||
prints crcval,2
|
||||
|
||||
Text f5Icon
|
||||
Attributes
|
||||
ID : 52
|
||||
@@ -981,6 +1076,21 @@ Text f5Icon
|
||||
Horizontal Spacing : 0
|
||||
Vertical Spacing : 0
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
tSend.txt="event,buttonPress2,"+entn5.txt+",button"
|
||||
//send calc crc
|
||||
btlen tSend.txt,sys0
|
||||
crcrest 1,0xffff // reset CRC
|
||||
crcputh 55 bb
|
||||
crcputs sys0,2
|
||||
crcputs tSend.txt,0
|
||||
//send cmd
|
||||
printh 55 bb
|
||||
prints sys0,2
|
||||
prints tSend.txt,0
|
||||
prints crcval,2
|
||||
|
||||
Text m0
|
||||
Attributes
|
||||
ID : 32
|
||||
@@ -1551,26 +1661,36 @@ Timer tmSerial
|
||||
//f1Icon Color
|
||||
spstr strCommand.txt,tTmp.txt,"~",64
|
||||
covx tTmp.txt,f1Icon.pco,0,0
|
||||
//f1Icon intNameEntity
|
||||
spstr strCommand.txt,entn1.txt,"~",62
|
||||
//f2Icon
|
||||
spstr strCommand.txt,f2Icon.txt,"~",69
|
||||
//f2Icon Color
|
||||
spstr strCommand.txt,tTmp.txt,"~",70
|
||||
covx tTmp.txt,f2Icon.pco,0,0
|
||||
//f2Icon intNameEntity
|
||||
spstr strCommand.txt,entn2.txt,"~",68
|
||||
//f3Icon
|
||||
spstr strCommand.txt,f3Icon.txt,"~",75
|
||||
//f3Icon Color
|
||||
spstr strCommand.txt,tTmp.txt,"~",76
|
||||
covx tTmp.txt,f3Icon.pco,0,0
|
||||
//f3Icon intNameEntity
|
||||
spstr strCommand.txt,entn3.txt,"~",74
|
||||
//f4Icon
|
||||
spstr strCommand.txt,f4Icon.txt,"~",81
|
||||
//f4Icon Color
|
||||
spstr strCommand.txt,tTmp.txt,"~",82
|
||||
covx tTmp.txt,f4Icon.pco,0,0
|
||||
//f4Icon intNameEntity
|
||||
spstr strCommand.txt,entn4.txt,"~",80
|
||||
//f5Icon
|
||||
spstr strCommand.txt,f5Icon.txt,"~",87
|
||||
//f5Icon Color
|
||||
spstr strCommand.txt,tTmp.txt,"~",88
|
||||
covx tTmp.txt,f5Icon.pco,0,0
|
||||
//f5Icon intNameEntity
|
||||
spstr strCommand.txt,entn5.txt,"~",86
|
||||
}
|
||||
if(tInstruction.txt=="notify")
|
||||
{
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
Page cardBurnRec
|
||||
Attributes
|
||||
Scope : local
|
||||
Dragging : 0
|
||||
Send Component ID : disabled
|
||||
Locked : no
|
||||
Swide up page ID : disabled
|
||||
Swide down page ID : disabled
|
||||
Swide left page ID : disabled
|
||||
Swide right page ID: disabled
|
||||
|
||||
Timer tm0
|
||||
Attributes
|
||||
Scope : local
|
||||
Period (ms): 1001
|
||||
Enabled : yes
|
||||
|
||||
Events
|
||||
Timer Event
|
||||
dim=100
|
||||
sys0=0
|
||||
sys1=0
|
||||
if(sys2==WHITE)
|
||||
{
|
||||
sys2=BLACK
|
||||
}else
|
||||
{
|
||||
sys2=WHITE
|
||||
}
|
||||
sya1=sys2
|
||||
while(sys0<8)
|
||||
{
|
||||
sya0=sys0%2
|
||||
if(sya1==WHITE)
|
||||
{
|
||||
sya1=BLACK
|
||||
}else
|
||||
{
|
||||
sya1=WHITE
|
||||
}
|
||||
fill 0,40*sys0,480,40,sya1
|
||||
sys0++
|
||||
}
|
||||
|
||||
TouchCap tc0
|
||||
Attributes
|
||||
Scope: local
|
||||
Value: 0
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
page pageStartup
|
||||
|
||||
@@ -141,19 +141,6 @@ Button b13
|
||||
Touch Press Event
|
||||
showqq
|
||||
|
||||
Button b14
|
||||
Attributes
|
||||
Scope : local
|
||||
Dragging : 0
|
||||
Send Component ID: disabled
|
||||
State : unpressed
|
||||
Text : burntest
|
||||
Max. Text Size : 10
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
page cardBurnRec
|
||||
|
||||
Button b15
|
||||
Attributes
|
||||
Scope : local
|
||||
|
||||
@@ -457,6 +457,11 @@ Timer tmSerial
|
||||
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
|
||||
|
||||
@@ -443,6 +443,10 @@ Timer tmSerial
|
||||
{
|
||||
page cardChart
|
||||
}
|
||||
if(tId.txt=="cardLChart")
|
||||
{
|
||||
page cardLChart
|
||||
}
|
||||
}
|
||||
// end of user code
|
||||
udelete payloadLength-1
|
||||
|
||||
@@ -48,11 +48,41 @@ Page screensaver2
|
||||
Postinitialize Event
|
||||
click m0,1
|
||||
|
||||
Variable (string) entn1
|
||||
Attributes
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 14
|
||||
|
||||
Variable (string) entn2
|
||||
Attributes
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 14
|
||||
|
||||
Variable (string) entn3
|
||||
Attributes
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 14
|
||||
|
||||
Variable (string) entn4
|
||||
Attributes
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 14
|
||||
|
||||
Variable (string) entn5
|
||||
Attributes
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 14
|
||||
|
||||
Variable (string) strCommand
|
||||
Attributes
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 1979
|
||||
Max. Text Size: 1935
|
||||
|
||||
Variable (string) strTmp
|
||||
Attributes
|
||||
@@ -70,7 +100,7 @@ Variable (string) tInstruction
|
||||
Attributes
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 50
|
||||
Max. Text Size: 15
|
||||
|
||||
Variable (string) tSend
|
||||
Attributes
|
||||
@@ -82,7 +112,7 @@ Variable (string) tTmp
|
||||
Attributes
|
||||
Scope : local
|
||||
Text :
|
||||
Max. Text Size: 50
|
||||
Max. Text Size: 30
|
||||
|
||||
Variable (int32) vaTap
|
||||
Attributes
|
||||
@@ -344,6 +374,21 @@ Text f1Icon
|
||||
Text :
|
||||
Max. Text Size : 4
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
tSend.txt="event,buttonPress2,"+entn1.txt+",button"
|
||||
//send calc crc
|
||||
btlen tSend.txt,sys0
|
||||
crcrest 1,0xffff // reset CRC
|
||||
crcputh 55 bb
|
||||
crcputs sys0,2
|
||||
crcputs tSend.txt,0
|
||||
//send cmd
|
||||
printh 55 bb
|
||||
prints sys0,2
|
||||
prints tSend.txt,0
|
||||
prints crcval,2
|
||||
|
||||
Text f2Icon
|
||||
Attributes
|
||||
Scope : local
|
||||
@@ -353,6 +398,21 @@ Text f2Icon
|
||||
Text :
|
||||
Max. Text Size : 4
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
tSend.txt="event,buttonPress2,"+entn2.txt+",button"
|
||||
//send calc crc
|
||||
btlen tSend.txt,sys0
|
||||
crcrest 1,0xffff // reset CRC
|
||||
crcputh 55 bb
|
||||
crcputs sys0,2
|
||||
crcputs tSend.txt,0
|
||||
//send cmd
|
||||
printh 55 bb
|
||||
prints sys0,2
|
||||
prints tSend.txt,0
|
||||
prints crcval,2
|
||||
|
||||
Text f3Icon
|
||||
Attributes
|
||||
Scope : local
|
||||
@@ -362,6 +422,21 @@ Text f3Icon
|
||||
Text :
|
||||
Max. Text Size : 4
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
tSend.txt="event,buttonPress2,"+entn3.txt+",button"
|
||||
//send calc crc
|
||||
btlen tSend.txt,sys0
|
||||
crcrest 1,0xffff // reset CRC
|
||||
crcputh 55 bb
|
||||
crcputs sys0,2
|
||||
crcputs tSend.txt,0
|
||||
//send cmd
|
||||
printh 55 bb
|
||||
prints sys0,2
|
||||
prints tSend.txt,0
|
||||
prints crcval,2
|
||||
|
||||
Text f4Icon
|
||||
Attributes
|
||||
Scope : local
|
||||
@@ -371,6 +446,21 @@ Text f4Icon
|
||||
Text :
|
||||
Max. Text Size : 4
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
tSend.txt="event,buttonPress2,"+entn4.txt+",button"
|
||||
//send calc crc
|
||||
btlen tSend.txt,sys0
|
||||
crcrest 1,0xffff // reset CRC
|
||||
crcputh 55 bb
|
||||
crcputs sys0,2
|
||||
crcputs tSend.txt,0
|
||||
//send cmd
|
||||
printh 55 bb
|
||||
prints sys0,2
|
||||
prints tSend.txt,0
|
||||
prints crcval,2
|
||||
|
||||
Text f5Icon
|
||||
Attributes
|
||||
Scope : local
|
||||
@@ -380,6 +470,21 @@ Text f5Icon
|
||||
Text :
|
||||
Max. Text Size : 4
|
||||
|
||||
Events
|
||||
Touch Press Event
|
||||
tSend.txt="event,buttonPress2,"+entn5.txt+",button"
|
||||
//send calc crc
|
||||
btlen tSend.txt,sys0
|
||||
crcrest 1,0xffff // reset CRC
|
||||
crcputh 55 bb
|
||||
crcputs sys0,2
|
||||
crcputs tSend.txt,0
|
||||
//send cmd
|
||||
printh 55 bb
|
||||
prints sys0,2
|
||||
prints tSend.txt,0
|
||||
prints crcval,2
|
||||
|
||||
Text m0
|
||||
Attributes
|
||||
Scope : local
|
||||
@@ -718,26 +823,36 @@ Timer tmSerial
|
||||
//f1Icon Color
|
||||
spstr strCommand.txt,tTmp.txt,"~",64
|
||||
covx tTmp.txt,f1Icon.pco,0,0
|
||||
//f1Icon intNameEntity
|
||||
spstr strCommand.txt,entn1.txt,"~",62
|
||||
//f2Icon
|
||||
spstr strCommand.txt,f2Icon.txt,"~",69
|
||||
//f2Icon Color
|
||||
spstr strCommand.txt,tTmp.txt,"~",70
|
||||
covx tTmp.txt,f2Icon.pco,0,0
|
||||
//f2Icon intNameEntity
|
||||
spstr strCommand.txt,entn2.txt,"~",68
|
||||
//f3Icon
|
||||
spstr strCommand.txt,f3Icon.txt,"~",75
|
||||
//f3Icon Color
|
||||
spstr strCommand.txt,tTmp.txt,"~",76
|
||||
covx tTmp.txt,f3Icon.pco,0,0
|
||||
//f3Icon intNameEntity
|
||||
spstr strCommand.txt,entn3.txt,"~",74
|
||||
//f4Icon
|
||||
spstr strCommand.txt,f4Icon.txt,"~",81
|
||||
//f4Icon Color
|
||||
spstr strCommand.txt,tTmp.txt,"~",82
|
||||
covx tTmp.txt,f4Icon.pco,0,0
|
||||
//f4Icon intNameEntity
|
||||
spstr strCommand.txt,entn4.txt,"~",80
|
||||
//f5Icon
|
||||
spstr strCommand.txt,f5Icon.txt,"~",87
|
||||
//f5Icon Color
|
||||
spstr strCommand.txt,tTmp.txt,"~",88
|
||||
covx tTmp.txt,f5Icon.pco,0,0
|
||||
//f5Icon intNameEntity
|
||||
spstr strCommand.txt,entn5.txt,"~",86
|
||||
}
|
||||
if(tInstruction.txt=="notify")
|
||||
{
|
||||
|
||||
BIN
HMI/nspanel.HMI
BIN
HMI/nspanel.HMI
Binary file not shown.
BIN
HMI/nspanel.tft
BIN
HMI/nspanel.tft
Binary file not shown.
@@ -65,3 +65,5 @@ SmartHomeNG: https://github.com/sisamiwe/shng-nspanel-plugin
|
||||
OpenHAB: https://github.com/donoo/o2n2l
|
||||
|
||||
NodeRed: https://github.com/laluz742/node-red-contrib-nspanel-lui
|
||||
|
||||
ESPHome without any Backend: https://github.com/olicooper/esphome-nspanel-lovelace-native
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
ha_api = None
|
||||
mqtt_api = None
|
||||
ad_api = None
|
||||
@@ -132,6 +132,7 @@ class LuiBackendConfig(object):
|
||||
'sleepTrackingZones': ["not_home", "off"],
|
||||
'sleepOverride': None,
|
||||
'locale': "en_US",
|
||||
'quiet': True,
|
||||
'timeFormat': "%H:%M",
|
||||
'dateFormatBabel': "full",
|
||||
'dateAdditionalTemplate': "",
|
||||
|
||||
@@ -3,6 +3,7 @@ import datetime
|
||||
import apis
|
||||
from helper import scale, pos_to_color, rgb_dec565
|
||||
from pages import LuiPagesGen
|
||||
from luibackend.config import Card
|
||||
|
||||
class LuiController(object):
|
||||
|
||||
@@ -458,3 +459,9 @@ class LuiController(object):
|
||||
apis.ha_api.get_entity(entity_id).call_service("pause")
|
||||
if button_type == "timer-finish":
|
||||
apis.ha_api.get_entity(entity_id).call_service("finish")
|
||||
|
||||
@property
|
||||
def current_card(self) -> Card:
|
||||
"""Used to get the current card"""
|
||||
|
||||
return self._current_card
|
||||
|
||||
@@ -213,6 +213,9 @@ def get_icon_ha(entity_id, overwrite=None, stateOverwrite=None):
|
||||
entity = apis.ha_api.get_entity(entity_id)
|
||||
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 type(overwrite) is str:
|
||||
return get_icon_char(overwrite)
|
||||
|
||||
@@ -77,12 +77,13 @@ class LuiMqttListener(object):
|
||||
self._controller.detail_open(msg[2], msg[3])
|
||||
|
||||
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._use_api = use_api
|
||||
self._topic_send = topic_send
|
||||
self._api_panel_name = api_panel_name
|
||||
self._prev_msg = ""
|
||||
self._quiet = quiet
|
||||
|
||||
def send_mqtt_msg(self, msg, topic=None, force=False):
|
||||
if not force and self._prev_msg == msg:
|
||||
@@ -90,7 +91,9 @@ class LuiMqttSender(object):
|
||||
return
|
||||
self._prev_msg = msg
|
||||
|
||||
if self._quiet is False:
|
||||
apis.ha_api.log(f"Sending Message: {msg}")
|
||||
|
||||
if self._use_api:
|
||||
apis.ha_api.call_service(service="esphome/" + self._api_panel_name + "_nspanelui_api_call", command=2, data=msg)
|
||||
else:
|
||||
|
||||
@@ -192,6 +192,9 @@ class LuiPagesGen(object):
|
||||
else:
|
||||
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")
|
||||
|
||||
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:
|
||||
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)
|
||||
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]
|
||||
if icon_res[-1] == ".":
|
||||
icon_res = icon_res[:-1]
|
||||
@@ -245,7 +248,7 @@ class LuiPagesGen(object):
|
||||
if status_entity:
|
||||
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)
|
||||
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]
|
||||
if icon_id[-1] == ".":
|
||||
icon_id = icon_id[:-1]
|
||||
@@ -318,7 +321,7 @@ class LuiPagesGen(object):
|
||||
value = value + unit_of_measurement
|
||||
if entityType == "binary_sensor":
|
||||
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]
|
||||
if icon_id[-1] == ".":
|
||||
icon_id = icon_id[:-1]
|
||||
@@ -779,6 +782,8 @@ class LuiPagesGen(object):
|
||||
if send_page_type:
|
||||
if card.cardType == "cardGrid" and len(card.entities) > 6:
|
||||
card.cardType = "cardGrid2"
|
||||
if card.cardType == "cardGrid1":
|
||||
card.cardType = "cardGrid"
|
||||
self.page_type(card.cardType)
|
||||
|
||||
# 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")}')
|
||||
|
||||
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)
|
||||
return
|
||||
if card.cardType == "cardThermo":
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import hassapi as hass
|
||||
import adbase as ad
|
||||
|
||||
from luibackend.config import LuiBackendConfig
|
||||
from luibackend.controller import LuiController
|
||||
@@ -6,15 +6,19 @@ from luibackend.mqtt import LuiMqttListener, LuiMqttSender
|
||||
from luibackend.updater import Updater
|
||||
|
||||
import apis
|
||||
import json
|
||||
from typing import Literal
|
||||
|
||||
class NsPanelLovelaceUIManager(hass.Hass):
|
||||
class NsPanelLovelaceUIManager(ad.ADBase):
|
||||
|
||||
def initialize(self):
|
||||
self.log('Starting')
|
||||
apis.ha_api = self
|
||||
self.adapi = self.get_ad_api()
|
||||
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")
|
||||
|
||||
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
|
||||
|
||||
@@ -22,10 +26,11 @@ class NsPanelLovelaceUIManager(hass.Hass):
|
||||
topic_recv = cfg.get("panelRecvTopic")
|
||||
api_panel_name = cfg.get("panelName")
|
||||
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_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")
|
||||
|
||||
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
|
||||
updater.request_berry_driver_version()
|
||||
|
||||
LuiMqttListener(use_api, topic_recv, api_panel_name, api_device_id, controller, updater)
|
||||
LuiMqttListener(use_api, topic_recv, api_panel_name, api_device_id, self._controller, updater)
|
||||
|
||||
self.log(f'Started ({version})')
|
||||
self.adapi.log(f'Started ({version})')
|
||||
|
||||
#
|
||||
# helpers
|
||||
#
|
||||
|
||||
def show_card(self, card_key: str) -> None:
|
||||
"""Used to show card on panel"""
|
||||
|
||||
msg = json.dumps({"CustomRecv":f"event,buttonPress2,navigate.{card_key},button"})
|
||||
topic = self._cfg.get("panelRecvTopic")
|
||||
self._mqttsender.send_mqtt_msg(msg, topic)
|
||||
|
||||
def navigate(self, direction: Literal['up', 'prev', 'next']) -> None:
|
||||
"""Used to navigate different directions on the panel"""
|
||||
|
||||
msg = json.dumps({"CustomRecv":f"event,buttonPress2,nav{direction.title()},button"})
|
||||
topic = self._cfg.get("panelRecvTopic")
|
||||
self._mqttsender.send_mqtt_msg(msg, topic)
|
||||
|
||||
@property
|
||||
def current_card(self) -> str:
|
||||
"""Used to get the panel's current card"""
|
||||
|
||||
return self._controller.current_card.key
|
||||
|
||||
@@ -93,3 +93,34 @@ Now, to install NSPanel Lovelace UI Backend with HACS, follow these steps:
|
||||
6. A confirmation panel will appear, click on `Download`, and wait for HACS to
|
||||
proceed with the download
|
||||
7. The Backend Application is now installed, and HACS will inform you when updates are available
|
||||
|
||||
# Workaround for HomeAssistant 2024.04
|
||||
AppDaemon is using the old REST API that until AppDaemon moved on the the websocket API this woraround is needed to get weather forecast data from homeassistant. (https://github.com/AppDaemon/appdaemon/issues/1837)
|
||||
|
||||
To get the forecast data in appdaemon, there is a script needed in homeassistant's configuration.yaml:
|
||||
|
||||
```yaml
|
||||
template:
|
||||
- trigger:
|
||||
- platform: time_pattern
|
||||
hours: /1
|
||||
action:
|
||||
- service: weather.get_forecasts
|
||||
data:
|
||||
type: daily
|
||||
target:
|
||||
entity_id: weather.k3ll3r # change to your weather entity in this line
|
||||
response_variable: daily
|
||||
sensor:
|
||||
- name: Weather Forecast Daily
|
||||
unique_id: weather_forecast_daily
|
||||
state: "{{ now().isoformat() }}"
|
||||
attributes:
|
||||
forecast: "{{ daily['weather.k3ll3r'].forecast }}" # change to your weather entity in this line
|
||||
```
|
||||

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

|
||||
|
||||
|
||||
1732
ioBroker/.iobroker/types/javascript.d.ts
vendored
Normal file
1732
ioBroker/.iobroker/types/javascript.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,74 +0,0 @@
|
||||
const idAbfalliCal = 'ical.1'; // iCal Instanz zum Abfallkalender
|
||||
const idZeichenLoeschen = 14; // x Zeichen links vom String abziehen, wenn vor dem Eventname noch Text steht z.B. Strassenname; Standard = 0
|
||||
const idRestmuellName ='Hausmüll'; // Schwarze Tonne
|
||||
const idWertstoffName = 'Gelber Sack'; // Gelbe Tonne / Sack
|
||||
const idPappePapierName = 'Papier'; // Blaue Tonne
|
||||
const idBioabfaelleName = 'Biomüll'; // Braune Tonne
|
||||
|
||||
|
||||
var i, Muell_JSON, Event2, Color = 0;
|
||||
|
||||
for (i = 1; i <= 4; i++) {
|
||||
if (!existsState('0_userdata.0.Abfallkalender.' + parseFloat(i) + '.date')) {
|
||||
log(i + '.date nicht vorhanden, wurde erstellt');
|
||||
createState('0_userdata.0.Abfallkalender.' + parseFloat(i) + '.date', '',
|
||||
{
|
||||
name: parseFloat(i) + '.date',
|
||||
role: 'state',
|
||||
type: 'string',
|
||||
read: true,
|
||||
write: true,
|
||||
def: ''
|
||||
});
|
||||
};
|
||||
if (!existsState('0_userdata.0.Abfallkalender.' + parseFloat(i) + '.event')) {
|
||||
log(i + '.event nicht vorhanden, wurde erstellt');
|
||||
createState('0_userdata.0.Abfallkalender.' + parseFloat(i) + '.event', '',
|
||||
{
|
||||
name: parseFloat(i) + '.event',
|
||||
role: 'state',
|
||||
type: 'string',
|
||||
read: true,
|
||||
write: true,
|
||||
def: ''
|
||||
});
|
||||
};
|
||||
if (!existsState('0_userdata.0.Abfallkalender.' + parseFloat(i) + '.color')) {
|
||||
log(i + '.color nicht vorhanden, wurde erstellt');
|
||||
createState('0_userdata.0.Abfallkalender.' + parseFloat(i) + '.color', 0,
|
||||
{
|
||||
name: parseFloat(i) + '.color',
|
||||
role: 'state',
|
||||
type: 'number',
|
||||
read: true,
|
||||
write: true,
|
||||
def: 0
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function subsequenceFromStartLast(sequence, at1) {
|
||||
var start = at1;
|
||||
var end = sequence.length;
|
||||
return sequence.slice(start, end);
|
||||
}
|
||||
|
||||
on({ id: idAbfalliCal + '.data.table', change: "ne" }, async function () {
|
||||
|
||||
for (i = 0; i <= 3; i++) {
|
||||
Muell_JSON = getState(idAbfalliCal + '.data.table').val;
|
||||
setStateDelayed((['0_userdata.0.Abfallkalender.', parseFloat(i) + 1, '.date'].join('')), getAttr(Muell_JSON, (String(i) + '.date')), false, parseInt(((0) || "").toString(), 10), false);
|
||||
Event2 = subsequenceFromStartLast(getAttr(Muell_JSON, (String(i) + '.event')), idZeichenLoeschen);
|
||||
setStateDelayed((['0_userdata.0.Abfallkalender.', parseFloat(i) + 1, '.event'].join('')), Event2, false, parseInt(((0) || "").toString(), 10), false);
|
||||
if (Event2 == idRestmuellName) {
|
||||
Color = 33840;
|
||||
} else if (Event2 == idBioabfaelleName) {
|
||||
Color = 2016;
|
||||
} else if (Event2 == idPappePapierName) {
|
||||
Color = 31;
|
||||
} else if (Event2 == idWertstoffName) {
|
||||
Color = 65504;
|
||||
}
|
||||
setStateDelayed((['0_userdata.0.Abfallkalender.', parseFloat(i) + 1, '.color'].join('')), Color, false, parseInt(((0) || "").toString(), 10), false);
|
||||
}
|
||||
});
|
||||
224
ioBroker/Blockly/Abfallkalender.ts
Normal file
224
ioBroker/Blockly/Abfallkalender.ts
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* @author 2023 @tt-tom
|
||||
*
|
||||
* Version 5.1.1
|
||||
*
|
||||
* Das Script erstellt die Datenpunkte und Alias für den Abfallkalender im Sonoff NSPanel
|
||||
* Es wird der iCal Adapter benötigt und eine URL mit Terminen vom Entsorger bzw. eine .ics-Datei mit den Terminen.
|
||||
* Das Script triggert auf dem bereitgestellten JSON im iCal adapter und füllt die 0_userdata.0 Datenpunkte
|
||||
* Weitere Informationen findest du in der FAQ auf Github https://github.com/joBr99/nspanel-lovelace-ui/wiki
|
||||
*
|
||||
* changelog
|
||||
* - 06.12.2023 - v5.0.2 add custom name for trashtype
|
||||
* - 06.12.2023 - v5.1.0 Refactoring
|
||||
* - 22.01.2024 - v5.1.1 Add tow Events more
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
const idTrashData: string = 'ical.0.data.table'; // Datenpunkt mit Daten im JSON Format
|
||||
const idUserdataAbfallVerzeichnis: string = '0_userdata.0.Abfallkalender'; // Name des Datenpunktverzeichnis unter 0_userdata.0 -> Strandard = 0_userdata.0.Abfallkalender
|
||||
const idAliasPanelVerzeichnis: string = 'alias.0.NSPanel.allgemein'; //Name PanelVerzeichnis unter alias.0. Standard = alias.0.NSPanel.1
|
||||
const idAliasAbfallVerzeichnis: string = 'Abfall'; //Name Verzeichnis unterhalb der idPanelverzeichnis Standard = Abfall
|
||||
|
||||
const anzahlZeichenLoeschen: number = 14; // x Zeichen links vom String abziehen, wenn vor dem Eventname noch Text steht z.B. Strassenname; Standard = 0
|
||||
const jsonEventName1: string = 'Hausmüll'; // Vergleichstring für Schwarze Tonne
|
||||
const customEventName1: string = ''; // benutzerdefinierter Text für schwarze Tonne
|
||||
const jsonEventName2: string = 'Gelber Sack'; // Vergleichstring für Gelbe Tonne / Sack
|
||||
const customEventName2: string = ''; // benutzerdefinierter Text für gelbe Tonne
|
||||
const jsonEventName3: string = 'Papier'; // Vergleichstring für Blaue Tonne
|
||||
const customEventName3: string = ''; // benutzerdefinierter Text für blaue Tonne
|
||||
const jsonEventName4: string = 'Biomüll'; // Vergleichstring für Braune Tonne
|
||||
const customEventName4: string = ''; // benutzerdefinierter Text für braune Tonne
|
||||
const jsonEventName5: string = 'Treppe'; // Vergleichstring für Event 5
|
||||
const customEventName5: string = 'Besen schwingen'; // benutzerdefinierter Text für Event 5
|
||||
const jsonEventName6: string = ''; // Vergleichstring für Event 6
|
||||
const customEventName6: string = ''; // benutzerdefinierter Text für Event 6
|
||||
|
||||
const Debug: boolean = false;
|
||||
|
||||
// ------------------------- Trigger zum füllen der 0_userdata Datenpunkte aus dem json vom ical Adapter -------------------------------
|
||||
|
||||
// Trigger auf JSON Datenpunkt
|
||||
on({ id: idTrashData, change: 'ne' }, async function () {
|
||||
JSON_auswerten();
|
||||
});
|
||||
|
||||
// ------------------------------------- Ende Trigger ------------------------------------
|
||||
|
||||
// ------------------------------------- Funktion JSON auswerten und DP füllen -------------------------------
|
||||
async function JSON_auswerten() {
|
||||
try {
|
||||
|
||||
let trashJSON: any;
|
||||
let instanzName: any;
|
||||
let eventName: string;
|
||||
let eventDatum: string;
|
||||
let eventStartdatum: string;
|
||||
let farbNummer: number = 0;
|
||||
let farbString: string;
|
||||
let abfallNummer: number = 1;
|
||||
|
||||
trashJSON = getState(idTrashData).val;
|
||||
instanzName = idTrashData.split('.');
|
||||
|
||||
if (Debug) log('Rohdaten von Instanz ' + instanzName[0] + ': ' + JSON.stringify(trashJSON), 'info')
|
||||
|
||||
|
||||
if (Debug) log('Anzahl Trash - Daten: ' + trashJSON.length, 'info');
|
||||
|
||||
for (let i = 0; i < trashJSON.length; i++) {
|
||||
if (abfallNummer === 7) {
|
||||
if (Debug) log('Alle Abfall-Datenpunkte gefüllt', 'warn');
|
||||
break;
|
||||
}
|
||||
|
||||
log('Daten vom ical Adapter werden ausgewertet', 'info');
|
||||
eventName = getAttr(trashJSON, (String(i) + '.event')).slice(anzahlZeichenLoeschen, getAttr(trashJSON, (String(i) + '.event')).length);
|
||||
// Leerzeichen vorne und hinten löschen
|
||||
eventName = eventName.trimEnd();
|
||||
eventName = eventName.trimStart();
|
||||
eventDatum = getAttr(trashJSON, (String(i) + '.date'));
|
||||
eventStartdatum = getAttr(trashJSON, (String(i) + '._date'));
|
||||
|
||||
let d: Date = currentDate();
|
||||
let d1: Date = new Date(eventStartdatum);
|
||||
|
||||
if (Debug) log('--------- Nächster Termin wird geprüft ---------', 'info');
|
||||
//if (Debug) log(d + ' ' + d1, 'info');
|
||||
if (Debug) log('Startdatum UTC: ' + eventStartdatum, 'info');
|
||||
if (Debug) log('Datum: ' + eventDatum, 'info');
|
||||
if (Debug) log('Event: ' + eventName, 'info');
|
||||
if (Debug) log('Kontrolle Leerzeichen %' + eventName + '%', 'info');
|
||||
|
||||
if (d.getTime() <= d1.getTime()) {
|
||||
if ((eventName == jsonEventName1) || (eventName == jsonEventName2) || (eventName == jsonEventName3) || (eventName == jsonEventName4) || (eventName == jsonEventName5) || (eventName == jsonEventName6)) {
|
||||
|
||||
switch (eventName) {
|
||||
case jsonEventName1:
|
||||
farbNummer = 33840;
|
||||
if (customEventName1 != '') {
|
||||
eventName = customEventName1;
|
||||
if (Debug) log('Event customName: ' + eventName, 'info');
|
||||
};
|
||||
break;
|
||||
case jsonEventName2:
|
||||
farbNummer = 65504;
|
||||
if (customEventName2 != '') {
|
||||
eventName = customEventName2;
|
||||
if (Debug) log('Event customName: ' + eventName, 'info');
|
||||
};
|
||||
break;
|
||||
case jsonEventName3:
|
||||
farbNummer = 31;
|
||||
if (customEventName3 != '') {
|
||||
eventName = customEventName3
|
||||
if (Debug) log('Event customName: ' + eventName, 'info');
|
||||
};
|
||||
break;
|
||||
case jsonEventName4:
|
||||
farbNummer = 2016;
|
||||
if (customEventName4 != '') {
|
||||
eventName = customEventName4;
|
||||
if (Debug) log('Event customName: ' + eventName, 'info');
|
||||
};
|
||||
break;
|
||||
case jsonEventName5:
|
||||
farbNummer = 2016;
|
||||
if (customEventName5 != '') {
|
||||
eventName = customEventName5;
|
||||
if (Debug) log('Event customName: ' + eventName, 'info');
|
||||
};
|
||||
break;
|
||||
case jsonEventName6:
|
||||
farbNummer = 2016;
|
||||
if (customEventName6 != '') {
|
||||
eventName = customEventName6
|
||||
if (Debug) log('Event customName: ' + eventName, 'info');
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
//if (farbString != undefined) farbNummer = rgb_dec565(hex_rgb(farbString));
|
||||
|
||||
|
||||
setState(idUserdataAbfallVerzeichnis + '.' + String(abfallNummer) + '.date', eventDatum);
|
||||
setState(idUserdataAbfallVerzeichnis + '.' + String(abfallNummer) + '.event', eventName);
|
||||
setState(idUserdataAbfallVerzeichnis + '.' + String(abfallNummer) + '.color', farbNummer);
|
||||
|
||||
|
||||
//if (Debug) log('farbString: ' + farbString + ' farbNummer: ' + farbNummer, 'info');
|
||||
if (Debug) log('Abfallnummer: ' + abfallNummer, 'info');
|
||||
|
||||
abfallNummer += 1
|
||||
} else {
|
||||
if (Debug) log('Kein Abfalltermin => Event passt mit keinem Abfallnamen überein.', 'warn');
|
||||
}
|
||||
} else {
|
||||
if (Debug) log('Termin liegt vor dem heutigen Tag', 'warn');
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
log('error at subscrption: ' + err.message, 'warn');
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------- Ende Funktion JSON ------------------------------
|
||||
|
||||
// ------------------------------------- Funktion zur Prüfung und Erstellung der Datenpunkte in 0_userdata.0 und alias.0 -----------------------
|
||||
|
||||
async function Init_Datenpunkte() {
|
||||
try {
|
||||
for (let i = 1; i <= 6; i++) {
|
||||
if (existsObject(idUserdataAbfallVerzeichnis + '.' + String(i)) == false) {
|
||||
log('Datenpunkt ' + idUserdataAbfallVerzeichnis + '.' + String(i) + ' werden angelegt', 'info')
|
||||
await createStateAsync(idUserdataAbfallVerzeichnis + '.' + String(i) + '.date', '', { type: 'string' });
|
||||
await createStateAsync(idUserdataAbfallVerzeichnis + '.' + String(i) + '.event', '', { type: 'string' });
|
||||
await createStateAsync(idUserdataAbfallVerzeichnis + '.' + String(i) + '.color', 0, { type: 'number' });
|
||||
setObject(idAliasPanelVerzeichnis + '.' + idAliasAbfallVerzeichnis, { type: 'device', common: { name: { de: 'Abfall', en: 'Trash' } }, native: {} });
|
||||
setObject(idAliasPanelVerzeichnis + '.' + idAliasAbfallVerzeichnis + '.event' + String(i), { type: 'channel', common: { role: 'warning', name: { de: 'Ereignis ' + String(i), en: 'Event' + String(i) } }, native: {} });
|
||||
await createAliasAsync(idAliasPanelVerzeichnis + '.' + idAliasAbfallVerzeichnis + '.event' + String(i) + '.TITLE', idUserdataAbfallVerzeichnis + '.' + String(i) + '.event', true, <iobJS.StateCommon>{ type: 'string', role: 'weather.title.short', name: { de: 'TITEL', en: 'TITLE' } });
|
||||
await createAliasAsync(idAliasPanelVerzeichnis + '.' + idAliasAbfallVerzeichnis + '.event' + String(i) + '.LEVEL', idUserdataAbfallVerzeichnis + '.' + String(i) + '.color', true, <iobJS.StateCommon>{ type: 'number', role: 'value.warning', name: { de: 'LEVEL', en: 'LEVEL' } });
|
||||
await createAliasAsync(idAliasPanelVerzeichnis + '.' + idAliasAbfallVerzeichnis + '.event' + String(i) + '.INFO', idUserdataAbfallVerzeichnis + '.' + String(i) + '.date', true, <iobJS.StateCommon>{ type: 'string', role: 'weather.title', name: { de: 'INFO', en: 'INFO' } });
|
||||
log('Fertig', 'info')
|
||||
} else {
|
||||
log('Datenpunkt ' + idUserdataAbfallVerzeichnis + '.' + String(i) + ' vorhanden', 'info')
|
||||
}
|
||||
}
|
||||
log('Startabfrage der Daten', 'info');
|
||||
JSON_auswerten();
|
||||
} catch (err) {
|
||||
log('error at function Init_Datenpunkte: ' + err.message, 'warn');
|
||||
}
|
||||
}
|
||||
Init_Datenpunkte();
|
||||
|
||||
// --------------------------- Ende Funktion Datenpunkte ------------------------------------------------
|
||||
|
||||
|
||||
// --------------------------- Zusatzfuktionen -------------------------------------------------------------
|
||||
function currentDate() {
|
||||
let d: Date = new Date();
|
||||
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
||||
}
|
||||
|
||||
function rgb_dec565(rgb: RGB): number {
|
||||
//return ((Math.floor(rgb.red / 255 * 31) << 11) | (Math.floor(rgb.green / 255 * 63) << 5) | (Math.floor(rgb.blue / 255 * 31)));
|
||||
return ((rgb.red >> 3) << 11) | ((rgb.green >> 2)) << 5 | ((rgb.blue) >> 3);
|
||||
}
|
||||
|
||||
function hex_rgb(colorhex: string): RGB {
|
||||
let r = parseInt(colorhex.substring(1, 3), 16);
|
||||
let g = parseInt(colorhex.substring(3, 5), 16);
|
||||
let b = parseInt(colorhex.substring(5, 7), 16);
|
||||
return { red: r, green: g, blue: b };
|
||||
}
|
||||
|
||||
type RGB = {
|
||||
red: number,
|
||||
green: number,
|
||||
blue: number
|
||||
};
|
||||
|
||||
// -------------------- Ende Zudatzfunktionen --------------------------------------------------------------------------
|
||||
@@ -975,7 +975,32 @@
|
||||
<shadow type="logic_boolean" id="I4PsJQb;6k+70^g*Xt/}">
|
||||
<field name="BOOL">TRUE</field>
|
||||
</shadow>
|
||||
<block type="math_random_float" id="C5/h)jq=yPM?,9J=(w65"></block>
|
||||
<block type="text_join" id="XdhGC7#MxGw|KhC1x#MY">
|
||||
<mutation items="2"></mutation>
|
||||
<value name="ADD0">
|
||||
<block type="text" id="[(_1;{xE-xfzeB4]$uk;">
|
||||
<field name="TEXT">ID</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="ADD1">
|
||||
<block type="convert_tostring" id="g{jZOA*6Clhc5`9::h.S">
|
||||
<value name="VALUE">
|
||||
<block type="math_random_int" id="SXG?j1]Jza!2fg[(cl!i">
|
||||
<value name="FROM">
|
||||
<shadow type="math_number" id="#/-;$~`{=}8wYY$kbvA9">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="TO">
|
||||
<shadow type="math_number" id="0x8~a;asHsiJ2Its%!VJ">
|
||||
<field name="NUM">100</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
<value name="DELAY_MS">
|
||||
<shadow type="math_number" id="+6#n%fO}e4h%;FhKPV0c">
|
||||
|
||||
44
ioBroker/Blockly/Alarm_clock.ts
Normal file
44
ioBroker/Blockly/Alarm_clock.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
const dp_userdata: string = '0_userdata.0.NSPanel';
|
||||
const dp_alias: string = 'alias.0.NSPanel';
|
||||
|
||||
// dpAction wird wenn der Wecker gestellt wird auf false geschaltet
|
||||
// dpAction wird wenn die Weckzeit erreicht ist auf true geschaltet
|
||||
// Der nachfolgende Datenpunkt muss manuell erstellt werden...
|
||||
const dpAction: string = '0_userdata.0.example_boolean';
|
||||
|
||||
const Debug = true;
|
||||
|
||||
let time: number;
|
||||
let scheduleAlarmTime: any = null;
|
||||
on({ id: dp_userdata + '.AlarmTime.State', change: 'ne' }, async (obj) => {
|
||||
|
||||
time = getState(dp_userdata + '.AlarmTime.Time').val;
|
||||
if (Debug) log('Uhrzeit: ' + time, 'info');
|
||||
if ('paused' == obj.state.val) {
|
||||
(function () { if (scheduleAlarmTime) {
|
||||
clearSchedule(scheduleAlarmTime);
|
||||
scheduleAlarmTime = null;
|
||||
}
|
||||
});
|
||||
} else if ('active' == obj.state.val) {
|
||||
let stunde: number = Math.floor(time / 60);
|
||||
let minute: number = time % 60;
|
||||
if (Debug) log('Weckzeit: ' + ('0' + stunde).slice(-2) + ':' + ('0' + minute).slice(-2), 'info');
|
||||
scheduleAlarmTime = schedule(minute + ' ' + stunde + ' * * *', async () => {
|
||||
await setStateAsync(dpAction, <iobJS.State>{ val: true, ack: true });
|
||||
await setStateAsync(dp_userdata + '.AlarmTime.State', <iobJS.State>{ val: 'paused', ack: true });
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
async function Init_Datenpunkte() {
|
||||
if (existsState(dp_alias + '.AlarmTime.ACTUAL') == false) {
|
||||
await createStateAsync(dp_userdata + '.AlarmTime.Time', '0', { type: 'number' });
|
||||
await createStateAsync(dp_userdata + '.AlarmTime.State', 'paused', { type: 'string' });
|
||||
setObject(dp_alias + '.AlarmTime', { type: 'channel', common: { role: 'value.alarmtime', name: 'Alarmtime' }, native: {} });
|
||||
await createAliasAsync(dp_alias + '.AlarmTime.ACTUAL', dp_userdata + '.AlarmTime.Time', true, <iobJS.StateCommon>{ type: 'number', role: 'state', name: 'ACTUAL' });
|
||||
await createAliasAsync(dp_alias + '.AlarmTime.STATE', dp_userdata + '.AlarmTime.State', true, <iobJS.StateCommon>{ type: 'string', role: 'state', name: 'STATE' });
|
||||
log("<PageItem>{id: '"+ dp_alias + ".AlarmTime', name: 'Wecker', onColor: Red, offColor: Green, useColor: true}", 'info');
|
||||
}
|
||||
}
|
||||
Init_Datenpunkte();
|
||||
50
ioBroker/Blockly/CardChart_History.js
Normal file
50
ioBroker/Blockly/CardChart_History.js
Normal file
@@ -0,0 +1,50 @@
|
||||
var sourceDP = 'alias.0.Wohnzimmer.Heizung.ACTUAL';
|
||||
var targetDP = '0_userdata.0.Test.chartTest';
|
||||
var rangeHours = 24;
|
||||
var maxXAchsisTicks = 6;
|
||||
var historyInstance = 'history.0';
|
||||
|
||||
on({id: sourceDP, change: "any"}, async function (obj) {
|
||||
sendTo(historyInstance, 'getHistory', {
|
||||
id: sourceDP,
|
||||
options: {
|
||||
start: Date.now() - (60 * 60 * 1000 * rangeHours),
|
||||
end: Date.now(),
|
||||
count: rangeHours,
|
||||
limit: rangeHours,
|
||||
aggregate: 'average'
|
||||
}
|
||||
}, function (result) {
|
||||
var cardChartString = "";
|
||||
var stepXAchsis = rangeHours / maxXAchsisTicks;
|
||||
|
||||
for (var i = 0; i < rangeHours; i++){
|
||||
var deltaHour = rangeHours - i;
|
||||
var targetDate = new Date(Date.now() - (deltaHour * 60 * 60 * 1000));
|
||||
|
||||
//Check history items for requested hours
|
||||
for (var j = 0, targetValue = 0; j < result.result.length; j++) {
|
||||
var valueDate = new Date(result.result[j].ts);
|
||||
var value = (Math.round(result.result[j].val * 10) / 10);
|
||||
|
||||
if (valueDate > targetDate){
|
||||
if ((targetDate.getHours() % stepXAchsis) == 0){
|
||||
cardChartString += targetValue + '^' + targetDate.getHours() + ':00' + '~';
|
||||
} else {
|
||||
cardChartString += targetValue + '~';
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
targetValue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cardChartString = cardChartString.substring(0,cardChartString.length-1);
|
||||
if (existsState(targetDP) == false ) {
|
||||
createState(targetDP, cardChartString, true, { type: 'string' });
|
||||
} else {
|
||||
setState(targetDP, cardChartString, true);
|
||||
}
|
||||
});
|
||||
});
|
||||
78
ioBroker/Blockly/CardLChart_History.js
Normal file
78
ioBroker/Blockly/CardLChart_History.js
Normal file
@@ -0,0 +1,78 @@
|
||||
const sourceDP = 'alias.0.Wohnzimmer.Heizung.ACTUAL';
|
||||
const targetDP = '0_userdata.0.Test.chartTest';
|
||||
const numberOfHoursAgo = 24; // Period of time in hours which shall be visualized
|
||||
const xAxisTicksEveryM = 60; // Time after x axis gets a tick in minutes
|
||||
const xAxisLabelEveryM = 240; // Time after x axis is labeled in minutes
|
||||
const historyInstance = 'history.0';
|
||||
|
||||
const Debug = false;
|
||||
const maxX = 1420;
|
||||
const limitMeasurements = 35;
|
||||
|
||||
createState(targetDP, "", {
|
||||
name: 'SensorGrid',
|
||||
desc: 'Sensor Values [~<time>:<value>]*',
|
||||
type: 'string',
|
||||
role: 'value',
|
||||
});
|
||||
|
||||
on({id: sourceDP, change: "any"}, async function (obj) {
|
||||
sendTo(historyInstance, 'getHistory', {
|
||||
id: sourceDP,
|
||||
options: {
|
||||
start: Date.now() - (numberOfHoursAgo * 60 * 60 * 1000 ), //Time in ms: hours * 60m * 60s * 1000ms
|
||||
end: Date.now(),
|
||||
count: limitMeasurements,
|
||||
limit: limitMeasurements,
|
||||
aggregate: 'average'
|
||||
}
|
||||
}, function (result) {
|
||||
var ticksAndLabels = ""
|
||||
var coordinates = "";
|
||||
var cardLChartString = "";
|
||||
|
||||
let ticksAndLabelsList = []
|
||||
var date = new Date();
|
||||
date.setMinutes(0, 0, 0);
|
||||
var ts = Math.round(date.getTime() / 1000);
|
||||
var tsYesterday = ts - (numberOfHoursAgo * 3600);
|
||||
|
||||
for (var x = tsYesterday, i = 0; x < ts; x += (xAxisTicksEveryM * 60), i += xAxisTicksEveryM)
|
||||
{
|
||||
if (i % xAxisLabelEveryM)
|
||||
{
|
||||
ticksAndLabelsList.push(i);
|
||||
} else
|
||||
{
|
||||
var currentDate = new Date(x * 1000);
|
||||
// Hours part from the timestamp
|
||||
var hours = "0" + currentDate.getHours();
|
||||
// Minutes part from the timestamp
|
||||
var minutes = "0" + currentDate.getMinutes();
|
||||
// Seconds part from the timestamp
|
||||
var seconds = "0" + currentDate.getSeconds();
|
||||
var formattedTime = hours.slice(-2) + ':' + minutes.slice(-2);
|
||||
ticksAndLabelsList.push(String(i) + "^" + formattedTime);
|
||||
}
|
||||
}
|
||||
ticksAndLabels = ticksAndLabelsList.join("+");
|
||||
|
||||
let list = [];
|
||||
let offSetTime = Math.round(result.result[0].ts / 1000);
|
||||
let counter = Math.round((result.result[result.result.length -1 ].ts / 1000 - offSetTime) / maxX);
|
||||
for (var i = 0; i < result.result.length; i++)
|
||||
{
|
||||
var time = Math.round(((result.result[i].ts / 1000) - offSetTime) / counter);
|
||||
var value = Math.round(result.result[i].val * 10);
|
||||
if ((value != null) && (value != 0)){
|
||||
list.push(time + ":" + value)
|
||||
}
|
||||
}
|
||||
|
||||
coordinates = list.join("~");
|
||||
cardLChartString = ticksAndLabels + '~' + coordinates
|
||||
setState(targetDP, cardLChartString, true);
|
||||
|
||||
if (Debug) console.log(cardLChartString);
|
||||
});
|
||||
});
|
||||
130
ioBroker/Blockly/CardLChart_Influx2.ts
Normal file
130
ioBroker/Blockly/CardLChart_Influx2.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Dieses Script fragt eine influxDb ab, um Daten für die cardLcart (Liniendiagramm) zuberechnen und im richtigen Format bereitzustellen.
|
||||
* Es erstellt automatisch einen Datenpunkt.
|
||||
* Die Abfrage muss ggf. angepasst werden. Aktuell ermittelt sie Werte der letzten 24h, zu Stundenwerten zusammengefasst.
|
||||
*/
|
||||
|
||||
const Debug = false; // true für erweiterte Ausgaben im Log
|
||||
|
||||
const NSPanel_Path = '0_userdata.0.NSPanel.';
|
||||
const Path = NSPanel_Path + 'Influx2NSPanel.cardLChart.';
|
||||
const InfluxInstance = 'influxdb.0';
|
||||
const influxDbBucket = 'storage_short';
|
||||
const numberOfHoursAgo = 24;
|
||||
const xAxisTicksEveryM = 60;
|
||||
const xAxisLabelEveryM = 240;
|
||||
//
|
||||
|
||||
const sensors : Record<string, Record <string, string>> = {};
|
||||
/**
|
||||
* Hier werden die Sensoren festgelegt nach flogendem Schema
|
||||
*
|
||||
* sensors[‘Datenpunkt(kompletter Pfad) des Messwertes'] = {'taget': 'Name des Datenpunkt für die Chartwerte', 'measurement': 'genutzter Alias in der Influxdb für den Messwert'};
|
||||
*
|
||||
* Wenn der Wert in der Datenbank keinen Alias hat bleibt der Wert 'measurement': weg.
|
||||
* Jeder Messwert bekommt einen eigenen sensors[...] = {'target':....}
|
||||
*/
|
||||
|
||||
|
||||
sensors['netatmo-crawler.0.stationData.1.temperature'] = {'target':'AussenTemp', 'measurement':'wetter.temperatur'};
|
||||
|
||||
// ##### ab hier keine Änderungen mehr nötig #####
|
||||
|
||||
// create data source for NsPanel on script startup
|
||||
Object.keys(sensors).forEach(async id => {
|
||||
await generateDateAsync(id);
|
||||
});
|
||||
|
||||
// then listen to the sensors and update the data source states accordingly
|
||||
on({ id: Object.keys(sensors), change: 'any' }, async function (obj) {
|
||||
if (!obj.id) {
|
||||
return;
|
||||
}
|
||||
await generateDateAsync(obj.id);
|
||||
});
|
||||
|
||||
//__________________________
|
||||
// Beschreibe diese Funktion: Daten generieren
|
||||
async function generateDateAsync(sensorId: string) {
|
||||
let idMeasurement = sensors[sensorId].measurement;
|
||||
if (idMeasurement =='' ||idMeasurement == undefined) {idMeasurement = sensorId};
|
||||
const dataPointId:string = Path + sensors[sensorId].target +'.ACTUAL';
|
||||
if (Debug) log(`(f) generateDateAsync: ${sensorId} ${dataPointId} > ${idMeasurement}`);
|
||||
|
||||
const query =[
|
||||
'from(bucket: "' + influxDbBucket + '")',
|
||||
'|> range(start: -' + numberOfHoursAgo + 'h)',
|
||||
'|> filter(fn: (r) => r["_measurement"] == "' + idMeasurement + '")',
|
||||
'|> filter(fn: (r) => r["_field"] == "value")',
|
||||
'|> drop(columns: ["from", "ack", "q"])',
|
||||
'|> aggregateWindow(every: 1h, fn: last, createEmpty: false)',
|
||||
'|> map(fn: (r) => ({ r with _rtime: int(v: r._time) - int(v: r._start)}))',
|
||||
'|> yield(name: "_result")'].join('');
|
||||
|
||||
if (Debug) console.log('Query: ' + query);
|
||||
|
||||
const result : any = await sendToAsync(InfluxInstance, 'query', query);
|
||||
if (result.error) {
|
||||
console.error(result.error);
|
||||
return;
|
||||
}
|
||||
if (Debug) console.log(JSON.stringify(result));
|
||||
const numResults = result.result.length;
|
||||
let coordinates : string = '';
|
||||
for (let r = 0; r < numResults; r++)
|
||||
{
|
||||
const list : string[] = [];
|
||||
const numValues = result.result[r].length;
|
||||
|
||||
for (let i = 0; i < numValues; i++)
|
||||
{
|
||||
const time = Math.round(result.result[r][i]._rtime/1000/1000/1000/60);
|
||||
const value = Math.round(result.result[r][i]._value * 10);
|
||||
list.push(time + ":" + value);
|
||||
}
|
||||
|
||||
coordinates = list.join("~");
|
||||
if (Debug) console.log(coordinates);
|
||||
}
|
||||
|
||||
const ticksAndLabelsList : string[] = []
|
||||
const date = new Date();
|
||||
date.setMinutes(0, 0, 0);
|
||||
const ts = Math.round(date.getTime() / 1000);
|
||||
const tsYesterday = ts - (numberOfHoursAgo * 3600);
|
||||
if (Debug) console.log('Iterate from ' + tsYesterday + ' to ' + ts + ' stepsize=' + (xAxisTicksEveryM * 60));
|
||||
for (let x = tsYesterday, i = 0; x < ts; x += (xAxisTicksEveryM * 60), i += xAxisTicksEveryM)
|
||||
{
|
||||
if ((i % xAxisLabelEveryM))
|
||||
ticksAndLabelsList.push('' + i);
|
||||
else
|
||||
{
|
||||
const currentDate = new Date(x * 1000);
|
||||
// Hours part from the timestamp
|
||||
const hours = "0" + String(currentDate.getHours());
|
||||
// Minutes part from the timestamp
|
||||
const minutes = "0" + String(currentDate.getMinutes());
|
||||
const formattedTime = hours.slice(-2) + ':' + minutes.slice(-2);
|
||||
|
||||
ticksAndLabelsList.push(String(i) + "^" + formattedTime);
|
||||
}
|
||||
}
|
||||
if (Debug) console.log('Ticks & Label: ' + ticksAndLabelsList);
|
||||
if (Debug) console.log('Coordinates: ' + coordinates);
|
||||
await setOrCreate(dataPointId, ticksAndLabelsList.join("+") + '~' + coordinates, true);
|
||||
}
|
||||
|
||||
//__________________________
|
||||
// Beschreibe diese Funktion: Datenpunkte anlegen bzw. schreiben
|
||||
async function setOrCreate(id : string, value : any, ack : boolean) {
|
||||
if (!(await existsStateAsync(id))) {
|
||||
await createStateAsync(id, value, {
|
||||
name: id.split('.').reverse()[0],
|
||||
desc: 'Sensor Values [~<time>:<value>]*',
|
||||
type: 'string',
|
||||
role: 'value',
|
||||
});
|
||||
} else {
|
||||
await setStateAsync(id, value, ack);
|
||||
}
|
||||
}
|
||||
54
ioBroker/Blockly/CardPower.js
Normal file
54
ioBroker/Blockly/CardPower.js
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* generate an JSON for display Power-Card on NSPanel
|
||||
* Source: https://github.com/joBr99/nspanel-lovelace-ui/wiki/ioBroker-Card-Definitionen-(Seiten)#cardpower-ab-ts-script-v341
|
||||
* Version: 0.1 - L4rs
|
||||
*/
|
||||
schedule("* * * * *", function () {
|
||||
|
||||
// Definition der Datenpunkte für das JSON der POWER-Card und der anzuzeigenden Leistungswerte
|
||||
var powerCardJson = "0_userdata.0.NSPanel.Energie.PowerCard",
|
||||
pwr1 = "", // Batterie
|
||||
pwr2 = Math.round(getState("mqtt.0.SmartHome.Energie.PV.openDTU.114180710360.0.power").val), // Solar
|
||||
pwr3 = "", // Wind
|
||||
pwr4 = "", // Verbraucher
|
||||
pwr5 = Math.round(getState("hm-rpc.0.MEQ0706303.1.POWER").val), // Stromnetz
|
||||
pwr6 = 0, // Auto
|
||||
pwrHome = Math.round(pwr5 - pwr2); // Berechnung des Energiefluss anstelle eines Datenpunktes
|
||||
|
||||
// Definition der Keys im JSON
|
||||
var keys = ["id", "value", "unit", "icon", "iconColor", "speed"];
|
||||
|
||||
// Definition der "Kacheln", inkl. StandardIcon. Es können alle Icon aus dem Iconmapping genutzt werden.
|
||||
// Kacheln die nicht genutzt werden sollen, müssen wie z.b. item1 formatiert sein
|
||||
var home = [0, pwrHome, "W", "home-lightning-bolt-outline", 0]; // Icon home
|
||||
var item1 = [1, pwr1, "", "", 0, ""]; // Icon battery-charging-60
|
||||
var item2 = [2, pwr2, "W", "solar-power-variant-outline", 3, pwr2 > 0 ? -2 : 0]; // Icon solar-power-variant
|
||||
var item3 = [3, pwr3, "", "", 0, ""]; // Icon wind-turbine
|
||||
var item4 = [4, pwr4, "", "", 0, ""]; // Icon shape
|
||||
var item5 = [5, pwr5, "W", "transmission-tower", 10, 10]; // Icon transmission-tower
|
||||
var item6 = [6, pwr6, "kW", "car-electric-outline", 5, 0]; // Icon car
|
||||
|
||||
/**
|
||||
* JSON generieren und in den Datenpunkt schreiben,
|
||||
*
|
||||
* --- ab hier keine Änderungen mehr ---
|
||||
*/
|
||||
function func(tags, values) {
|
||||
return Object.assign(
|
||||
...tags.map((element, index) => ({ [element]: values[index] }))
|
||||
);
|
||||
}
|
||||
|
||||
setState(
|
||||
powerCardJson,
|
||||
JSON.stringify([
|
||||
func(keys, home),
|
||||
func(keys, item1),
|
||||
func(keys, item2),
|
||||
func(keys, item3),
|
||||
func(keys, item4),
|
||||
func(keys, item5),
|
||||
func(keys, item6),
|
||||
])
|
||||
);
|
||||
});
|
||||
46
ioBroker/Blockly/Countdown_Timer.ts
Normal file
46
ioBroker/Blockly/Countdown_Timer.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
const dp_userdata: string = '0_userdata.0.NSPanel';
|
||||
const dp_alias: string = 'alias.0.NSPanel';
|
||||
|
||||
// Der nachfolgende Datenpunkt muss manuell angelegt werden
|
||||
const dpAction: string = '0_userdata.0.example_boolean'; // anpassen
|
||||
|
||||
const Debug = false;
|
||||
|
||||
let intervallCounter: any;
|
||||
|
||||
let sec_timer = getState(dp_userdata + '.Countdown.Time').val;
|
||||
on({ id: dp_userdata + '.Countdown.State', change: 'ne' }, async (obj) => {
|
||||
|
||||
switch (obj.state.val) {
|
||||
case 'active':
|
||||
if (intervallCounter) { clearInterval(intervallCounter); intervallCounter = null; };
|
||||
intervallCounter = setInterval(async () => {
|
||||
if (getState(dp_userdata + '.Countdown.Time').val > 0) {
|
||||
sec_timer = getState(dp_userdata + '.Countdown.Time').val;
|
||||
setState(dp_userdata + '.Countdown.Time', (sec_timer - 1), false);
|
||||
} else {
|
||||
setState(dp_userdata + '.Countdown.Time', 0, false);
|
||||
setState(dp_userdata + '.Countdown.State', 'idle', false);
|
||||
// An dieser Stelle kann auch noch eine Meldung an Alexa oder Telegram, etc. erfolgen
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
break;
|
||||
default:
|
||||
if (intervallCounter) { clearInterval(intervallCounter); intervallCounter = null; };
|
||||
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
async function Init_Datenpunkte() {
|
||||
if (existsState(dp_alias + '.Countdown.ACTUAL') == false) {
|
||||
await createStateAsync(dp_userdata + '.Countdown.Time', '0', { type: 'number'});
|
||||
await createStateAsync(dp_userdata + '.Countdown.State', 'paused', { type: 'string' });
|
||||
setObject(dp_alias + '.Countdown', { type: 'channel', common: { role: 'level.timer', name: 'Countdown' }, native: {} });
|
||||
await createAliasAsync(dp_alias + '.Countdown.ACTUAL', dp_userdata + '.Countdown.Time', true, <iobJS.StateCommon>{ type: 'number', role: 'state', name: 'ACTUAL' });
|
||||
await createAliasAsync(dp_alias + '.Countdown.STATE', dp_userdata + '.Countdown.State', true, <iobJS.StateCommon>{ type: 'string', role: 'state', name: 'STATE' });
|
||||
log("<PageItem>{id: '"+ dp_alias + ".Countdown', name: 'Timer'}", 'info');
|
||||
}
|
||||
}
|
||||
Init_Datenpunkte();
|
||||
10262
ioBroker/DEV/NSPanelTs.ts
Normal file
10262
ioBroker/DEV/NSPanelTs.ts
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1047,6 +1047,14 @@
|
||||
"zh-CN":"空闲",
|
||||
"zh-TW":"暫停"
|
||||
},
|
||||
"on":{
|
||||
"en-US":"On",
|
||||
"de-DE":"Ein"
|
||||
},
|
||||
"off":{
|
||||
"en-US":"Off",
|
||||
"de-DE":"Aus"
|
||||
},
|
||||
"paused":{
|
||||
"en-US":"Paused",
|
||||
"de-DE":"pausiert",
|
||||
@@ -2489,6 +2497,14 @@
|
||||
"vi-VN":"Mật khẩu",
|
||||
"zh-CN":"密码",
|
||||
"zh-TW":"密碼"
|
||||
},
|
||||
"Wlan enabled":{
|
||||
"en-US":"Wlan enabled",
|
||||
"de-DE":"Wlan aktiviert"
|
||||
},
|
||||
"Wlan disabled":{
|
||||
"en-US":"Wlan disabled",
|
||||
"de-DE":"Wlan deaktiviert"
|
||||
}
|
||||
},
|
||||
"media":{
|
||||
@@ -2533,6 +2549,22 @@
|
||||
"zh-CN":"没有音乐可以控制",
|
||||
"zh-TW":"沒有音樂可以控制"
|
||||
},
|
||||
"on":{
|
||||
"en-US":"On",
|
||||
"de-DE":"An"
|
||||
},
|
||||
"off":{
|
||||
"en-US":"Off",
|
||||
"de-DE":"Aus"
|
||||
},
|
||||
"seek":{
|
||||
"en-US":"Seek",
|
||||
"de-DE":"Suchen"
|
||||
},
|
||||
"crossfade":{
|
||||
"en-US":"Crossfade",
|
||||
"de-DE":"Überblenden"
|
||||
},
|
||||
"speaker":{
|
||||
"en-US":"Speakerlist",
|
||||
"de-DE":"Wiedergabegeräte",
|
||||
|
||||
@@ -2693,5 +2693,13 @@
|
||||
"update_nextion_tft":{
|
||||
"en-US":"Update Nextion TFT",
|
||||
"de-DE":"Nextion TFT Update"
|
||||
},
|
||||
"update_message":{
|
||||
"en-US":"Update Notifications",
|
||||
"de-DE":"Update Mitteilungen"
|
||||
},
|
||||
"scriptname":{
|
||||
"en-US":"Script name",
|
||||
"de-DE":"Skriptname"
|
||||
}
|
||||
}
|
||||
|
||||
28
ioBroker/tsconfig.json
Normal file
28
ioBroker/tsconfig.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"compileOnSave": true,
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"strict": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitAny": false,
|
||||
"target": "ES2022",
|
||||
"typeRoots": [
|
||||
".iobroker/types",
|
||||
"node_modules/@types"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.js",
|
||||
"**/*.ts",
|
||||
"./.iobroker/types/javascript.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules/**"
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config
|
||||
name: NSPanel Lovelace UI Addon
|
||||
version: "4.7.54"
|
||||
version: "4.7.80"
|
||||
slug: nspanel-lovelace-ui
|
||||
description: NSPanel Lovelace UI Addon
|
||||
services:
|
||||
|
||||
@@ -52,6 +52,8 @@ class HAEntity(panel_cards.Entity):
|
||||
self.state = data.get("state")
|
||||
self.attributes = data.get("attributes", [])
|
||||
else:
|
||||
self.state = "not found"
|
||||
self.attributes = []
|
||||
return "~text~iid.404~X~6666~not found~"
|
||||
|
||||
# HA Entities
|
||||
@@ -188,7 +190,7 @@ class HAEntity(panel_cards.Entity):
|
||||
icon_char = value
|
||||
case 'binary_sensor':
|
||||
device_class = self.attributes.get("device_class", "")
|
||||
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}.{self.state}")
|
||||
case 'weather':
|
||||
attr = self.config.get("attribute", "temperature")
|
||||
value = str(self.attributes.get(attr, self.state))
|
||||
@@ -207,11 +209,11 @@ class HAEntity(panel_cards.Entity):
|
||||
forecast = libs.home_assistant.execute_script(
|
||||
entity_name=self.entity_id,
|
||||
domain='weather',
|
||||
service="get_forecast",
|
||||
service="get_forecasts",
|
||||
service_data={
|
||||
'type': forecast_type
|
||||
}
|
||||
).get("forecast", [])
|
||||
).get(self.entity_id,{}).get("forecast", [])
|
||||
if len(forecast) > pos:
|
||||
forcast_pos = forecast[pos]
|
||||
forcast_condition = forcast_pos.get("condition", "")
|
||||
@@ -297,21 +299,19 @@ class EntitiesCard(HACard):
|
||||
result = f"{self.title}~{self.gen_nav()}"
|
||||
for e in self.entities:
|
||||
result += e.render(cardType=self.type)
|
||||
libs.panel_cmd.entityUpd(self.panel.sendTopic, result)
|
||||
libs.panel_cmd.entityUpd(self.panel.msg_out_queue, self.panel.sendTopic, result)
|
||||
|
||||
class QRCard(HACard):
|
||||
def __init__(self, locale, config, panel):
|
||||
super().__init__(locale, config, panel)
|
||||
self.qrcode = config.get("qrCode", "https://www.youtube.com/watch?v=dQw4w9WgXcQ")
|
||||
def render(self):
|
||||
# TODO: Render QRCode as HomeAssistant Template
|
||||
#qrcode = apis.ha_api.render_template(qrcode)
|
||||
if self.qrcode.startswith("ha:"):
|
||||
self.qrcode = libs.home_assistant.get_template(self.qrcode)[3:]
|
||||
result = f"{self.title}~{self.gen_nav()}~{self.qrcode}"
|
||||
for e in self.entities:
|
||||
result += e.render()
|
||||
libs.panel_cmd.entityUpd(self.panel.sendTopic, result)
|
||||
libs.panel_cmd.entityUpd(self.panel.msg_out_queue, self.panel.sendTopic, result)
|
||||
|
||||
class PowerCard(HACard):
|
||||
def __init__(self, locale, config, panel):
|
||||
@@ -329,7 +329,7 @@ class PowerCard(HACard):
|
||||
# if isinstance(speed, str):
|
||||
# speed = apis.ha_api.render_template(speed)
|
||||
result += f"~{speed}"
|
||||
libs.panel_cmd.entityUpd(self.panel.sendTopic, result)
|
||||
libs.panel_cmd.entityUpd(self.panel.msg_out_queue, self.panel.sendTopic, result)
|
||||
|
||||
class MediaCard(HACard):
|
||||
def __init__(self, locale, config, panel):
|
||||
@@ -366,7 +366,7 @@ class MediaCard(HACard):
|
||||
for e in self.entities[1:]:
|
||||
button_str += e.render()
|
||||
result = f"{self.title}~{self.gen_nav()}~{main_entity.entity_id}~{title}~~{author}~~{volume}~{iconplaypause}~{onoffbutton}~{shuffleBtn}{media_icon}{button_str}"
|
||||
libs.panel_cmd.entityUpd(self.panel.sendTopic, result)
|
||||
libs.panel_cmd.entityUpd(self.panel.msg_out_queue, self.panel.sendTopic, result)
|
||||
|
||||
class ClimateCard(HACard):
|
||||
def __init__(self, locale, config, panel):
|
||||
@@ -375,9 +375,8 @@ class ClimateCard(HACard):
|
||||
def render(self):
|
||||
main_entity = self.entities[0]
|
||||
|
||||
#TODO: temp unit
|
||||
temp_unit = "celsius"
|
||||
if(temp_unit == "celsius"):
|
||||
temp_unit = self.panel.temp_unit
|
||||
if temp_unit == "celsius":
|
||||
temperature_unit_icon = get_icon_char("temperature-celsius")
|
||||
temperature_unit = "°C"
|
||||
|
||||
@@ -411,7 +410,12 @@ class ClimateCard(HACard):
|
||||
|
||||
min_temp = int(main_entity.attributes.get("min_temp", 0)*10)
|
||||
max_temp = int(main_entity.attributes.get("max_temp", 0)*10)
|
||||
step_temp = int(main_entity.attributes.get("target_temp_step", 0.5)*10)
|
||||
|
||||
if temp_unit == "celsius":
|
||||
step_default = 0.5
|
||||
else:
|
||||
step_default = 0.5
|
||||
step_temp = int(main_entity.attributes.get("target_temp_step", step_default)*10)
|
||||
icon_res_list = []
|
||||
icon_res = ""
|
||||
|
||||
@@ -460,8 +464,8 @@ class ClimateCard(HACard):
|
||||
if any(x in ["preset_modes", "swing_modes", "fan_modes"] for x in main_entity.attributes):
|
||||
detailPage = "0"
|
||||
|
||||
result = f"{self.title}~{self.gen_nav()}~{main_entity.entity_id}~{current_temp} {temperature_unit}~{dest_temp}~{state_value}~{min_temp}~{max_temp}~{step_temp}{icon_res}~{currently_translation}~{state_translation}~{action_translation}~{temperature_unit_icon}~{dest_temp2}~{detailPage}"
|
||||
libs.panel_cmd.entityUpd(self.panel.sendTopic, result)
|
||||
result = f"{self.title}~{self.gen_nav()}~iid.{main_entity.iid}~{current_temp} {temperature_unit}~{dest_temp}~{state_value}~{min_temp}~{max_temp}~{step_temp}{icon_res}~{currently_translation}~{state_translation}~{action_translation}~{temperature_unit_icon}~{dest_temp2}~{detailPage}"
|
||||
libs.panel_cmd.entityUpd(self.panel.msg_out_queue, self.panel.sendTopic, result)
|
||||
|
||||
class AlarmCard(HACard):
|
||||
def __init__(self, locale, config, panel):
|
||||
@@ -471,6 +475,8 @@ class AlarmCard(HACard):
|
||||
main_entity = self.entities[0]
|
||||
main_entity.render()
|
||||
|
||||
print(main_entity.state)
|
||||
|
||||
icon = get_icon_char("shield-off")
|
||||
color = rgb_dec565([255,255,255])
|
||||
supported_modes = []
|
||||
@@ -531,7 +537,7 @@ class AlarmCard(HACard):
|
||||
if len(supported_modes) < 4:
|
||||
arm_buttons += "~"*((4-len(supported_modes))*2)
|
||||
result = f"{self.title}~{self.gen_nav()}~{main_entity.entity_id}{arm_buttons}~{icon}~{color}~{numpad}~{flashing}~{add_btn}"
|
||||
libs.panel_cmd.entityUpd(self.panel.sendTopic, result)
|
||||
libs.panel_cmd.entityUpd(self.panel.msg_out_queue, self.panel.sendTopic, result)
|
||||
|
||||
|
||||
class UnlockCard(HACard):
|
||||
@@ -544,7 +550,7 @@ class UnlockCard(HACard):
|
||||
icon = get_icon_char("lock")
|
||||
supported_modes = ["cardUnlock-unlock"]
|
||||
|
||||
entity_id = self.config.get("entity")
|
||||
entity_id = self.config.get("destination")
|
||||
|
||||
# add padding to arm buttons
|
||||
arm_buttons = ""
|
||||
@@ -555,7 +561,7 @@ class UnlockCard(HACard):
|
||||
numpad = "enable"
|
||||
|
||||
result = f"{self.title}~{self.gen_nav()}~{entity_id}{arm_buttons}~{icon}~{color}~{numpad}~disable~"
|
||||
libs.panel_cmd.entityUpd(self.panel.sendTopic, result)
|
||||
libs.panel_cmd.entityUpd(self.panel.msg_out_queue, self.panel.sendTopic, result)
|
||||
|
||||
class Screensaver(HACard):
|
||||
def __init__(self, locale, config, panel):
|
||||
@@ -583,7 +589,7 @@ class Screensaver(HACard):
|
||||
result = ""
|
||||
for e in self.entities:
|
||||
result += e.render(cardType=self.type)
|
||||
libs.panel_cmd.weatherUpdate(self.panel.sendTopic, result[1:])
|
||||
libs.panel_cmd.weatherUpdate(self.panel.msg_out_queue, self.panel.sendTopic, result[1:])
|
||||
|
||||
statusUpdateResult = ""
|
||||
icon1font = ""
|
||||
@@ -601,7 +607,7 @@ class Screensaver(HACard):
|
||||
else:
|
||||
statusUpdateResult += "~~"
|
||||
|
||||
libs.panel_cmd.statusUpdate(self.panel.sendTopic, f"{statusUpdateResult}~{icon1font}~{icon2font}")
|
||||
libs.panel_cmd.statusUpdate(self.panel.msg_out_queue, self.panel.sendTopic, f"{statusUpdateResult}~{icon1font}~{icon2font}")
|
||||
|
||||
|
||||
def card_factory(locale, settings, panel):
|
||||
@@ -625,7 +631,7 @@ def card_factory(locale, settings, panel):
|
||||
return "NotImplemented", None
|
||||
return card.iid, card
|
||||
|
||||
def detail_open(locale, detail_type, ha_entity_id, entity_id, sendTopic=None):
|
||||
def detail_open(locale, detail_type, ha_entity_id, entity_id, msg_out_queue, sendTopic=None, options_list=None):
|
||||
data = libs.home_assistant.get_entity_data(ha_entity_id)
|
||||
if data:
|
||||
state = data.get("state")
|
||||
@@ -762,9 +768,51 @@ def detail_open(locale, detail_type, ha_entity_id, entity_id, sendTopic=None):
|
||||
|
||||
return f'{entity_id}~~{icon_color}~{switch_val}~{speed}~{speedMax}~{speed_translation}~{preset_mode}~{preset_modes}'
|
||||
case 'popupThermo' | 'climate':
|
||||
print(f"not implemented {detail_type}")
|
||||
case 'popupInSel' | 'input_select' | 'select':
|
||||
print(f"not implemented {detail_type}")
|
||||
icon_id = ha_icons.get_icon_ha("climate", state)
|
||||
icon_color = ha_colors.get_entity_color("climate", state, attributes)
|
||||
|
||||
modes_out = ""
|
||||
for mode in ["preset_modes", "swing_modes", "fan_modes"]:
|
||||
heading = get_translation(locale, f"frontend.ui.card.climate.{mode[:-1]}")
|
||||
cur_mode = attributes.get(mode[:-1], "")
|
||||
modes = attributes.get(mode, [])
|
||||
if modes is not None:
|
||||
if mode == "preset_modes":
|
||||
translated_modes = []
|
||||
for elem in modes:
|
||||
translated_modes.append(get_translation(locale, f"frontend.state_attributes.climate.preset_mode.{elem}"))
|
||||
cur_mode = get_translation(locale, f"frontend.state_attributes.climate.preset_mode.{cur_mode}")
|
||||
modes_res = "?".join(translated_modes)
|
||||
else:
|
||||
modes_res = "?".join(modes)
|
||||
if modes:
|
||||
modes_out += f"{heading}~{mode}~{cur_mode}~{modes_res}~"
|
||||
|
||||
return f"{entity_id}~{icon_id}~{icon_color}~{modes_out}"
|
||||
|
||||
|
||||
|
||||
case 'popupInSel' | 'input_select' | 'select' | 'media_player':
|
||||
hatype = ha_entity_id.split(".")[0]
|
||||
options = []
|
||||
icon_color = 0
|
||||
icon_color = ha_colors.get_entity_color(detail_type, state, attributes)
|
||||
state = state
|
||||
if hatype in ["input_select", "select"]:
|
||||
options = attributes.get("options", [])
|
||||
elif hatype == "light":
|
||||
if options_list is not None:
|
||||
options = options_list
|
||||
else:
|
||||
options = attributes.get("effect_list", [])[:15]
|
||||
state = attributes.get("effect")
|
||||
elif hatype == "media_player":
|
||||
state = attributes.get("source", "")
|
||||
options = attributes.get("source_list", [])
|
||||
options = "?".join(options)
|
||||
return f"{entity_id}~~{icon_color}~{hatype}~{state}~{options}~"
|
||||
|
||||
|
||||
case 'popupTimer' | 'timer':
|
||||
icon_color = ha_colors.get_entity_color("timer", state, attributes)
|
||||
if state in ["idle", "paused"]:
|
||||
@@ -787,8 +835,8 @@ def detail_open(locale, detail_type, ha_entity_id, entity_id, sendTopic=None):
|
||||
#update timer in a second
|
||||
def update_time():
|
||||
time.sleep(1)
|
||||
out = detail_open(locale, detail_type, ha_entity_id, entity_id, sendTopic=sendTopic)
|
||||
libs.panel_cmd.entityUpdateDetail(sendTopic, out)
|
||||
out = detail_open(locale, detail_type, ha_entity_id, entity_id, msg_out_queue, sendTopic=sendTopic)
|
||||
libs.panel_cmd.entityUpdateDetail(msg_out_queue, sendTopic, out)
|
||||
tt = threading.Thread(target=update_time, args=())
|
||||
tt.daemon = True
|
||||
tt.start()
|
||||
|
||||
@@ -8,6 +8,7 @@ def wait_for_ha_cache():
|
||||
while time.time() < mustend:
|
||||
if len(libs.home_assistant.home_assistant_entity_state_cache) == 0:
|
||||
time.sleep(0.1)
|
||||
time.sleep(1)
|
||||
|
||||
def calculate_dim_values(sleepTracking, sleepTrackingZones, sleepBrightness, screenBrightness, sleepOverride, return_involved_entities=False):
|
||||
dimmode = 10
|
||||
@@ -17,17 +18,34 @@ def calculate_dim_values(sleepTracking, sleepTrackingZones, sleepBrightness, scr
|
||||
if sleepBrightness:
|
||||
if isinstance(sleepBrightness, int):
|
||||
dimmode = sleepBrightness
|
||||
elif isinstance(sleepBrightness, list):
|
||||
logging.error("list style config for sleepBrightness no longer supported")
|
||||
#elif sleepBrightness.startswith("ha:"):
|
||||
# time.sleep(1)
|
||||
# dimmode = int(float(libs.home_assistant.get_template(sleepBrightness)[3:]))
|
||||
# involved_entities.extend(libs.home_assistant.get_template_listener_entities(sleepBrightness))
|
||||
elif libs.home_assistant.is_existent(sleepBrightness):
|
||||
involved_entities.append(sleepBrightness)
|
||||
try:
|
||||
dimmode = int(float(libs.home_assistant.get_entity_data(sleepBrightness).get('state', 10)))
|
||||
except ValueError:
|
||||
print("sleepBrightness entity invalid")
|
||||
|
||||
if screenBrightness:
|
||||
if isinstance(screenBrightness, int):
|
||||
dimValueNormal = screenBrightness
|
||||
elif isinstance(screenBrightness, list):
|
||||
logging.error("list style config for screenBrightness no longer supported")
|
||||
#elif screenBrightness.startswith("ha:"):
|
||||
# time.sleep(1)
|
||||
# dimValueNormal = int(float(libs.home_assistant.get_template(screenBrightness)[3:]))
|
||||
# involved_entities.extend(libs.home_assistant.get_template_listener_entities(screenBrightness))
|
||||
elif libs.home_assistant.is_existent(screenBrightness):
|
||||
involved_entities.append(screenBrightness)
|
||||
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
|
||||
if sleepTracking:
|
||||
if libs.home_assistant.is_existent(sleepTracking):
|
||||
@@ -51,7 +69,7 @@ def calculate_dim_values(sleepTracking, sleepTrackingZones, sleepBrightness, scr
|
||||
else:
|
||||
return dimmode, dimValueNormal
|
||||
|
||||
def handle_buttons(entity_id, btype, value):
|
||||
def handle_buttons(entity_id, btype, value, entity_config=None):
|
||||
match btype:
|
||||
case 'button':
|
||||
button_press(entity_id, value)
|
||||
@@ -60,7 +78,7 @@ def handle_buttons(entity_id, btype, value):
|
||||
case 'number-set':
|
||||
if entity_id.startswith('fan'):
|
||||
attr = libs.home_assistant.get_entity_data(entity_id).get('attributes', [])
|
||||
value = float(value) * float(attr.get(percentage_step, 0))
|
||||
value = float(value) * float(attr.get('percentage_step', 0))
|
||||
service_data = {
|
||||
"value": int(value)
|
||||
}
|
||||
@@ -156,19 +174,20 @@ def handle_buttons(entity_id, btype, value):
|
||||
}
|
||||
call_ha_service(entity_id, f"alarm_{btype}", service_data=service_data)
|
||||
case 'mode-preset_modes' | 'mode-swing_modes' | 'mode-fan_modes':
|
||||
attr = libs.home_assistant.get_entity_data(entity_id).get('attributes', [])
|
||||
mapping = {
|
||||
'mode-preset_modes': 'preset_modes',
|
||||
'mode-swing_modes': 'swing_modes',
|
||||
'mode-fan_modes': 'fan_mode'
|
||||
'mode-fan_modes': 'fan_modes'
|
||||
}
|
||||
if btype in mapping:
|
||||
modes = libs.home_assistant.get_entity_data(entity_id).get('attributes', []).get(mapping[btype], [])
|
||||
modes = attr.get(mapping[btype], [])
|
||||
if modes:
|
||||
mode = modes[int(value)]
|
||||
service_data = {
|
||||
mapping[btype]: mode
|
||||
mapping[btype][:-1]: mode
|
||||
}
|
||||
call_ha_service(entity_id, f"set_{mapping[btype]}", service_data=service_data)
|
||||
call_ha_service(entity_id, f"set_{mapping[btype][:-1]}", service_data=service_data)
|
||||
case 'mode-input_select' | 'mode-select':
|
||||
options = libs.home_assistant.get_entity_data(entity_id).get('attributes', []).get("options", [])
|
||||
if options:
|
||||
@@ -186,7 +205,7 @@ def handle_buttons(entity_id, btype, value):
|
||||
}
|
||||
call_ha_service(entity_id, "select_source", service_data=service_data)
|
||||
case 'mode-light':
|
||||
options = libs.home_assistant.get_entity_data(entity_id).get('attributes', []).get("effect_list", [])
|
||||
options = entity_config.get("effectList", libs.home_assistant.get_entity_data(entity_id).get('attributes', []).get("effect_list", []))
|
||||
if options:
|
||||
option = options[int(value)]
|
||||
service_data = {
|
||||
@@ -216,30 +235,6 @@ def handle_buttons(entity_id, btype, value):
|
||||
case _:
|
||||
logging.error("Not implemented: %s", btype)
|
||||
|
||||
|
||||
# # for cardUnlock
|
||||
# if button_type == "cardUnlock-unlock":
|
||||
# curCard = self._config.get_card_by_uuid(
|
||||
# entity_id.replace('navigate.', ''))
|
||||
# if curCard is not None:
|
||||
# if int(curCard.raw_config.get("pin")) == int(value):
|
||||
# dstCard = self._config.search_card(
|
||||
# curCard.raw_config.get("destination"))
|
||||
# if dstCard is not None:
|
||||
# if dstCard.hidden:
|
||||
# self._previous_cards.append(self._current_card)
|
||||
# self._current_card = dstCard
|
||||
# self._pages_gen.render_card(self._current_card)
|
||||
|
||||
# if button_type == "opnSensorNotify":
|
||||
# msg = ""
|
||||
# entity = apis.ha_api.get_entity(entity_id)
|
||||
# if "open_sensors" in entity.attributes and entity.attributes.open_sensors is not None:
|
||||
# for e in entity.attributes.open_sensors:
|
||||
# msg += f"- {apis.ha_api.get_entity(e).attributes.friendly_name}\r\n"
|
||||
# self._pages_gen.send_message_page(
|
||||
# "opnSensorNotifyRes", "", msg, "", "")
|
||||
|
||||
def call_ha_service(entity_id, service, service_data = {}):
|
||||
etype = entity_id.split(".")[0]
|
||||
libs.home_assistant.call_service(
|
||||
|
||||
@@ -70,7 +70,8 @@ def on_message(ws, message):
|
||||
for template, template_cache_entry in template_cache.items():
|
||||
if entity_id in template_cache_entry.get("listener-entities", []):
|
||||
cache_template(template)
|
||||
|
||||
elif json_msg["type"] == "event" and json_msg["event"]["event_type"] == "esphome.nspanel.data":
|
||||
nspanel_data_callback(json_msg["event"]["data"]["device_id"], json_msg["event"]["data"]["CustomRecv"])
|
||||
elif json_msg["type"] == "result" and not json_msg["success"]:
|
||||
logging.error("Failed result: ")
|
||||
logging.error(json_msg)
|
||||
@@ -143,6 +144,15 @@ def subscribe_to_events():
|
||||
}
|
||||
send_message(json.dumps(msg))
|
||||
|
||||
def subscribe_to_nspanel_events(nsp_callback):
|
||||
global next_id, nspanel_data_callback
|
||||
nspanel_data_callback = nsp_callback
|
||||
msg = {
|
||||
"id": next_id,
|
||||
"type": "subscribe_events",
|
||||
"event_type": "esphome.nspanel.data"
|
||||
}
|
||||
send_message(json.dumps(msg))
|
||||
|
||||
def _get_all_states():
|
||||
global next_id, request_all_states_id
|
||||
@@ -158,6 +168,10 @@ def send_entity_update(entity_id):
|
||||
global on_ha_update
|
||||
on_ha_update(entity_id)
|
||||
|
||||
def nspanel_data_callback(device_id, msg):
|
||||
global nspanel_data_callback
|
||||
nspanel_data_callback(device_id, msg)
|
||||
|
||||
def call_service(entity_name: str, domain: str, service: str, service_data: dict) -> bool:
|
||||
global next_id
|
||||
try:
|
||||
@@ -177,6 +191,22 @@ def call_service(entity_name: str, domain: str, service: str, service_data: dict
|
||||
logging.exception("Failed to call Home Assisatant service.")
|
||||
return False
|
||||
|
||||
def send_msg_to_panel(service: str, service_data: dict) -> bool:
|
||||
global next_id
|
||||
try:
|
||||
msg = {
|
||||
"id": next_id,
|
||||
"type": "call_service",
|
||||
"domain": "esphome",
|
||||
"service": service,
|
||||
"service_data": service_data,
|
||||
}
|
||||
send_message(json.dumps(msg))
|
||||
return True
|
||||
except Exception as e:
|
||||
logging.exception("Failed to call Home Assisatant service.")
|
||||
return False
|
||||
|
||||
def execute_script(entity_name: str, domain: str, service: str, service_data: dict) -> str:
|
||||
global next_id, response_buffer
|
||||
try:
|
||||
@@ -202,7 +232,7 @@ def execute_script(entity_name: str, domain: str, service: str, service_data: di
|
||||
]
|
||||
}
|
||||
send_message(json.dumps(msg))
|
||||
# busy waiting for response with a timeout of 0.2 seconds - maybe there's a better way of doing this
|
||||
# busy waiting for response with a timeout of 0.4 seconds- maybe there's a better way of doing this
|
||||
mustend = time.time() + 0.4
|
||||
while time.time() < mustend:
|
||||
if response_buffer[call_id] == True:
|
||||
@@ -216,6 +246,8 @@ def execute_script(entity_name: str, domain: str, service: str, service_data: di
|
||||
return {}
|
||||
|
||||
def cache_template(template):
|
||||
if not template:
|
||||
raise Exception("Invalid template")
|
||||
global next_id, response_buffer
|
||||
try:
|
||||
call_id = next_id
|
||||
@@ -243,6 +275,18 @@ def get_template(template):
|
||||
else:
|
||||
return template_cache.get(template, []).get("result", "404")
|
||||
|
||||
def get_template_listener_entities(template):
|
||||
global template_cache
|
||||
if template in template_cache:
|
||||
return template_cache[template].get("listener-entities")
|
||||
else:
|
||||
mustend = time.time() + 0.5
|
||||
while time.time() < mustend:
|
||||
if template not in template_cache:
|
||||
time.sleep(0.0001)
|
||||
else:
|
||||
return template_cache.get(template, []).get("listener-entities", "404")
|
||||
|
||||
def get_entity_data(entity_id: str):
|
||||
if entity_id in home_assistant_entity_state_cache:
|
||||
return home_assistant_entity_state_cache[entity_id]
|
||||
|
||||
@@ -1,46 +1,47 @@
|
||||
import logging
|
||||
|
||||
def init(mqtt_client_from_manager):
|
||||
global mqtt_client
|
||||
mqtt_client = mqtt_client_from_manager
|
||||
|
||||
|
||||
def custom_send(topic, msg):
|
||||
global mqtt_client
|
||||
mqtt_client.publish(topic, msg)
|
||||
def custom_send(msg_out_queue, topic, msg):
|
||||
msg_out_queue.put((topic, msg))
|
||||
logging.debug("Sent Message to NsPanel (%s): %s", topic, msg)
|
||||
|
||||
|
||||
def page_type(topic, target_page):
|
||||
def page_type(msg_out_queue, topic, target_page):
|
||||
if target_page == "cardUnlock":
|
||||
target_page = "cardAlarm"
|
||||
custom_send(topic, f"pageType~{target_page}")
|
||||
custom_send(msg_out_queue, topic, f"pageType~{target_page}")
|
||||
|
||||
|
||||
def send_time(topic, time, addTimeText=""):
|
||||
custom_send(topic, f"time~{time}~{addTimeText}")
|
||||
def send_time(msg_out_queue, topic, time, addTimeText=""):
|
||||
custom_send(msg_out_queue, topic, f"time~{time}~{addTimeText}")
|
||||
|
||||
|
||||
def send_date(topic, date):
|
||||
custom_send(topic, f"date~{date}")
|
||||
def send_date(msg_out_queue, topic, date):
|
||||
custom_send(msg_out_queue, topic, f"date~{date}")
|
||||
|
||||
|
||||
def entityUpd(topic, data):
|
||||
custom_send(topic, f"entityUpd~{data}")
|
||||
def entityUpd(msg_out_queue, topic, data):
|
||||
custom_send(msg_out_queue, topic, f"entityUpd~{data}")
|
||||
|
||||
def weatherUpdate(topic, data):
|
||||
custom_send(topic, f"weatherUpdate~{data}")
|
||||
def weatherUpdate(msg_out_queue, topic, data):
|
||||
custom_send(msg_out_queue, topic, f"weatherUpdate~{data}")
|
||||
|
||||
def timeout(topic, timeout):
|
||||
custom_send(topic, f"timeout~{timeout}")
|
||||
def timeout(msg_out_queue, topic, timeout):
|
||||
custom_send(msg_out_queue, topic, f"timeout~{timeout}")
|
||||
|
||||
def dimmode(topic, dimValue, dimValueNormal, backgroundColor, fontColor, featExperimentalSliders):
|
||||
def dimmode(msg_out_queue, topic, dimValue, dimValueNormal, backgroundColor, fontColor, featExperimentalSliders):
|
||||
if dimValue==dimValueNormal:
|
||||
dimValue=dimValue-1
|
||||
custom_send(topic, f"dimmode~{dimValue}~{dimValueNormal}~{backgroundColor}~{fontColor}~{featExperimentalSliders}")
|
||||
custom_send(msg_out_queue, topic, f"dimmode~{dimValue}~{dimValueNormal}~{backgroundColor}~{fontColor}~{featExperimentalSliders}")
|
||||
|
||||
def entityUpdateDetail(topic, data):
|
||||
custom_send(topic, f"entityUpdateDetail~{data}")
|
||||
def entityUpdateDetail(msg_out_queue, topic, data):
|
||||
custom_send(msg_out_queue, topic, f"entityUpdateDetail~{data}")
|
||||
|
||||
def statusUpdate(topic, data):
|
||||
custom_send(topic, f"statusUpdate~{data}")
|
||||
def entityUpdateDetail2(msg_out_queue, topic, data):
|
||||
custom_send(msg_out_queue, topic, f"entityUpdateDetail2~{data}")
|
||||
|
||||
def statusUpdate(msg_out_queue, topic, data):
|
||||
custom_send(msg_out_queue, topic, f"statusUpdate~{data}")
|
||||
|
||||
def send_message_page(msg_out_queue, topic, ident, heading, msg, b1, b2):
|
||||
page_type(msg_out_queue, topic, "popupNotify")
|
||||
custom_send(msg_out_queue, topic, f"entityUpdateDetail~{ident}~{heading}~65535~{b1}~65535~{b2}~65535~{msg}~65535~0")
|
||||
@@ -1,13 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
import logging
|
||||
import paho.mqtt.client as mqtt
|
||||
import time
|
||||
import json
|
||||
import subprocess
|
||||
import libs.home_assistant
|
||||
import libs.panel_cmd
|
||||
import yaml
|
||||
from uuid import getnode as get_mac
|
||||
from panel import LovelaceUIPanel
|
||||
import os
|
||||
import threading
|
||||
@@ -16,52 +13,97 @@ from watchdog.observers import Observer
|
||||
import signal
|
||||
import sys
|
||||
from queue import Queue
|
||||
from mqtt import MqttManager
|
||||
|
||||
logging.getLogger("watchdog").propagate = False
|
||||
|
||||
settings = {}
|
||||
panels = {}
|
||||
panel_queues = {}
|
||||
panel_in_queues = {}
|
||||
panel_out_queue = Queue(maxsize=20)
|
||||
last_settings_file_mtime = 0
|
||||
mqtt_connect_time = 0
|
||||
has_sent_reload_command = False
|
||||
mqtt_client_name = "NSPanelLovelaceManager_" + str(get_mac())
|
||||
client = mqtt.Client(mqtt_client_name)
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
def on_connect(client, userdata, flags, rc):
|
||||
global settings
|
||||
logging.info("Connected to MQTT Server")
|
||||
# subscribe to panelRecvTopic of each panel
|
||||
for settings_panel in settings["nspanels"].values():
|
||||
client.subscribe(settings_panel["panelRecvTopic"])
|
||||
|
||||
def on_ha_update(entity_id):
|
||||
global panel_queues
|
||||
for queue in panel_queues.values():
|
||||
global panel_in_queues
|
||||
# send HA updates to all panels
|
||||
for queue in panel_in_queues.values():
|
||||
queue.put(("HA:", entity_id))
|
||||
|
||||
def on_message(client, userdata, msg):
|
||||
global panel_queues
|
||||
try:
|
||||
if msg.payload.decode() == "":
|
||||
return
|
||||
parts = msg.topic.split('/')
|
||||
if msg.topic in panel_queues.keys():
|
||||
data = json.loads(msg.payload.decode('utf-8'))
|
||||
if "CustomRecv" in data:
|
||||
queue = panel_queues[msg.topic]
|
||||
queue.put(("MQTT:", data["CustomRecv"]))
|
||||
else:
|
||||
logging.debug("Received unhandled message on topic: %s", msg.topic)
|
||||
def on_ha_panel_event(device_id, msg):
|
||||
global panel_in_queues
|
||||
|
||||
except Exception: # pylint: disable=broad-exception-caught
|
||||
logging.exception("Something went wrong during processing of message:")
|
||||
try:
|
||||
logging.error(msg.payload.decode('utf-8'))
|
||||
except: # pylint: disable=bare-except
|
||||
logging.error(
|
||||
"Something went wrong when processing the exception message, couldn't decode payload to utf-8.")
|
||||
if device_id in panel_in_queues.keys():
|
||||
queue = panel_in_queues[device_id]
|
||||
queue.put(("MQTT:", msg))
|
||||
|
||||
def process_output_to_panel():
|
||||
while True:
|
||||
msg = panel_out_queue.get()
|
||||
|
||||
#client.publish(msg[0], msg[1])
|
||||
#apis.ha_api.call_service(service="esphome/" + self._api_panel_name + "_nspanelui_api_call", command=2, data=msg)
|
||||
service = msg[0] + "_nspanelui_api_call"
|
||||
service_data = {
|
||||
"data": msg[1],
|
||||
"command":2
|
||||
}
|
||||
libs.home_assistant.send_msg_to_panel(
|
||||
service = service,
|
||||
service_data = service_data
|
||||
)
|
||||
|
||||
|
||||
def connect():
|
||||
global settings, panel_out_queue
|
||||
if "mqtt_server" in settings and not "use_ha_api" in settings:
|
||||
MqttManager(settings, panel_out_queue, panel_in_queues)
|
||||
else:
|
||||
logging.info("MQTT values not configured, will not connect.")
|
||||
|
||||
# MQTT Connected, start APIs if configured
|
||||
if settings["home_assistant_address"] != "" and settings["home_assistant_token"] != "":
|
||||
libs.home_assistant.init(settings, on_ha_update)
|
||||
libs.home_assistant.connect()
|
||||
else:
|
||||
logging.info("Home Assistant values not configured, will not connect.")
|
||||
|
||||
while not libs.home_assistant.ws_connected:
|
||||
time.sleep(1)
|
||||
if settings.get("use_ha_api"):
|
||||
libs.home_assistant.subscribe_to_nspanel_events(on_ha_panel_event)
|
||||
send_to_panel_thread = threading.Thread(target=process_output_to_panel, args=())
|
||||
send_to_panel_thread.daemon = True
|
||||
send_to_panel_thread.start()
|
||||
|
||||
def setup_panels():
|
||||
global settings, panel_in_queues
|
||||
# Create NsPanel object
|
||||
for name, settings_panel in settings["nspanels"].items():
|
||||
if "timeZone" not in settings_panel:
|
||||
settings_panel["timeZone"] = settings.get("timeZone", "Europe/Berlin")
|
||||
if "locale" not in settings_panel:
|
||||
settings_panel["timezone"] = settings.get("locale", "en_US")
|
||||
if "hiddenCards" not in settings_panel:
|
||||
settings_panel["hiddenCards"] = settings.get("hiddenCards", [])
|
||||
|
||||
msg_in_queue = Queue(maxsize=20)
|
||||
panel_in_queues[settings_panel["panelRecvTopic"]] = msg_in_queue
|
||||
panel_thread = threading.Thread(target=panel_thread_target, args=(msg_in_queue, name, settings_panel, panel_out_queue))
|
||||
panel_thread.daemon = True
|
||||
panel_thread.start()
|
||||
|
||||
def panel_thread_target(queue_in, name, settings_panel, queue_out):
|
||||
panel = LovelaceUIPanel(name, settings_panel, queue_out)
|
||||
while True:
|
||||
msg = queue_in.get()
|
||||
if msg[0] == "MQTT:":
|
||||
panel.customrecv_event_callback(msg[1])
|
||||
elif msg[0] == "HA:":
|
||||
panel.ha_event_callback(msg[1])
|
||||
|
||||
def get_config_file():
|
||||
CONFIG_FILE = os.getenv('CONFIG_FILE')
|
||||
@@ -109,79 +151,6 @@ def get_config(file):
|
||||
settings["is_addon"] = True
|
||||
return True
|
||||
|
||||
def connect():
|
||||
global settings, home_assistant, client
|
||||
client.on_connect = on_connect
|
||||
client.on_message = on_message
|
||||
client.username_pw_set(
|
||||
settings["mqtt_username"], settings["mqtt_password"])
|
||||
# Wait for connection
|
||||
connection_return_code = 0
|
||||
mqtt_server = settings["mqtt_server"]
|
||||
mqtt_port = int(settings["mqtt_port"])
|
||||
logging.info("Connecting to %s:%i as %s",
|
||||
mqtt_server, mqtt_port, mqtt_client_name)
|
||||
while True:
|
||||
try:
|
||||
client.connect(mqtt_server, mqtt_port, 5)
|
||||
break # Connection call did not raise exception, connection is sucessfull
|
||||
except: # pylint: disable=bare-except
|
||||
logging.exception(
|
||||
"Failed to connect to MQTT %s:%i. Will try again in 10 seconds. Code: %s", mqtt_server, mqtt_port, connection_return_code)
|
||||
time.sleep(10.)
|
||||
|
||||
# MQTT Connected, start APIs if configured
|
||||
if settings["home_assistant_address"] != "" and settings["home_assistant_token"] != "":
|
||||
libs.home_assistant.init(settings, on_ha_update)
|
||||
libs.home_assistant.connect()
|
||||
else:
|
||||
logging.info("Home Assistant values not configured, will not connect.")
|
||||
|
||||
libs.panel_cmd.init(client)
|
||||
|
||||
setup_panels()
|
||||
|
||||
def loop():
|
||||
global client
|
||||
# Loop MQTT
|
||||
client.loop_forever()
|
||||
|
||||
def setup_panels():
|
||||
global settings, panel_queues
|
||||
# Create NsPanel object
|
||||
for name, settings_panel in settings["nspanels"].items():
|
||||
if "timeZone" not in settings_panel:
|
||||
settings_panel["timeZone"] = settings.get("timeZone", "Europe/Berlin")
|
||||
if "locale" not in settings_panel:
|
||||
settings_panel["timezone"] = settings.get("locale", "en_US")
|
||||
if "hiddenCards" not in settings_panel:
|
||||
settings_panel["hiddenCards"] = settings.get("hiddenCards", [])
|
||||
|
||||
#panels[name] = LovelaceUIPanel(name, settings_panel)
|
||||
|
||||
mqtt_queue = Queue(maxsize=20)
|
||||
panel_queues[settings_panel["panelRecvTopic"]] = mqtt_queue
|
||||
panel_thread = threading.Thread(target=panel_thread_target, args=(mqtt_queue, name, settings_panel))
|
||||
panel_thread.daemon = True
|
||||
|
||||
panel_thread.start()
|
||||
|
||||
def panel_thread_target(queue, name, settings_panel):
|
||||
panel = LovelaceUIPanel(name, settings_panel)
|
||||
while True:
|
||||
msg = queue.get()
|
||||
#print(msg)
|
||||
if msg[0] == "MQTT:":
|
||||
panel.customrecv_event_callback(msg[1])
|
||||
elif msg[0] == "HA:":
|
||||
panel.ha_event_callback(msg[1])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def config_watch():
|
||||
class ConfigChangeEventHandler(FileSystemEventHandler):
|
||||
def __init__(self, base_paths):
|
||||
@@ -218,7 +187,11 @@ if __name__ == '__main__':
|
||||
threading.Thread(target=config_watch).start()
|
||||
if (get_config(get_config_file())):
|
||||
connect()
|
||||
loop()
|
||||
setup_panels()
|
||||
|
||||
# main thread sleep forever
|
||||
while True:
|
||||
time.sleep(100)
|
||||
else:
|
||||
while True:
|
||||
time.sleep(100)
|
||||
68
nspanel-lovelace-ui/rootfs/usr/bin/mqtt-manager/mqtt.py
Normal file
68
nspanel-lovelace-ui/rootfs/usr/bin/mqtt-manager/mqtt.py
Normal file
@@ -0,0 +1,68 @@
|
||||
from uuid import getnode as get_mac
|
||||
import paho.mqtt.client as mqtt
|
||||
import logging
|
||||
import time
|
||||
import json
|
||||
import threading
|
||||
|
||||
|
||||
class MqttManager:
|
||||
def __init__(self, settings, msg_in_queue, msg_out_queue_list):
|
||||
mqtt_client_name = "NSPanelLovelaceManager_" + str(get_mac())
|
||||
self.client = mqtt.Client(mqtt_client_name)
|
||||
self.msg_in_queue = msg_in_queue
|
||||
self.msg_out_queue_list = msg_out_queue_list
|
||||
self.settings = settings
|
||||
|
||||
self.client.on_connect = self.on_mqtt_connect
|
||||
self.client.on_message = self.on_mqtt_message
|
||||
self.client.username_pw_set(
|
||||
settings["mqtt_username"], settings["mqtt_password"])
|
||||
# Wait for connection
|
||||
connection_return_code = 0
|
||||
mqtt_server = settings["mqtt_server"]
|
||||
mqtt_port = int(settings["mqtt_port"])
|
||||
logging.info("Connecting to %s:%i as %s",
|
||||
mqtt_server, mqtt_port, mqtt_client_name)
|
||||
while True:
|
||||
try:
|
||||
self.client.connect(mqtt_server, mqtt_port, 5)
|
||||
break # Connection call did not raise exception, connection is sucessfull
|
||||
except: # pylint: disable=bare-except
|
||||
logging.exception(
|
||||
"Failed to connect to MQTT %s:%i. Will try again in 10 seconds. Code: %s", mqtt_server, mqtt_port, connection_return_code)
|
||||
time.sleep(10.)
|
||||
self.client.loop_start()
|
||||
process_thread = threading.Thread(target=self.process_in_queue, args=(self.client, self.msg_in_queue))
|
||||
process_thread.daemon = True
|
||||
process_thread.start()
|
||||
|
||||
def on_mqtt_connect(self, client, userdata, flags, rc):
|
||||
logging.info("Connected to MQTT Server")
|
||||
# subscribe to panelRecvTopic of each panel
|
||||
for settings_panel in self.settings["nspanels"].values():
|
||||
client.subscribe(settings_panel["panelRecvTopic"])
|
||||
|
||||
def on_mqtt_message(self, client, userdata, msg):
|
||||
try:
|
||||
if msg.payload.decode() == "":
|
||||
return
|
||||
if msg.topic in self.msg_out_queue_list.keys():
|
||||
data = json.loads(msg.payload.decode('utf-8'))
|
||||
if "CustomRecv" in data:
|
||||
queue = self.msg_out_queue_list[msg.topic]
|
||||
queue.put(("MQTT:", data["CustomRecv"]))
|
||||
else:
|
||||
logging.debug("Received unhandled message on topic: %s", msg.topic)
|
||||
except Exception: # pylint: disable=broad-exception-caught
|
||||
logging.exception("Something went wrong during processing of message:")
|
||||
try:
|
||||
logging.error(msg.payload.decode('utf-8'))
|
||||
except: # pylint: disable=bare-except
|
||||
logging.error(
|
||||
"Something went wrong when processing the exception message, couldn't decode payload to utf-8.")
|
||||
|
||||
def process_in_queue(self, client, msg_in_queue):
|
||||
while True:
|
||||
msg = msg_in_queue.get()
|
||||
client.publish(msg[0], msg[1])
|
||||
@@ -7,18 +7,20 @@ from scheduler import Scheduler
|
||||
import scheduler.trigger as trigger
|
||||
import time
|
||||
import babel.dates
|
||||
from ha_cards import Screensaver, EntitiesCard, card_factory, detail_open
|
||||
from ha_cards import Screensaver, card_factory, detail_open
|
||||
import ha_control
|
||||
|
||||
class LovelaceUIPanel:
|
||||
|
||||
def __init__(self, name_panel, settings_panel):
|
||||
def __init__(self, name_panel, settings_panel, msg_out_queue):
|
||||
self.name = name_panel
|
||||
self.settings = settings_panel
|
||||
self.msg_out_queue = msg_out_queue
|
||||
self.sendTopic = self.settings["panelSendTopic"]
|
||||
self.recvTopic = self.settings["panelRecvTopic"]
|
||||
self.model = self.settings.get("model", "eu")
|
||||
|
||||
self.temp_unit = self.settings.get("temp_unit", "celsius")
|
||||
|
||||
self.current_card = None
|
||||
self.privious_cards = []
|
||||
@@ -65,7 +67,7 @@ class LovelaceUIPanel:
|
||||
self.schedule = Scheduler()
|
||||
self.schedule.minutely(datetime.time(second=0), self.update_time)
|
||||
self.schedule.hourly(datetime.time(
|
||||
minute=0, second=0), self.update_time)
|
||||
minute=0, second=0), self.update_date)
|
||||
schedule_thread = threading.Thread(target=self.schedule_thread_target)
|
||||
schedule_thread.daemon = True
|
||||
schedule_thread.start()
|
||||
@@ -74,6 +76,10 @@ class LovelaceUIPanel:
|
||||
ha_control.wait_for_ha_cache()
|
||||
|
||||
#request templates on cards
|
||||
if isinstance(self.settings.get("sleepBrightness",""), str) and self.settings.get("sleepBrightness", "").startswith("ha:"):
|
||||
libs.home_assistant.cache_template(self.settings.get("sleepBrightness"))
|
||||
if isinstance(self.settings.get("sleepBrightness",""), str) and self.settings.get("screenBrightness", "").startswith("ha:"):
|
||||
libs.home_assistant.cache_template(self.settings.get("screenBrightness"))
|
||||
for c in self.cards.values():
|
||||
if hasattr(c, "qrcode"):
|
||||
if c.qrcode.startswith("ha:"):
|
||||
@@ -94,7 +100,7 @@ class LovelaceUIPanel:
|
||||
for e in self.screensaver.entities:
|
||||
e.prerender()
|
||||
|
||||
libs.panel_cmd.page_type(self.sendTopic, "pageStartup")
|
||||
libs.panel_cmd.page_type(self.msg_out_queue, self.sendTopic, "pageStartup")
|
||||
|
||||
|
||||
def schedule_thread_target(self):
|
||||
@@ -106,13 +112,13 @@ class LovelaceUIPanel:
|
||||
use_timezone = tz.gettz(self.settings["timeZone"])
|
||||
time_string = datetime.datetime.now(
|
||||
use_timezone).strftime(self.settings["timeFormat"])
|
||||
libs.panel_cmd.send_time(self.sendTopic, time_string)
|
||||
libs.panel_cmd.send_time(self.msg_out_queue, self.sendTopic, time_string)
|
||||
|
||||
def update_date(self):
|
||||
dateformat = self.settings["dateFormat"]
|
||||
date_string = babel.dates.format_date(
|
||||
datetime.datetime.now(), dateformat, locale=self.settings["locale"])
|
||||
libs.panel_cmd.send_date(self.sendTopic, date_string)
|
||||
libs.panel_cmd.send_date(self.msg_out_queue, self.sendTopic, date_string)
|
||||
|
||||
def searchCard(self, iid):
|
||||
if iid in self.navigate_keys:
|
||||
@@ -129,13 +135,23 @@ class LovelaceUIPanel:
|
||||
|
||||
# send update for detail popup in case it's open
|
||||
etype = entity_id.split('.')[0]
|
||||
if etype in ['light', 'timer', 'cover', 'input_select', 'select', 'fan']:
|
||||
if etype in ['light', 'timer', 'cover', 'input_select', 'select', 'fan', 'climate']:
|
||||
# figure out iid of entity
|
||||
entity_id_iid = ""
|
||||
for e in self.current_card.get_iid_entities():
|
||||
if entity_id == e[1]:
|
||||
entity_id_iid = f'iid.{e[0]}'
|
||||
libs.panel_cmd.entityUpdateDetail(self.sendTopic, detail_open(self.settings["locale"], etype, entity_id, entity_id_iid, sendTopic=self.sendTopic))
|
||||
for e in self.current_card.entities:
|
||||
if entity_id == e.entity_id:
|
||||
entity_id_iid = f'iid.{e.iid}'
|
||||
|
||||
effectList = None
|
||||
if etype=="light":
|
||||
effectList = e.config.get("effectList")
|
||||
if etype == 'light':
|
||||
libs.panel_cmd.entityUpdateDetail2(self.msg_out_queue, self.sendTopic, detail_open(self.settings["locale"], "popupInSel", entity_id, entity_id_iid, self.msg_out_queue, sendTopic=self.sendTopic, options_list=effectList))
|
||||
libs.panel_cmd.entityUpdateDetail(self.msg_out_queue, self.sendTopic, detail_open(self.settings["locale"], "popupLight", entity_id, entity_id_iid, self.msg_out_queue, sendTopic=self.sendTopic))
|
||||
elif etype in ['input_select', 'media_player']:
|
||||
libs.panel_cmd.entityUpdateDetail2(self.msg_out_queue, self.sendTopic, detail_open(self.settings["locale"], etype, entity_id, entity_id_iid, self.msg_out_queue, sendTopic=self.sendTopic))
|
||||
else:
|
||||
libs.panel_cmd.entityUpdateDetail(self.msg_out_queue, self.sendTopic, detail_open(self.settings["locale"], etype, entity_id, entity_id_iid, self.msg_out_queue, sendTopic=self.sendTopic))
|
||||
|
||||
involved_entities = ha_control.calculate_dim_values(
|
||||
self.settings.get("sleepTracking"),
|
||||
@@ -150,16 +166,12 @@ class LovelaceUIPanel:
|
||||
|
||||
|
||||
def render_current_page(self, switchPages=False, requested=False):
|
||||
if not self.current_card:
|
||||
return
|
||||
if switchPages:
|
||||
libs.panel_cmd.page_type(self.sendTopic, self.current_card.type)
|
||||
libs.panel_cmd.page_type(self.msg_out_queue, self.sendTopic, self.current_card.type)
|
||||
if requested:
|
||||
self.current_card.render()
|
||||
# send sleepTimeout
|
||||
#sleepTimeout = self.settings.get("sleepTimeout", 20)
|
||||
#if self.current_card.config.get("sleepTimeout"):
|
||||
# sleepTimeout = self.current_card.config.get("sleepTimeout")
|
||||
#libs.panel_cmd.timeout(self.sendTopic, sleepTimeout)
|
||||
#self.dimmode()
|
||||
|
||||
def dimmode(self):
|
||||
# send dimmode
|
||||
@@ -178,8 +190,15 @@ class LovelaceUIPanel:
|
||||
backgroundColor = 0
|
||||
fontColor = ""
|
||||
featExperimentalSliders = self.settings.get("featExperimentalSliders", 0)
|
||||
libs.panel_cmd.dimmode(self.sendTopic, dimValue, dimValueNormal, backgroundColor, fontColor, featExperimentalSliders)
|
||||
libs.panel_cmd.dimmode(self.msg_out_queue, self.sendTopic, dimValue, dimValueNormal, backgroundColor, fontColor, featExperimentalSliders)
|
||||
|
||||
def get_default_card(self):
|
||||
defaultCard = self.settings.get("defaultCard")
|
||||
if defaultCard and "." in defaultCard:
|
||||
card = self.searchCard(defaultCard.split(".")[1])
|
||||
if card:
|
||||
return card
|
||||
return list(self.cards.values())[0]
|
||||
|
||||
def customrecv_event_callback(self, msg):
|
||||
logging.debug("Recv Message from NsPanel (%s): %s", self.name, msg)
|
||||
@@ -198,7 +217,7 @@ class LovelaceUIPanel:
|
||||
sleepTimeout = self.settings.get("sleepTimeout", 20)
|
||||
if self.current_card.config.get("sleepTimeout"):
|
||||
sleepTimeout = self.current_card.config.get("sleepTimeout")
|
||||
libs.panel_cmd.timeout(self.sendTopic, sleepTimeout)
|
||||
libs.panel_cmd.timeout(self.msg_out_queue, self.sendTopic, sleepTimeout)
|
||||
self.dimmode()
|
||||
|
||||
if msg[1] == "sleepReached":
|
||||
@@ -212,13 +231,17 @@ class LovelaceUIPanel:
|
||||
btype = msg[3]
|
||||
value = msg[4] if len(msg) > 4 else None
|
||||
if btype == "bExit":
|
||||
if entity_id=="screensaver" and self.settings.get("screensaver").get("doubleTapToUnlock") and value == "1":
|
||||
if entity_id in ["screensaver", "screensaver2"] and self.settings.get("screensaver").get("doubleTapToUnlock") and value == "1":
|
||||
return
|
||||
|
||||
# in case privious_cards is empty add a default card
|
||||
if len(self.privious_cards) == 0:
|
||||
self.privious_cards.append(
|
||||
list(self.cards.values())[0]) # TODO: Impelement default card config
|
||||
self.privious_cards.append(self.get_default_card())
|
||||
|
||||
if self.settings.get("defaultCard") and entity_id in ["screensaver", "screensaver2"]:
|
||||
logging.debug("Defaulting to card %s", self.settings.get("defaultCard"))
|
||||
self.privious_cards = [self.get_default_card()]
|
||||
|
||||
self.current_card = self.privious_cards.pop()
|
||||
self.render_current_page(switchPages=True)
|
||||
return
|
||||
@@ -226,8 +249,10 @@ class LovelaceUIPanel:
|
||||
# replace iid with real entity id
|
||||
if entity_id.startswith("iid."):
|
||||
iid = entity_id.split(".")[1]
|
||||
if iid in self.entity_iids:
|
||||
entity_id = self.entity_iids[iid]
|
||||
for e in self.current_card.entities:
|
||||
if e.iid == iid:
|
||||
entity_id = e.entity_id
|
||||
entity_config = e.config
|
||||
|
||||
match btype:
|
||||
case 'button':
|
||||
@@ -236,8 +261,9 @@ class LovelaceUIPanel:
|
||||
case 'navigate':
|
||||
card_iid = entity_id.split(".")[1]
|
||||
if card_iid == "UP":
|
||||
if len(self.privious_cards) == 0:
|
||||
self.privious_cards.append(self.get_default_card())
|
||||
self.current_card = self.privious_cards.pop()
|
||||
# TODO Handle privious_cards empty with default card
|
||||
self.render_current_page(switchPages=True)
|
||||
else:
|
||||
self.privious_cards.append(self.current_card)
|
||||
@@ -245,7 +271,7 @@ class LovelaceUIPanel:
|
||||
self.render_current_page(switchPages=True)
|
||||
# send ha stuff to ha
|
||||
case _:
|
||||
ha_control.handle_buttons(entity_id, btype, value)
|
||||
ha_control.handle_buttons(entity_id, btype, value, entity_config=entity_config)
|
||||
case 'cardUnlock-unlock':
|
||||
card_iid = entity_id.split(".")[1]
|
||||
if int(self.current_card.config.get("pin")) == int(value):
|
||||
@@ -260,6 +286,15 @@ class LovelaceUIPanel:
|
||||
# replace iid with real entity id
|
||||
if entity_id.startswith("iid."):
|
||||
iid = entity_id.split(".")[1]
|
||||
if iid in self.entity_iids:
|
||||
entity_id = self.entity_iids[iid]
|
||||
libs.panel_cmd.entityUpdateDetail(self.sendTopic, detail_open(self.settings["locale"], msg[2], entity_id, msg[3], sendTopic=self.sendTopic))
|
||||
for e in self.current_card.entities:
|
||||
if e.iid == iid:
|
||||
entity_id = e.entity_id
|
||||
effectList = None
|
||||
if entity_id.startswith("light"):
|
||||
effectList = e.config.get("effectList")
|
||||
if msg[2] == "popupInSel": #entity_id.split(".")[0] in ['input_select', 'media_player']:
|
||||
libs.panel_cmd.entityUpdateDetail2(self.msg_out_queue, self.sendTopic, detail_open(self.settings["locale"], msg[2], entity_id, msg[3], self.msg_out_queue, sendTopic=self.sendTopic, options_list=effectList))
|
||||
else:
|
||||
libs.panel_cmd.entityUpdateDetail(self.msg_out_queue, self.sendTopic, detail_open(self.settings["locale"], msg[2], entity_id, msg[3], self.msg_out_queue, sendTopic=self.sendTopic))
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
paho-mqtt
|
||||
paho-mqtt==1.6.1
|
||||
pyyaml
|
||||
websockets
|
||||
websocket-client
|
||||
|
||||
Reference in New Issue
Block a user