Compare commits

..

156 Commits

Author SHA1 Message Date
Johannes
34340d2ac4 update docs 2022-03-28 22:36:45 +02:00
Johannes
ca59b35b87 update pic 2022-03-28 22:34:08 +02:00
Johannes
1539149c09 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-28 22:19:52 +02:00
Johannes
2851c80bb5 fix shutter detail page 2022-03-28 22:19:45 +02:00
joBr99
383fc978fd Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-28 20:16:08 +00:00
Johannes
1e57b46f9d Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-28 22:15:44 +02:00
Johannes
2c1868ba29 fix 2022-03-28 22:15:36 +02:00
Johannes
8366555eed bump version for next release 2022-03-28 22:08:58 +02:00
joBr99
6bccd8dd50 added on off button to media page (add nextion2text) 2022-03-28 19:38:22 +00:00
Johannes
6ccc5bafe1 added on off button to media page 2022-03-28 21:37:53 +02:00
Johannes
89174c2bbd Update pages.py 2022-03-28 20:08:35 +02:00
Johannes
f5395153ee Merge pull request #89 from britzelpuf/main
Fixes for version 20
2022-03-28 20:00:13 +02:00
britzelpuf
e9fb5ba32b Resolve changes 2022-03-28 19:56:59 +02:00
britzelpuf
661494b0b5 Fix for Version 20 2022-03-28 19:52:01 +02:00
britzelpuf
ea49bc9d70 Merge branch 'joBr99:main' into main 2022-03-28 19:39:35 +02:00
Johannes
1210838186 Update README.md 2022-03-28 18:12:54 +02:00
joBr99
0c872bfa87 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-28 15:49:36 +00:00
Johannes
e3a30e2da8 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-28 17:47:50 +02:00
Johannes
2a829e7217 added flashing 2022-03-28 17:47:45 +02:00
joBr99
15c79b60fa Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-28 15:32:29 +00:00
Johannes
05e05c7cb5 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-28 17:32:02 +02:00
Johannes
a27bc617a2 implemented buttons #81 and triggered state 2022-03-28 17:31:57 +02:00
joBr99
0a9e174c23 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-28 14:37:51 +00:00
Johannes
4fd2d3b260 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-28 16:37:25 +02:00
Johannes
28a43f46d7 added shield-airplane in HMI #81 2022-03-28 16:37:20 +02:00
joBr99
fffb73e310 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-28 14:35:44 +00:00
Johannes
7aacef87bd Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-28 16:35:17 +02:00
Johannes
1bf01b28a3 added some more alarm states #81 2022-03-28 16:35:13 +02:00
Johannes
0e6ec05056 change layout of alarm page #81 2022-03-28 16:19:02 +02:00
joBr99
2cd39b0abd Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-28 13:59:05 +00:00
Johannes
e3ab0d5594 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-28 15:58:41 +02:00
Johannes
f0bdc3c8ac implemented server side rendering of alarm page content #81 2022-03-28 15:58:37 +02:00
joBr99
e958eabc86 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-28 12:03:50 +00:00
Johannes
a742fbb2ae Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-28 14:03:27 +02:00
Johannes
b3eb283544 hide slider on page load 2022-03-28 14:03:19 +02:00
Johannes
2fa535a888 Update README.md 2022-03-28 13:29:08 +02:00
Johannes
31b8c566ed Update README.md 2022-03-28 12:40:29 +02:00
joBr99
ef6c42d1e0 add gui elements for slider on entities page (add nextion2text) 2022-03-27 21:07:54 +00:00
Johannes
af7edd37ad add gui elements for slider on entities page 2022-03-27 23:07:35 +02:00
Johannes
9525b5ad2c Update controller.py 2022-03-27 22:32:35 +02:00
Johannes
e882934d1b Update controller.py 2022-03-27 22:30:40 +02:00
Johannes
7477af1d2b Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-27 22:24:00 +02:00
Johannes
f2c67e47b3 fix thermo None values 2022-03-27 22:23:55 +02:00
joBr99
d35c990cc0 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-27 20:10:34 +00:00
Johannes
03c0940baa Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-27 22:10:15 +02:00
Johannes
48a0f331a8 increased entity char limit 2022-03-27 22:10:09 +02:00
joBr99
3081804f5a increase cooldown (add nextion2text) 2022-03-27 19:31:49 +00:00
Johannes
daf9fc5181 increase cooldown 2022-03-27 21:31:28 +02:00
joBr99
b6b12a2855 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-27 19:26:40 +00:00
Johannes
94eaebb542 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-27 21:26:15 +02:00
Johannes
dbe7725e48 changed cooldowns 2022-03-27 21:26:13 +02:00
Johannes
98e5249a43 fix pic 2022-03-27 20:28:44 +02:00
joBr99
43211467b2 added double tap feature for screensaver (add nextion2text) 2022-03-27 18:26:28 +00:00
Johannes
07260c0d0b added double tap feature for screensaver 2022-03-27 20:26:06 +02:00
Johannes
071b56f488 Update config.py 2022-03-27 20:04:58 +02:00
Johannes
d30fcf4157 Update controller.py 2022-03-27 19:48:49 +02:00
Johannes
3d04f77961 Do not display speaker selection item, in case there is only one speaker 2022-03-27 19:30:54 +02:00
joBr99
0b206e7fe3 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-27 14:29:36 +00:00
Johannes
f6e5e1ffdb Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-27 16:29:11 +02:00
Johannes
d2695b0437 more locations for sensor data on screensaver 2022-03-27 16:29:06 +02:00
Johannes
04bc737fd1 changed forecast on screensaver 2022-03-27 16:03:54 +02:00
joBr99
5586b57c9b implemented speaker control on media page (add nextion2text) 2022-03-27 13:49:18 +00:00
Johannes
11fc578984 implemented speaker control on media page 2022-03-27 15:48:57 +02:00
Johannes
a74043e4aa added speaker controls to hmi 2022-03-27 14:52:14 +02:00
Johannes
816d6787b7 Update pages.py 2022-03-27 12:05:44 +02:00
Johannes
01e4e233bf Update pages.py 2022-03-27 11:52:21 +02:00
Johannes
f78e03e5ec fixes #82 2022-03-27 11:34:54 +02:00
Johannes
33afd31d8f Check that page is existent #55 2022-03-26 21:06:59 +01:00
joBr99
4dccdfb014 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-26 15:41:05 +00:00
Johannes
2d6b8634bf Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-26 16:40:43 +01:00
Johannes
f11177c5c1 fix updater msg and bump to v1.8.3 2022-03-26 16:40:36 +01:00
joBr99
645aef4cfa fix bump for 1.8.2 (add nextion2text) 2022-03-26 15:26:46 +00:00
Johannes
d5fe05f806 fix bump for 1.8.2 2022-03-26 16:26:25 +01:00
Johannes
64cb8563aa bump to 18 for v1.8.1 2022-03-26 16:21:31 +01:00
Johannes
b91629421e Add name and icon to navigation buttons 2022-03-26 14:15:26 +01:00
Johannes
814cd4a295 implements #78 2022-03-26 13:44:48 +01:00
Johannes
9c2d91e3d9 fix brightness scale 2022-03-26 11:23:19 +01:00
Johannes
028ddb7896 Update pages.py 2022-03-26 11:16:39 +01:00
Johannes
afdc05a239 Add unit to forecast 2022-03-26 11:12:07 +01:00
Johannes
f63f7f7861 fix weather override 2022-03-26 11:08:32 +01:00
Johannes
c9d8f622cb fix weather override 2022-03-26 11:05:25 +01:00
Johannes
e6bb202823 Merge pull request #77 from gerard33/patch-2
Fix weather override
2022-03-26 11:00:01 +01:00
joBr99
7080facb10 added volume buttons to media page (add nextion2text) 2022-03-26 09:56:34 +00:00
Johannes
dcce889b3e added volume buttons to media page 2022-03-26 10:56:14 +01:00
Johannes
2e15482ed1 limit lower bound of color brightness scale 2022-03-26 10:45:22 +01:00
joBr99
adb99623e9 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-26 09:31:24 +00:00
Johannes
27f48819a4 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-26 10:31:02 +01:00
Johannes
1b52c885f6 added cooldown to sliders on light detail page 2022-03-26 10:30:54 +01:00
Gerard
1f937f75f2 Fix weather override 2022-03-26 10:10:58 +01:00
Johannes
269b983c2a fix current_page on nested page nav 2022-03-26 09:57:37 +01:00
Johannes
29dfa5671d Update README.md 2022-03-26 09:55:15 +01:00
Johannes
74a3860aa0 Merge pull request #76 from gerard33/patch-2
Fix weather forecast
2022-03-26 09:47:39 +01:00
Gerard
1bc69128a9 Fix weather forecast
Show the correct day and icon for day 2
2022-03-26 09:46:26 +01:00
Johannes
4529d5e34e Update README.md 2022-03-26 09:14:49 +01:00
Johannes
0db8983b4a Update README.md 2022-03-26 09:12:21 +01:00
Johannes
dc5e732e04 Update README.md 2022-03-26 09:11:47 +01:00
Johannes
7e7d14a999 add overwrite for forecast's on screensaver 2022-03-26 08:51:21 +01:00
joBr99
7ebc29b4a4 allow empty type as alternative for delete (add nextion2text) 2022-03-26 00:28:30 +00:00
Johannes
8b24f70ae0 allow empty type as alternative for delete 2022-03-26 01:28:10 +01:00
Johannes
edfe79e3c4 implemented navigation within tree 2022-03-26 01:23:41 +01:00
Johannes
93d223141b fixes #72 at least for now 2022-03-25 22:58:34 +01:00
Johannes
853de19a40 fixes #69 2022-03-25 22:34:31 +01:00
Johannes
da2b4565a4 fixes #74 2022-03-25 22:30:00 +01:00
Johannes
18d360d339 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-25 22:23:36 +01:00
Johannes
af494ada10 fixes #73 2022-03-25 22:23:27 +01:00
Johannes
05d6ee1f5f fixed localization for buttons 2022-03-25 20:58:04 +01:00
Johannes
a4344ade18 send brightness and timeout on startup 2022-03-25 20:50:45 +01:00
Johannes
1470ee5c82 Update localization.py 2022-03-25 20:44:19 +01:00
Johannes
9ae898c30f Update localization.py 2022-03-25 20:43:07 +01:00
Johannes
ec65eebb74 Add localization to thermo page status 2022-03-25 20:39:26 +01:00
Johannes
f7a768de7c Update localization.py 2022-03-25 20:37:40 +01:00
Johannes
e7aa27128c Merge pull request #70 from gerard33/patch-2
Some textual updates
2022-03-25 20:26:51 +01:00
Johannes
11bbad78d1 Update localization.py 2022-03-25 20:25:28 +01:00
Gerard
95e3dfa0ea Some textual updates 2022-03-25 20:23:28 +01:00
Johannes
70557ab748 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-25 16:57:17 +01:00
Johannes
2ecc7caedd update config 2022-03-25 16:57:11 +01:00
joBr99
6fd8553450 added am/pm on screensaver (add nextion2text) 2022-03-25 15:31:46 +00:00
Johannes
83396c283f added am/pm on screensaver 2022-03-25 16:31:28 +01:00
Johannes
a388efb5b5 Merge pull request #65 from gerard33/patch-3
Rename `getEntityColor` to `get_entity_color`
2022-03-25 15:46:22 +01:00
Johannes
77b05b8079 add min brightness 2022-03-25 15:46:03 +01:00
Johannes
0aae22118b fix ext update 2022-03-25 15:44:12 +01:00
Johannes
4a0a2d3620 merged main into pr 2022-03-25 15:29:40 +01:00
Johannes Braun
cfd0d2cbe8 fixed erron in gen items 2022-03-25 15:11:33 +01:00
Johannes
39575935b6 Merge pull request #68 from joBr99/newConfigFormat
new config parseing
2022-03-25 15:05:09 +01:00
Johannes Braun
9f8900bf78 fixed altert 2022-03-25 14:43:33 +01:00
joBr99
a054f7a7b3 fixed alerts (add nextion2text) 2022-03-25 13:34:26 +00:00
Johannes Braun
464e625eaa fixed alerts 2022-03-25 14:34:06 +01:00
Johannes
505db42064 Merge branch 'main' into newConfigFormat 2022-03-25 14:13:07 +01:00
Johannes Braun
36459145e4 added localization fixed updater 2022-03-25 14:06:40 +01:00
Johannes Braun
32b84bba9f upd docs 2022-03-25 12:11:53 +01:00
Johannes Braun
952398a827 added updater 2022-03-25 12:09:53 +01:00
Johannes Braun
ff106be9cb added state change callback 2022-03-25 00:26:43 +01:00
Johannes Braun
0ab7900ec0 basic navigation and event handling 2022-03-24 22:51:51 +01:00
Johannes
f328107f75 Merge pull request #66 from gerard33/patch-2
Show alert icon instead of shutter icon
2022-03-24 22:37:07 +01:00
Gerard
8deb0fd35e Show alert icon instead of shutter icon
When no mediaplayer is found
2022-03-24 20:20:14 +01:00
Gerard
ed207b6e1a Rename getEntityColor to get_entity_color
I have also set a minimum brightness for the icon otherwise it's almost not visible anymore when the brightness value is very low. What do you think?
2022-03-24 20:14:15 +01:00
Johannes
83e3316458 Merge pull request #63 from gerard33/patch-2
Add language settings
2022-03-24 20:10:45 +01:00
Johannes
53c4ed370b Merge pull request #64 from gerard33/patch-3
Add icon_color for binary sensor
2022-03-24 20:10:10 +01:00
Gerard
050a8e6fd2 Add icon_color for binary sensor
Blue when `off` and yellow when `on`
Not sure about the colors though, but at least it's nice to show different icon colors based on the state
2022-03-24 20:07:36 +01:00
Gerard
907f814ac7 Add config options for buttons and scenes 2022-03-24 19:45:18 +01:00
Gerard
e91c514fe1 Add language settings
Make `PRESS` and `ACTIVATE` text configurable
2022-03-24 19:42:48 +01:00
Johannes
5566f20e47 fixes #61 2022-03-24 17:24:47 +01:00
Johannes
4810679ac5 Update README.md 2022-03-24 16:18:35 +01:00
Johannes
48ed2daa33 Merge pull request #59 closes #58
Add name as config item
2022-03-24 16:14:46 +01:00
Johannes Braun
482cee0552 redesign of config format 2022-03-24 16:12:42 +01:00
Gerard
8813331299 Update README.md 2022-03-24 16:11:06 +01:00
Gerard
abf4868281 Update README.md 2022-03-24 16:10:06 +01:00
Gerard
420905db04 Add name as config item
See FR #58
2022-03-24 16:08:21 +01:00
Johannes
4151aba6ea Update README.md 2022-03-24 14:56:48 +01:00
britzelpuf
8a48ff35d4 Fix Startup routine 2022-03-24 12:23:01 +01:00
Johannes
35b15c92e0 Merge pull request #54 from joBr99/patch-buttonPress2
Migrate to new buttonPress cmd format
2022-03-23 22:11:48 +01:00
Johannes
c40906fdfe Merge pull request #56 from britzelpuf/patch-buttonPress2
Update NsPanelTs.ts
2022-03-23 22:11:23 +01:00
britzelpuf
66a65c03e8 Update NsPanelTs.ts
Update HandleMessage function to switch
Fix tempupd
2022-03-23 22:08:25 +01:00
Johannes
20e6f21307 Migrate to new buttonPress cmd format 2022-03-23 11:25:21 +01:00
joBr99
342a97df0f don't show palette icon if color temp isn't supported (add nextion2text) 2022-03-23 10:13:32 +00:00
Johannes Braun
0d343d4919 don't show palette icon if color temp isn't supported 2022-03-23 11:13:06 +01:00
36 changed files with 2644 additions and 1264 deletions

View File

@@ -71,13 +71,11 @@ change the page type:
`pageType,popupNotify` `pageType,popupNotify`
`pageType,screensaver`
### screensaver page ### screensaver page
`weatherUpdate,? tMainIcon? tMainText? tMRIcon? tMR? tForecast1? tF1Icon? tForecast1Val? tForecast2? tF2Icon? tForecast2Val` `weatherUpdate,? tMainIcon? tMainText? tMRIcon? tMR? tForecast1? tF1Icon? tForecast1Val? tForecast2? tF2Icon? tForecast2Val?tForecast3? tF3Icon? tForecast3Val?tForecast4? tF4Icon? tForecast4Val`
`weatherUpdate,?0?2,3 C?0?0 mm?Mi?0?9,3 C?Do?0?11,5 C`
`page,0`
### cardEntities Page ### cardEntities Page
@@ -117,7 +115,7 @@ The following message can be used to update the content on the cardEntities Page
`entityUpdateDetail,*internalName*,*tHeading*,*tHeadingColor*,*b1*,*tB1Color*,*b2*,*tB2Color*,*tText*,*tTextColor*,*sleepTimeout*` `entityUpdateDetail,*internalName*,*tHeading*,*tHeadingColor*,*b1*,*tB1Color*,*b2*,*tB2Color*,*tText*,*tTextColor*,*sleepTimeout*`
`popupExit` `exitPopup`
### cardThermo Page ### cardThermo Page
@@ -127,29 +125,36 @@ The following message can be used to update the content on the cardEntities Page
### cardMedia Page ### cardMedia Page
`entityUpd,|*internalNameEntiy*|*heading*|*icon*|*title*|*author*|*volume*|*playpauseicon*` `entityUpd,|*internalNameEntiy*|*heading*|*icon*|*title*|*author*|*volume*|*playpauseicon*|currentSpeaker|speakerList-seperated-by-?`
### cardAlarm Page ### cardAlarm Page
`entityUpd,*internalNameEntity*,*arm1*,*arm1ActionName*,*arm2*,*arm2ActionName*,*arm3*,*arm3ActionName*,*arm4*,*arm4ActionName*,*icon*,*numpadStatus*` `entityUpd,*internalNameEntity*,*arm1*,*arm1ActionName*,*arm2*,*arm2ActionName*,*arm3*,*arm3ActionName*,*arm4*,*arm4ActionName*,*icon*,*iconcolor*,*numpadStatus*,*flashing*`
## Messages from Nextion Display ## Messages from Nextion Display
`event,buttonPress2,pageName,bNext`
`event,buttonPress2,pageName,bPrev`
`event,buttonPress2,pageName,bExit,number_of_taps`
### startup page ### startup page
`event,startup,version` `event,startup,version`
### screensaver page ### screensaver page
`event,screensaverOpen` `event,buttonPress2,screensaver,exit` - Touch Event on Screensaver
`event,screensaverOpen` - Screensaver has opened
### cardEntities Page ### cardEntities Page
`event,*eventName*,*entityName*,*actionName*,*optionalValue*` `event,*eventName*,*entityName*,*actionName*,*optionalValue*`
`event,pageOpen,0`
`event,buttonPress2,internalNameEntity,up` `event,buttonPress2,internalNameEntity,up`
`event,buttonPress2,internalNameEntity,down` `event,buttonPress2,internalNameEntity,down`
@@ -186,8 +191,6 @@ The following message can be used to update the content on the cardEntities Page
### cardThermo Page ### cardThermo Page
`event,pageOpen,0`
`event,buttonPress2,*entityName*,tempUpd,*temperature*` `event,buttonPress2,*entityName*,tempUpd,*temperature*`
`event,buttonPress2,*entityName*,hvac_action,*hvac_action*` `event,buttonPress2,*entityName*,hvac_action,*hvac_action*`

View File

@@ -40,7 +40,12 @@ icons = [
"shield-home", "shield-home",
"door-open", "door-open",
"door-closed", "door-closed",
"window-closed" "window-closed",
"shield-off",
"shield",
"shield-lock",
"shield-airplane",
"bell-ring"
] ]
@@ -66,7 +71,7 @@ for icon_name in icons:
icon_name_list.append(icon_name) icon_name_list.append(icon_name)
# write mapping lib for python # write mapping lib for python
with open(os.path.join(__location__, "../../../apps/nspanel-lovelace-ui", "icon_mapping.py"), 'w') as f: with open(os.path.join(__location__, "../../../apps/nspanel-lovelace-ui/luibackend", "icon_mapping.py"), 'w') as f:
f.write("icons = {\n") f.write("icons = {\n")
for idx, val in enumerate(icon_name_list): for idx, val in enumerate(icon_name_list):
f.write(f" '{val}': {idx},\n") f.write(f" '{val}': {idx},\n")

View File

@@ -43,3 +43,8 @@ ID | MD Icon Name | Icon
36 | door-open | ![door-open](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/door-open.svg) 36 | door-open | ![door-open](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/door-open.svg)
37 | door-closed | ![door-closed](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/door-closed.svg) 37 | door-closed | ![door-closed](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/door-closed.svg)
38 | window-closed | ![window-closed](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/window-closed.svg) 38 | window-closed | ![window-closed](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/window-closed.svg)
39 | shield-off | ![shield-off](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/shield-off.svg)
40 | shield | ![shield](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/shield.svg)
41 | shield-lock | ![shield-lock](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/shield-lock.svg)
42 | shield-airplane | ![shield-airplane](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/shield-airplane.svg)
43 | bell-ring | ![bell-ring](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/bell-ring.svg)

View File

@@ -5,24 +5,11 @@ Program.s
int recvCrc=0 int recvCrc=0
int payloadLength=0 int payloadLength=0
int par0=0,par1=0 int par0=0,par1=0
// landsspace orientation x has 480px and y has 320px xy limits todo: adjust xy values to something that fit's resulution
//Maximum values in directional change for Swipes beeing detected as swipe (diagonal swipes are invalid) (for one axis at a time)
int xLimit=125,yLimit=125
int ixLimit=-125,iyLimit=-125
//Minimum values for swipes, directional changes below theese values are ignored, because they could be unintended swipes
int xLimitMin=80,yLimitMin=80
int ixLimitMin=-80,iyLimitMin=-80
// Swipe Result Vars
int ycR=0,xcR=0
// Start End Swipe Touch Locations
int yc1=0,xc1=0,yc2=0,xc2=0
// sleep timeout in s // sleep timeout in s
int sleepTimeout=20 int sleepTimeout=20
int sleepValue=0 int sleepValue=0
// dim value // dim value
int dimValue=40 int dimValue=40
// current page
int nPage=0
// fix touch offset // fix touch offset
lcd_dev fffb 0002 0000 0020 lcd_dev fffb 0002 0000 0020
page pageStartup page pageStartup

View File

@@ -222,7 +222,7 @@ Text tCode
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 92 x coordinate : 92
y coordinate : 12 y coordinate : 16
Width : 192 Width : 192
Height : 49 Height : 49
Effect : load Effect : load
@@ -252,7 +252,7 @@ Text tIcon
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 300 x coordinate : 300
y coordinate : 12 y coordinate : 16
Width : 64 Width : 64
Height : 49 Height : 49
Effect : load Effect : load
@@ -267,7 +267,7 @@ Text tIcon
Horizontal Alignment : center Horizontal Alignment : center
Vertical Alignment : center Vertical Alignment : center
Input Type : character Input Type : character
Text :  Text :
Max. Text Size : 10 Max. Text Size : 10
Word wrap : disabled Word wrap : disabled
Horizontal Spacing : 0 Horizontal Spacing : 0
@@ -324,14 +324,7 @@ Button bNext
Events Events
Touch Press Event Touch Press Event
nPage=nPage+1 tSend.txt="event,buttonPress2,cardAlarm,bNext"
nPageDisp.val=nPage
//page open event
// event,pageOpen,cardEntities,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC
@@ -378,14 +371,7 @@ Button bPrev
Events Events
Touch Press Event Touch Press Event
nPage=nPage-1 tSend.txt="event,buttonPress2,cardAlarm,bPrev"
nPageDisp.val=nPage
//page open event
// event,pageOpen,cardEntities,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC
@@ -406,8 +392,8 @@ Button b0
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 52 x coordinate : 25
y coordinate : 146 y coordinate : 94
Width : 75 Width : 75
Height : 50 Height : 50
Effect : load Effect : load
@@ -444,8 +430,8 @@ Button b1
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 144 x coordinate : 117
y coordinate : 146 y coordinate : 94
Width : 75 Width : 75
Height : 50 Height : 50
Effect : load Effect : load
@@ -482,8 +468,8 @@ Button b2
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 236 x coordinate : 209
y coordinate : 145 y coordinate : 93
Width : 75 Width : 75
Height : 50 Height : 50
Effect : load Effect : load
@@ -520,8 +506,8 @@ Button b3
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 52 x coordinate : 25
y coordinate : 204 y coordinate : 152
Width : 75 Width : 75
Height : 50 Height : 50
Effect : load Effect : load
@@ -558,8 +544,8 @@ Button b4
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 144 x coordinate : 117
y coordinate : 204 y coordinate : 152
Width : 75 Width : 75
Height : 50 Height : 50
Effect : load Effect : load
@@ -596,8 +582,8 @@ Button b5
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 236 x coordinate : 209
y coordinate : 204 y coordinate : 152
Width : 75 Width : 75
Height : 50 Height : 50
Effect : load Effect : load
@@ -634,8 +620,8 @@ Button b6
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 52 x coordinate : 25
y coordinate : 262 y coordinate : 210
Width : 75 Width : 75
Height : 50 Height : 50
Effect : load Effect : load
@@ -672,8 +658,8 @@ Button b7
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 144 x coordinate : 117
y coordinate : 262 y coordinate : 210
Width : 75 Width : 75
Height : 50 Height : 50
Effect : load Effect : load
@@ -710,8 +696,8 @@ Button b8
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 236 x coordinate : 209
y coordinate : 262 y coordinate : 210
Width : 75 Width : 75
Height : 50 Height : 50
Effect : load Effect : load
@@ -748,8 +734,8 @@ Button b9
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 328 x coordinate : 116
y coordinate : 204 y coordinate : 266
Width : 75 Width : 75
Height : 50 Height : 50
Effect : load Effect : load
@@ -786,8 +772,8 @@ Button b10
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 328 x coordinate : 209
y coordinate : 262 y coordinate : 266
Width : 75 Width : 75
Height : 50 Height : 50
Effect : load Effect : load
@@ -806,7 +792,7 @@ Button b10
Horizontal Alignment : center Horizontal Alignment : center
Vertical Alignment : center Vertical Alignment : center
State : unpressed State : unpressed
Text : CLEAR Text : CLR
Max. Text Size : 10 Max. Text Size : 10
Word wrap : disabled Word wrap : disabled
Horizontal Spacing : 0 Horizontal Spacing : 0
@@ -824,10 +810,10 @@ Button arm1
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 59 x coordinate : 300
y coordinate : 72 y coordinate : 91
Width : 64 Width : 141
Height : 64 Height : 50
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
Effect Time : 300 Effect Time : 300
@@ -845,7 +831,7 @@ Button arm1
Vertical Alignment : center Vertical Alignment : center
State : unpressed State : unpressed
Text : Text :
Max. Text Size : 10 Max. Text Size : 40
Word wrap : enabled Word wrap : enabled
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0
@@ -868,6 +854,7 @@ Button arm1
prints sys0,2 prints sys0,2
prints tSend.txt,0 prints tSend.txt,0
prints crcval,2 prints crcval,2
tCode.txt=""
Button arm3 Button arm3
Attributes Attributes
@@ -877,10 +864,10 @@ Button arm3
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 239 x coordinate : 300
y coordinate : 72 y coordinate : 210
Width : 64 Width : 140
Height : 64 Height : 50
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
Effect Time : 300 Effect Time : 300
@@ -898,7 +885,7 @@ Button arm3
Vertical Alignment : center Vertical Alignment : center
State : unpressed State : unpressed
Text : Text :
Max. Text Size : 10 Max. Text Size : 40
Word wrap : enabled Word wrap : enabled
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0
@@ -921,6 +908,7 @@ Button arm3
prints sys0,2 prints sys0,2
prints tSend.txt,0 prints tSend.txt,0
prints crcval,2 prints crcval,2
tCode.txt=""
Button arm2 Button arm2
Attributes Attributes
@@ -930,10 +918,10 @@ Button arm2
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 149 x coordinate : 300
y coordinate : 72 y coordinate : 152
Width : 64 Width : 141
Height : 64 Height : 50
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
Effect Time : 300 Effect Time : 300
@@ -951,7 +939,7 @@ Button arm2
Vertical Alignment : center Vertical Alignment : center
State : unpressed State : unpressed
Text : Text :
Max. Text Size : 10 Max. Text Size : 40
Word wrap : enabled Word wrap : enabled
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0
@@ -974,6 +962,7 @@ Button arm2
prints sys0,2 prints sys0,2
prints tSend.txt,0 prints tSend.txt,0
prints crcval,2 prints crcval,2
tCode.txt=""
Button arm4 Button arm4
Attributes Attributes
@@ -983,10 +972,10 @@ Button arm4
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 329 x coordinate : 300
y coordinate : 72 y coordinate : 266
Width : 64 Width : 141
Height : 64 Height : 50
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
Effect Time : 300 Effect Time : 300
@@ -1004,7 +993,7 @@ Button arm4
Vertical Alignment : center Vertical Alignment : center
State : unpressed State : unpressed
Text : Text :
Max. Text Size : 10 Max. Text Size : 40
Word wrap : enabled Word wrap : enabled
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0
@@ -1027,6 +1016,7 @@ Button arm4
prints sys0,2 prints sys0,2
prints tSend.txt,0 prints tSend.txt,0
prints crcval,2 prints crcval,2
tCode.txt=""
Timer tmSerial Timer tmSerial
Attributes Attributes
@@ -1120,8 +1110,12 @@ Timer tmSerial
spstr strCommand.txt,tTmp.txt,",",10 spstr strCommand.txt,tTmp.txt,",",10
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tIcon.txt,sys0,1 substr pageIcons.tIcons.txt,tIcon.txt,sys0,1
//numpad status //icon color
spstr strCommand.txt,tTmp.txt,",",11 spstr strCommand.txt,tTmp.txt,",",11
covx tTmp.txt,sys0,0,0
tIcon.pco=sys0
//numpad status
spstr strCommand.txt,tTmp.txt,",",12
if(tTmp.txt!="disable") if(tTmp.txt!="disable")
{ {
vis b0,1 vis b0,1
@@ -1137,6 +1131,15 @@ Timer tmSerial
vis b10,1 vis b10,1
vis tCode,1 vis tCode,1
} }
//flashing status
spstr strCommand.txt,tTmp.txt,",",13
if(tTmp.txt=="enable")
{
tmFlash.en=1
}else
{
tmFlash.en=0
}
} }
if(tInstruction.txt=="time") if(tInstruction.txt=="time")
{ {
@@ -1235,6 +1238,25 @@ Timer tmSleep
} }
} }
Timer tmFlash
Attributes
ID : 35
Scope : local
Period (ms): 600
Enabled : no
Events
Timer Event
if(tIcon.isbr==1)
{
tIcon.isbr=0
vis tIcon,0
}else
{
tIcon.isbr=1
vis tIcon,1
}
TouchCap tc0 TouchCap tc0
Attributes Attributes
ID : 12 ID : 12

View File

@@ -38,6 +38,7 @@ Page cardEntities
vis tIcon1,0 vis tIcon1,0
vis tEntity1,0 vis tEntity1,0
vis bText1,0 vis bText1,0
vis hSlider1,0
//ui e2 //ui e2
vis btOnOff2,0 vis btOnOff2,0
vis bUp2,0 vis bUp2,0
@@ -46,6 +47,7 @@ Page cardEntities
vis tIcon2,0 vis tIcon2,0
vis tEntity2,0 vis tEntity2,0
vis bText2,0 vis bText2,0
vis hSlider2,0
//ui e3 //ui e3
vis btOnOff3,0 vis btOnOff3,0
vis bUp3,0 vis bUp3,0
@@ -54,6 +56,7 @@ Page cardEntities
vis tIcon3,0 vis tIcon3,0
vis tEntity3,0 vis tEntity3,0
vis bText3,0 vis bText3,0
vis hSlider3,0
//ui e4 //ui e4
vis btOnOff4,0 vis btOnOff4,0
vis bUp4,0 vis bUp4,0
@@ -62,6 +65,7 @@ Page cardEntities
vis tIcon4,0 vis tIcon4,0
vis tEntity4,0 vis tEntity4,0
vis bText4,0 vis bText4,0
vis hSlider4,0
Variable (string) strCommand Variable (string) strCommand
Attributes Attributes
@@ -103,28 +107,28 @@ Variable (string) entn1
ID : 49 ID : 49
Scope : local Scope : local
Text : Text :
Max. Text Size: 50 Max. Text Size: 70
Variable (string) entn2 Variable (string) entn2
Attributes Attributes
ID : 50 ID : 50
Scope : local Scope : local
Text : Text :
Max. Text Size: 50 Max. Text Size: 70
Variable (string) entn3 Variable (string) entn3
Attributes Attributes
ID : 51 ID : 51
Scope : local Scope : local
Text : Text :
Max. Text Size: 50 Max. Text Size: 70
Variable (string) entn4 Variable (string) entn4
Attributes Attributes
ID : 52 ID : 52
Scope : local Scope : local
Text : Text :
Max. Text Size: 50 Max. Text Size: 70
Text tHeading Text tHeading
Attributes Attributes
@@ -533,6 +537,106 @@ Picture p0
Effect Time : 300 Effect Time : 300
Picture ID : 0 Picture ID : 0
Slider hSlider1
Attributes
ID : 54
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 275
y coordinate : 77
Width : 150
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Direction : horizontal
Fill : image
Cursor width : auto
Cursor height : 255
Back. Picture ID : 5
Slided Back. Picture ID : 4
Position : 50
Upper range limit : 100
Lower range limit : 0
Slider hSlider2
Attributes
ID : 55
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 276
y coordinate : 133
Width : 150
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Direction : horizontal
Fill : image
Cursor width : auto
Cursor height : 255
Back. Picture ID : 5
Slided Back. Picture ID : 4
Position : 50
Upper range limit : 100
Lower range limit : 0
Slider hSlider3
Attributes
ID : 56
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 276
y coordinate : 187
Width : 150
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Direction : horizontal
Fill : image
Cursor width : auto
Cursor height : 255
Back. Picture ID : 5
Slided Back. Picture ID : 4
Position : 50
Upper range limit : 100
Lower range limit : 0
Slider hSlider4
Attributes
ID : 57
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 275
y coordinate : 243
Width : 150
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Direction : horizontal
Fill : image
Cursor width : auto
Cursor height : 255
Back. Picture ID : 5
Slided Back. Picture ID : 4
Position : 50
Upper range limit : 100
Lower range limit : 0
Button bDown1 Button bDown1
Attributes Attributes
ID : 11 ID : 11
@@ -1131,13 +1235,14 @@ Button bPrev
Events Events
Touch Press Event Touch Press Event
nPage=nPage-1 tSend.txt="event,buttonPress2,cardEntities,"
//page open event if(bPrev.isbr==1)
// event,pageOpen,cardEntities,pageNumber {
// craft command tSend.txt+="bBack"
// convert pageNumber and write to tTmp }else
covx nPage,tTmp.txt,0,0 {
tSend.txt="event,pageOpen,"+tTmp.txt tSend.txt+="bPrev"
}
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC
@@ -1184,13 +1289,7 @@ Button bNext
Events Events
Touch Press Event Touch Press Event
nPage=nPage+1 tSend.txt="event,buttonPress2,cardEntities,bNext"
//page open event
// event,pageOpen,cardEntities,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC
@@ -1776,6 +1875,27 @@ Timer tmSerial
if(tInstruction.txt=="entityUpdHeading") if(tInstruction.txt=="entityUpdHeading")
{ {
spstr strCommand.txt,tHeading.txt,",",1 spstr strCommand.txt,tHeading.txt,",",1
spstr strCommand.txt,tTmp.txt,",",2
if(tTmp.txt=="0")
{
vis bPrev,0
}else
{
vis bPrev,1
if(tTmp.txt=="2")
{
bPrev.txt=""
bPrev.isbr=1
}
}
spstr strCommand.txt,tTmp.txt,",",3
if(tTmp.txt=="0")
{
vis bNext,0
}else
{
vis bNext,1
}
} }
if(tInstruction.txt=="entityUpd") if(tInstruction.txt=="entityUpd")
{ {
@@ -1784,7 +1904,7 @@ Timer tmSerial
spstr strCommand.txt,type1.txt,",",1 spstr strCommand.txt,type1.txt,",",1
// get internal name // get internal name
spstr strCommand.txt,entn1.txt,",",2 spstr strCommand.txt,entn1.txt,",",2
if(type1.txt=="delete") if(type1.txt=="delete"||type1.txt=="")
{ {
vis bUp1,0 vis bUp1,0
vis bStop1,0 vis bStop1,0
@@ -1793,6 +1913,7 @@ Timer tmSerial
vis tEntity1,0 vis tEntity1,0
vis tIcon1,0 vis tIcon1,0
vis bText1,0 vis bText1,0
vis hSlider1,0
}else }else
{ {
// change icon // change icon
@@ -1815,6 +1936,7 @@ Timer tmSerial
vis bDown1,1 vis bDown1,1
vis btOnOff1,0 vis btOnOff1,0
vis bText1,0 vis bText1,0
vis hSlider1,0
} }
if(type1.txt=="light") if(type1.txt=="light")
{ {
@@ -1823,6 +1945,7 @@ Timer tmSerial
vis bDown1,0 vis bDown1,0
vis btOnOff1,1 vis btOnOff1,1
vis bText1,0 vis bText1,0
vis hSlider1,0
// get Button State (optional Value) // get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",6 spstr strCommand.txt,tTmp.txt,",",6
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
@@ -1835,6 +1958,7 @@ Timer tmSerial
vis bDown1,0 vis bDown1,0
vis btOnOff1,1 vis btOnOff1,1
vis bText1,0 vis bText1,0
vis hSlider1,0
// get Button State (optional Value) // get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",6 spstr strCommand.txt,tTmp.txt,",",6
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
@@ -1848,6 +1972,7 @@ Timer tmSerial
vis btOnOff1,0 vis btOnOff1,0
vis bText1,1 vis bText1,1
tsw bText1,0 tsw bText1,0
vis hSlider1,0
bText1.pco=65535 bText1.pco=65535
bText1.pco2=65535 bText1.pco2=65535
// get Text (optional Value) // get Text (optional Value)
@@ -1861,17 +1986,29 @@ Timer tmSerial
vis btOnOff1,0 vis btOnOff1,0
vis bText1,1 vis bText1,1
tsw bText1,1 tsw bText1,1
vis hSlider1,0
bText1.pco=1374 bText1.pco=1374
bText1.pco2=1374 bText1.pco2=1374
// get Text (optional Value) // get Text (optional Value)
spstr strCommand.txt,bText1.txt,",",6 spstr strCommand.txt,bText1.txt,",",6
} }
// id2 if(type1.txt=="number")
{
vis bUp1,0
vis bStop1,0
vis bDown1,0
vis btOnOff1,0
vis bText1,0
tsw bText1,0
vis hSlider1,1
// get Text (optional Value)
spstr strCommand.txt,bText1.txt,",",6
}
// get Type // get Type
spstr strCommand.txt,type2.txt,",",7 spstr strCommand.txt,type2.txt,",",7
// get internal name // get internal name
spstr strCommand.txt,entn2.txt,",",8 spstr strCommand.txt,entn2.txt,",",8
if(type2.txt=="delete") if(type2.txt=="delete"||type2.txt=="")
{ {
vis bUp2,0 vis bUp2,0
vis bStop2,0 vis bStop2,0
@@ -1880,9 +2017,10 @@ Timer tmSerial
vis tEntity2,0 vis tEntity2,0
vis tIcon2,0 vis tIcon2,0
vis bText2,0 vis bText2,0
vis hSlider2,0
}else }else
{ {
//change icon // change icon
spstr strCommand.txt,tTmp.txt,",",9 spstr strCommand.txt,tTmp.txt,",",9
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tIcon2.txt,sys0,1 substr pageIcons.tIcons.txt,tIcon2.txt,sys0,1
@@ -1902,6 +2040,7 @@ Timer tmSerial
vis bDown2,1 vis bDown2,1
vis btOnOff2,0 vis btOnOff2,0
vis bText2,0 vis bText2,0
vis hSlider2,0
} }
if(type2.txt=="light") if(type2.txt=="light")
{ {
@@ -1910,6 +2049,7 @@ Timer tmSerial
vis bDown2,0 vis bDown2,0
vis btOnOff2,1 vis btOnOff2,1
vis bText2,0 vis bText2,0
vis hSlider2,0
// get Button State (optional Value) // get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",12 spstr strCommand.txt,tTmp.txt,",",12
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
@@ -1922,6 +2062,7 @@ Timer tmSerial
vis bDown2,0 vis bDown2,0
vis btOnOff2,1 vis btOnOff2,1
vis bText2,0 vis bText2,0
vis hSlider2,0
// get Button State (optional Value) // get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",12 spstr strCommand.txt,tTmp.txt,",",12
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
@@ -1935,6 +2076,7 @@ Timer tmSerial
vis btOnOff2,0 vis btOnOff2,0
vis bText2,1 vis bText2,1
tsw bText2,0 tsw bText2,0
vis hSlider2,0
bText2.pco=65535 bText2.pco=65535
bText2.pco2=65535 bText2.pco2=65535
// get Text (optional Value) // get Text (optional Value)
@@ -1948,17 +2090,29 @@ Timer tmSerial
vis btOnOff2,0 vis btOnOff2,0
vis bText2,1 vis bText2,1
tsw bText2,1 tsw bText2,1
vis hSlider2,0
bText2.pco=1374 bText2.pco=1374
bText2.pco2=1374 bText2.pco2=1374
// get Text (optional Value) // get Text (optional Value)
spstr strCommand.txt,bText2.txt,",",12 spstr strCommand.txt,bText2.txt,",",12
} }
// id3 if(type2.txt=="number")
{
vis bUp2,0
vis bStop2,0
vis bDown2,0
vis btOnOff2,0
vis bText2,0
tsw bText2,0
vis hSlider2,1
// get Text (optional Value)
spstr strCommand.txt,bText2.txt,",",12
}
// get Type // get Type
spstr strCommand.txt,type3.txt,",",13 spstr strCommand.txt,type3.txt,",",13
// get internal name // get internal name
spstr strCommand.txt,entn3.txt,",",14 spstr strCommand.txt,entn3.txt,",",14
if(type3.txt=="delete") if(type3.txt=="delete"||type3.txt=="")
{ {
vis bUp3,0 vis bUp3,0
vis bStop3,0 vis bStop3,0
@@ -1967,9 +2121,10 @@ Timer tmSerial
vis tEntity3,0 vis tEntity3,0
vis tIcon3,0 vis tIcon3,0
vis bText3,0 vis bText3,0
vis hSlider3,0
}else }else
{ {
//change icon // change icon
spstr strCommand.txt,tTmp.txt,",",15 spstr strCommand.txt,tTmp.txt,",",15
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tIcon3.txt,sys0,1 substr pageIcons.tIcons.txt,tIcon3.txt,sys0,1
@@ -1989,14 +2144,16 @@ Timer tmSerial
vis bDown3,1 vis bDown3,1
vis btOnOff3,0 vis btOnOff3,0
vis bText3,0 vis bText3,0
vis hSlider3,0
} }
if(type3.txt=="light") if(type3.txt=="light")
{ {
vis bUp3,0 vis bUp3,0
vis bStop3,0 vis bStop3,0
vis bDown3,0 vis bDown3,0
vis bText3,0
vis btOnOff3,1 vis btOnOff3,1
vis bText3,0
vis hSlider3,0
// get Button State (optional Value) // get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",18 spstr strCommand.txt,tTmp.txt,",",18
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
@@ -2007,8 +2164,9 @@ Timer tmSerial
vis bUp3,0 vis bUp3,0
vis bStop3,0 vis bStop3,0
vis bDown3,0 vis bDown3,0
vis bText3,0
vis btOnOff3,1 vis btOnOff3,1
vis bText3,0
vis hSlider3,0
// get Button State (optional Value) // get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",18 spstr strCommand.txt,tTmp.txt,",",18
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
@@ -2022,6 +2180,7 @@ Timer tmSerial
vis btOnOff3,0 vis btOnOff3,0
vis bText3,1 vis bText3,1
tsw bText3,0 tsw bText3,0
vis hSlider3,0
bText3.pco=65535 bText3.pco=65535
bText3.pco2=65535 bText3.pco2=65535
// get Text (optional Value) // get Text (optional Value)
@@ -2035,17 +2194,29 @@ Timer tmSerial
vis btOnOff3,0 vis btOnOff3,0
vis bText3,1 vis bText3,1
tsw bText3,1 tsw bText3,1
vis hSlider3,0
bText3.pco=1374 bText3.pco=1374
bText3.pco2=1374 bText3.pco2=1374
// get Text (optional Value) // get Text (optional Value)
spstr strCommand.txt,bText3.txt,",",18 spstr strCommand.txt,bText3.txt,",",18
} }
// id4 if(type3.txt=="number")
{
vis bUp3,0
vis bStop3,0
vis bDown3,0
vis btOnOff3,0
vis bText3,0
tsw bText3,0
vis hSlider3,1
// get Text (optional Value)
spstr strCommand.txt,bText3.txt,",",18
}
// get Type // get Type
spstr strCommand.txt,type4.txt,",",19 spstr strCommand.txt,type4.txt,",",19
// get internal name // get internal name
spstr strCommand.txt,entn4.txt,",",20 spstr strCommand.txt,entn4.txt,",",20
if(type4.txt=="delete") if(type4.txt=="delete"||type4.txt=="")
{ {
vis bUp4,0 vis bUp4,0
vis bStop4,0 vis bStop4,0
@@ -2054,9 +2225,10 @@ Timer tmSerial
vis tEntity4,0 vis tEntity4,0
vis tIcon4,0 vis tIcon4,0
vis bText4,0 vis bText4,0
vis hSlider4,0
}else }else
{ {
//change icon // change icon
spstr strCommand.txt,tTmp.txt,",",21 spstr strCommand.txt,tTmp.txt,",",21
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tIcon4.txt,sys0,1 substr pageIcons.tIcons.txt,tIcon4.txt,sys0,1
@@ -2076,14 +2248,16 @@ Timer tmSerial
vis bDown4,1 vis bDown4,1
vis btOnOff4,0 vis btOnOff4,0
vis bText4,0 vis bText4,0
vis hSlider4,0
} }
if(type4.txt=="light") if(type4.txt=="light")
{ {
vis bUp4,0 vis bUp4,0
vis bStop4,0 vis bStop4,0
vis bDown4,0 vis bDown4,0
vis bText4,0
vis btOnOff4,1 vis btOnOff4,1
vis bText4,0
vis hSlider4,0
// get Button State (optional Value) // get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",24 spstr strCommand.txt,tTmp.txt,",",24
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
@@ -2094,8 +2268,9 @@ Timer tmSerial
vis bUp4,0 vis bUp4,0
vis bStop4,0 vis bStop4,0
vis bDown4,0 vis bDown4,0
vis bText4,0
vis btOnOff4,1 vis btOnOff4,1
vis bText4,0
vis hSlider4,0
// get Button State (optional Value) // get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",24 spstr strCommand.txt,tTmp.txt,",",24
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
@@ -2109,6 +2284,7 @@ Timer tmSerial
vis btOnOff4,0 vis btOnOff4,0
vis bText4,1 vis bText4,1
tsw bText4,0 tsw bText4,0
vis hSlider4,0
bText4.pco=65535 bText4.pco=65535
bText4.pco2=65535 bText4.pco2=65535
// get Text (optional Value) // get Text (optional Value)
@@ -2122,11 +2298,24 @@ Timer tmSerial
vis btOnOff4,0 vis btOnOff4,0
vis bText4,1 vis bText4,1
tsw bText4,1 tsw bText4,1
vis hSlider4,0
bText4.pco=1374 bText4.pco=1374
bText4.pco2=1374 bText4.pco2=1374
// get Text (optional Value) // get Text (optional Value)
spstr strCommand.txt,bText4.txt,",",24 spstr strCommand.txt,bText4.txt,",",24
} }
if(type4.txt=="number")
{
vis bUp4,0
vis bStop4,0
vis bDown4,0
vis btOnOff4,0
vis bText4,0
tsw bText4,0
vis hSlider4,1
// get Text (optional Value)
spstr strCommand.txt,bText4.txt,",",24
}
} }
if(tInstruction.txt=="pageType") if(tInstruction.txt=="pageType")
{ {

View File

@@ -83,28 +83,28 @@ Variable (string) entn1
ID : 18 ID : 18
Scope : local Scope : local
Text : Text :
Max. Text Size: 50 Max. Text Size: 70
Variable (string) entn2 Variable (string) entn2
Attributes Attributes
ID : 19 ID : 19
Scope : local Scope : local
Text : Text :
Max. Text Size: 50 Max. Text Size: 70
Variable (string) entn3 Variable (string) entn3
Attributes Attributes
ID : 20 ID : 20
Scope : local Scope : local
Text : Text :
Max. Text Size: 50 Max. Text Size: 70
Variable (string) entn4 Variable (string) entn4
Attributes Attributes
ID : 21 ID : 21
Scope : local Scope : local
Text : Text :
Max. Text Size: 50 Max. Text Size: 70
Variable (string) type5 Variable (string) type5
Attributes Attributes
@@ -515,13 +515,7 @@ Button bPrev
Events Events
Touch Press Event Touch Press Event
nPage=nPage-1 tSend.txt="event,buttonPress2,cardGrid,bPrev"
//page open event
// event,pageOpen,cardEntities,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC
@@ -568,13 +562,7 @@ Button bNext
Events Events
Touch Press Event Touch Press Event
nPage=nPage+1 tSend.txt="event,buttonPress2,cardGrid,bNext"
//page open event
// event,pageOpen,cardEntities,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC

View File

@@ -23,54 +23,37 @@ Page cardMedia
vis p0,0 vis p0,0
vis tSend,0 vis tSend,0
vis tInstruction,0 vis tInstruction,0
vis nPageDisp,0
vis tTmp,0 vis tTmp,0
vis tId,0 vis tId,0
vis t5,0
//vis nPageDisp,0 //vis nPageDisp,0
Variable (string) strCommand Variable (string) strCommand
Attributes Attributes
ID : 8 ID : 7
Scope : local Scope : local
Text : Text :
Max. Text Size: 200 Max. Text Size: 500
Variable (string) entn Variable (string) entn
Attributes Attributes
ID : 19 ID : 18
Scope : local Scope : local
Text : Text :
Max. Text Size: 50 Max. Text Size: 50
Number nPageDisp Variable (string) vaSpeakerList
Attributes Attributes
ID : 6 ID : 27
Scope : local Scope : local
Dragging : 0 Text :
Disable release event after dragging: 0 Max. Text Size: 200
Send Component ID : disabled
Opacity : 127 Variable (int32) vaSpeakerPos
x coordinate : 426 Attributes
y coordinate : 0 ID : 28
Width : 42 Scope: local
Height : 24 Value: 0
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 0
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
Vertical Alignment : center
Value : 0
Significant digits shown : all
Format : decimal
Word wrap : enabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tSend Text tSend
Attributes Attributes
@@ -83,7 +66,7 @@ Text tSend
x coordinate : 0 x coordinate : 0
y coordinate : 0 y coordinate : 0
Width : 230 Width : 230
Height : 23 Height : 15
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
Effect Time : 300 Effect Time : 300
@@ -96,8 +79,8 @@ Text tSend
Horizontal Alignment : center Horizontal Alignment : center
Vertical Alignment : center Vertical Alignment : center
Input Type : character Input Type : character
Text : newtxt Text :
Max. Text Size : 100 Max. Text Size : 200
Word wrap : disabled Word wrap : disabled
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0
@@ -110,9 +93,9 @@ Text tTmp
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 406 x coordinate : 450
y coordinate : 277 y coordinate : 145
Width : 34 Width : 27
Height : 30 Height : 30
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
@@ -134,16 +117,16 @@ Text tTmp
Text tInstruction Text tInstruction
Attributes Attributes
ID : 9 ID : 8
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 0 x coordinate : 296
y coordinate : 290 y coordinate : 0
Width : 100 Width : 100
Height : 30 Height : 20
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
Effect Time : 300 Effect Time : 300
@@ -164,15 +147,15 @@ Text tInstruction
Text tId Text tId
Attributes Attributes
ID : 10 ID : 9
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 99 x coordinate : 449
y coordinate : 290 y coordinate : 187
Width : 39 Width : 30
Height : 30 Height : 30
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
@@ -194,7 +177,7 @@ Text tId
Text tHeading Text tHeading
Attributes Attributes
ID : 11 ID : 10
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -224,7 +207,7 @@ Text tHeading
Text tTitle Text tTitle
Attributes Attributes
ID : 12 ID : 11
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -254,7 +237,7 @@ Text tTitle
Text tAuthor Text tAuthor
Attributes Attributes
ID : 13 ID : 12
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -284,14 +267,14 @@ Text tAuthor
Text t2 Text t2
Attributes Attributes
ID : 14 ID : 13
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 314 x coordinate : 306
y coordinate : 159 y coordinate : 145
Width : 50 Width : 50
Height : 50 Height : 50
Effect : load Effect : load
@@ -333,14 +316,14 @@ Text t2
Text tPlayPause Text tPlayPause
Attributes Attributes
ID : 15 ID : 14
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 203 x coordinate : 203
y coordinate : 159 y coordinate : 145
Width : 50 Width : 50
Height : 50 Height : 50
Effect : load Effect : load
@@ -382,14 +365,14 @@ Text tPlayPause
Text t0 Text t0
Attributes Attributes
ID : 16 ID : 15
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 92 x coordinate : 96
y coordinate : 159 y coordinate : 145
Width : 50 Width : 50
Height : 50 Height : 50
Effect : load Effect : load
@@ -431,7 +414,7 @@ Text t0
Text tIcon Text tIcon
Attributes Attributes
ID : 18 ID : 17
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -459,6 +442,276 @@ Text tIcon
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0
Text t1
Attributes
ID : 22
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 5
y coordinate : 201
Width : 50
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 2
Back. Color : 6371
Font Color : 50712
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text : 
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
hVolume.val=hVolume.val-5
// event,buttonPress2,internalNameEntity,volumeSlider,50
//craft command
tSend.txt="event,buttonPress2,"+entn.txt+",volumeSlider,"
covx hVolume.val,tTmp.txt,0,0
tSend.txt+=tTmp.txt
//send calc crc
btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC
crcputh 55 bb
crcputs sys0,1
crcputs tSend.txt,0
//send cmd
printh 55 bb
prints sys0,2
prints tSend.txt,0
prints crcval,2
Text t3
Attributes
ID : 23
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 397
y coordinate : 201
Width : 50
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 2
Back. Color : 6371
Font Color : 50712
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text : 
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
hVolume.val=hVolume.val+5
// event,buttonPress2,internalNameEntity,volumeSlider,50
//craft command
tSend.txt="event,buttonPress2,"+entn.txt+",volumeSlider,"
covx hVolume.val,tTmp.txt,0,0
tSend.txt+=tTmp.txt
//send calc crc
btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC
crcputh 55 bb
crcputs sys0,1
crcputs tSend.txt,0
//send cmd
printh 55 bb
prints sys0,2
prints tSend.txt,0
prints crcval,2
Text t4
Attributes
ID : 24
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 21
y coordinate : 262
Width : 50
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 2
Back. Color : 6371
Font Color : 50712
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text : 
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tSpeaker
Attributes
ID : 25
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 94
y coordinate : 262
Width : 267
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 0
Back. Color : 6371
Font Color : 65535
Horizontal Alignment : left
Vertical Alignment : center
Input Type : character
Text :
Max. Text Size : 50
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
// event,buttonPress2,entn,media-next
//craft command
tSend.txt="event,buttonPress2,"
tSend.txt+=entn.txt+","
tSend.txt+="speaker-sel,"+tSpeaker.txt
//send calc crc
btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC
crcputh 55 bb
crcputs sys0,1
crcputs tSend.txt,0
//send cmd
printh 55 bb
prints sys0,2
prints tSend.txt,0
prints crcval,2
Text t6
Attributes
ID : 26
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 381
y coordinate : 262
Width : 50
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 2
Back. Color : 6371
Font Color : 50712
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text : 
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
//speaker
tSpeaker.pco=65535
spstr vaSpeakerList.txt,tSpeaker.txt,"?",vaSpeakerPos.val
vaSpeakerPos.val+=1
if(tSpeaker.txt=="")
{
vaSpeakerPos.val=0
spstr vaSpeakerList.txt,tSpeaker.txt,"?",vaSpeakerPos.val
}
Text t5
Attributes
ID : 29
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 397
y coordinate : 145
Width : 50
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 2
Back. Color : 6371
Font Color : 50712
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text : 
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
// event,buttonPress2,entn,media-next
//craft command
tSend.txt="event,buttonPress2,"
tSend.txt+=entn.txt+","
tSend.txt+="media-OnOff"
//send calc crc
btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC
crcputh 55 bb
crcputs sys0,1
crcputs tSend.txt,0
//send cmd
printh 55 bb
prints sys0,2
prints tSend.txt,0
prints crcval,2
Picture p0 Picture p0
Attributes Attributes
ID : 1 ID : 1
@@ -478,14 +731,14 @@ Picture p0
Slider hVolume Slider hVolume
Attributes Attributes
ID : 17 ID : 16
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 61 x coordinate : 59
y coordinate : 227 y coordinate : 206
Width : 335 Width : 335
Height : 43 Height : 43
Effect : load Effect : load
@@ -503,6 +756,8 @@ Slider hVolume
Events Events
Touch Release Event Touch Release Event
tmCooldown.en=1
tmCooldown.tim=800
// event,buttonPress2,internalNameEntity,volumeSlider,50 // event,buttonPress2,internalNameEntity,volumeSlider,50
//craft command //craft command
tSend.txt="event,buttonPress2,"+entn.txt+",volumeSlider," tSend.txt="event,buttonPress2,"+entn.txt+",volumeSlider,"
@@ -554,14 +809,7 @@ Button bNext
Events Events
Touch Press Event Touch Press Event
nPage=nPage+1 tSend.txt="event,buttonPress2,cardMedia,bNext"
nPageDisp.val=nPage
//page open event
// event,pageOpen,cardEntities,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC
@@ -608,14 +856,7 @@ Button bPrev
Events Events
Touch Press Event Touch Press Event
nPage=nPage-1 tSend.txt="event,buttonPress2,cardMedia,bPrev"
nPageDisp.val=nPage
//page open event
// event,pageOpen,cardEntities,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC
@@ -630,7 +871,7 @@ Button bPrev
Timer tmSerial Timer tmSerial
Attributes Attributes
ID : 7 ID : 6
Scope : local Scope : local
Period (ms): 50 Period (ms): 50
Enabled : yes Enabled : yes
@@ -702,6 +943,32 @@ Timer tmSerial
spstr strCommand.txt,tTmp.txt,"|",7 spstr strCommand.txt,tTmp.txt,"|",7
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tPlayPause.txt,sys0,1 substr pageIcons.tIcons.txt,tPlayPause.txt,sys0,1
//speaker current
spstr strCommand.txt,tSpeaker.txt,"|",8
if(tSpeaker.txt!="")
{
tSpeaker.pco=1374
}else
{
tSpeaker.pco=65535
}
//speaker list
spstr strCommand.txt,vaSpeakerList.txt,"|",9
if(vaSpeakerList.txt=="")
{
vis t6,0
}
vaSpeakerPos.val=0
// on off button
spstr strCommand.txt,tTmp.txt,"|",10
if(tTmp.txt=="disable")
{
vis t5,0
}else
{
vis t5,1
covx tTmp.txt,t5.pco,0,0
}
} }
if(tInstruction.txt=="time") if(tInstruction.txt=="time")
{ {
@@ -791,7 +1058,7 @@ Timer tmSerial
Timer tmSleep Timer tmSleep
Attributes Attributes
ID : 20 ID : 19
Scope : local Scope : local
Period (ms): 1000 Period (ms): 1000
Enabled : yes Enabled : yes
@@ -809,9 +1076,20 @@ Timer tmSleep
} }
} }
Timer tmCooldown
Attributes
ID : 21
Scope : local
Period (ms): 100
Enabled : no
Events
Timer Event
tmCooldown.en=0
TouchCap tc0 TouchCap tc0
Attributes Attributes
ID : 21 ID : 20
Scope: local Scope: local
Value: 0 Value: 0

View File

@@ -559,14 +559,7 @@ Button bNext
Events Events
Touch Press Event Touch Press Event
nPage=nPage+1 tSend.txt="event,buttonPress2,cardThermo,bNext"
nPageDisp.val=nPage
//page open event
// event,pageOpen,cardEntities,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC
@@ -721,14 +714,7 @@ Button bPrev
Events Events
Touch Press Event Touch Press Event
nPage=nPage-1 tSend.txt="event,buttonPress2,cardThermo,bPrev"
nPageDisp.val=nPage
//page open event
// event,pageOpen,cardEntities,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC

View File

@@ -1,66 +1,62 @@
Program.s Program.s
0 Component(s) 0 Component(s)
17 Line(s) of event code 10 Line(s) of event code
17 Unique line(s) of event code 10 Unique line(s) of event code
pageIcons pageIcons
6 Component(s) 6 Component(s)
0 Line(s) of event code 0 Line(s) of event code
0 Unique line(s) of event code 0 Unique line(s) of event code
pageTest
13 Component(s)
13 Line(s) of event code
13 Unique line(s) of event code
pageSerialTest pageSerialTest
13 Component(s) 13 Component(s)
48 Line(s) of event code 48 Line(s) of event code
43 Unique line(s) of event code 43 Unique line(s) of event code
popupNotify
17 Component(s)
180 Line(s) of event code
119 Unique line(s) of event code
pageStartup
19 Component(s)
146 Line(s) of event code
111 Unique line(s) of event code
cardMedia
22 Component(s)
200 Line(s) of event code
115 Unique line(s) of event code
pageSwipeTest
18 Component(s)
62 Line(s) of event code
44 Unique line(s) of event code
popupShutter popupShutter
19 Component(s) 19 Component(s)
180 Line(s) of event code 179 Line(s) of event code
103 Unique line(s) of event code 102 Unique line(s) of event code
pageTest popupNotify
14 Component(s) 17 Component(s)
14 Line(s) of event code 179 Line(s) of event code
14 Unique line(s) of event code 118 Unique line(s) of event code
popupLight cardEntities
26 Component(s) 58 Component(s)
304 Line(s) of event code 824 Line(s) of event code
167 Unique line(s) of event code 346 Unique line(s) of event code
screensaver cardMedia
25 Component(s) 30 Component(s)
173 Line(s) of event code 278 Line(s) of event code
124 Unique line(s) of event code 139 Unique line(s) of event code
pageStartup
19 Component(s)
150 Line(s) of event code
113 Unique line(s) of event code
cardThermo cardThermo
42 Component(s) 42 Component(s)
412 Line(s) of event code 406 Line(s) of event code
221 Unique line(s) of event code 218 Unique line(s) of event code
cardGrid cardGrid
39 Component(s) 39 Component(s)
382 Line(s) of event code 378 Line(s) of event code
221 Unique line(s) of event code 219 Unique line(s) of event code
cardEntities popupLight
54 Component(s) 27 Component(s)
728 Line(s) of event code 323 Line(s) of event code
317 Unique line(s) of event code 174 Unique line(s) of event code
screensaver
31 Component(s)
183 Line(s) of event code
133 Unique line(s) of event code
cardAlarm cardAlarm
35 Component(s) 36 Component(s)
259 Line(s) of event code 277 Line(s) of event code
163 Unique line(s) of event code 173 Unique line(s) of event code
Total Total
14 Page(s) 13 Page(s)
349 Component(s) 350 Component(s)
3105 Line(s) of event code 3248 Line(s) of event code
827 Unique line(s) of event code 869 Unique line(s) of event code

View File

@@ -72,8 +72,8 @@ Text tIcons
Horizontal Alignment : left Horizontal Alignment : left
Vertical Alignment : top Vertical Alignment : top
Input Type : character Input Type : character
Text :  Text : 
Max. Text Size : 120 Max. Text Size : 150
Word wrap : enabled Word wrap : enabled
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0

View File

@@ -402,7 +402,7 @@ Text tVersion
Horizontal Alignment : center Horizontal Alignment : center
Vertical Alignment : center Vertical Alignment : center
Input Type : character Input Type : character
Text : 16 Text : 21
Max. Text Size : 10 Max. Text Size : 10
Word wrap : disabled Word wrap : disabled
Horizontal Spacing : 0 Horizontal Spacing : 0
@@ -592,6 +592,10 @@ Timer tmSerial
{ {
page cardThermo page cardThermo
} }
if(tId.txt=="screensaver")
{
page screensaver
}
if(tId.txt=="popupLight") if(tId.txt=="popupLight")
{ {
pageIcons.tTmp1.txt=tTmp.txt pageIcons.tTmp1.txt=tTmp.txt

View File

@@ -111,45 +111,9 @@ Button b1
Touch Press Event Touch Press Event
page pageSerialTest page pageSerialTest
Button b2
Attributes
ID : 4
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 7
y coordinate : 265
Width : 100
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 4
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 : swipe
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
page pageSwipeTest
Button b3 Button b3
Attributes Attributes
ID : 5 ID : 4
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -185,7 +149,7 @@ Button b3
Button b6 Button b6
Attributes Attributes
ID : 6 ID : 5
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -221,7 +185,7 @@ Button b6
Button b4 Button b4
Attributes Attributes
ID : 7 ID : 6
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -257,7 +221,7 @@ Button b4
Button b5 Button b5
Attributes Attributes
ID : 8 ID : 7
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -293,7 +257,7 @@ Button b5
Button b7 Button b7
Attributes Attributes
ID : 9 ID : 8
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -329,7 +293,7 @@ Button b7
Button b8 Button b8
Attributes Attributes
ID : 10 ID : 9
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -366,7 +330,7 @@ Button b8
Button b9 Button b9
Attributes Attributes
ID : 11 ID : 10
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -402,7 +366,7 @@ Button b9
Button b10 Button b10
Attributes Attributes
ID : 12 ID : 11
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -438,7 +402,7 @@ Button b10
Button b11 Button b11
Attributes Attributes
ID : 13 ID : 12
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0

View File

@@ -500,6 +500,8 @@ Slider hBrightness
Events Events
Touch Release Event Touch Release Event
tmCooldown.en=1
tmCooldown.tim=2500
//craft command //craft command
tSend.txt="event,buttonPress2,"+entn.txt+",brightnessSlider," tSend.txt="event,buttonPress2,"+entn.txt+",brightnessSlider,"
covx hBrightness.val,tTmp.txt,0,0 covx hBrightness.val,tTmp.txt,0,0
@@ -543,6 +545,8 @@ Slider hTempSlider
Events Events
Touch Release Event Touch Release Event
tmCooldown.en=1
tmCooldown.tim=2500
//craft command //craft command
tSend.txt="event,buttonPress2,"+entn.txt+",colorTempSlider," tSend.txt="event,buttonPress2,"+entn.txt+",colorTempSlider,"
covx hTempSlider.val,tTmp.txt,0,0 covx hTempSlider.val,tTmp.txt,0,0
@@ -593,12 +597,7 @@ Button b0
Events Events
Touch Press Event Touch Press Event
//page open event tSend.txt="event,buttonPress2,popupLight,bExit"
// event,pageOpen,cardEntities,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC
@@ -815,7 +814,10 @@ Timer tmSerial
vis t2,1 vis t2,1
vis hBrightness,1 vis hBrightness,1
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
hBrightness.val=sys0 if(tmCooldown.en==0)
{
hBrightness.val=sys0
}
} }
// get ColorTemp value // get ColorTemp value
spstr strCommand.txt,tTmp.txt,",",5 spstr strCommand.txt,tTmp.txt,",",5
@@ -844,10 +846,15 @@ Timer tmSerial
} }
}else }else
{ {
mode_temp.val=0 mode_temp.val=1
vis hTempSlider,1 vis hTempSlider,1
vis t3,1 vis t3,1
vis t4,1 vis t4,1
if(tmCooldown.en==0)
{
covx tTmp.txt,sys0,0,0
hTempSlider.val=sys0
}
// mode == 0 is rgb controls currently shown // mode == 0 is rgb controls currently shown
if(mode.val==0) if(mode.val==0)
{ {
@@ -867,7 +874,11 @@ Timer tmSerial
}else }else
{ {
vis t0,1 vis t0,1
vis bColor,1 //only enable bColor button if color temp is also supported
if(mode_temp.val==1)
{
vis bColor,1
}
if(mode.val==0) if(mode.val==0)
{ {
vis pColorWheel,1 vis pColorWheel,1
@@ -945,6 +956,17 @@ Timer tmSerial
} }
} }
Timer tmCooldown
Attributes
ID : 26
Scope : local
Period (ms): 100
Enabled : no
Events
Timer Event
tmCooldown.en=0
TouchCap tc0 TouchCap tc0
Attributes Attributes
ID : 14 ID : 14

View File

@@ -278,12 +278,7 @@ Button b0
Events Events
Touch Press Event Touch Press Event
sleepTimeout=vaOldSleepT.val sleepTimeout=vaOldSleepT.val
//page open event tSend.txt="event,buttonPress2,popupNotify,bExit"
// event,pageOpen,cardEntities,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC

View File

@@ -364,12 +364,7 @@ Button b0
Events Events
Touch Press Event Touch Press Event
//page open event tSend.txt="event,buttonPress2,popupShutter,bExit"
// event,pageOpen,cardEntities,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC

View File

@@ -27,12 +27,26 @@ Page screensaver
vis tTmp,0 vis tTmp,0
vis p0,0 vis p0,0
//load gloabl time string from pageIcons //load gloabl time string from pageIcons
tTime.txt=vaTime.txt //tTime.txt=vaTime.txt
spstr vaTime.txt,tTime.txt,"?",0
spstr vaTime.txt,tAMPM.txt,"?",1
if(tAMPM.txt=="")
{
vis tAMPM,0
}
tDate.txt=vaDate.txt tDate.txt=vaDate.txt
dim=dimValue dim=dimValue
vis tSend,0 vis tSend,0
//page open event //page open event
// craft command // clear weather elements, to keep example content in HMI
tMainIcon.txt=""
tMainText.txt=""
tForecast1.txt=""
tF1Icon.txt=""
tForecast1Val.txt=""
tForecast2.txt=""
tF2Icon.txt=""
tForecast2Val.txt=""
tSend.txt="event,screensaverOpen" tSend.txt="event,screensaverOpen"
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
@@ -45,31 +59,20 @@ Page screensaver
prints sys0,2 prints sys0,2
prints tSend.txt,0 prints tSend.txt,0
prints crcval,2 prints crcval,2
// clear weather elements, to keep example content in HMI
tMainIcon.txt=""
tMainText.txt=""
tMRIcon.txt=""
tMR.txt=""
tForecast1.txt=""
tF1Icon.txt=""
tForecast1Val.txt=""
tForecast2.txt=""
tF2Icon.txt=""
tForecast2Val.txt=""
Variable (string) strCommand Variable (string) strCommand
Attributes Attributes
ID : 5 ID : 5
Scope : local Scope : local
Text : Text :
Max. Text Size: 100 Max. Text Size: 200
Variable (string) vaTime Variable (string) vaTime
Attributes Attributes
ID : 10 ID : 10
Scope : global Scope : global
Text : Text :
Max. Text Size: 10 Max. Text Size: 15
Variable (string) vaDate Variable (string) vaDate
Attributes Attributes
@@ -80,11 +83,17 @@ Variable (string) vaDate
Variable (string) tId Variable (string) tId
Attributes Attributes
ID : 24 ID : 22
Scope : local Scope : local
Text : Text :
Max. Text Size: 25 Max. Text Size: 25
Variable (int32) vaTap
Attributes
ID : 30
Scope: local
Value: 0
Number originPage Number originPage
Attributes Attributes
ID : 3 ID : 3
@@ -140,7 +149,7 @@ Text tInstruction
Vertical Alignment : center Vertical Alignment : center
Input Type : character Input Type : character
Text : Text :
Max. Text Size : 20 Max. Text Size : 50
Word wrap : disabled Word wrap : disabled
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0
@@ -170,7 +179,7 @@ Text tTmp
Vertical Alignment : center Vertical Alignment : center
Input Type : character Input Type : character
Text : Text :
Max. Text Size : 20 Max. Text Size : 50
Word wrap : disabled Word wrap : disabled
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0
@@ -199,8 +208,8 @@ Text tTime
Horizontal Alignment : center Horizontal Alignment : center
Vertical Alignment : center Vertical Alignment : center
Input Type : character Input Type : character
Text : 21:32 Text : 21:32
Max. Text Size : 10 Max. Text Size : 15
Word wrap : disabled Word wrap : disabled
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0
@@ -260,7 +269,7 @@ Text tSend
Vertical Alignment : center Vertical Alignment : center
Input Type : character Input Type : character
Text : Text :
Max. Text Size : 25 Max. Text Size : 50
Word wrap : disabled Word wrap : disabled
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0
@@ -273,9 +282,9 @@ Text tMainIcon
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 6 x coordinate : 26
y coordinate : 223 y coordinate : 202
Width : 100 Width : 70
Height : 66 Height : 66
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
@@ -303,8 +312,8 @@ Text tMainText
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 114 x coordinate : 7
y coordinate : 214 y coordinate : 267
Width : 110 Width : 110
Height : 43 Height : 43
Effect : load Effect : load
@@ -325,7 +334,7 @@ Text tMainText
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0
Text tMRIcon Text tForecast1
Attributes Attributes
ID : 15 ID : 15
Scope : local Scope : local
@@ -333,69 +342,9 @@ Text tMRIcon
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 115 x coordinate : 128
y coordinate : 268
Width : 40
Height : 35
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 1
Back. Color : 0
Font Color : 65535
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text : 
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tMR
Attributes
ID : 16
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 157
y coordinate : 275
Width : 67
Height : 22
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 0
Back. Color : 0
Font Color : 65535
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text : 0 mm
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tForecast1
Attributes
ID : 17
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 228
y coordinate : 210 y coordinate : 210
Width : 108 Width : 72
Height : 26 Height : 26
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
@@ -417,15 +366,15 @@ Text tForecast1
Text tForecast1Val Text tForecast1Val
Attributes Attributes
ID : 18 ID : 16
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 228 x coordinate : 126
y coordinate : 277 y coordinate : 277
Width : 108 Width : 72
Height : 26 Height : 26
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
@@ -447,13 +396,13 @@ Text tForecast1Val
Text tF1Icon Text tF1Icon
Attributes Attributes
ID : 19 ID : 17
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 262 x coordinate : 146
y coordinate : 239 y coordinate : 239
Width : 40 Width : 40
Height : 35 Height : 35
@@ -477,15 +426,15 @@ Text tF1Icon
Text tForecast2 Text tForecast2
Attributes Attributes
ID : 20 ID : 18
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 341 x coordinate : 212
y coordinate : 210 y coordinate : 210
Width : 107 Width : 72
Height : 25 Height : 25
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
@@ -507,16 +456,16 @@ Text tForecast2
Text tF2Icon Text tF2Icon
Attributes Attributes
ID : 21 ID : 19
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 375 x coordinate : 228
y coordinate : 238 y coordinate : 239
Width : 40 Width : 40
Height : 33 Height : 35
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
Effect Time : 300 Effect Time : 300
@@ -537,15 +486,15 @@ Text tF2Icon
Text tForecast2Val Text tForecast2Val
Attributes Attributes
ID : 22 ID : 20
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
Send Component ID : disabled Send Component ID : disabled
Opacity : 127 Opacity : 127
x coordinate : 341 x coordinate : 212
y coordinate : 277 y coordinate : 277
Width : 107 Width : 72
Height : 25 Height : 25
Effect : load Effect : load
Effect Priority : 0 Effect Priority : 0
@@ -567,7 +516,7 @@ Text tForecast2Val
Text t10 Text t10
Attributes Attributes
ID : 23 ID : 21
Scope : local Scope : local
Dragging : 0 Dragging : 0
Disable release event after dragging: 0 Disable release event after dragging: 0
@@ -595,6 +544,216 @@ Text t10
Horizontal Spacing : 0 Horizontal Spacing : 0
Vertical Spacing : 0 Vertical Spacing : 0
Text tAMPM
Attributes
ID : 23
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 343
y coordinate : 48
Width : 104
Height : 57
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 3
Back. Color : 0
Font Color : 65535
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text : PM
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tForecast3Val
Attributes
ID : 24
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 292
y coordinate : 277
Width : 71
Height : 25
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 0
Back. Color : 0
Font Color : 65535
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text :
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tF3Icon
Attributes
ID : 25
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 309
y coordinate : 239
Width : 40
Height : 35
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 1
Back. Color : 0
Font Color : 65535
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text :
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tForecast3
Attributes
ID : 26
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 293
y coordinate : 210
Width : 72
Height : 25
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 0
Back. Color : 0
Font Color : 65535
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text :
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tForecast4
Attributes
ID : 27
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 374
y coordinate : 210
Width : 72
Height : 25
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 0
Back. Color : 0
Font Color : 65535
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text :
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tF4Icon
Attributes
ID : 28
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 390
y coordinate : 239
Width : 40
Height : 35
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 1
Back. Color : 0
Font Color : 65535
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text :
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tForecast4Val
Attributes
ID : 29
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 374
y coordinate : 277
Width : 72
Height : 25
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 0
Back. Color : 0
Font Color : 65535
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text :
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Picture p0 Picture p0
Attributes Attributes
ID : 1 ID : 1
@@ -680,7 +839,12 @@ Timer tmSerial
{ {
//get set time to global variable //get set time to global variable
spstr strCommand.txt,vaTime.txt,",",1 spstr strCommand.txt,vaTime.txt,",",1
tTime.txt=vaTime.txt spstr vaTime.txt,tTime.txt,"?",0
spstr vaTime.txt,tAMPM.txt,"?",1
if(tAMPM.txt=="")
{
vis tAMPM,0
}
} }
if(tInstruction.txt=="date") if(tInstruction.txt=="date")
{ {
@@ -702,36 +866,38 @@ Timer tmSerial
substr pageIcons.tIcons.txt,tMainIcon.txt,sys0,1 substr pageIcons.tIcons.txt,tMainIcon.txt,sys0,1
//tMainText //tMainText
spstr strCommand.txt,tMainText.txt,"?",2 spstr strCommand.txt,tMainText.txt,"?",2
//tMRIcon
spstr strCommand.txt,tTmp.txt,"?",3
covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tMRIcon.txt,sys0,1
//tMR
spstr strCommand.txt,tMR.txt,"?",4
//tForecast1 //tForecast1
spstr strCommand.txt,tForecast1.txt,"?",5 spstr strCommand.txt,tForecast1.txt,"?",3
//tF1Icon //tF1Icon
spstr strCommand.txt,tTmp.txt,"?",6 spstr strCommand.txt,tTmp.txt,"?",4
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tF1Icon.txt,sys0,1 substr pageIcons.tIcons.txt,tF1Icon.txt,sys0,1
//tForecast1Val //tForecast1Val
spstr strCommand.txt,tForecast1Val.txt,"?",7 spstr strCommand.txt,tForecast1Val.txt,"?",5
//tForecast2 //tForecast2
spstr strCommand.txt,tForecast2.txt,"?",8 spstr strCommand.txt,tForecast2.txt,"?",6
//tF2Icon //tF2Icon
spstr strCommand.txt,tTmp.txt,"?",9 spstr strCommand.txt,tTmp.txt,"?",7
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tF2Icon.txt,sys0,1 substr pageIcons.tIcons.txt,tF2Icon.txt,sys0,1
//tForecast2Val //tForecast2Val
spstr strCommand.txt,tForecast2Val.txt,"?",10 spstr strCommand.txt,tForecast2Val.txt,"?",8
} //tForecast3
if(tInstruction.txt=="page") spstr strCommand.txt,tForecast3.txt,"?",9
{ //tF3Icon
//pagenumber spstr strCommand.txt,tTmp.txt,"?",10
spstr strCommand.txt,tTmp.txt,",",1
covx tTmp.txt,sys0,0,0 covx tTmp.txt,sys0,0,0
nPage=sys0 substr pageIcons.tIcons.txt,tF3Icon.txt,sys0,1
//don't send current page number, wake will do //tForecast3Val
spstr strCommand.txt,tForecast3Val.txt,"?",11
//tForecast4
spstr strCommand.txt,tForecast4.txt,"?",12
//tF4Icon
spstr strCommand.txt,tTmp.txt,"?",13
covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tF4Icon.txt,sys0,1
//tForecast4Val
spstr strCommand.txt,tForecast4Val.txt,"?",14
} }
if(tInstruction.txt=="pageType") if(tInstruction.txt=="pageType")
{ {
@@ -804,12 +970,10 @@ TouchCap tc0
Events Events
Touch Press Event Touch Press Event
//page open event dim=100
// event,pageOpen,cardEntities,pageNumber vaTap.val+=1
// craft command covx vaTap.val,tTmp.txt,0,0
// convert pageNumber and write to tTmp tSend.txt="event,buttonPress2,screensaver,bExit,"+tTmp.txt
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+tTmp.txt
//send calc crc //send calc crc
btlen tSend.txt,sys0 btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC crcrest 1,0xffff // reset CRC

Binary file not shown.

Binary file not shown.

View File

@@ -202,7 +202,7 @@ Due the limitations of Berry, it's not possible to download the tft file directl
The following Link has always the latest version from this repository, just execute the following Command in Tasmota: The following Link has always the latest version from this repository, just execute the following Command in Tasmota:
`FlashNextion http://nspanel.pky.eu/lui.tft` `FlashNextion http://nspanel.pky.eu/lui-release.tft`
## Configuration ## Configuration
@@ -244,26 +244,25 @@ Confiure your NSPanel as you like, you need to edit the `apps.yaml` inside of yo
You can have multiple nspanel sections. You can have multiple nspanel sections.
```yaml ```yaml
---
nspanel-1: nspanel-1:
module: nspanel-lovelace-ui module: nspanel-lovelace-ui
class: NsPanelLovelaceUIManager class: NsPanelLovelaceUIManager
config: config:
panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT" panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT"
panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend" panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend"
updateMode: auto-notify # possible values are auto, auto-notify and manual timeoutScreensaver: 20
timeoutScreensaver: 15 #in seconds
#brightnessScreensaver: 10 #brightnessScreensaver: 10
brightnessScreensaver: brightnessScreensaver:
- time: "7:00:00" - time: "7:00:00"
value: 10 value: 10
- time: "23:00:00" - time: "23:00:00"
value: 0 value: 0
locale: "de_DE" # only used if babel python package is installed locale: "de_DE"
dateFormatBabel: "full" # only used if babel python package is installed dateFormatBabel: "full"
# formatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields
timeFormat: "%H:%M" timeFormat: "%H:%M"
dateFormat: "%A, %d. %B %Y" # ignored if babel python package is installed dateFormat: "%A, %d. %B %Y" # ignored if babel python package is installed
weatherEntity: weather.example weather: weather.example
pages: pages:
- type: cardEntities - type: cardEntities
heading: Example Page 1 heading: Example Page 1
@@ -299,8 +298,9 @@ nspanel-1:
heading: Exmaple Thermostat heading: Exmaple Thermostat
item: climate.example_climate item: climate.example_climate
- type: cardMedia - type: cardMedia
heading: Exampe Media
item: media_player.spotify_user item: media_player.spotify_user
- type: cardAlarm
item: alarm_control_panel.alarmo
``` ```
key | optional | type | default | description key | optional | type | default | description
@@ -309,9 +309,42 @@ key | optional | type | default | description
`class` | False | string | | The name of the Class. `class` | False | string | | The name of the Class.
`config` | False | complex | | Config/Mapping between Homeassistant and your NsPanel `config` | False | complex | | Config/Mapping between Homeassistant and your NsPanel
### Override Icons Possible configuration values for config key:
To override Icons of entities you can configure an icon name in your configuration, please see the following example. key | optional | type | default | description
-- | -- | -- | -- | --
`panelRecvTopic` | False | string | `tele/tasmota_your_mqtt_topic/RESULT` | The mqtt topic used to receive messages.
`panelSendTopic` | False | string | `cmnd/tasmota_your_mqtt_topic/CustomSend` | The mqtt topic used to send messages.
`timeoutScreensaver` | True | integer | `20` | Timeout for the screen to enter screensaver, to disable screensaver use 0
`brightnessScreensaver` | True | integer/complex | `20` | Brightness for the screen to enter screensaver, see example below for complex/scheduled config.
`brightnessScreensaverTracking` | True | string | None | Forces screensaver brightness to 0 in case entity state is not_home, can be a group, person or device_tracker entity.
`locale` | True | string | `en_US` | Used by babel to determinante Date format on screensaver, also used for localization.
`dateFormatBabel` | True | string | `full` | formatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields
`timeFormat` | True | string | `%H:%M` | Time Format on screensaver. Substring after `?` is displayed in a seperate smaller textbox. Useful for 12h time format with AM/PM `"%I:%M ?%p"`
`dateFormat` | True | string | `%A, %d. %B %Y` | date format used if babel is not installed
`weather` | True | string | `weather.example` | weather entity from homeassistant
`weatherOverrideForecast1` | True | string | `None` | sensor entity from home assistant here to override the first weather forecast item on the screensaver
`weatherOverrideForecast2` | True | string | `None` | sensor entity from home assistant here to override the second weather forecast item on the screensaver
`weatherOverrideForecast3` | True | string | `None` | sensor entity from home assistant here to override the third weather forecast item on the screensaver
`weatherOverrideForecast4` | True | string | `None` | sensor entity from home assistant here to override the forth weather forecast item on the screensaver
`doubleTapToUnlock` | True | boolean | `False` | requires to tap screensaver two times
`pages` | False | complex | | configuration for pages on panel
#### Schedule screensaver brightness
It is possible to schedule a brightness change for the screen at specific times.
```yaml
brightnessScreensaver:
- time: "7:00:00"
value: 10
- time: "23:00:00"
value: 0
```
#### Override Icons or Names
To override Icons or Names of entities you can configure an icon and/or name in your configuration, please see the following example.
Only the icons listed in the [Icon Table](HMI#icons-ids) are useable. Only the icons listed in the [Icon Table](HMI#icons-ids) are useable.
```yaml ```yaml
@@ -322,6 +355,7 @@ Only the icons listed in the [Icon Table](HMI#icons-ids) are useable.
- light.schreibtischlampe - light.schreibtischlampe
- switch.deckenbeleuchtung_hinten: - switch.deckenbeleuchtung_hinten:
icon: lightbulb icon: lightbulb
name: Lampe
- delete - delete
- delete - delete
- type: cardMedia - type: cardMedia
@@ -342,13 +376,9 @@ HACS will show you that there is an update avalible and ask you to update.
### Update Display Firmware ### Update Display Firmware
Use the following command to update or use your own webserver. FlashNextionFast will use Nextion Upload Protocol 1.2 and try to skip unchanged parts of the firmware. Use the following command to update or use your own webserver.
`FlashNextionFast http://nspanel.pky.eu/lui.tft` `FlashNextion http://nspanel.pky.eu/lui-release.tft`
In case this Update failes, reboot tasmota and use the following command:
`FlashNextion http://nspanel.pky.eu/lui.tft`
### Update Tasmota Berry Driver ### Update Tasmota Berry Driver
@@ -377,4 +407,23 @@ Reboot Tasmota and try to flash it a second time.
Please check your MQTT Topics in your apps.yaml and your mqtt configuration on tasmota. Please check your MQTT Topics in your apps.yaml and your mqtt configuration on tasmota.
### How to upgrade from a release to the current development version
1. Update App in HACS to main
Click redownload in the menu of the app in HACS.
Select main version.
![hacs-main](doc-pics/hacs-main.png)
**Wait for it to load, dropdown needs to be selectable again**
Click download.
2. Restart AppDaemon
3. Flash current Development Firmware in Tasmota Console.
`FlashNextion http://nspanel.pky.eu/lui.tft`

View File

@@ -1,12 +1,12 @@
--- ---
nspanel: nspanel-1:
module: nspanel-lovelace-ui module: nspanel-lovelace-ui
class: NsPanelLovelaceUIManager class: NsPanelLovelaceUIManager
config: config:
panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT" panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT"
panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend" panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend"
updateMode: auto-notify # possible values are auto, auto-notify and manual updateMode: "auto-notify"
timeoutScreensaver: 15 #in seconds timeoutScreensaver: 20
#brightnessScreensaver: 10 #brightnessScreensaver: 10
brightnessScreensaver: brightnessScreensaver:
- time: "7:00:00" - time: "7:00:00"
@@ -18,7 +18,7 @@ nspanel:
# formatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields # formatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields
timeFormat: "%H:%M" timeFormat: "%H:%M"
dateFormat: "%A, %d. %B %Y" # ignored if babel python package is installed dateFormat: "%A, %d. %B %Y" # ignored if babel python package is installed
weatherEntity: weather.example weather: weather.example
pages: pages:
- type: cardEntities - type: cardEntities
heading: Example Page 1 heading: Example Page 1
@@ -54,6 +54,6 @@ nspanel:
heading: Exmaple Thermostat heading: Exmaple Thermostat
item: climate.example_climate item: climate.example_climate
- type: cardMedia - type: cardMedia
heading: Exampe Media
item: media_player.spotify_user item: media_player.spotify_user
- type: cardAlarm
item: alarm_control_panel.alarmo

View File

@@ -0,0 +1,160 @@
import logging
LOGGER = logging.getLogger(__name__)
class PageNode(object):
def __init__(self, data, parent=None):
self.data = data
self.name = None
self.childs = []
self.parent = parent
self.pos = None
if "items" in data:
childs = data.pop("items")
for page in childs:
self.add_child(PageNode(page, self))
name = self.data.get("heading", "unkown") if type(self.data) is dict else self.data
ptype = self.data.get("type", "unkown") if type(self.data) is dict else "leaf"
self.name = f"{ptype}.{name}" if type(self.data) is dict else self.data
self.name = self.name.replace(".","_")
self.name = self.name.replace(",","_")
self.name = self.name.replace(" ","_")
def add_child(self, obj):
obj.pos = len(self.childs)
self.childs.append(obj)
def next(self):
if self.parent is not None:
pos = self.pos
length = len(self.parent.childs)
return self.parent.childs[(pos+1)%length]
else:
return self
def prev(self):
if self.parent is not None:
pos = self.pos
length = len(self.parent.childs)
return self.parent.childs[(pos-1)%length]
else:
return self
def search_page_by_name(self, name):
name = name.replace("navigate.", "")
pages = []
for i in self.childs:
# compare name of current page
if i.name == name:
pages.append(i)
# current pages has also childs
if len(i.childs) > 0:
pages.extend(i.search_page_by_name(name))
return pages
return items
def dump(self, indent=0):
"""dump tree to string"""
tab = ' '*(indent-1) + ' |- ' if indent > 0 else ''
name = self.name
parent = self.parent.name if self.parent is not None else "root"
dumpstring = f"{tab}{self.pos}:{name} -> {parent} \n"
for obj in self.childs:
dumpstring += obj.dump(indent + 1)
return dumpstring
def get_items(self):
items = []
for i in self.childs:
if len(i.childs) > 0:
items.append(f"navigate.{i.name}")
else:
items.append(i.data)
return items
def get_all_item_names(self, recursive=True):
items = []
# current page
if type(self.data) is dict:
items.append(self.data.get("item", next(iter(self.data))))
else:
items.append(self.data)
# childs of page
for i in self.childs:
if len(i.childs) > 0:
if recursive:
items.extend(i.get_all_item_names())
else:
if type(i.data) is dict:
items.append(i.data.get("item", next(iter(i.data))))
else:
items.append(i.data)
return items
class LuiBackendConfig(object):
_DEFAULT_CONFIG = {
'panelRecvTopic': "tele/tasmota_your_mqtt_topic/RESULT",
'panelSendTopic': "cmnd/tasmota_your_mqtt_topic/CustomSend",
'updateMode': "auto-notify",
'timeoutScreensaver': 20,
'brightnessScreensaver': 20,
'brightnessScreensaverTracking': None,
'locale': "en_US",
'timeFormat': "%H:%M",
'dateFormatBabel': "full",
'dateFormat': "%A, %d. %B %Y",
'weather': 'weather.example',
'weatherOverrideForecast1': None,
'weatherOverrideForecast2': None,
'weatherOverrideForecast3': None,
'weatherOverrideForecast4': None,
'doubleTapToUnlock': False,
'pages': [{
'type': 'cardEntities',
'heading': 'Test Entities 1',
'items': ['switch.test_item', 'switch.test_item', 'switch.test_item']
}, {
'type': 'cardGrid',
'heading': 'Test Grid 1',
'items': ['switch.test_item', 'switch.test_item', 'switch.test_item']
}
]
}
def __init__(self, args=None, check=True):
self._config = {}
self._page_config = None
if args:
self.load(args)
if check:
self.check()
def load(self, args):
for k, v in args.items():
if k in self._DEFAULT_CONFIG:
self._config[k] = v
LOGGER.info(f"Loaded config: {self._config}")
root_page = {"items": self.get("pages"), "type": "internal", "heading": "root"}
self._page_config = PageNode(root_page)
LOGGER.info(f"Parsed Page config to the following Tree: \n {self._page_config.dump()}")
def check(self):
return
def get(self, name):
value = self._config.get(name)
if value is None:
value = self._DEFAULT_CONFIG.get(name)
return value
def get_root_page(self):
return self._page_config

View File

@@ -0,0 +1,224 @@
import logging
import datetime
from helper import scale, pos_to_color
from pages import LuiPagesGen
LOGGER = logging.getLogger(__name__)
class LuiController(object):
def __init__(self, ha_api, config, send_mqtt_msg):
self._ha_api = ha_api
self._config = config
self._send_mqtt_msg = send_mqtt_msg
# first child of root page (default, after startup)
self._current_page = self._config._page_config.childs[0]
self._pages_gen = LuiPagesGen(ha_api, config, send_mqtt_msg)
# send panel back to startup page on restart of this script
self._pages_gen.page_type("pageStartup")
# time update callback
time = datetime.time(0, 0, 0)
ha_api.run_minutely(self._pages_gen.update_time, time)
# weather callback
weather_interval = 15 * 60 # 15 minutes
ha_api.run_every(self.weather_update, "now", weather_interval)
# register callbacks
self.register_callbacks()
# register callbacks for each time
if type(self._config.get("brightnessScreensaver")) == list:
for index, timeset in enumerate(self._config.get("brightnessScreensaver")):
self._ha_api.run_daily(self.update_screensaver_brightness, timeset["time"], value=timeset["value"])
# calculate current brightness
self.current_screensaver_brightness = self.calc_current_screensaver_brightness()
# call update_screensaver_brightness on changes of entity configured in brightnessScreensaverTracking
bst = self._config.get("brightnessScreensaverTracking")
if bst is not None and self._ha_api.entity_exists(bst):
self._ha_api.listen_state(self.update_screensaver_brightness, entity_id=bst, value=self.current_screensaver_brightness)
def startup(self):
LOGGER.info(f"Startup Event")
# send time and date on startup
self._pages_gen.update_time("")
self._pages_gen.update_date("")
# set screensaver timeout
timeout = self._config.get("timeoutScreensaver")
self._send_mqtt_msg(f"timeout,{timeout}")
# set current screensaver brightness
self.update_screensaver_brightness(kwargs={"value": self.current_screensaver_brightness})
# send panel to screensaver
self._pages_gen.page_type("screensaver")
self.weather_update("")
def update_screensaver_brightness(self, kwargs):
bst = self._config.get("brightnessScreensaverTracking")
if bst is not None and self._ha_api.entity_exists(bst) and self._ha_api.get_entity(bst).state == "not_home":
self.current_screensaver_brightness = 0
else:
self.current_screensaver_brightness = kwargs['value']
self._send_mqtt_msg(f"dimmode,{self.current_screensaver_brightness}")
def calc_current_screensaver_brightness(self):
current_screensaver_brightness = 20
# set brightness of screensaver
if type(self._config.get("brightnessScreensaver")) == int:
current_screensaver_brightness = self._config.get("brightnessScreensaver")
elif type(self._config.get("brightnessScreensaver")) == list:
sorted_timesets = sorted(self._config.get("brightnessScreensaver"), key=lambda d: self._ha_api.parse_time(d['time']))
# calc current screensaver brightness
found_current_dim_value = False
for index, timeset in enumerate(sorted_timesets):
LOGGER.info("Current time %s", self._ha_api.get_now().time())
if self._ha_api.parse_time(timeset["time"]) > self._ha_api.get_now().time() and not found_current_dim_value:
# first time after current time, set dim value
current_screensaver_brightness = sorted_timesets[index-1]["value"]
LOGGER.info("Setting dim value to %s", sorted_timesets[index-1])
found_current_dim_value = True
# still no dim value
if not found_current_dim_value:
self.current_screensaver_brightness = sorted_timesets[-1]["value"]
return current_screensaver_brightness
def weather_update(self, kwargs):
we_name = self._config.get("weather")
unit = "°C"
self._pages_gen.update_screensaver_weather(kwargs={"weather": we_name, "unit": unit})
def register_callbacks(self):
items = self._config.get_root_page().get_all_item_names()
LOGGER.debug(f"Registering callbacks for the following items: {items}")
for item in items:
if self._ha_api.entity_exists(item):
self._ha_api.listen_state(self.state_change_callback, entity_id=item, attribute="all")
def state_change_callback(self, entity, attribute, old, new, kwargs):
LOGGER.debug(f"Got callback for: {entity}")
LOGGER.debug(f"Current page has the following items: {self._current_page.get_items()}")
if entity in self._current_page.get_all_item_names(recursive=False):
LOGGER.debug(f"Callback Entity is on current page: {entity}")
self._pages_gen.render_page(self._current_page, send_page_type=False)
# send detail page update, just in case
if self._current_page.data.get("type", "unknown") in ["cardGrid", "cardEntities"]:
if entity.startswith("light"):
self._pages_gen.generate_light_detail_page(entity)
if entity.startswith("cover"):
self._pages_gen.generate_shutter_detail_page(entity)
def detail_open(self, detail_type, entity_id):
if detail_type == "popupShutter":
self._pages_gen.generate_shutter_detail_page(entity_id)
if detail_type == "popupLight":
self._pages_gen.generate_light_detail_page(entity_id)
def button_press(self, entity_id, button_type, value):
LOGGER.info(f"Button Press Event; entity_id: {entity_id}; button_type: {button_type}; value: {value} ")
# internal buttons
if entity_id == "screensaver" and button_type == "bExit":
if self._config.get("doubleTapToUnlock") and int(value) >= 2:
self._pages_gen.render_page(self._current_page)
elif not self._config.get("doubleTapToUnlock"):
self._pages_gen.render_page(self._current_page)
return
if button_type == "bExit":
self._pages_gen.render_page(self._current_page)
if button_type == "bNext":
self._current_page = self._current_page.next()
self._pages_gen.render_page(self._current_page)
if button_type == "bPrev":
self._current_page = self._current_page.prev()
self._pages_gen.render_page(self._current_page)
elif entity_id == "updateDisplayNoYes" and value == "no":
self._pages_gen.render_page(self._current_page)
# buttons with actions on HA
if button_type == "OnOff":
if value == "1":
self._ha_api.turn_on(entity_id)
else:
self._ha_api.turn_off(entity_id)
# for shutter / covers
if button_type == "up":
self._ha_api.get_entity(entity_id).call_service("open_cover")
if button_type == "stop":
self._ha_api.get_entity(entity_id).call_service("stop_cover")
if button_type == "down":
self._ha_api.get_entity(entity_id).call_service("close_cover")
if button_type == "positionSlider":
pos = int(value)
self._ha_api.get_entity(entity_id).call_service("set_cover_position", position=pos)
if button_type == "button":
if entity_id.startswith('navigate'):
# internal for navigation to nested pages
self._current_page = self._config.get_root_page().search_page_by_name(entity_id)[0]
self._pages_gen.render_page(self._current_page)
elif entity_id.startswith('scene'):
self._ha_api.get_entity(entity_id).call_service("turn_on")
elif entity_id.startswith('light') or entity_id.startswith('switch') or entity_id.startswith('input_boolean'):
self._ha_api.get_entity(entity_id).call_service("toggle")
else:
self._ha_api.get_entity(entity_id).call_service("press")
# for media page
if button_type == "media-next":
self._ha_api.get_entity(entity_id).call_service("media_next_track")
if button_type == "media-back":
self._ha_api.get_entity(entity_id).call_service("media_previous_track")
if button_type == "media-pause":
self._ha_api.get_entity(entity_id).call_service("media_play_pause")
if button_type == "media-OnOff":
if player.state == "off":
self._ha_api.get_entity(entity_id).call_service("turn_on")
else:
self._ha_api.get_entity(entity_id).call_service("turn_off")
if button_type == "volumeSlider":
pos = int(value)
# HA wants this value between 0 and 1 as float
pos = pos/100
self._ha_api.get_entity(entity_id).call_service("volume_set", volume_level=pos)
if button_type == "speaker-sel":
self._ha_api.get_entity(entity_id).call_service("select_source", source=value)
# for light detail page
if button_type == "brightnessSlider":
# scale 0-100 to ha brightness range
brightness = int(scale(int(value),(0,100),(0,255)))
self._ha_api.get_entity(entity_id).call_service("turn_on", brightness=brightness)
if button_type == "colorTempSlider":
entity = self._ha_api.get_entity(entity_id)
#scale 0-100 from slider to color range of lamp
color_val = scale(int(value), (0, 100), (entity.attributes.min_mireds, entity.attributes.max_mireds))
self._ha_api.get_entity(entity_id).call_service("turn_on", color_temp=color_val)
if button_type == "colorWheel":
self._ha_api.log(value)
value = value.split('|')
color = pos_to_color(int(value[0]), int(value[1]))
self._ha_api.log(color)
self._ha_api.get_entity(entity_id).call_service("turn_on", rgb_color=color)
# for climate page
if button_type == "tempUpd":
temp = int(value)/10
self._ha_api.get_entity(entity_id).call_service("set_temperature", temperature=temp)
if button_type == "hvac_action":
self._ha_api.get_entity(entity_id).call_service("set_hvac_mode", hvac_mode=value)
# for alarm page
if button_type in ["disarm", "arm_home", "arm_away", "arm_night", "arm_vacation"]:
self._ha_api.get_entity(entity_id).call_service(f"alarm_{button_type}", code=value)

View File

@@ -10,6 +10,7 @@ def scale(val, src, dst):
def hsv2rgb(h, s, v): def hsv2rgb(h, s, v):
hsv = colorsys.hsv_to_rgb(h,s,v) hsv = colorsys.hsv_to_rgb(h,s,v)
return tuple(round(i * 255) for i in hsv) return tuple(round(i * 255) for i in hsv)
def pos_to_color(x, y): def pos_to_color(x, y):
r = 160/2 r = 160/2
x = round((x - r) / r * 100) / 100 x = round((x - r) / r * 100) / 100
@@ -26,10 +27,13 @@ def pos_to_color(x, y):
return rgb return rgb
def rgb_brightness(rgb_color, brightness): def rgb_brightness(rgb_color, brightness):
# brightness values are in range 0-255
# to make sure that the color is not completly lost we need to rescale this to 70-255
brightness = int(scale(brightness,(0,255),(70,255)))
red = rgb_color[0]/255*brightness red = rgb_color[0]/255*brightness
green = rgb_color[1]/255*brightness green = rgb_color[1]/255*brightness
blue = rgb_color[2]/255*brightness blue = rgb_color[2]/255*brightness
return [red, green, blue] return [int(red), int(green), int(blue)]
def rgb_dec565(rgb_color): def rgb_dec565(rgb_color):
red = rgb_color[0] red = rgb_color[0]
@@ -37,4 +41,8 @@ def rgb_dec565(rgb_color):
blue = rgb_color[2] blue = rgb_color[2]
# take in the red, green and blue values (0-255) as 8 bit values and then combine # take in the red, green and blue values (0-255) as 8 bit values and then combine
# and shift them to make them a 16 bit dec value in 565 format. # and shift them to make them a 16 bit dec value in 565 format.
return ((int(red / 255 * 31) << 11) | (int(green / 255 * 63) << 5) | (int(blue / 255 * 31))) return ((int(red / 255 * 31) << 11) | (int(green / 255 * 63) << 5) | (int(blue / 255 * 31)))
def get_attr_safe(entity, attr, default):
res = entity.attributes.get(attr, default) if not None else default
return res

View File

@@ -38,6 +38,11 @@ icons = {
'door-open': 36, 'door-open': 36,
'door-closed': 37, 'door-closed': 37,
'window-closed': 38, 'window-closed': 38,
'shield-off': 39,
'shield': 40,
'shield-lock': 41,
'shield-airplane': 42,
'bell-ring': 43,
} }
def get_icon_id(ma_name): def get_icon_id(ma_name):

View File

@@ -0,0 +1,349 @@
translations = {
'af_ZA': {
'ACTIVATE': "Aktiveer",
'aux_heat': "Aanvullende hitte",
'cooling': "Koel Af",
'drying': "Droog Uit",
'fan': "Waaier",
'idle': "Onaktief",
'off': "Af",
'arm_away': "Bewapen weg",
'arm_custom_bypass': "Pasgemaakte omseil",
'arm_home': "Bewapen Huis",
'arm_night': "Nag alarm",
'clear_code': "Maak skoon",
'code': "Kode",
'disarm': "Skakel Af",
},
'ca_ES': {
'PRESS': "Prem",
'ACTIVATE': "Activar",
'aux_heat': "Calefactor auxiliar",
'cooling': "Refredant",
'drying': "Assecant",
'fan': "Ventilació",
'idle': "Inactiu",
'off': "OFF",
'arm_away': "Activar, fora",
'arm_custom_bypass': "Bypass personalitzat",
'arm_home': "Activar, a casa",
'arm_night': "Activar, nocturn",
'arm_vacation': "Activa en mode vacances",
'clear_code': "Borrar",
'code': "Codi",
'disarm': "Desactivar",
},
'cs_CZ': {
'PRESS': "Stisknutí",
'ACTIVATE': "Aktivovat",
'aux_heat': "Pomocné teplo",
'cooling': "Chlazení",
'drying': "Sušení",
'fan': "Ventilátor",
'idle': "Nečinný",
'off': "Vypnuto",
'arm_away': "Aktivovat režim nepřítomnost",
'arm_custom_bypass': "Vlastní obejítí",
'arm_home': "Aktivovat režim domov",
'arm_night': "Aktivovat noční režim",
'arm_vacation': "Aktivovat režim dovolená",
'clear_code': "Zrušit",
'code': "Kód",
'disarm': "Odbezpečit",
},
'cy_GB': {
'ACTIVATE': "Actifadu",
'off': "I ffwrdd",
'arm_custom_bypass': "Ffordd osgoi personol",
'arm_night': "Larwm nos",
'code': "Cod dilysu dwy-ffactor",
},
'da_DK': {
'PRESS': "Tryk",
'ACTIVATE': "Aktiver",
'aux_heat': "Støtte-varme",
'cooling': "Køling",
'drying': "Tørring",
'fan': "Blæser",
'idle': "Inaktiv",
'off': "Fra",
'arm_away': "Tilkobl ude",
'arm_custom_bypass': "Brugerdefineret bypass",
'arm_home': "Tilkobl hjemme",
'arm_night': "Tilkoblet nat",
'arm_vacation': "Tilkobl ferie",
'clear_code': "Ryd",
'code': "Kode",
'disarm': "Frakobl",
},
'de_DE': {
'PRESS': "Drücken",
'ACTIVATE': "Aktivieren",
'aux_heat': "Hilfswärme",
'cooling': "Kühlung",
'drying': "Trocknen",
'fan': "Ventilator",
'idle': "Leerlauf",
'off': "Aus",
'arm_away': "Aktivieren - Unterwegs",
'arm_custom_bypass': "Benutzerdefinierter Bypass",
'arm_home': "Aktivieren - Zuhause",
'arm_night': "Aktivieren - Nacht",
'arm_vacation': "Aktiviere Urlaub",
'clear_code': "Löschen",
'code': "Code",
'disarm': "Deaktivieren",
},
'en_US': {
'PRESS': "Press",
'ACTIVATE': "Activate",
'aux_heat': "Aux heat",
'cooling': "Cooling",
'drying': "Drying",
'fan': "Fan",
'idle': "Idle",
'off': "Off",
'arm_away': "Arm away",
'arm_custom_bypass': "Custom bypass",
'arm_home': "Arm home",
'arm_night': "Arm night",
'arm_vacation': "Arm vacation",
'clear_code': "Clear",
'code': "Code",
'disarm': "Disarm",
},
'es_ES': {
'PRESS': "Pulsa",
'ACTIVATE': "Activar",
'aux_heat': "Calor auxiliar",
'cooling': "Enfriando",
'drying': "Secando",
'fan': "Ventilador",
'idle': "Inactivo",
'off': "Apagado",
'arm_away': "Armar ausente",
'arm_custom_bypass': "Bypass personalizada",
'arm_home': "Armar en casa",
'arm_night': "Armar noche",
'arm_vacation': "Armar por vacaciones",
'clear_code': "Limpiar",
'code': "Código",
'disarm': "Desarmar",
},
'et_EE': {
'PRESS': "Vajuta nuppu",
'ACTIVATE': "Aktiveeri",
'aux_heat': "Abiküte",
'cooling': "Jahutamine",
'drying': "Kuivatamine",
'fan': "Ventilaator",
'idle': "Ootel",
'off': "Väljas",
'arm_away': "Valvesta eemal",
'arm_custom_bypass': "Eranditega",
'arm_home': "Valvesta kodus",
'arm_night': "Valvesta öine",
'arm_vacation': "Valvesta puhkuse režiimis",
'clear_code': "Puhasta",
'code': "Kood",
'disarm': "Valvest maha",
},
'eu_ES': {
'ACTIVATE': "Aktibatu",
'off': "Itzalita",
'clear_code': "Garbitu",
'code': "Kodea",
},
'fi_FI': {
'PRESS': "Paina",
'ACTIVATE': "Aktivoi",
'aux_heat': "Lisälämpö",
'cooling': "Jäähdytys",
'drying': "Kuivaus",
'fan': "Tuuletin",
'idle': "Lepotilassa",
'off': "Pois",
'arm_away': "Viritä (poissa)",
'arm_custom_bypass': "Mukautettu ohitus",
'arm_home': "Viritä (kotona)",
'arm_night': "Viritä yöksi",
'arm_vacation': "Aktivoi lomatila",
'clear_code': "Tyhjennä",
'code': "Koodi",
'disarm': "Poista hälytys",
},
'fr_FR': {
'PRESS': "Appui",
'ACTIVATE': "Activer",
'aux_heat': "Chauffage d'appoint",
'cooling': "Refroidissement",
'drying': "Séchage",
'fan': "Ventilateur",
'idle': "Inactif",
'off': "Off",
'arm_away': "Armer (absent)",
'arm_custom_bypass': "Bypass personnalisé",
'arm_home': "Armer (présent)",
'arm_night': "Armer nuit",
'arm_vacation': "Armer vacances",
'clear_code': "Effacer",
'code': "Code",
'disarm': "Désarmer",
},
'fy_DE': {
'off': "Út",
},
'gl_ES': {
'off': "Apagado",
},
'hr_HR': {
'ACTIVATE': "Aktivirati",
'aux_heat': "Pomoćno grijanje",
'cooling': "Hlađenje",
'drying': "Sušenje",
'fan': "Ventilator",
'idle': "Neaktivan",
'off': "Isključen",
'arm_away': "Aktiviran odsutno",
'arm_custom_bypass': "Prilagođena premosnica",
'arm_home': "Aktiviran doma",
'arm_night': "Aktiviran nočni",
'clear_code': "Vedro",
'code': "Kod",
'disarm': "Deaktiviraj",
},
'id_ID': {
'PRESS': "Tekan",
'ACTIVATE': "Aktifkan",
'aux_heat': "Pemanasan tambahan",
'cooling': "Mendinginkan",
'drying': "Mengeringkan",
'fan': "Kipas",
'idle': "Diam",
'off': "Mati",
'arm_away': "Aktifkan utk keluar",
'arm_custom_bypass': "Diaktifkan khusus",
'arm_home': "Aktifkan utk di rumah",
'arm_night': "Aktifkan utk malam",
'arm_vacation': "Aktifkan utk liburan",
'clear_code': "Hapus",
'code': "Kode",
'disarm': "Nonaktifkan",
},
'is_IS': {
'PRESS': "Ýttu á",
'ACTIVATE': "Virkja",
'cooling': "Kæling",
'drying': "Þurrkun",
'fan': "Vifta",
'idle': "Aðgerðalaus",
'off': "Slökkt",
'arm_away': "Vörður úti",
'arm_custom_bypass': "Sérsniðin hjáleið",
'arm_home': "Vörður heima",
'arm_night': "Vörður nótt",
'arm_vacation': "Vörður frí",
'clear_code': "Hreinsa",
'code': "Kóði",
'disarm': "Taka af verði",
},
'it_IT': {
'PRESS': "Premi",
'ACTIVATE': "Attiva",
'aux_heat': "Riscaldamento ausiliario",
'cooling': "Raffreddamento",
'drying': "Deumidificazione",
'fan': "Ventilatore",
'idle': "Inattivo",
'off': "Spento",
'arm_away': "Attiva fuori casa",
'arm_custom_bypass': "Bypass personalizzato",
'arm_home': "Attiva in casa",
'arm_night': "Attiva notte",
'arm_vacation': "Attiva in vacanza",
'clear_code': "Canc",
'code': "Codice",
'disarm': "Disattiva",
},
'nl_NL': {
'PRESS': "Klik",
'ACTIVATE': "Activeren",
'aux_heat': "Extra warmte",
'cooling': "Koelen",
'drying': "Ontvochtigen",
'fan': "Ventilator",
'idle': "Inactief",
'off': "Uit",
'arm_away': "Inschakelen voor vertrek",
'arm_custom_bypass': "Inschakelen met overbrugging",
'arm_home': "Inschakelen voor thuis",
'arm_night': "Inschakelen voor 's nachts",
'arm_vacation': "Inschakelen voor vakantie",
'clear_code': "Wis",
'code': "Code",
'disarm': "Uitschakelen",
},
'nn_NO': {
'ACTIVATE': "Aktiver",
'aux_heat': "Aux-varme",
'cooling': "Nedkjøling",
'drying': "Tørkar",
'fan': "Vifte",
'idle': "Tomgang",
'off': "Av",
'arm_away': "Bortemodus",
'arm_custom_bypass': "Tilpassa bypass",
'arm_home': "Heimemodus",
'arm_night': "Aktiver natt",
'arm_vacation': "Armert feriemodus",
'clear_code': "Slett alt",
'code': "Kode",
'disarm': "Skru av",
},
'pt_PT': {
'PRESS': "Pressione",
'ACTIVATE': "Ativar",
'aux_heat': "Calor auxiliar",
'cooling': "Resfriar",
'drying': "Secagem",
'fan': "Ventoinha",
'idle': "Em espera",
'off': "Desligado",
'arm_away': "Armado ausente",
'arm_custom_bypass': "Desvio personalizado",
'arm_home': "Armado casa",
'arm_night': "Armado noite",
'clear_code': "Apagar",
'code': "Código",
'disarm': "Desarmar",
},
'sr_RS': {
'PRESS': "Pritisnite taster",
'ACTIVATE': "Aktiviraj",
'off': "Isključen",
},
'sv_SE': {
'PRESS': "Tryck",
'ACTIVATE': "Aktivera",
'aux_heat': "Underhållsvärme",
'cooling': "Kyler",
'drying': "Avfuktar",
'fan': "Fläkt",
'idle': "Inaktiv",
'off': "Av",
'arm_away': "Larma bortaläge",
'arm_custom_bypass': "Larm förbikopplat",
'arm_home': "Larma hemmaläge",
'arm_night': "Larma nattläge",
'arm_vacation': "Larma semesterläge",
'clear_code': "Rensa",
'code': "Kod",
'disarm': "Larma från",
},
}
def get_translation(locale, input):
if locale in translations:
return translations.get(locale).get(input, input)
else:
return translations.get("en_US").get(input, input)

View File

@@ -0,0 +1,54 @@
import json
import logging
LOGGER = logging.getLogger(__name__)
class LuiMqttListener(object):
def __init__(self, mqtt_api, topic, controller, updater):
self._controller = controller
self._updater = updater
# Setup, mqtt subscription and callback
mqtt_api.mqtt_subscribe(topic=topic)
mqtt_api.listen_event(self.mqtt_event_callback, "MQTT_MESSAGE", topic=topic, namespace='mqtt')
def mqtt_event_callback(self, event_name, data, kwargs):
LOGGER.debug(f'MQTT callback for: {data}')
# Parse Json Message from Tasmota and strip out message from nextion display
data = json.loads(data["payload"])
if("nlui_driver_version" in data):
msg = data["nlui_driver_version"]
self._updater.set_tasmota_driver_version(int(msg))
self._updater.check_updates()
if("CustomRecv" not in data):
return
msg = data["CustomRecv"]
LOGGER.info(f"Received Message from Screen: {msg}")
# Split message into parts seperated by ","
msg = msg.split(",")
# run action based on received command
if msg[0] == "event":
if msg[1] == "startup":
display_firmware_version = int(msg[2])
self._updater.set_current_display_firmware_version(display_firmware_version)
# check for updates
msg_send = self._updater.check_updates()
# send messages for current page
if not msg_send:
self._controller.startup()
if msg[1] == "screensaverOpen":
self._controller.weather_update("")
if msg[1] == "buttonPress2":
entity_id = msg[2]
btype = msg[3]
value = msg[4] if len(msg) > 4 else None
if entity_id == "updateDisplayNoYes" and value == "yes":
self._updater.update_panel_driver()
self._controller.button_press(entity_id, btype, value)
if msg[1] == "pageOpenDetail":
self._controller.detail_open(msg[2], msg[3])

View File

@@ -0,0 +1,375 @@
import logging
import datetime
from icon_mapping import get_icon_id
from icons import get_icon_id_ha
from helper import scale, rgb_dec565, rgb_brightness, get_attr_safe
from localization import get_translation
# check Babel
import importlib
babel_spec = importlib.util.find_spec("babel")
if babel_spec is not None:
import babel.dates
LOGGER = logging.getLogger(__name__)
class LuiPagesGen(object):
def __init__(self, ha_api, config, send_mqtt_msg):
self._ha_api = ha_api
self._config = config
self._locale = config.get("locale")
self._send_mqtt_msg = send_mqtt_msg
def get_entity_color(self, entity):
attr = entity.attributes
default_color_on = rgb_dec565([253, 216, 53])
default_color_off = rgb_dec565([68, 115, 158])
icon_color = default_color_on if entity.state == "on" else default_color_off
if "rgb_color" in attr:
color = attr.rgb_color
if "brightness" in attr:
color = rgb_brightness(color, attr.brightness)
icon_color = rgb_dec565(color)
elif "brightness" in attr:
color = rgb_brightness([253, 216, 53], attr.brightness)
icon_color = rgb_dec565(color)
return icon_color
def update_time(self, kwargs):
time = datetime.datetime.now().strftime(self._config.get("timeFormat"))
self._send_mqtt_msg(f"time,{time}")
def update_date(self, kwargs):
global babel_spec
if babel_spec is not None:
dateformat = self._config.get("dateFormatBabel")
date = babel.dates.format_date(datetime.datetime.now(), dateformat, locale=self._locale)
else:
dateformat = self._config.get("dateFormat")
date = datetime.datetime.now().strftime(dateformat)
self._send_mqtt_msg(f"date,?{date}")
def page_type(self, target_page):
self._send_mqtt_msg(f"pageType,{target_page}")
def update_screensaver_weather(self, kwargs):
global babel_spec
we_name = kwargs['weather']
unit = kwargs['unit']
if self._ha_api.entity_exists(we_name):
we = self._ha_api.get_entity(we_name)
else:
LOGGER.error("Skipping Weather Update, entitiy not found")
return
icon_cur = get_icon_id_ha("weather", state=we.state)
text_cur = f"{we.attributes.temperature}{unit}"
weather_res = ""
for i in range(1,5):
wOF = self._config.get(f"weatherOverrideForecast{i}")
if wOF is None:
up = we.attributes.forecast[i-1]['datetime']
up = datetime.datetime.fromisoformat(up)
if babel_spec is not None:
up = babel.dates.format_date(up, "E", locale=self._locale)
else:
up = up.strftime("%a")
icon = get_icon_id_ha("weather", state=we.attributes.forecast[i-1]['condition'])
down = f"{we.attributes.forecast[i-1]['temperature']} {unit}"
else:
LOGGER.info(f"Forecast 1 is overrriden with {wOF}")
icon = None
name = None
if type(wOF) is dict:
icon = next(iter(wOF.items()))[1].get('icon')
name = next(iter(wOF.items()))[1].get('name')
wOF = next(iter(wOF.items()))[0]
entity = self._ha_api.get_entity(wOF)
up = name if name is not None else entity.attributes.friendly_name
icon = get_icon_id_ha("sensor", state=entity.state, device_class=entity.attributes.get("device_class", ""), overwrite=icon)
unit_of_measurement = entity.attributes.get("unit_of_measurement", "")
down = f"{entity.state} {unit_of_measurement}"
weather_res+=f"?{up}?{icon}?{down}"
self._send_mqtt_msg(f"weatherUpdate,?{icon_cur}?{text_cur}{weather_res}")
def generate_entities_item(self, item):
icon = None
name = None
if type(item) is dict:
icon = next(iter(item.items()))[1].get('icon')
name = next(iter(item.items()))[1].get('name')
item = next(iter(item.items()))[0]
# type of the item is the string before the "." in the item name
item_type = item.split(".")[0]
LOGGER.debug(f"Generating item command for {item} with type {item_type}",)
# Internal Entities
if item_type == "delete":
return f",{item_type},,,,,"
if item_type == "navigate":
page_search = self._config.get_root_page().search_page_by_name(item)
if len(page_search) > 0:
page_data = page_search[0].data
if name is None:
name = page_data.get("heading")
text = get_translation(self._locale,"PRESS")
icon_id = get_icon_id(icon) if icon is not None else get_icon_id(page_data.get("icon", "gesture-tap-button"))
return f",button,{item},{icon_id},17299,{name},{text}"
else:
return f",text,{item},{get_icon_id('alert-circle-outline')},17299,page not found,"
if not self._ha_api.entity_exists(item):
return f",text,{item},{get_icon_id('alert-circle-outline')},17299,Not found check, apps.yaml"
# HA Entities
entity = self._ha_api.get_entity(item)
name = name if name is not None else entity.attributes.friendly_name
if item_type == "cover":
icon_id = get_icon_id_ha("cover", state=entity.state, overwrite=icon)
return f",shutter,{item},{icon_id},17299,{name},"
if item_type in "light":
switch_val = 1 if entity.state == "on" else 0
icon_color = self.get_entity_color(entity)
icon_id = get_icon_id_ha("light", overwrite=icon)
return f",{item_type},{item},{icon_id},{icon_color},{name},{switch_val}"
if item_type in ["switch", "input_boolean"]:
switch_val = 1 if entity.state == "on" else 0
icon_color = self.get_entity_color(entity)
icon_id = get_icon_id_ha(item_type, state=entity.state, overwrite=icon)
return f",switch,{item},{icon_id},{icon_color},{name},{switch_val}"
if item_type in ["sensor", "binary_sensor"]:
device_class = entity.attributes.get("device_class", "")
icon_id = get_icon_id_ha("sensor", state=entity.state, device_class=device_class, overwrite=icon)
unit_of_measurement = entity.attributes.get("unit_of_measurement", "")
value = entity.state + " " + unit_of_measurement
icon_color = self.get_entity_color(entity)
return f",text,{item},{icon_id},{icon_color},{name},{value}"
if item_type in ["button", "input_button"]:
icon_id = get_icon_id_ha("button", overwrite=icon)
text = get_translation(self._locale,"PRESS")
return f",button,{item},{icon_id},17299,{name},{text}"
if item_type == "scene":
icon_id = get_icon_id_ha("scene", overwrite=icon)
text = get_translation(self._locale,"ACTIVATE")
return f",button,{item},{icon_id},17299,{name},{text}"
def generate_entities_page(self, heading, items):
# Set Heading of Page
self._send_mqtt_msg(f"entityUpdHeading,{heading}")
# Get items and construct cmd string
command = "entityUpd"
for item in items:
command += self.generate_entities_item(item)
self._send_mqtt_msg(command)
def generate_thermo_page(self, item):
if not self._ha_api.entity_exists(item):
command = f"entityUpd,{item},Not found,220,220,Not found,150,300,5"
else:
entity = self._ha_api.get_entity(item)
heading = entity.attributes.friendly_name
current_temp = int(get_attr_safe(entity, "current_temperature", 0)*10)
dest_temp = int(get_attr_safe(entity, "temperature", 0)*10)
status = get_attr_safe(entity, "hvac_action", "")
status = get_translation(self._locale,status)
min_temp = int(get_attr_safe(entity, "min_temp", 0)*10)
max_temp = int(get_attr_safe(entity, "max_temp", 0)*10)
step_temp = int(get_attr_safe(entity, "target_temp_step", 0.5)*10)
icon_res = ""
hvac_modes = get_attr_safe(entity, "hvac_modes", [])
for mode in hvac_modes:
icon_id = get_icon_id('alert-circle-outline')
color_on = 64512
if mode == "auto":
icon_id = get_icon_id("calendar-sync")
color_on = 1024
if mode == "heat":
icon_id = get_icon_id("fire")
color_on = 64512
if mode == "off":
icon_id = get_icon_id("power")
color_on = 35921
if mode == "cool":
icon_id = get_icon_id("snowflake")
color_on = 11487
if mode == "dry":
icon_id = get_icon_id("water-percent")
color_on = 60897
if mode == "fan_only":
icon_id = get_icon_id("fan")
color_on = 35921
state = 0
if(mode == entity.state):
state = 1
icon_res += f",{icon_id},{color_on},{state},{mode}"
len_hvac_modes = len(hvac_modes)
if len_hvac_modes%2 == 0:
# even
padding_len = int((4-len_hvac_modes)/2)
icon_res = ","*4*padding_len + icon_res + ","*4*padding_len
# use last 4 icons
icon_res = ","*4*5 + icon_res
else:
# uneven
padding_len = int((5-len_hvac_modes)/2)
icon_res = ","*4*padding_len + icon_res + ","*4*padding_len
# use first 5 icons
icon_res = icon_res + ","*4*4
command = f"entityUpd,{item},{heading},{current_temp},{dest_temp},{status},{min_temp},{max_temp},{step_temp}{icon_res}"
self._send_mqtt_msg(command)
def generate_media_page(self, item):
if not self._ha_api.entity_exists(item):
command = f"entityUpd,|{item}|Not found|{get_icon_id('alert-circle-outline')}|Please check your|apps.yaml in AppDaemon|50|{get_icon_id('alert-circle-outline')}"
else:
entity = self._ha_api.get_entity(item)
heading = entity.attributes.friendly_name
icon = 0
title = get_attr_safe(entity, "media_title", "")
author = get_attr_safe(entity, "media_artist", "")
volume = int(get_attr_safe(entity, "volume_level", 0)*100)
iconplaypause = get_icon_id("pause") if entity.state == "playing" else get_icon_id("play")
if "media_content_type" in entity.attributes:
if entity.attributes.media_content_type == "music":
icon = get_icon_id("music")
source = get_attr_safe(entity, "source", "")
speakerlist = get_attr_safe(entity, "source_list",[])
if source in speakerlist:
# move current source to the end of the list
speakerlist.remove(source)
speakerlist.append(source)
if len(speakerlist) == 1:
speakerlist = []
speakerlist = "?".join(speakerlist)
bits = entity.attributes.supported_features
onoffbutton = "disable"
if bits & 0b01000000:
if entity.state == "off":
onoffbutton = 1374
else:
onoffbutton = rgb_dec565([255,255,255])
command = f"entityUpd,|{item}|{heading}|{icon}|{title}|{author}|{volume}|{iconplaypause}|{source}|{speakerlist}|{onoffbutton}"
self._send_mqtt_msg(command)
def generate_alarm_page(self, item):
if not self._ha_api.entity_exists(item):
command = f"entityUpd,{item},Not found,Not found,Check your,Check your,apps.,apps.,yaml,yaml,0,,0"
else:
entity = self._ha_api.get_entity(item)
icon = get_icon_id("shield-off")
color = rgb_dec565([255,255,255])
supported_modes = []
numpad = "enable"
if entity.state == "disarmed":
color = rgb_dec565([13,160,53])
icon = get_icon_id("shield-off")
test = entity.attributes.get("code_arm_required", "false")
if not entity.attributes.get("code_arm_required", False):
numpad = "disable"
bits = entity.attributes.supported_features
if bits & 0b000001:
supported_modes.append("arm_home")
if bits & 0b000010:
supported_modes.append("arm_away")
if bits & 0b000100:
supported_modes.append("arm_night")
if bits & 0b100000:
supported_modes.append("arm_vacation")
else:
supported_modes.append("disarm")
if entity.state == "armed_home":
color = rgb_dec565([223,76,30])
icon = get_icon_id("shield-home")
if entity.state == "armed_away":
color = rgb_dec565([223,76,30])
icon = get_icon_id("shield-lock")
if entity.state == "armed_night":
color = rgb_dec565([223,76,30])
icon = get_icon_id("weather-night")
if entity.state == "armed_vacation":
color = rgb_dec565([223,76,30])
icon = get_icon_id("shield-airplane")
flashing = "disable"
if entity.state in ["arming", "pending"]:
color = rgb_dec565([243,179,0])
icon = get_icon_id("shield")
flashing = "enable"
if entity.state == "triggered":
color = rgb_dec565([223,76,30])
icon = get_icon_id("bell-ring")
flashing = "enable"
# add padding to arm buttons
arm_buttons = ""
for b in supported_modes:
arm_buttons += f",{get_translation(self._locale, b)},{b}"
if len(supported_modes) < 4:
arm_buttons += ","*((4-len(supported_modes))*2)
command = f"entityUpd,{item}{arm_buttons},{icon},{color},{numpad},{flashing}"
self._send_mqtt_msg(command)
def render_page(self, page, send_page_type=True):
config = page.data
page_type = config["type"]
LOGGER.info(f"Started rendering of page {page.pos} with type {page_type}")
# Switch to page
if send_page_type:
self.page_type(page_type)
if page_type in ["cardEntities", "cardGrid"]:
heading = config.get("heading", "unknown")
self.generate_entities_page(heading, page.get_items())
return
if page_type == "cardThermo":
self.generate_thermo_page(page.data.get("item"))
if page_type == "cardMedia":
self.generate_media_page(page.data.get("item"))
if page_type == "cardAlarm":
self.generate_alarm_page(page.data.get("item"))
def generate_light_detail_page(self, entity):
entity = self._ha_api.get_entity(entity)
switch_val = 1 if entity.state == "on" else 0
icon_color = self.get_entity_color(entity)
brightness = "disable"
color_temp = "disable"
color = "disable"
if entity.state == "on":
if "brightness" in entity.attributes:
# scale 0-255 brightness from ha to 0-100
brightness = int(scale(entity.attributes.brightness,(0,255),(0,100)))
else:
brightness = "disable"
if "color_temp" in entity.attributes.supported_color_modes:
if "color_temp" in entity.attributes:
# scale ha color temp range to 0-100
color_temp = int(scale(entity.attributes.color_temp,(entity.attributes.min_mireds, entity.attributes.max_mireds),(0,100)))
else:
color_temp = "unknown"
else:
color_temp = "disable"
list_color_modes = ["xy", "rgb", "rgbw", "hs"]
if any(item in list_color_modes for item in entity.attributes.supported_color_modes):
color = "enable"
else:
color = "disable"
self._send_mqtt_msg(f"entityUpdateDetail,{get_icon_id('lightbulb')},{icon_color},{switch_val},{brightness},{color_temp},{color}")
def generate_shutter_detail_page(self, entity):
entity = self._ha_api.get_entity(entity)
pos = 100-int(entity.attributes.get("current_position", 50))
self._send_mqtt_msg(f"entityUpdateDetail,{pos}")
def send_message_page(self, id, heading, msg, b1, b2):
self._send_mqtt_msg(f"pageType,popupNotify")
self._send_mqtt_msg(f"entityUpdateDetail,|{id}|{heading}|65535|{b1}|65535|{b2}|65535|{msg}|65535|0")

View File

@@ -0,0 +1,77 @@
import logging
LOGGER = logging.getLogger(__name__)
class Updater:
def __init__(self, send_mqtt_msg, topic_send, mode, desired_display_firmware_version, desired_display_firmware_url, desired_tasmota_driver_version, desired_tasmota_driver_url):
self.desired_display_firmware_version = desired_display_firmware_version
self.desired_display_firmware_url = desired_display_firmware_url
self.desired_tasmota_driver_version = desired_tasmota_driver_version
self.desired_tasmota_driver_url = desired_tasmota_driver_url
self.mode = mode
self._send_mqtt_msg = send_mqtt_msg
self.topic_send = topic_send
self.current_tasmota_driver_version = None
self.current_display_firmware_version = None
def set_tasmota_driver_version(self, driver_version):
self.current_tasmota_driver_version = driver_version
def set_current_display_firmware_version(self, panel_version):
self.current_display_firmware_version = panel_version
def check_pre_req(self):
# we need to know both versions to continue
if self.current_tasmota_driver_version is not None and self.current_display_firmware_version is not None:
# tasmota driver has to be at least version 2 for Update command
# and panel has to be at version 11 for notify commands
# version 16 for new button cmd format
if self.current_tasmota_driver_version >= 2 and self.current_display_firmware_version >= 16:
return True
return False
def send_message_page(self, id, heading, msg, b1, b2):
self._send_mqtt_msg(f"pageType,popupNotify")
self._send_mqtt_msg(f"entityUpdateDetail,|{id}|{heading}|65535|{b1}|65535|{b2}|65535|{msg}|65535|0")
def check_updates(self):
# return's true if a notification was send to the panel
# run pre req check
if self.check_pre_req():
LOGGER.info("Update Pre-Check sucessful Tasmota Driver Version: %s Panel Version: %s", self.current_tasmota_driver_version, self.current_display_firmware_version)
# check if tasmota driver needs update
if self.current_tasmota_driver_version < self.desired_tasmota_driver_version:
LOGGER.info("Update of Tasmota Driver needed")
# in auto mode just do the update
if self.mode == "auto":
self.update_berry_driver()
return False
# send notification about the update
if self.mode == "auto-notify":
update_msg = "There's an update available for the Tasmota Berry driver, do you want to start the update now? If you encounter issues after the update or this message appears frequently, please check the manual and repeat the installation steps for the Tasmota Berry driver. "
self.send_message_page("updateBerryNoYes", "Driver Update available!", update_msg, "Dismiss", "Yes")
return True
return False
# check if display firmware needs an update
if self.current_display_firmware_version < self.desired_display_firmware_version:
LOGGER.info("Update of Display Firmware needed")
# in auto mode just do the update
if self.mode == "auto":
self.update_panel_driver()
return False
# send notification about the update
if self.mode == "auto-notify":
update_msg = "There's a firmware update available for the Nextion screen of the NSPanel. Do you want tostart the update now? If the update fails check the installation manual and flash again over the Tasmota console. Be patient, the update will take a while."
self.send_message_page("updateDisplayNoYes", "Display Update available!", update_msg, "Dismiss", "Yes")
return True
return False
else:
LOGGER.info("Update Pre-Check failed Tasmota Driver Version: %s Panel Version: %s", self.current_tasmota_driver_version, self.current_display_firmware_version)
return False
def update_berry_driver(self):
topic = self.topic_send.replace("CustomSend", "UpdateDriverVersion")
self._send_mqtt_msg(self.desired_tasmota_driver_url, topic=topic)
def update_panel_driver(self):
topic = self.topic_send.replace("CustomSend", "FlashNextion")
self._send_mqtt_msg(self.desired_display_firmware_url, topic=topic)

View File

@@ -1,627 +1,79 @@
import json import logging
import datetime import traceback
import hassapi as hass import hassapi as hass
from helper import scale, pos_to_color, rgb_dec565, rgb_brightness
from icon_mapping import get_icon_id from luibackend.config import LuiBackendConfig
from icons import get_icon_id_ha from luibackend.controller import LuiController
# check Babel from luibackend.mqttListener import LuiMqttListener
import importlib from luibackend.updater import Updater
babel_spec = importlib.util.find_spec("babel")
if babel_spec is not None: LOGGER = logging.getLogger(__name__)
import babel.dates
class AppDaemonLoggingHandler(logging.Handler):
def __init__(self, app):
super().__init__()
self._app = app
def emit(self, record):
message = record.getMessage()
if record.exc_info:
message += '\nTraceback (most recent call last):\n'
message += '\n'.join(traceback.format_tb(record.exc_info[2]))
message += f'{record.exc_info[0].__name__}: {record.exc_info[1]}'
self._app.log(message, level=record.levelname)
class NsPanelLovelaceUIManager(hass.Hass): class NsPanelLovelaceUIManager(hass.Hass):
def initialize(self): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._redirect_logging()
data = self.args["config"] def _redirect_logging(self):
LovelaceUIPanel(self, data) # Add a handler for the logging module that will convert the
# calls to AppDaemon's logger with the self instance, so that
# we can simply use logging in the rest of the application
rlogger = logging.getLogger()
rlogger.handlers = [
h for h in rlogger.handlers
if type(h).__name__ != AppDaemonLoggingHandler.__name__
]
rlogger.addHandler(AppDaemonLoggingHandler(self))
class Updater: # We want to grab all the logs, AppDaemon will
def __init__(self, nsplui, mode): # then care about filtering those we asked for
self.desired_display_firmware_version = 16 rlogger.setLevel(logging.DEBUG)
self.desired_display_firmware_url = "http://nspanel.pky.eu/lovelace-ui/github/nspanel-v1.7.0.tft"
self.desired_tasmota_driver_version = 3
self.desired_tasmota_driver_url = "https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be"
self.mode = mode
self.nsplui = nsplui
self.current_tasmota_driver_version = None
self.current_display_firmware_version = None
def set_tasmota_driver_version(self, driver_version):
self.current_tasmota_driver_version = driver_version
def set_current_display_firmware_version(self, panel_version):
self.current_display_firmware_version = panel_version
def check_pre_req(self):
# we need to know both versions to continue
if self.current_tasmota_driver_version is not None and self.current_display_firmware_version is not None:
# tasmota driver has to be at least version 2 for Update command and panel has to be at version 11 for notify commands
if self.current_tasmota_driver_version >= 2 and self.current_display_firmware_version >= 11:
return True
return False
def check_updates(self):
# return's true if a notification was send to the panel
# run pre req check
if self.check_pre_req():
self.nsplui.api.log("Update Pre-Check sucessful Tasmota Driver Version: %s Panel Version: %s", self.current_tasmota_driver_version, self.current_display_firmware_version, level="DEBUG")
# check if tasmota driver needs update
if self.current_tasmota_driver_version < self.desired_tasmota_driver_version:
self.nsplui.api.log("Update of Tasmota Driver needed")
# in auto mode just do the update
if self.mode == "auto":
self.update_berry_driver()
return False
# send notification about the update
if self.mode == "auto-notify":
update_msg = "There's an update avalible for the tasmota berry driver, do you want to start the update now? If you encounter issues after the update or this message appears frequently, please checkthe manual and repeat the installation steps for the tasmota berry driver. "
self.nsplui.send_message_page("updateBerryNoYes", "Driver Update available!", update_msg, "Dismiss", "Yes")
return True
return False
# check if display firmware needs an update
if self.current_display_firmware_version < self.desired_display_firmware_version:
self.nsplui.api.log("Update of Display Firmware needed")
# in auto mode just do the update
if self.mode == "auto":
self.update_panel_driver()
return False
# send notification about the update
if self.mode == "auto-notify":
update_msg = "There's a firmware update avalible for the nextion sceen inside of nspanel, do you want to start the update now? If the update fails check the installation manual and flash again over the tasmota console. Be pationed the update will take a while."
self.nsplui.send_message_page("updateDisplayNoYes", "Display Update available!", update_msg, "Dismiss", "Yes")
return True
return False
else:
self.nsplui.api.log("Update Pre-Check failed Tasmota Driver Version: %s Panel Version: %s", self.current_tasmota_driver_version, self.current_display_firmware_version)
return False
def update_berry_driver(self):
self.nsplui.mqtt.mqtt_publish(self.nsplui.config["panelSendTopic"].replace("CustomSend", "UpdateDriverVersion"), self.desired_tasmota_driver_url)
def update_panel_driver(self):
self.nsplui.mqtt.mqtt_publish(self.nsplui.config["panelSendTopic"].replace("CustomSend", "FlashNextion"), self.desired_display_firmware_url)
class LovelaceUIPanel: def initialize(self):
def __init__(self, api, config): LOGGER.info('Starting')
self.api = api mqtt_api = self._mqtt_api = self.get_plugin_api("MQTT")
self.config = config cfg = self._cfg = LuiBackendConfig(self.args["config"])
self.current_page_nr = 0
self.current_screensaver_brightness = 10
# check configured items
self.check_items()
# Setup, mqtt subscription and callback
self.mqtt = self.api.get_plugin_api("MQTT")
self.mqtt.mqtt_subscribe(topic=self.config["panelRecvTopic"])
self.mqtt.listen_event(self.handle_mqtt_incoming_message, "MQTT_MESSAGE", topic=self.config["panelRecvTopic"], namespace='mqtt')
# Read updateMode and use "auto-notify" as default
update_mode = self.config["updateMode"] if "updateMode" in self.config else "auto-notify"
self.updater = Updater(self, update_mode)
# Request Tasmota Driver Version
self.mqtt.mqtt_publish(self.config["panelSendTopic"].replace("CustomSend", "GetDriverVersion"), "x")
# send panel back to startup page on restart of this script
self.send_mqtt_msg("pageType,pageStartup")
# Setup time callback
time = datetime.time(0, 0, 0)
self.api.run_minutely(self.update_time, time)
# Setup date callback
time = datetime.time(0, 0, 0)
self.api.run_daily(self.update_date, time)
# send date update in case config has been changed
self.update_date("")
# Setup weather callback
weather_interval = 15 * 60 # 15 minutes
self.api.run_every(self.update_screensaver_weather, "now", weather_interval)
# set brightness of screensaver
if type(self.config["brightnessScreensaver"]) == int:
self.current_screensaver_brightness = self.config["brightnessScreensaver"]
elif type(self.config["brightnessScreensaver"]) == list:
sorted_timesets = sorted(self.config["brightnessScreensaver"], key=lambda d: self.api.parse_time(d['time']))
found_current_dim_value = False
for index, timeset in enumerate(sorted_timesets):
self.api.run_daily(self.update_screensaver_brightness, timeset["time"], value=timeset["value"])
self.api.log("Current time %s", self.api.get_now().time(), level="DEBUG")
if self.api.parse_time(timeset["time"]) > self.api.get_now().time() and not found_current_dim_value:
# first time after current time, set dim value
self.current_screensaver_brightness = sorted_timesets[index-1]["value"]
self.api.log("Setting dim value to %s", sorted_timesets[index-1]) #level="DEBUG"
found_current_dim_value = True
# still no dim value
if not found_current_dim_value:
self.current_screensaver_brightness = sorted_timesets[-1]["value"]
# send screensaver brightness in case config has changed
self.update_screensaver_brightness(kwargs={"value": self.current_screensaver_brightness})
# register callbacks
self.register_callbacks()
def filter_dict_from_item_list(self, items):
# remove all dicts from list
cleaned_list = []
for item in items:
# in case item is a dict, grab the item name
if type(item) is dict:
cleaned_list.append(next(iter(item)))
else:
cleaned_list.append(item)
return cleaned_list
def get_all_configured_items(self):
items = []
for page in self.config["pages"]:
if "item" in page:
items.append(page["item"])
if "items" in page:
items.extend(page["items"])
return self.filter_dict_from_item_list(items)
def check_items(self):
items = self.get_all_configured_items()
for item in items:
if self.api.entity_exists(item) or item == "delete":
self.api.log("Found configured item in Home Assistant %s", item, level="DEBUG")
else:
self.api.error("The following item does not exist in Home Assistant, configuration error: %s", item)
def register_callbacks(self):
items = self.get_all_configured_items()
for item in items:
self.api.log("Enable state callback for %s", item, level="DEBUG")
self.api.handle = self.api.listen_state(self.state_change_callback, entity_id=item, attribute="all")
def state_change_callback(self, entity, attribute, old, new, kwargs):
current_page_config = self.config["pages"][self.current_page_nr]
page_type = current_page_config["type"]
self.api.log(f"Got state_callback from {entity}", level="DEBUG")
if page_type in ["cardEntities", "cardGrid"]:
items = current_page_config["items"]
items_filtered = self.filter_dict_from_item_list(items)
if entity in items_filtered:
self.api.log(f"State change on current page for {entity}", level="DEBUG")
# send update of the page
self.generate_entities_page(items)
# send detail pages in case they are open
if(entity.startswith("cover")):
self.generate_shutter_detail_page(entity)
if(entity.startswith("light")):
self.generate_light_detail_page(entity)
return
if page_type in ["cardThermo", "cardMedia"]:
if entity == current_page_config["item"]:
self.api.log(f"State change on current page for {entity}", level="DEBUG")
# send update of the whole page
if page_type == "cardThermo":
self.generate_thermo_page(entity)
return
if page_type == "cardMedia":
self.generate_media_page(entity)
return
return
def send_mqtt_msg(self,msg):
self.api.log("Send Message to Tasmota: %s", msg) #, level="DEBUG"
self.mqtt.mqtt_publish(self.config["panelSendTopic"], msg)
def handle_mqtt_incoming_message(self, event_name, data, kwargs):
# Parse Json Message from Tasmota and strip out message from nextion display
data = json.loads(data["payload"])
# pass tasmota driver version to updater class
if("nlui_driver_version" in data):
msg = data["nlui_driver_version"]
self.api.log("Received Driver Version from Tasmota: %s", int(msg), level="DEBUG")
self.updater.set_tasmota_driver_version(int(msg))
return
if("CustomRecv" not in data):
self.api.log("Received Message from Tasmota, but not from nextion screen: %s", data, level="DEBUG")
return
msg = data["CustomRecv"]
self.api.log("Received Message from Tasmota: %s", msg) #, level="DEBUG"
# Split message into parts seperated by ","
msg = msg.split(",")
# run action based on received command
if msg[0] == "event":
if msg[1] == "startup":
self.api.log("Handling startup event", level="DEBUG")
# grab version from screen and pass to updater class
self.updater.set_current_display_firmware_version(int(msg[2]))
# send date and time
self.update_time("")
self.update_date("")
# set screensaver timeout
timeout = self.config["timeoutScreensaver"]
self.send_mqtt_msg(f"timeout,{timeout}")
# send screensaver brightness
self.update_screensaver_brightness(kwargs={"value": self.current_screensaver_brightness})
# check for updates
msg_send = self.updater.check_updates()
# send messages for current page
if not msg_send:
self.generate_page(self.current_page_nr)
if msg[1] == "pageOpen":
# Calculate current page
recv_page = int(msg[2])
self.current_page_nr = recv_page % len(self.config["pages"])
self.api.log("Received pageOpen command, raw page: %i, calc page: %i", recv_page, self.current_page_nr, level="DEBUG")
# generate commands for current page
self.generate_page(self.current_page_nr)
if msg[1] == "buttonPress": topic_send = cfg.get("panelSendTopic")
entity_id = msg[4] def send_mqtt_msg(msg, topic=None):
btype = msg[6] if topic is None:
if len(msg) > 7: topic = topic_send
value = msg[7] LOGGER.info(f"Sending MQTT Message: {msg}")
else: mqtt_api.mqtt_publish(topic, msg)
value = None
self.handle_button_press(entity_id, btype, value) # Request Tasmota Driver Version
mqtt_api.mqtt_publish(topic_send.replace("CustomSend", "GetDriverVersion"), "x")
controller = LuiController(self, cfg, send_mqtt_msg)
desired_display_firmware_version = 21
desired_display_firmware_url = "http://nspanel.pky.eu/lovelace-ui/github/nspanel-v1.9.1.tft"
desired_tasmota_driver_version = 3
desired_tasmota_driver_url = "https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be"
if msg[1] == "buttonPress2": mode = cfg.get("updateMode")
entity_id = msg[2] topic_send = cfg.get("panelSendTopic")
btype = msg[3] updater = Updater(send_mqtt_msg, topic_send, mode, desired_display_firmware_version, desired_display_firmware_url, desired_tasmota_driver_version, desired_tasmota_driver_url)
if len(msg) > 4:
value = msg[4]
else:
value = None
self.handle_button_press(entity_id, btype, value)
if msg[1] == "pageOpenDetail": topic_recv = cfg.get("panelRecvTopic")
self.api.log("Received pageOpenDetail command", level="DEBUG") LuiMqttListener(mqtt_api, topic_recv, controller, updater)
if msg[2] == "popupShutter":
self.generate_shutter_detail_page(msg[3])
if msg[2] == "popupLight":
self.generate_light_detail_page(msg[3])
if msg[1] == "screensaverOpen": LOGGER.info('Started')
self.update_screensaver_weather("")
def update_time(self, kwargs):
time = datetime.datetime.now().strftime(self.config["timeFormat"])
self.send_mqtt_msg(f"time,{time}")
def update_date(self, kwargs):
global babel_spec
if babel_spec is not None:
self.api.log("Babel package found", level="DEBUG")
if "dateFormatBabel" in self.config:
dateformat = self.config["dateFormatBabel"]
else:
dateformat = "full"
date = babel.dates.format_date(datetime.datetime.now(), dateformat, locale=self.config["locale"])
self.send_mqtt_msg(f"date,?{date}")
else:
self.api.log("Babel package not found", level="DEBUG")
date = datetime.datetime.now().strftime(self.config["dateFormat"])
self.send_mqtt_msg(f"date,?{date}")
def update_screensaver_brightness(self, kwargs):
self.current_screensaver_brightness = kwargs['value']
self.send_mqtt_msg(f"dimmode,{self.current_screensaver_brightness}")
def update_screensaver_weather(self, kwargs):
if not ("weatherEntity" in self.config and self.api.entity_exists(self.config["weatherEntity"])):
return
we = self.api.get_entity(self.config["weatherEntity"])
unit = "°C"
icon_cur = get_icon_id_ha("weather", state=we.state)
text_cur = f"{we.attributes.temperature}{unit}"
icon_cur_detail = get_icon_id("water-percent")
text_cur_detail = f"{we.attributes.humidity} %"
up1 = we.attributes.forecast[0]['datetime']
up1 = datetime.datetime.fromisoformat(up1)
icon1 = get_icon_id_ha("weather", state=we.attributes.forecast[0]['condition'])
down1 = we.attributes.forecast[0]['temperature']
up2 = we.attributes.forecast[1]['datetime']
up2 = datetime.datetime.fromisoformat(up2)
icon2 = get_icon_id_ha("weather", state=we.attributes.forecast[1]['condition'])
down2 = we.attributes.forecast[1]['temperature']
global babel_spec
if babel_spec is not None:
up1 = babel.dates.format_date(up1, "E", locale=self.config["locale"])
up2 = babel.dates.format_date(up2, "E", locale=self.config["locale"])
else:
up1 = up1.strftime("%a")
up2 = up2.strftime("%a")
self.send_mqtt_msg(f"weatherUpdate,?{icon_cur}?{text_cur}?{icon_cur_detail}?{text_cur_detail}?{up1}?{icon1}?{down1}?{up2}?{icon2}?{down2}")
def handle_button_press(self, entity_id, btype, optVal=None):
if entity_id == "updateBerryNoYes" and optVal == "yes":
# go back to main page before starting the update
self.generate_page(self.current_page_nr)
self.updater.update_berry_driver()
elif entity_id == "updateBerryNoYes" and optVal == "no":
self.generate_page(self.current_page_nr)
if entity_id == "updateDisplayNoYes" and optVal == "yes":
self.updater.update_panel_driver()
elif entity_id == "updateDisplayNoYes" and optVal == "no":
self.generate_page(self.current_page_nr)
if btype == "OnOff":
if optVal == "1":
self.api.turn_on(entity_id)
else:
self.api.turn_off(entity_id)
if btype == "up":
self.api.get_entity(entity_id).call_service("open_cover")
if btype == "stop":
self.api.get_entity(entity_id).call_service("stop_cover")
if btype == "down":
self.api.get_entity(entity_id).call_service("close_cover")
if btype == "button":
if entity_id.startswith('scene'):
self.api.get_entity(entity_id).call_service("turn_on")
elif entity_id.startswith('light') or entity_id.startswith('switch') or entity_id.startswith('input_boolean'):
self.api.get_entity(entity_id).call_service("toggle")
else:
self.api.get_entity(entity_id).call_service("press")
if btype == "media-next":
self.api.get_entity(entity_id).call_service("media_next_track")
if btype == "media-back":
self.api.get_entity(entity_id).call_service("media_previous_track")
if btype == "media-pause":
self.api.get_entity(entity_id).call_service("media_play_pause")
if btype == "hvac_action":
self.api.get_entity(entity_id).call_service("set_hvac_mode", hvac_mode=optVal)
if btype == "brightnessSlider":
# scale 0-100 to ha brightness range
brightness = int(scale(int(optVal),(0,100),(0,255)))
self.api.get_entity(entity_id).call_service("turn_on", brightness=brightness)
if btype == "colorTempSlider":
entity = self.api.get_entity(entity_id)
#scale 0-100 from slider to color range of lamp
color_val = scale(int(optVal), (0, 100), (entity.attributes.min_mireds, entity.attributes.max_mireds))
self.api.get_entity(entity_id).call_service("turn_on", color_temp=color_val)
if btype == "colorWheel":
self.api.log(optVal)
optVal = optVal.split('|')
color = pos_to_color(int(optVal[0]), int(optVal[1]))
self.api.log(color)
self.api.get_entity(entity_id).call_service("turn_on", rgb_color=color)
if btype == "positionSlider":
pos = int(optVal)
self.api.get_entity(entity_id).call_service("set_cover_position", position=pos)
if btype == "volumeSlider":
pos = int(optVal)
# HA wants this value between 0 and 1 as float
pos = pos/100
self.api.get_entity(entity_id).call_service("volume_set", volume_level=pos)
if btype == "tempUpd":
temp = int(optVal)/10
self.api.get_entity(msg[3]).call_service("set_temperature", temperature=temp)
def generate_page(self, page_number):
# get type of page
page_type = self.config["pages"][self.current_page_nr]["type"]
self.api.log("Generating page commands for page %i with type %s", self.current_page_nr, page_type, level="DEBUG")
# Send page type
self.send_mqtt_msg(f"pageType,{page_type}")
if page_type in ["cardEntities", "cardGrid"]:
self.generate_entities_page(self.config["pages"][self.current_page_nr]["items"])
if page_type == "cardThermo":
self.generate_thermo_page(self.config["pages"][self.current_page_nr]["item"])
if page_type == "cardMedia":
self.generate_media_page(self.config["pages"][self.current_page_nr]["item"])
def generate_entities_item(self, item):
icon = None
if type(item) is dict:
icon = next(iter(item.items()))[1]['icon']
item = next(iter(item.items()))[0]
# type of the item is the string before the "." in the item name
item_type = item.split(".")[0]
self.api.log("Generating item command for %s with type %s", item, item_type, level="DEBUG")
if item_type == "delete":
return f",{item_type},,,,,"
if not self.api.entity_exists(item):
return f",text,{item},{get_icon_id('alert-circle-outline')},17299,Not found check, apps.yaml"
entity = self.api.get_entity(item)
name = entity.attributes.friendly_name
if item_type == "cover":
icon_id = get_icon_id_ha("cover", state=entity.state, overwrite=icon)
return f",shutter,{item},{icon_id},17299,{name},"
if item_type == "light":
switch_val = 1 if entity.state == "on" else 0
icon_color = self.getEntityColor(entity)
icon_id = get_icon_id_ha("light", overwrite=icon)
return f",{item_type},{item},{icon_id},{icon_color},{name},{switch_val}"
if item_type == "switch" or item_type == "input_boolean":
icon_id = get_icon_id_ha(item_type, state=entity.state, overwrite=icon)
switch_val = 1 if entity.state == "on" else 0
icon_color = self.getEntityColor(entity)
return f",switch,{item},{icon_id},{icon_color},{name},{switch_val}"
if item_type in ["sensor", "binary_sensor"]:
device_class = self.get_safe_ha_attribute(entity.attributes, "device_class", "")
icon_id = get_icon_id_ha("sensor", state=entity.state, device_class=device_class, overwrite=icon)
unit_of_measurement = self.get_safe_ha_attribute(entity.attributes, "unit_of_measurement", "")
value = entity.state + " " + unit_of_measurement
return f",text,{item},{icon_id},17299,{name},{value}"
if item_type in ["button", "input_button"]:
icon_id = get_icon_id_ha("button", overwrite=icon)
return f",button,{item},{icon_id},17299,{name},PRESS"
if item_type == "scene":
icon_id = get_icon_id_ha("scene", overwrite=icon)
return f",button,{item},{icon_id},17299,{name},ACTIVATE"
def generate_entities_page(self, items):
# Set Heading of Page
self.send_mqtt_msg(f"entityUpdHeading,{self.config['pages'][self.current_page_nr]['heading']}")
# Get items and construct cmd string
command = "entityUpd"
for item in items:
command += self.generate_entities_item(item)
self.send_mqtt_msg(command)
def get_safe_ha_attribute(self, eattr, attr, default):
return eattr[attr] if attr in eattr else default
def generate_thermo_page(self, item):
if not self.api.entity_exists(item):
command = f"entityUpd,{item},Not found,220,220,Not found,150,300,5"
else:
entity = self.api.get_entity(item)
heading = entity.attributes.friendly_name
current_temp = int(self.get_safe_ha_attribute(entity.attributes, "current_temperature", 0)*10)
dest_temp = int(self.get_safe_ha_attribute(entity.attributes, "temperature", 0)*10)
status = self.get_safe_ha_attribute(entity.attributes, "hvac_action", "")
min_temp = int(self.get_safe_ha_attribute(entity.attributes, "min_temp", 0)*10)
max_temp = int(self.get_safe_ha_attribute(entity.attributes, "max_temp", 0)*10)
step_temp = int(self.get_safe_ha_attribute(entity.attributes, "target_temp_step", 0.5)*10)
icon_res = ""
hvac_modes = self.get_safe_ha_attribute(entity.attributes, "hvac_modes", [])
for mode in hvac_modes:
icon_id = get_icon_id('alert-circle-outline')
color_on = 64512
if mode == "auto":
icon_id = get_icon_id("calendar-sync")
color_on = 1024
if mode == "heat":
icon_id = get_icon_id("fire")
color_on = 64512
if mode == "off":
icon_id = get_icon_id("power")
color_on = 35921
if mode == "cool":
icon_id = get_icon_id("snowflake")
color_on = 11487
if mode == "dry":
icon_id = get_icon_id("water-percent")
color_on = 60897
if mode == "fan_only":
icon_id = get_icon_id("fan")
color_on = 35921
state = 0
if(mode == entity.state):
state = 1
icon_res += f",{icon_id},{color_on},{state},{mode}"
len_hvac_modes = len(hvac_modes)
if len_hvac_modes%2 == 0:
# even
padding_len = int((4-len_hvac_modes)/2)
icon_res = ","*4*padding_len + icon_res + ","*4*padding_len
# use last 4 icons
icon_res = ","*4*5 + icon_res
else:
# uneven
padding_len = int((5-len_hvac_modes)/2)
icon_res = ","*4*padding_len + icon_res + ","*4*padding_len
# use first 5 icons
icon_res = icon_res + ","*4*4
command = f"entityUpd,{item},{heading},{current_temp},{dest_temp},{status},{min_temp},{max_temp},{step_temp}{icon_res}"
self.send_mqtt_msg(command)
def generate_media_page(self, item):
if not self.api.entity_exists(item):
command = f"entityUpd,|{item}|Not found|{get_icon_id('alert-circle-outline')}|Please check your|apps.yaml in AppDaemon|50|11"
else:
entity = self.api.get_entity(item)
heading = entity.attributes.friendly_name
icon = 0
title = self.get_safe_ha_attribute(entity.attributes, "media_title", "")
author = self.get_safe_ha_attribute(entity.attributes, "media_artist", "")
volume = int(self.get_safe_ha_attribute(entity.attributes, "volume_level", 0)*100)
iconplaypause = get_icon_id("pause") if entity.state == "playing" else get_icon_id("play")
if "media_content_type" in entity.attributes:
if entity.attributes.media_content_type == "music":
icon = get_icon_id("music")
command = f"entityUpd,|{item}|{heading}|{icon}|{title}|{author}|{volume}|{iconplaypause}"
self.send_mqtt_msg(command)
def getEntityColor(self, entity):
attr = entity.attributes
default_color_on = rgb_dec565([253, 216, 53])
default_color_off = rgb_dec565([68, 115, 158])
icon_color = default_color_on if entity.state == "on" else default_color_off
if "rgb_color" in attr:
color = attr.rgb_color
if "brightness" in attr:
color = rgb_brightness(color, attr.brightness)
icon_color = rgb_dec565(color)
elif "brightness" in attr:
color = rgb_brightness([253, 216, 53], attr.brightness)
icon_color = rgb_dec565(color)
return icon_color
def generate_light_detail_page(self, entity):
entity = self.api.get_entity(entity)
switch_val = 1 if entity.state == "on" else 0
icon_color = self.getEntityColor(entity)
brightness = "disable"
color_temp = "disable"
color = "disable"
# scale 0-255 brightness from ha to 0-100
if entity.state == "on":
if "brightness" in entity.attributes:
brightness = int(scale(entity.attributes.brightness,(0,255),(0,100)))
else:
brightness = "disable"
if "color_temp" in entity.attributes.supported_color_modes:
if "color_temp" in entity.attributes:
# scale ha color temp range to 0-100
color_temp = int(scale(entity.attributes.color_temp,(entity.attributes.min_mireds, entity.attributes.max_mireds),(0,100)))
else:
color_temp = "unknown"
else:
color_temp = "disable"
list_color_modes = ["xy", "rgb", "rgbw", "hs"]
if any(item in list_color_modes for item in entity.attributes.supported_color_modes):
color = "enable"
else:
color = "disable"
self.send_mqtt_msg(f"entityUpdateDetail,{get_icon_id('lightbulb')},{icon_color},{switch_val},{brightness},{color_temp},{color}")
def generate_shutter_detail_page(self, entity):
pos = int(self.get_safe_ha_attribute(entity.attributes, "current_position", 50))
# reverse position for slider
pos = 100-pos
self.send_mqtt_msg(f"entityUpdateDetail,{pos}")
def send_message_page(self, id, heading, msg, b1, b2):
self.send_mqtt_msg(f"pageType,popupNotify")
self.send_mqtt_msg(f"entityUpdateDetail,|{id}|{heading}|65535|{b1}|65535|{b2}|65535|{msg}|65535|0")

BIN
doc-pics/hacs-main.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 KiB

After

Width:  |  Height:  |  Size: 321 KiB

10
info.md
View File

@@ -5,14 +5,15 @@ Checkout [README](https://github.com/joBr99/nspanel-lovelace-ui/blob/main/README
### App Configuration ### App Configuration
```yaml ```yaml
---
nspanel-1: nspanel-1:
module: nspanel-lovelace-ui module: nspanel-lovelace-ui
class: NsPanelLovelaceUIManager class: NsPanelLovelaceUIManager
config: config:
panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT" panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT"
panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend" panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend"
updateMode: auto-notify # possible values are auto, auto-notify and manual updateMode: "auto-notify"
timeoutScreensaver: 15 #in seconds timeoutScreensaver: 20
#brightnessScreensaver: 10 #brightnessScreensaver: 10
brightnessScreensaver: brightnessScreensaver:
- time: "7:00:00" - time: "7:00:00"
@@ -24,7 +25,7 @@ nspanel-1:
# formatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields # formatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields
timeFormat: "%H:%M" timeFormat: "%H:%M"
dateFormat: "%A, %d. %B %Y" # ignored if babel python package is installed dateFormat: "%A, %d. %B %Y" # ignored if babel python package is installed
weatherEntity: weather.example weather: weather.example
pages: pages:
- type: cardEntities - type: cardEntities
heading: Example Page 1 heading: Example Page 1
@@ -60,8 +61,9 @@ nspanel-1:
heading: Exmaple Thermostat heading: Exmaple Thermostat
item: climate.example_climate item: climate.example_climate
- type: cardMedia - type: cardMedia
heading: Exampe Media
item: media_player.spotify_user item: media_player.spotify_user
- type: cardAlarm
item: alarm_control_panel.alarmo
``` ```
key | optional | type | default | description key | optional | type | default | description

View File

@@ -62,16 +62,13 @@ var button2Page: PageEntities =
export const config: Config = { export const config: Config = {
panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT", panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT",
panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend", panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend",
leftEntity: "alias.0.Batterie.ACTUAL", firstScreensaverEntity: { ScreensaverEntity: "alias.0.Wetter.HUMIDITY", ScreensaverEntityIcon: 26, ScreensaverEntityText: "Luft", ScreensaverEntityUnitText: "%" },
leftEntityIcon: 34, secondScreensaverEntity: { ScreensaverEntity: "alias.0.Wetter.PRECIPITATION_CHANCE", ScreensaverEntityIcon: 19, ScreensaverEntityText: "Regen", ScreensaverEntityUnitText: "%" },
leftEntityText: "Batterie", thirdScreensaverEntity: { ScreensaverEntity: "alias.0.Batterie.ACTUAL", ScreensaverEntityIcon: 34, ScreensaverEntityText: "Batterie", ScreensaverEntityUnitText: "%" },
leftEntityUnitText: "%", fourthScreensaverEntity: { ScreensaverEntity: "alias.0.Pv.ACTUAL", ScreensaverEntityIcon: 32, ScreensaverEntityText: "PV", ScreensaverEntityUnitText: "W" },
rightEntity: "alias.0.Pv.ACTUAL",
rightEntityIcon: 32,
rightEntityText: "PV",
rightEntityUnitText: "W",
timeoutScreensaver: 15, timeoutScreensaver: 15,
dimmode: 8, dimmode: 8,
screenSaverDoubleClick: false,
locale: "de_DE", locale: "de_DE",
timeFormat: "%H:%M", timeFormat: "%H:%M",
dateFormat: "%A, %d. %B %Y", dateFormat: "%A, %d. %B %Y",
@@ -92,8 +89,6 @@ export const config: Config = {
button2Page: button2Page button2Page: button2Page
}; };
var subscriptions: any = {}; var subscriptions: any = {};
var pageId = 0; var pageId = 0;
@@ -106,15 +101,21 @@ schedule("0 * * * *", function () {
}); });
// Only monitor the extra nodes if one or both are present // Only monitor the extra nodes if present
var updateArray: string[] = []; var updateArray: string[] = [];
if (config.rightEntity !== null && existsState(config.rightEntity)) { if (config.firstScreensaverEntity !== null && config.firstScreensaverEntity.ScreensaverEntity != null && existsState(config.firstScreensaverEntity.ScreensaverEntity)) {
updateArray.push(config.rightEntity) updateArray.push(config.firstScreensaverEntity.ScreensaverEntity)
}
if (config.secondScreensaverEntity !== null && config.secondScreensaverEntity.ScreensaverEntity != null && existsState(config.secondScreensaverEntity.ScreensaverEntity)) {
updateArray.push(config.secondScreensaverEntity.ScreensaverEntity)
}
if (config.thirdScreensaverEntity !== null && config.thirdScreensaverEntity.ScreensaverEntity != null && existsState(config.thirdScreensaverEntity.ScreensaverEntity)) {
updateArray.push(config.thirdScreensaverEntity.ScreensaverEntity)
}
if (config.fourthScreensaverEntity !== null && config.fourthScreensaverEntity.ScreensaverEntity != null && existsState(config.fourthScreensaverEntity.ScreensaverEntity)) {
updateArray.push(config.fourthScreensaverEntity.ScreensaverEntity)
} }
if (config.leftEntity !== null && existsState(config.leftEntity)) {
updateArray.push(config.leftEntity)
}
if (updateArray.length > 0) { if (updateArray.length > 0) {
on(updateArray, function () { on(updateArray, function () {
HandleScreensaverUpdate(); HandleScreensaverUpdate();
@@ -125,15 +126,7 @@ on({ id: config.panelRecvTopic }, function (obj) {
var json = JSON.parse(obj.state.val); var json = JSON.parse(obj.state.val);
var split = json.CustomRecv.split(","); var split = json.CustomRecv.split(",");
if (split[1] == "pageOpenDetail") { HandleMessage(split[0], split[1], parseInt(split[2]), split);
UnsubscribeWatcher();
let pageItem = config.pages[pageId].items.find(e => e.id === split[3]);
if (pageItem !== undefined)
SendToPanel(GenerateDetailPage(split[2], pageItem));
}
else {
HandleMessage(split[0], split[1], parseInt(split[2]), split);
}
} }
}); });
@@ -149,28 +142,29 @@ function SendToPanel(val: Payload | Payload[]): void {
function HandleMessage(typ: string, method: string, page: number, words: Array<string>): void { function HandleMessage(typ: string, method: string, page: number, words: Array<string>): void {
if (typ == "event") { if (typ == "event") {
var pageNum = (page % config.pages.length); switch (method) {
pageId = Math.abs(pageNum); case "startup":
UnsubscribeWatcher();
if (method == 'pageOpen' || method == 'startup') {
UnsubscribeWatcher();
if (method == 'startup')
HandleStartupProcess(); HandleStartupProcess();
pageId = 0;
GeneratePage(config.pages[pageId]); GeneratePage(config.pages[0]);
} break;
case "pageOpenDetail":
if (method == 'buttonPress' || method == "tempUpd") { UnsubscribeWatcher();
HandleButtonEvent(words) let pageItem = config.pages[pageId].items.find(e => e.id === words[3]);
} if (pageItem !== undefined)
SendToPanel(GenerateDetailPage(words[2], pageItem));
if (method == 'screensaverOpen') { case "buttonPress2":
HandleScreensaver() HandleButtonEvent(words);
} break;
case "screensaverOpen":
if (method == 'button1' || method == 'button2') { HandleScreensaver();
HandleHardwareButton(method); break;
case "button1":
case "button2":
HandleHardwareButton(method);
default:
break;
} }
} }
} }
@@ -237,7 +231,7 @@ function SendTime(): void {
function GenerateEntitiesPage(page: PageEntities): Payload[] { function GenerateEntitiesPage(page: PageEntities): Payload[] {
var out_msgs: Array<Payload> = []; var out_msgs: Array<Payload> = [];
out_msgs = [{ payload: "pageType,cardEntities" }, { payload: "entityUpdHeading," + page.heading }] out_msgs = [{ payload: "pageType,cardEntities" }, { payload: "entityUpdHeading," + page.heading }]
out_msgs.push({ payload: GeneratePageElements(page.items, 4,page.useColor) }); out_msgs.push({ payload: GeneratePageElements(page.items, 4, page.useColor) });
return out_msgs return out_msgs
} }
@@ -276,11 +270,11 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean =
if (existsState(pageItem.id + ".GET")) { if (existsState(pageItem.id + ".GET")) {
val = getState(pageItem.id + ".GET").val; val = getState(pageItem.id + ".GET").val;
RegisterEntityWatcher(pageItem.id + ".GET", pageItem.id, placeId); RegisterEntityWatcher(pageItem.id + ".GET");
} }
else if (existsState(pageItem.id + ".SET")) { else if (existsState(pageItem.id + ".SET")) {
val = getState(pageItem.id + ".SET").val; val = getState(pageItem.id + ".SET").val;
RegisterEntityWatcher(pageItem.id + ".SET", pageItem.id, placeId); RegisterEntityWatcher(pageItem.id + ".SET");
} }
var iconColor = rgb_dec565(config.defaultColor); var iconColor = rgb_dec565(config.defaultColor);
@@ -303,11 +297,11 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean =
var optVal = "0" var optVal = "0"
if (existsState(pageItem.id + ".ON_ACTUAL")) { if (existsState(pageItem.id + ".ON_ACTUAL")) {
val = getState(pageItem.id + ".ON_ACTUAL").val; val = getState(pageItem.id + ".ON_ACTUAL").val;
RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL", pageItem.id, placeId); RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL");
} }
else if (existsState(pageItem.id + ".ON_SET")) { else if (existsState(pageItem.id + ".ON_SET")) {
val = getState(pageItem.id + ".ON_SET").val; val = getState(pageItem.id + ".ON_SET").val;
RegisterEntityWatcher(pageItem.id + ".ON_SET", pageItem.id, placeId); RegisterEntityWatcher(pageItem.id + ".ON_SET");
} }
if (val === true || val === "true") { if (val === true || val === "true") {
optVal = "1" optVal = "1"
@@ -318,25 +312,26 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean =
case "blind": case "blind":
type = "shutter" type = "shutter"
iconId = pageItem.icon !== undefined ? pageItem.icon : 0; iconId = pageItem.icon !== undefined ? pageItem.icon : 11;
iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ACTUAL") ? getState(pageItem.id + ".ACTUAL").val : true, useColors); iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ACTUAL") ? getState(pageItem.id + ".ACTUAL").val : true, useColors);
return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + "," return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + ","
case "info": case "info":
case "value.temperature": case "value.temperature":
case "thermostat":
type = "text"; type = "text";
iconId = pageItem.icon !== undefined ? pageItem.icon : 11; iconId = pageItem.icon !== undefined ? pageItem.icon : o.common.role == "value.temperature" || o.common.role == "thermostat" ? 2 : 0;
let unit = ""; let unit = "";
var optVal = "0" var optVal = "0"
if (existsState(pageItem.id + ".ON_ACTUAL")) { if (existsState(pageItem.id + ".ON_ACTUAL")) {
optVal = getState(pageItem.id + ".ON_ACTUAL").val; optVal = getState(pageItem.id + ".ON_ACTUAL").val;
unit = GetUnitOfMeasurement(pageItem.id + ".ON_ACTUAL"); unit = GetUnitOfMeasurement(pageItem.id + ".ON_ACTUAL");
RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL", pageItem.id, placeId); RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL");
} }
else if (existsState(pageItem.id + ".ACTUAL")) { else if (existsState(pageItem.id + ".ACTUAL")) {
optVal = getState(pageItem.id + ".ACTUAL").val; optVal = getState(pageItem.id + ".ACTUAL").val;
unit = GetUnitOfMeasurement(pageItem.id + ".ACTUAL"); unit = GetUnitOfMeasurement(pageItem.id + ".ACTUAL");
RegisterEntityWatcher(pageItem.id + ".ACTUAL", pageItem.id, placeId); RegisterEntityWatcher(pageItem.id + ".ACTUAL");
} }
if (o.common.role == "value.temperature") { if (o.common.role == "value.temperature") {
@@ -384,11 +379,12 @@ function GetIconColor(pageItem: PageItem, value: (boolean | number), useColors:
return rgb_dec565(pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor); return rgb_dec565(pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor);
} }
function RegisterEntityWatcher(id: string, entityId: string, placeId: number): void { function RegisterEntityWatcher(id: string): void {
if (subscriptions.hasOwnProperty(id)) { if (subscriptions.hasOwnProperty(id)) {
return; return;
} }
subscriptions[id] = (on({ id: id, change: 'any' }, function (data) { subscriptions[id] = (on({ id: id, change: 'any' }, function (data) {
log("RegisterEntityWatcher PageId:" + pageId.toString())
GeneratePage(config.pages[pageId]); GeneratePage(config.pages[pageId]);
})) }))
} }
@@ -432,12 +428,15 @@ function GenerateThermoPage(page: PageThermo): Payload[] {
currentTemp = parseInt(getState(id + ".ACTUAL").val) * 10; currentTemp = parseInt(getState(id + ".ACTUAL").val) * 10;
let destTemp = 0; let destTemp = 0;
if (existsState(id + ".SET")) if (existsState(id + ".SET")) {
destTemp = parseInt(getState(id + ".SET").val) * 10; destTemp = getState(id + ".SET").val.toFixed(2) * 10;
log(id + ".SET " + destTemp)
}
let status = "" let status = ""
if (existsState(id + ".MODE")) if (existsState(id + ".MODE"))
status = destTemp = getState(id + ".MODE").val; status = getState(id + ".MODE").val;
let minTemp = 180 let minTemp = 180
let maxTemp = 300 let maxTemp = 300
let stepTemp = 5 let stepTemp = 5
@@ -459,7 +458,6 @@ function setIfExists(id: string, value: any, type: string | null = null): boolea
else { else {
let obj = getObject(id); let obj = getObject(id);
if (existsState(id) && obj.common.type !== undefined && obj.common.type === type) { if (existsState(id) && obj.common.type !== undefined && obj.common.type === type) {
log(id)
setState(id, value); setState(id, value);
return true; return true;
} }
@@ -477,50 +475,66 @@ function toggleState(id: string): boolean {
} }
function HandleButtonEvent(words): void { function HandleButtonEvent(words): void {
let id = words[4] let id = words[2]
let buttonAction = words[3];
if (words[6] == "OnOff" && existsObject(id)) { switch (buttonAction) {
var action = false case "bNext":
if (words[7] == "1") var pageNum = ((pageId + 1) % config.pages.length);
action = true pageId = Math.abs(pageNum);
let o = getObject(id) UnsubscribeWatcher();
switch (o.common.role) { GeneratePage(config.pages[pageId]);
case "light": break;
setState(id + ".SET", action); case "bPrev":
break; var pageNum = ((pageId - 1) % config.pages.length);
case "dimmer": pageId = Math.abs(pageNum);
if (existsState(id + ".ON_SET")) UnsubscribeWatcher();
setState(id + ".ON_SET", action); GeneratePage(config.pages[pageId]);
else if (existsState(id + ".ON_ACTUAL")) break;
setState(id + ".ON_ACTUAL", action); case "bExit":
} if (config.screenSaverDoubleClick) {
} if (words[4] == 2)
GeneratePage(config.pages[pageId]);
if (words[6] == "up") }
setState(id + ".OPEN", true) else
if (words[6] == "stop") GeneratePage(config.pages[pageId]);
setState(id + ".STOP", true) break;
if (words[6] == "down") case "OnOff":
setState(id + ".CLOSE", true) if (existsObject(id)) {
if (words[6] == "button") { var action = false
let switchOn = true; if (words[4] == "1")
if (words[5] !== "1") action = true
switchOn = false; let o = getObject(id)
toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET") switch (o.common.role) {
} case "light":
if (words[6] == "positionSlider") setIfExists(id + ".SET", action);
setState(id + ".SET", parseInt(words[7])) break;
case "dimmer":
if (words[6] == "brightnessSlider") setIfExists(id + ".ON_SET", action) ? true : setIfExists(id + ".ON_ACTUAL", action);
if (existsState(id + ".SET")) }
setState(id + ".SET", parseInt(words[7])); }
else if (existsState(id + ".ACTUAL")) break;
setState(id + ".ACTUAL", parseInt(words[7])); case "up":
// out_msgs.push({ payload: id, action: "turn_on", domain: "lightBrightness", brightness: parseInt(words[7]) }) setIfExists(id + ".OPEN", true)
// if (words[6] == "colorTempSlider") break;
// out_msgs.push({ payload: id, action: "turn_on", domain: "lightTemperature", temperature: parseInt(words[7]) }) case "stop":
if (words[1] == "tempUpd") { setIfExists(id + ".STOP", true)
setState(words[3] + ".SET", parseInt(words[4]) / 10) break;
case "down":
setIfExists(id + ".CLOSE", true)
break;
case "button":
toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET")
break;
case "positionSlider":
case "brightnessSlider":
setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4]));
break;
case "tempUpd":
setIfExists(id + ".SET", parseInt(words[4]) / 10)
break;
default:
break;
} }
} }
@@ -619,33 +633,30 @@ function HandleScreensaverUpdate(): void {
let temperature: string = let temperature: string =
existsState(config.weatherEntity + ".ACTUAL") ? getState(config.weatherEntity + ".ACTUAL").val : existsState(config.weatherEntity + ".ACTUAL") ? getState(config.weatherEntity + ".ACTUAL").val :
existsState(config.weatherEntity + ".TEMP") ? getState(config.weatherEntity + ".TEMP").val : "null"; existsState(config.weatherEntity + ".TEMP") ? getState(config.weatherEntity + ".TEMP").val : "null";
let humidity = getState(config.weatherEntity + ".HUMIDITY").val;
let payloadString = let payloadString =
"weatherUpdate,?" + GetAccuWeatherIcon(parseInt(icon)) + "?" "weatherUpdate,?" + GetAccuWeatherIcon(parseInt(icon)) + "?"
+ temperature + " " + config.temperatureUnit + "?26?" + temperature + " " + config.temperatureUnit + "?"
+ humidity + " %?";
if (existsState(config.leftEntity)) { payloadString += GetScreenSaverEntityString(config.firstScreensaverEntity);
let u1 = getState(config.leftEntity).val; payloadString += GetScreenSaverEntityString(config.secondScreensaverEntity);
payloadString += config.leftEntityText + "?" + config.leftEntityIcon + "?" + u1 + " " + config.leftEntityUnitText + "?"; payloadString += GetScreenSaverEntityString(config.thirdScreensaverEntity);
} payloadString += GetScreenSaverEntityString(config.fourthScreensaverEntity);
else {
payloadString += "???";
}
if (existsState(config.rightEntity)) {
let u2 = getState(config.rightEntity).val;
payloadString += config.rightEntityText + "?" + config.rightEntityIcon + "?" + u2 + " " + config.rightEntityUnitText;
}
else {
payloadString += "??";
}
SendToPanel(<Payload>{ payload: payloadString }); SendToPanel(<Payload>{ payload: payloadString });
} }
} }
function GetScreenSaverEntityString(configElement: ScreenSaverElement | null): string {
if (configElement != null && configElement.ScreensaverEntity != null && existsState(configElement.ScreensaverEntity)) {
let u1 = getState(configElement.ScreensaverEntity).val;
return configElement.ScreensaverEntityText + "?" + configElement.ScreensaverEntityIcon + "?" + u1 + " " + configElement.ScreensaverEntityUnitText + "?";
}
else {
return "???";
}
}
function GetAccuWeatherIcon(icon: number): number { function GetAccuWeatherIcon(icon: number): number {
switch (icon) { switch (icon) {
case 24: // Ice case 24: // Ice
@@ -796,15 +807,12 @@ type Config = {
timeFormat: string, timeFormat: string,
dateFormat: string, dateFormat: string,
weatherEntity: string | null, weatherEntity: string | null,
screenSaverDoubleClick: boolean,
temperatureUnit: string, temperatureUnit: string,
leftEntity: string, firstScreensaverEntity: ScreenSaverElement | null,
leftEntityIcon: number, secondScreensaverEntity: ScreenSaverElement | null,
leftEntityText: string, thirdScreensaverEntity: ScreenSaverElement | null,
leftEntityUnitText: string | null, fourthScreensaverEntity: ScreenSaverElement | null,
rightEntity: string,
rightEntityIcon: number,
rightEntityText: string,
rightEntityUnitText: string | null,
defaultColor: RGB, defaultColor: RGB,
defaultOnColor: RGB, defaultOnColor: RGB,
defaultOffColor: RGB, defaultOffColor: RGB,
@@ -812,3 +820,10 @@ type Config = {
button1Page: (PageThermo | PageEntities | PageGrid | null), button1Page: (PageThermo | PageEntities | PageGrid | null),
button2Page: (PageThermo | PageEntities | PageGrid | null), button2Page: (PageThermo | PageEntities | PageGrid | null),
}; };
type ScreenSaverElement = {
ScreensaverEntity: string | null,
ScreensaverEntityIcon: number | null,
ScreensaverEntityText: string | null,
ScreensaverEntityUnitText: string | null,
}

View File

@@ -66,14 +66,12 @@ const BatteryEmpty: RGB = { red: 179, green: 45, blue: 25 }
var config: Config = { var config: Config = {
panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT", // This is the object where the panel send the data to. panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT", // This is the object where the panel send the data to.
panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend", // This is the object where data is send to the panel. panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend", // This is the object where data is send to the panel.
leftEntity: "alias.0.Batterie.ACTUAL", // This is a state will be displayed on the left side. firstScreensaverEntity: { ScreensaverEntity: "alias.0.Wetter.HUMIDITY", ScreensaverEntityIcon: 26, ScreensaverEntityText: "Luft", ScreensaverEntityUnitText: "%" },
leftEntityIcon: 34, // This is a icon which will be displayed on the left side. // Items which should be presented on the screensaver page
leftEntityText: "Batterie", // The label for the left side. secondScreensaverEntity: { ScreensaverEntity: "alias.0.Wetter.PRECIPITATION_CHANCE", ScreensaverEntityIcon: 19, ScreensaverEntityText: "Regen", ScreensaverEntityUnitText: "%" },
leftEntityUnitText: "%", // The unit which will be appendon the left side. thirdScreensaverEntity: { ScreensaverEntity: "alias.0.Batterie.ACTUAL", ScreensaverEntityIcon: 34, ScreensaverEntityText: "Batterie", ScreensaverEntityUnitText: "%" },
rightEntity: "alias.0.Pv.ACTUAL", // The same but for the right side. fourthScreensaverEntity: { ScreensaverEntity: "alias.0.Pv.ACTUAL", ScreensaverEntityIcon: 32, ScreensaverEntityText: "PV", ScreensaverEntityUnitText: "W" },
rightEntityIcon: 32, screenSaverDoubleClick: false, // Doubletouch needed for leaving screensaver.
rightEntityText: "PV",
rightEntityUnitText: "W",
timeoutScreensaver: 15, // Timeout for screensaver timeoutScreensaver: 15, // Timeout for screensaver
dimmode: 8, // Display dim dimmode: 8, // Display dim
locale: "de_DE", // not used right now locale: "de_DE", // not used right now
@@ -84,6 +82,14 @@ var config: Config = {
defaultOnColor: RGB, // Default on state color for items defaultOnColor: RGB, // Default on state color for items
defaultOffColor: RGB, // Default off state color for page defaultOffColor: RGB, // Default off state color for page
temperatureUnit: "°C", // Unit to append on temperature sensors temperatureUnit: "°C", // Unit to append on temperature sensors
<<<<<<< HEAD
pages: [Wohnen, Strom,
{
"type": "cardThermo",
"heading": "Thermostat",
"useColor": true,
"items": [<PageItem>{ id: "alias.0.WzNsPanel" }]
=======
pages: [ pages: [
{ {
"type": "cardEntities", // card type (cardEntities, cardThermo) "type": "cardEntities", // card type (cardEntities, cardThermo)
@@ -114,6 +120,7 @@ var config: Config = {
"heading": "Thermostat", "heading": "Thermostat",
"useColor": false, // should colors be enabled on this page, can be overridden in PageItem "useColor": false, // should colors be enabled on this page, can be overridden in PageItem
"item": "alias.0.WzNsPanel" // Needs to be a thermostat in the device panel "item": "alias.0.WzNsPanel" // Needs to be a thermostat in the device panel
>>>>>>> 8a48ff35d408a7712a3052ee3cf8fc84e8b699c7
} }
], ],
button1Page: button1Page, // A cardEntities, cardThermo or nothing. This will be opened when pressing button1 button1Page: button1Page, // A cardEntities, cardThermo or nothing. This will be opened when pressing button1