Compare commits

...

157 Commits

Author SHA1 Message Date
Johannes Braun
4ce16095b5 change requirements for auto update 2022-03-20 20:35:25 +01:00
Johannes Braun
9bd6925f75 Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui 2022-03-20 20:27:33 +01:00
Johannes Braun
0b58f16a0e added auto update to config examples 2022-03-20 20:27:02 +01:00
Johannes Braun
6983ff1532 implemented auto update 2022-03-20 20:20:44 +01:00
joBr99
f7f63d00a4 fixed dimmode on popup pages (add nextion2text) 2022-03-20 19:16:13 +00:00
Johannes Braun
b0027d4c3c fixed dimmode on popup pages 2022-03-20 20:15:53 +01:00
joBr99
622f9bf0c7 fix pagetype notify on startup page (add nextion2text) 2022-03-20 19:09:32 +00:00
Johannes Braun
b6b0249bfe fix pagetype notify on startup page 2022-03-20 20:09:11 +01:00
joBr99
27251104ee preserve sleep also on page type command (add nextion2text) 2022-03-20 18:58:43 +00:00
Johannes Braun
7822782fc6 preserve sleep also on page type command 2022-03-20 19:58:19 +01:00
Johannes Braun
763dbb6ef8 preserve sleep timeout on notify page 2022-03-20 19:57:05 +01:00
joBr99
45b59d4d01 remove dummy text (add nextion2text) 2022-03-20 18:37:40 +00:00
Johannes Braun
ae515df4c9 remove dummy text 2022-03-20 19:37:17 +01:00
joBr99
498f8bf234 Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-20 18:28:46 +00:00
Johannes Braun
3f531da6f0 Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui 2022-03-20 19:28:24 +01:00
Johannes Braun
264e9cd61c increase cmd buffer 2022-03-20 19:28:08 +01:00
joBr99
fc0f24a794 extend msg length (add nextion2text) 2022-03-20 18:21:05 +00:00
Johannes Braun
f9549a7dc6 extend msg length 2022-03-20 19:20:44 +01:00
joBr99
b698d67f79 set dimval on pageType startup (add nextion2text) 2022-03-20 18:16:28 +00:00
Johannes Braun
d0d456c49d set dimval on pageType startup 2022-03-20 19:16:02 +01:00
Johannes Braun
e3909e457c Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui 2022-03-20 19:01:18 +01:00
Johannes Braun
b1768f2b80 startet implementation on auto update 2022-03-20 19:01:05 +01:00
joBr99
6643d6c284 swap default tasmota driver (add nextion2text) 2022-03-20 16:18:47 +00:00
Johannes Braun
c683a9bc7c swap default tasmota driver 2022-03-20 17:18:15 +01:00
Johannes Braun
721a41ce3e fix detail pages exit 2022-03-20 16:41:12 +01:00
Johannes Braun
94891bf2cb Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui 2022-03-20 16:17:15 +01:00
Johannes Braun
0de9d83b50 remove event form notify page 2022-03-20 16:17:01 +01:00
joBr99
25f3913010 Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-20 14:54:41 +00:00
Johannes Braun
a023d2e04a Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui 2022-03-20 15:54:21 +01:00
Johannes Braun
741ff125f3 changed delimiter on notify page 2022-03-20 15:54:12 +01:00
joBr99
0d883983fa Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-20 14:48:55 +00:00
Johannes Braun
646ec6cf92 Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui 2022-03-20 15:48:32 +01:00
Johannes Braun
411ef851a7 added sleepTimeout to notify command 2022-03-20 15:48:22 +01:00
joBr99
65886ca9fc Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-20 14:43:53 +00:00
Johannes Braun
a789c39fa1 Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui 2022-03-20 15:43:30 +01:00
Johannes Braun
3930408ebf fixed pagetype notify 2022-03-20 15:43:11 +01:00
joBr99
17554fd57d modified notify page commands (add nextion2text) 2022-03-20 14:31:33 +00:00
Johannes Braun
5d6f59df71 modified notify page commands 2022-03-20 15:31:12 +01:00
Johannes Braun
818405fa73 fixed forecast icons 2022-03-20 15:08:53 +01:00
joBr99
2451c353f8 fixed dim value on wake (add nextion2text) 2022-03-20 14:05:54 +00:00
Johannes Braun
d3475a948e fixed dim value on wake 2022-03-20 15:05:28 +01:00
joBr99
0b7fec2f99 Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-20 13:56:05 +00:00
Johannes Braun
81487e580b Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui 2022-03-20 14:54:57 +01:00
Johannes Braun
6347297d1f simplified pageOpen 2022-03-20 14:54:45 +01:00
joBr99
6e3dbc4057 modified notify commands (add nextion2text) 2022-03-20 13:36:33 +00:00
Johannes Braun
8849e18e48 modified notify commands 2022-03-20 14:36:11 +01:00
Johannes Braun
5e6348dc70 migration to icon mapper 2022-03-20 14:20:57 +01:00
Johannes Braun
b1399aad81 fix ident 2022-03-20 13:55:46 +01:00
Johannes Braun
fe3e0c882e migrate weather to icon mapper 2022-03-20 13:54:03 +01:00
Johannes Braun
59691cc591 fixed file ending in links 2022-03-20 13:43:54 +01:00
Johannes Braun
0d85dac1e1 added code gen for stuff related to icons ids 2022-03-20 13:37:45 +01:00
Johannes Braun
f08010d74b Merge branch 'main' of github.com:joBr99/nspanel-lovelace-ui 2022-03-20 12:32:22 +01:00
Johannes Braun
470a891f65 update docs 2022-03-20 12:32:06 +01:00
joBr99
860f4a3dd0 fix shutter on grid page (add nextion2text) 2022-03-20 11:09:44 +00:00
Johannes Braun
64cb6c58e3 fix shutter on grid page 2022-03-20 12:09:26 +01:00
Johannes
21d1ad9a1e fix icon for switches 2022-03-20 12:05:10 +01:00
Johannes
7a55c1c876 added light toggle to buttonpress 2022-03-20 10:57:44 +01:00
Johannes
ae9254eda2 Merge pull request #45 from gerard33/patch-2
Change check for supported_color_modes
2022-03-20 01:42:03 +01:00
joBr99
2b0e16d633 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-20 00:30:03 +00:00
Johannes
330744ca9c Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-20 01:29:45 +01:00
Johannes
7584516ac9 fixed shutter 2022-03-20 01:29:35 +01:00
joBr99
7937368f73 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-20 00:26:46 +00:00
Johannes
1aca308970 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-20 01:26:23 +01:00
Johannes
5a9ffc1889 changed sel color 2022-03-20 01:26:15 +01:00
Johannes
6a9b4d4f0e Update nspanel-lovelace-ui.py 2022-03-20 01:16:48 +01:00
Johannes
0809443b5d Update nspanel-lovelace-ui.py 2022-03-20 01:15:40 +01:00
joBr99
9ca085e296 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-20 00:14:24 +00:00
Johannes
5120a87472 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-20 01:14:00 +01:00
Johannes
8c3df900fe added long press for cardgrid 2022-03-20 01:13:50 +01:00
Gerard
3af3fd5172 Change check for supported_color_modes 2022-03-20 01:04:01 +01:00
joBr99
13d1e95e74 added usercode to buttons (add nextion2text) 2022-03-19 23:49:48 +00:00
Johannes
36ab2eb09c added usercode to buttons 2022-03-20 00:49:30 +01:00
Johannes
66f3e2955b Merge pull request #44 from gerard33/patch-2
Change indent for popup shutter
2022-03-20 00:42:34 +01:00
Gerard
e01d4a8bc8 Change indent for popup shutter 2022-03-20 00:35:53 +01:00
Johannes
63e7ecd60a Merge pull request #43 from gerard33/patch-1
Fix light with brightness
2022-03-20 00:33:17 +01:00
joBr99
2ad0ad4c35 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-19 23:31:11 +00:00
Johannes
a1665075b5 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-20 00:30:51 +01:00
Johannes
d095f7ef28 fixed delete on grid page 2022-03-20 00:30:48 +01:00
Gerard
9a4fef98d3 Create nspanel-lovelace-ui.py 2022-03-20 00:28:29 +01:00
Gerard
1e9a8df3f8 Fix light with brightness 2022-03-20 00:17:50 +01:00
joBr99
2f21594289 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-19 23:13:44 +00:00
Johannes
63778275dc Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-20 00:13:18 +01:00
Johannes
ff43743ae3 fixed grind command 2022-03-20 00:13:09 +01:00
Johannes
a7d710bb6f Merge pull request #42 from britzelpuf/main
Fixed Typo in HMI/README.md
2022-03-19 23:51:28 +01:00
joBr99
ee66eb13f6 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-19 22:50:58 +00:00
Johannes
441bedf5a2 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-19 23:50:35 +01:00
Johannes
85b0ed4154 fixed grid cmd 2022-03-19 23:50:26 +01:00
joBr99
890236f683 added grid page (add nextion2text) 2022-03-19 22:26:58 +00:00
britzelpuf
18c96ee0f8 Fixed Typo in HMI/README.md
Updated to NsPanelTs.ts to support new FW
Updated README.md
2022-03-19 23:26:57 +01:00
Johannes
00442c82b0 added grid page 2022-03-19 23:26:39 +01:00
Johannes
dc3062eba0 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-19 22:00:39 +01:00
Johannes
cfdfb9404c added light color to detail page 2022-03-19 22:00:31 +01:00
joBr99
246c03ee4b added icon to popup light command (add nextion2text) 2022-03-19 20:49:20 +00:00
Johannes
940ee10fc4 added icon to popup light command 2022-03-19 21:48:56 +01:00
Johannes
ba887cf60c added light with brightness only 2022-03-19 21:30:00 +01:00
Johannes
e5706d848f added brightness 2022-03-19 21:24:03 +01:00
Johannes
eac1095bbd set current rgb_color 2022-03-19 20:56:15 +01:00
Johannes
1f6cd2d1aa Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-19 20:39:18 +01:00
Johannes
1201142cb5 move color stuff to seperate file 2022-03-19 20:39:11 +01:00
joBr99
dddff76d11 added color to commands for entity page (add nextion2text) 2022-03-19 19:14:22 +00:00
Johannes
e74de74ede added color to commands for entity page 2022-03-19 20:14:02 +01:00
Johannes
e859c338b3 added color to update command on entity card 2022-03-19 20:08:58 +01:00
Johannes
0921dd81b8 Update nspanel-lovelace-ui.py 2022-03-19 19:16:43 +01:00
Johannes
413401b1f9 Update nspanel-lovelace-ui.py 2022-03-19 18:26:12 +01:00
Johannes
fcc8d44bfd Merge pull request #41 from gerard33/patch-1
Change to f-string
2022-03-19 18:10:18 +01:00
joBr99
d4ff842dee Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-19 17:09:24 +00:00
Johannes
4cd0ecbe56 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-19 18:09:03 +01:00
Johannes
cfba107246 increase max mem for cmd 2022-03-19 18:08:54 +01:00
Gerard
e5b4fb4743 Change to f-string 2022-03-19 17:58:11 +01:00
joBr99
a35467830f bind startup animation to ui element (add nextion2text) 2022-03-19 16:06:25 +00:00
Johannes
625bddc894 bind startup animation to ui element 2022-03-19 17:06:01 +01:00
Johannes
6124a24887 fixed function call 2022-03-19 16:47:41 +01:00
Johannes
39e44bc820 fixed state callback 2022-03-19 16:23:23 +01:00
joBr99
f3351af4e5 fixed page command (add nextion2text) 2022-03-19 14:45:12 +00:00
Johannes Braun
0cc735566f fixed page command 2022-03-19 15:44:52 +01:00
Johannes Braun
90e2b1622b fixed callback 2022-03-19 14:46:03 +01:00
Johannes Braun
9f8be27835 changed to new entities msg format 2022-03-19 14:30:24 +01:00
Johannes Braun
b852703aa1 Merge branch 'main' of github.com:joBr99/nspanel-widget-ui 2022-03-19 14:07:35 +01:00
Johannes Braun
cce36c281e extended cmd length 2022-03-19 14:07:24 +01:00
joBr99
9267e7be4e changed entities page message format (add nextion2text) 2022-03-19 12:36:24 +00:00
Johannes Braun
91434bfdd3 changed entities page message format 2022-03-19 13:36:00 +01:00
Johannes Braun
9153b602d7 changed entities page message format 2022-03-19 13:35:34 +01:00
joBr99
7c7241bc98 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui (add nextion2text) 2022-03-19 07:32:22 +00:00
Johannes
9a111720e5 Merge branch 'main' of https://github.com/joBr99/nspanel-lovelace-ui 2022-03-19 08:31:54 +01:00
Johannes
a93681f262 removed font 3, to save some space 2022-03-19 08:31:35 +01:00
joBr99
dfe82dcd45 added page command to screensaver (add nextion2text) 2022-03-19 07:22:33 +00:00
Johannes
6f792443ad added page command to screensaver 2022-03-19 08:22:04 +01:00
joBr99
4b21961707 Merge branch 'main' of github.com:joBr99/nspanel-widget-ui (add nextion2text) 2022-03-19 07:08:42 +00:00
Johannes Braun
699ba7855b Merge branch 'main' of github.com:joBr99/nspanel-widget-ui 2022-03-19 08:08:14 +01:00
Johannes Braun
0b740fb14d added early version of alarm screen 2022-03-19 08:07:53 +01:00
Johannes
19764eb220 Merge pull request #40 from gerard33/patch-1
Add localization for weather forecast
2022-03-17 21:54:02 +01:00
Gerard
8fee0af87f Update info.md 2022-03-17 21:29:23 +01:00
Gerard
ccd914c1a7 Update apps.yaml 2022-03-17 21:28:57 +01:00
Gerard
49f6631d5a Update README.md 2022-03-17 21:28:05 +01:00
Gerard
6fd1ddb432 Add localization for weather forecast
Show the day in local format for the weather forecast
2022-03-17 21:21:59 +01:00
Johannes
3fae02ebe2 Merge pull request #39 from britzelpuf/main
some cleanup and some fixes
2022-03-17 20:39:14 +01:00
Johannes
6e073f7181 Update codeql-analysis.yml 2022-03-17 20:34:52 +01:00
britzelpuf
9ea6c218fa - general cleanup
- updated Accuweather mapping
- added Button code
2022-03-17 20:05:15 +01:00
Johannes
f48510e03e Update README.md 2022-03-16 23:53:39 +01:00
Johannes
b5e3133d77 added localization support for date 2022-03-16 23:39:36 +01:00
Johannes
fc1614e243 Update README.md 2022-03-16 18:55:11 +01:00
Johannes
2d39e15b9d Update README.md 2022-03-16 18:46:44 +01:00
Johannes
025a3bd700 Update README.md 2022-03-16 18:30:45 +01:00
joBr99
93393ac877 Merge branch 'main' of github.com:joBr99/nspanel-widget-ui (add nextion2text) 2022-03-16 17:27:22 +00:00
Johannes Braun
b28c4e46eb Merge branch 'main' of github.com:joBr99/nspanel-widget-ui 2022-03-16 18:27:00 +01:00
Johannes Braun
48e17ed986 added another icon 2022-03-16 18:26:48 +01:00
joBr99
f0857aeec7 added two icons (add nextion2text) 2022-03-16 17:24:34 +00:00
Johannes Braun
36dddb0dc2 added two icons 2022-03-16 18:24:07 +01:00
Johannes
e1ac4d4cec Update README.md 2022-03-16 18:11:40 +01:00
Johannes
d82c4127b7 Update README.md 2022-03-16 18:11:03 +01:00
Johannes
991c882373 Update README.md 2022-03-16 18:10:08 +01:00
Johannes
e35b9d4a82 Update Icon Reference with Table in HMI Doc
Since I won't update this picture I think it's better to link the table where I'm documenting the icons, even if the HMI documentation isn't great :)
2022-03-16 18:09:58 +01:00
Johannes
0cdbfc5708 Update README.md 2022-03-16 18:06:38 +01:00
Johannes
21e8300191 Merge pull request #38 from britzelpuf/main
Added README.md
2022-03-16 17:49:06 +01:00
britzelpuf
d534ba30ac Added note where to change the screensaver value 2022-03-16 17:44:34 +01:00
britzelpuf
491ad5ea25 Update README.md 2022-03-16 17:42:18 +01:00
britzelpuf
fb5145561f Create README.md 2022-03-16 17:39:01 +01:00
36 changed files with 30488 additions and 1703 deletions

View File

@@ -37,7 +37,7 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
language: [ 'python', 'typescript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support

View File

@@ -77,33 +77,35 @@ change the page type:
`weatherUpdate,?0?2,3 C?0?0 mm?Mi?0?9,3 C?Do?0?11,5 C`
`page,0`
### cardEntities Page
The following message can be used to update the content on the cardEntities Page
`entityUpdHeading,heading1337`
`entityUpd,*id*,*type*,*internalNameEntity*,*iconId*,*displayNameEntity*,*optionalValue*`
`entityUpd[,*type*,*internalNameEntity*,*iconId*,*iconColor*,*displayNameEntity*,*optionalValue*]x4`
`entityUpd,1,light,light.entityName,1,Light1,0`
`,light,light.entityName,1,17299,Light1,0`
`entityUpd,2,shutter,cover.entityName,0,Shutter2`
`,shutter,cover.entityName,0,17299,Shutter2,`
`entityUpd,3,delete`
`,delete,,,,`
`entityUpd,4,text,sensor.entityName,3,Temperature,content`
`,text,sensor.entityName,3,17299,Temperature,content`
`entityUpd,4,button,button.entityName,3,bt-name,bt-text`
`,button,button.entityName,3,17299,bt-name,bt-text`
`entityUpd,1,switch,switch.entityName,4,Switch1,0`
`,switch,switch.entityName,4,17299,Switch1,0`
### popupLight Page
`entityUpdateDetail,*buttonState*,*sliderBrightnessPos*,*sliderColorTempPos*,*colorMode*`
`entityUpdateDetail,*iconId*,*iconColor*,*buttonState*,*sliderBrightnessPos*,*sliderColorTempPos*,*colorMode*`
`entityUpdateDetail,1,100,78,enable`
`entityUpdateDetail,1,17299,1,100,78,enable`
`entityUpdateDetail,1,100,disable`
`entityUpdateDetail,1,17299,1,100,disable`
### popupShutter Page
@@ -113,7 +115,7 @@ The following message can be used to update the content on the cardEntities Page
### popupNotify Page
`entityUpdateDetail,*tHeading*,*b1*,*b2*,*tText*`
`entityUpdateDetail,*internalName*,*tHeading*,*tHeadingColor*,*b1*,*tB1Color*,*b2*,*tB2Color*,*tText*,*tTextColor*,*sleepTimeout*`
### cardThermo Page
@@ -171,9 +173,9 @@ The following message can be used to update the content on the cardEntities Page
### popupNotify Page
`event,buttonPress,D,D,D,1,notifyAction,yes`
`event,buttonPress,D,D,*internalName*,1,notifyAction,yes`
`event,buttonPress,D,D,D,1,notifyAction,no`
`event,buttonPress,D,D,*internalName*,1,notifyAction,no`
### cardThermo Page
@@ -197,40 +199,7 @@ The following message can be used to update the content on the cardEntities Page
# Icons IDs
ID | Icon
-- | ----
0 | ![window-open](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/window-open.svg)
1 | ![lightbulb](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/lightbulb.svg)
2 | ![thermometer](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/thermometer.svg)
3 | ![gesture-tap-button](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/gesture-tap-button.svg)
4 | ![flash](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/flash.svg)
5 | ![music](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/music.svg)
6 | ![check-circle-outline](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/check-circle-outline.svg)
7 | ![close-circle-outline](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/close-circle-outline.svg)
8 | ![pause](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/pause.svg)
9 | ![play](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/play.svg)
10 | ![palette](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/palette.svg)
11 | ![alert-circle-outline](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/alert-circle-outline.svg)
12 | ![weather-cloudy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-cloudy.svg)
13 | ![weather-fog](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-fog.svg)
14 | ![weather-hail](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-hail.svg)
15 | ![weather-lightning](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-lightning.svg)
16 | ![weather-lightning-rainy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-lightning-rainy.svg)
17 | ![weather-night](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-night.svg)
18 | ![weather-partly-cloudy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-partly-cloudy.svg)
19 | ![weather-pouring](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-pouring.svg)
20 | ![weather-rainy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-rainy.svg)
21 | ![weather-snowy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-snowy.svg)
22 | ![weather-snowy-rainy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-snowy-rainy.svg)
23 | ![weather-sunny](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-sunny.svg)
24 | ![weather-windy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-windy.svg)
25 | ![weather-windy-variant](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-windy-variant.svg)
26 | ![water-percent](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/water-percent.svg)
27 | ![power](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/power.svg)
28 | ![fire](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/fire.svg)
29 | ![calendar-sync](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/calendar-sync.svg)
30 | ![fan](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/fan.svg)
31 | ![snowflake](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/snowflake.svg)
Please see Icon's int the [icons.md file](icons.md)
# Design Guidelines for Nextion HMI Project

25592
HMI/code_gen/icons/icons.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,93 @@
import json
import os
icons = [
"window-open",
"lightbulb",
"thermometer",
"gesture-tap-button",
"flash",
"music",
"check-circle-outline",
"close-circle-outline",
"pause",
"play",
"palette",
"alert-circle-outline",
"weather-cloudy",
"weather-fog",
"weather-hail",
"weather-lightning",
"weather-lightning-rainy",
"weather-night",
"weather-partly-cloudy",
"weather-pouring",
"weather-rainy",
"weather-snowy",
"weather-snowy-rainy",
"weather-sunny",
"weather-windy",
"weather-windy-variant",
"water-percent",
"power",
"fire",
"calendar-sync",
"fan",
"snowflake",
"solar-power",
"battery-charging-medium",
"battery-medium"
]
__location__ = os.path.realpath(
os.path.join(os.getcwd(), os.path.dirname(__file__)))
with open(os.path.join(__location__, "icons.json"),'r') as f:
icon_metadata = json.load(f)
icon_nextion_string = ""
icon_name_list = []
for icon_name in icons:
#print(icon_name)
icon = next((item for item in icon_metadata if item["name"] == icon_name), None)
if icon == None:
print(f"WARNING ICON NOT FOUND: {icon_name}")
else:
hex = icon['hex']
s = int(hex, 16)
#print(chr(s), end = '')
icon_nextion_string += chr(s)
icon_name_list.append(icon_name)
# write mapping lib for python
with open(os.path.join(__location__, "../../../apps/nspanel-lovelace-ui", "icon_mapper.py"), 'w') as f:
f.write("icons = {\n")
for idx, val in enumerate(icon_name_list):
f.write(f" '{val}': {idx},\n")
f.write("}\n")
f.write("""
def get_icon_id(ma_name):
if ma_name in icons:
return icons[ma_name]
else:
return icons["alert-circle-outline"]
""")
# write documentation file
with open(os.path.join(__location__, "../..","icons.md"), 'w') as f:
f.write("""
# Icons IDs
This file contains the Icons IDs included in the display firmware, addressable via serial.
ID | MD Icon Name | Icon
-- | ------------ | ----
""")
for idx, val in enumerate(icon_name_list):
f.write(f"{idx} | {val} | ![{val}](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/{val}.svg)\n")
print("=== STRING for HMI Project ===")
print("=== Put the following string into the txt field in nextion ===")
print(icon_nextion_string)

41
HMI/icons.md Normal file
View File

@@ -0,0 +1,41 @@
# Icons IDs
This file contains the Icons IDs included in the display firmware, addressable via serial.
ID | MD Icon Name | Icon
-- | ------------ | ----
0 | window-open | ![window-open](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/window-open.svg)
1 | lightbulb | ![lightbulb](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/lightbulb.svg)
2 | thermometer | ![thermometer](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/thermometer.svg)
3 | gesture-tap-button | ![gesture-tap-button](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/gesture-tap-button.svg)
4 | flash | ![flash](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/flash.svg)
5 | music | ![music](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/music.svg)
6 | check-circle-outline | ![check-circle-outline](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/check-circle-outline.svg)
7 | close-circle-outline | ![close-circle-outline](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/close-circle-outline.svg)
8 | pause | ![pause](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/pause.svg)
9 | play | ![play](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/play.svg)
10 | palette | ![palette](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/palette.svg)
11 | alert-circle-outline | ![alert-circle-outline](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/alert-circle-outline.svg)
12 | weather-cloudy | ![weather-cloudy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-cloudy.svg)
13 | weather-fog | ![weather-fog](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-fog.svg)
14 | weather-hail | ![weather-hail](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-hail.svg)
15 | weather-lightning | ![weather-lightning](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-lightning.svg)
16 | weather-lightning-rainy | ![weather-lightning-rainy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-lightning-rainy.svg)
17 | weather-night | ![weather-night](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-night.svg)
18 | weather-partly-cloudy | ![weather-partly-cloudy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-partly-cloudy.svg)
19 | weather-pouring | ![weather-pouring](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-pouring.svg)
20 | weather-rainy | ![weather-rainy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-rainy.svg)
21 | weather-snowy | ![weather-snowy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-snowy.svg)
22 | weather-snowy-rainy | ![weather-snowy-rainy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-snowy-rainy.svg)
23 | weather-sunny | ![weather-sunny](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-sunny.svg)
24 | weather-windy | ![weather-windy](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-windy.svg)
25 | weather-windy-variant | ![weather-windy-variant](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/weather-windy-variant.svg)
26 | water-percent | ![water-percent](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/water-percent.svg)
27 | power | ![power](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/power.svg)
28 | fire | ![fire](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/fire.svg)
29 | calendar-sync | ![calendar-sync](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/calendar-sync.svg)
30 | fan | ![fan](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/fan.svg)
31 | snowflake | ![snowflake](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/snowflake.svg)
32 | solar-power | ![solar-power](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/solar-power.svg)
33 | battery-charging-medium | ![battery-charging-medium](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/battery-charging-medium.svg)
34 | battery-medium | ![battery-medium](https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/0aeb4d612644d80d9d1fe242f705f362985de5dc/svg/battery-medium.svg)

997
HMI/n2t-out/cardAlarm.txt Normal file
View File

@@ -0,0 +1,997 @@
Page cardAlarm
Attributes
ID : 0
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
Width : 480
Effect : load
Effect Priority : 0
Effect Time : 300
Locked : no
Swide up page ID : disabled
Swide down page ID : disabled
Swide left page ID : disabled
Swide right page ID : disabled
Fill : solid color
Back. Color : 6371
Events
Preinitialize Event
vis p0,0
vis tSend,0
vis tInstruction,0
vis nPageDisp,0
vis tTmp,0
vis tId,0
//vis nPageDisp,0
Variable (string) strCommand
Attributes
ID : 8
Scope : local
Text :
Max. Text Size: 200
Variable (string) entn
Attributes
ID : 11
Scope : local
Text :
Max. Text Size: 50
Number nPageDisp
Attributes
ID : 6
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 426
y coordinate : 0
Width : 42
Height : 24
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
Attributes
ID : 2
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 0
y coordinate : 0
Width : 230
Height : 23
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
Input Type : character
Text : newtxt
Max. Text Size : 100
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tTmp
Attributes
ID : 3
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 406
y coordinate : 277
Width : 34
Height : 30
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
Input Type : character
Text :
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tInstruction
Attributes
ID : 9
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 0
y coordinate : 290
Width : 100
Height : 30
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
Input Type : character
Text :
Max. Text Size : 20
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tId
Attributes
ID : 10
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 99
y coordinate : 290
Width : 39
Height : 30
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
Input Type : character
Text :
Max. Text Size : 20
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Text tCode
Attributes
ID : 25
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 162
y coordinate : 79
Width : 126
Height : 49
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 0
Back. Color : 10565
Font Color : 40179
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
Attributes
ID : 1
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 0
y coordinate : 0
Width : 480
Height : 320
Effect : load
Effect Priority : 0
Effect Time : 300
Picture ID : 0
Button bNext
Attributes
ID : 4
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 391
y coordinate : 16
Width : 50
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Font ID : 2
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : 
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
nPage=nPage+1
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
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
Button bPrev
Attributes
ID : 5
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 9
y coordinate : 16
Width : 50
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : flat
Font ID : 2
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : 
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
nPage=nPage-1
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
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
Button b0
Attributes
ID : 14
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 51
y coordinate : 139
Width : 75
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : 1
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
tCode.txt=tCode.txt+"1"
Button b1
Attributes
ID : 15
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 143
y coordinate : 139
Width : 75
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : 2
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
tCode.txt=tCode.txt+"2"
Button b2
Attributes
ID : 16
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 235
y coordinate : 138
Width : 75
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : 3
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
tCode.txt=tCode.txt+"3"
Button b3
Attributes
ID : 17
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 51
y coordinate : 197
Width : 75
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : 4
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
tCode.txt=tCode.txt+"4"
Button b4
Attributes
ID : 18
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 143
y coordinate : 197
Width : 75
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : 5
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
tCode.txt=tCode.txt+"5"
Button b5
Attributes
ID : 19
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 235
y coordinate : 197
Width : 75
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : 6
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
tCode.txt=tCode.txt+"6"
Button b6
Attributes
ID : 20
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 51
y coordinate : 255
Width : 75
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : 7
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
tCode.txt=tCode.txt+"7"
Button b7
Attributes
ID : 21
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 143
y coordinate : 255
Width : 75
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : 8
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
tCode.txt=tCode.txt+"8"
Button b8
Attributes
ID : 22
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 235
y coordinate : 255
Width : 75
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : 9
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
tCode.txt=tCode.txt+"9"
Button b9
Attributes
ID : 23
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 327
y coordinate : 197
Width : 75
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : 0
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
tCode.txt=tCode.txt+"0"
Button b10
Attributes
ID : 24
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 327
y coordinate : 255
Width : 75
Height : 50
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : CLEAR
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
tCode.txt=""
Button b11
Attributes
ID : 26
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 96
y coordinate : 32
Width : 113
Height : 33
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : ARM HOME
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Button b12
Attributes
ID : 27
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 242
y coordinate : 32
Width : 113
Height : 33
Effect : load
Effect Priority : 0
Effect Time : 300
Fill : solid color
Style : border
Border Color : 6371
Border Width : 2
Font ID : 0
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 1374
Font Color (Pressed) : 65535
Horizontal Alignment : center
Vertical Alignment : center
State : unpressed
Text : ARM AWAY
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Timer tmSerial
Attributes
ID : 7
Scope : local
Period (ms): 50
Enabled : yes
Events
Timer Event
// data available
if(usize>1)
{
bufferPos=0
while(bufferPos<usize)
{
// check for 0x55 0xBB - Command Init Secuence
if(u[bufferPos]==187&&u[bufferPos-1]==85)
{
//remove garbage at the start of the buffer if there's any to free buffer for command
if(u[bufferPos]!=1)
{
udelete bufferPos-1
}
//instruction is now aligned with buffer, because we deleted garbage before instrcution
//get length after init sequence (check if there are more than to bytes in buffer)
if(3<usize)
{
// check if serial buffer has reached the announced length
ucopy payloadLength,2,2,0
// we are only checking payload length so we have to skip first 3 bytes (init+payload length) (-1 because of < instead of <=)
payloadLength+=3
// payload length does also not contain crc, so we are adding another 2 bytes for crc
payloadLength+=2
if(payloadLength<usize)
{
// calculate crc
crcrest 1,0xFFFF
// u[2] contains payload legth at 3rd pos in buffer, we are calculating crc from 3rd pos with number of bytes from payload length
//crcputu 3,u[2]
// u[2] cotnains payload length, we are calculating a crc over the whole message, so we have to add 3 to the length from u[2]
crcputu 0,payloadLength-1
// get recived crc to be able to compare it
ucopy recvCrc,payloadLength-1,2,0
// compare crc with recived value
if(crcval==recvCrc)
{
// crc is okay
// here is the location where acual code should be
// write command to variable strCommand
ucopy strCommand.txt,4,payloadLength-5,0
// write instruction to tInstuction (debug output, but used as variable here, ui elements will be disabled by default)
spstr strCommand.txt,tInstruction.txt,",",0
if(tInstruction.txt=="entityUpd")
{
}
if(tInstruction.txt=="time")
{
// get set time to global variable
spstr strCommand.txt,screensaver.vaTime.txt,",",1
}
if(tInstruction.txt=="date")
{
// get set date to global variable
spstr strCommand.txt,screensaver.vaDate.txt,"?",1
}
if(tInstruction.txt=="dimmode")
{
// get value
spstr strCommand.txt,tTmp.txt,",",1
covx tTmp.txt,dimValue,0,0
dim=dimValue
}
if(tInstruction.txt=="timeout")
{
//set timeout to global var
spstr strCommand.txt,tTmp.txt,",",1
covx tTmp.txt,sleepTimeout,0,0
}
if(tInstruction.txt=="pageType")
{
//command format pageType,specialPageName
//write name of speical page to tId
spstr strCommand.txt,tId.txt,",",1
//save second arg if there's one
spstr strCommand.txt,tTmp.txt,",",2
//save third arg if there's one
spstr strCommand.txt,pageIcons.tTmp2.txt,",",3
//we are going to exit this page with this command, so we have to clear the buffer, so we are not getting into a stupid loop ...
udelete payloadLength-1
bufferPos=0
if(tId.txt=="popupLight")
{
pageIcons.tTmp1.txt=tTmp.txt
page popupLight
}
if(tId.txt=="cardEntities")
{
page cardEntities
}
if(tId.txt=="cardThermo")
{
page cardThermo
}
if(tId.txt=="pageStartup")
{
page pageStartup
}
if(tId.txt=="popupNotify")
{
page popupNotify
}
if(tId.txt=="cardGrid")
{
page cardGrid
}
if(tId.txt=="cardMedia")
{
page cardMedia
}
}
// end of user code
udelete payloadLength-1
bufferPos=0
}
}
}
}
// next character
bufferPos++
}
}
Timer tmSleep
Attributes
ID : 12
Scope : local
Period (ms): 1000
Enabled : yes
Events
Timer Event
if(sleepTimeout!=0)
{
sleepValue+=1
if(sleepTimeout<=sleepValue)
{
screensaver.originPage.val=dp
sleepValue=0
page screensaver
}
}
TouchCap tc0
Attributes
ID : 13
Scope: local
Value: 0
Events
Touch Press Event
sleepValue=0

View File

@@ -27,7 +27,6 @@ Page cardEntities
bauds=115200
//debug stuff
vis tTmp,0
vis nPageDisp,0
vis tSend,0
vis tInstruction,0
vis tId,0
@@ -63,119 +62,70 @@ Page cardEntities
vis tIcon4,0
vis tEntity4,0
vis bText4,0
//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
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
//display current page from global var
nPageDisp.val=nPage
Variable (string) strCommand
Attributes
ID : 27
Scope : local
Text :
Max. Text Size: 150
Max. Text Size: 500
Variable (string) type1
Attributes
ID : 46
ID : 45
Scope : local
Text :
Max. Text Size: 10
Variable (string) type2
Attributes
ID : 47
ID : 46
Scope : local
Text :
Max. Text Size: 10
Variable (string) type3
Attributes
ID : 48
ID : 47
Scope : local
Text :
Max. Text Size: 10
Variable (string) type4
Attributes
ID : 49
ID : 48
Scope : local
Text :
Max. Text Size: 10
Variable (string) entn1
Attributes
ID : 50
ID : 49
Scope : local
Text :
Max. Text Size: 50
Variable (string) entn2
Attributes
ID : 51
ID : 50
Scope : local
Text :
Max. Text Size: 50
Variable (string) entn3
Attributes
ID : 52
ID : 51
Scope : local
Text :
Max. Text Size: 50
Variable (string) entn4
Attributes
ID : 53
ID : 52
Scope : local
Text :
Max. Text Size: 50
Number nPageDisp
Attributes
ID : 35
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 409
y coordinate : 0
Width : 42
Height : 24
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 tHeading
Attributes
ID : 2
@@ -603,7 +553,7 @@ Button bDown1
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -657,7 +607,7 @@ Button bUp1
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -711,7 +661,7 @@ Button bStop1
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -765,7 +715,7 @@ Button bStop2
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -819,7 +769,7 @@ Button bDown2
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -873,7 +823,7 @@ Button bUp2
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -927,7 +877,7 @@ Button bStop3
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -981,7 +931,7 @@ Button bDown3
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -1035,7 +985,7 @@ Button bUp3
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -1089,7 +1039,7 @@ Button bStop4
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -1143,7 +1093,7 @@ Button bDown4
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -1197,7 +1147,7 @@ Button bUp4
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -1251,7 +1201,7 @@ Button bPrev
Font ID : 2
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -1266,7 +1216,6 @@ Button bPrev
Events
Touch Press Event
nPage=nPage-1
nPageDisp.val=nPage
//page open event
// event,pageOpen,cardEntities,pageNumber
// craft command
@@ -1305,7 +1254,7 @@ Button bNext
Font ID : 2
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -1320,7 +1269,6 @@ Button bNext
Events
Touch Press Event
nPage=nPage+1
nPageDisp.val=nPage
//page open event
// event,pageOpen,cardEntities,pageNumber
// craft command
@@ -1341,7 +1289,7 @@ Button bNext
Button bText1
Attributes
ID : 38
ID : 37
Scope : local
Dragging : 0
Disable release event after dragging: 0
@@ -1395,7 +1343,7 @@ Button bText1
Button bText2
Attributes
ID : 39
ID : 38
Scope : local
Dragging : 0
Disable release event after dragging: 0
@@ -1449,7 +1397,7 @@ Button bText2
Button bText3
Attributes
ID : 40
ID : 39
Scope : local
Dragging : 0
Disable release event after dragging: 0
@@ -1503,7 +1451,7 @@ Button bText3
Button bText4
Attributes
ID : 41
ID : 40
Scope : local
Dragging : 0
Disable release event after dragging: 0
@@ -1765,7 +1713,7 @@ Dual-state Button btOnOff4
Hotspot mSpecial
Attributes
ID : 36
ID : 35
Scope : local
Dragging : 0
Disable release event after dragging: 0
@@ -1791,7 +1739,7 @@ Hotspot mSpecial
Hotspot m2
Attributes
ID : 42
ID : 41
Scope : local
Dragging : 0
Disable release event after dragging: 0
@@ -1822,7 +1770,7 @@ Hotspot m2
Hotspot m1
Attributes
ID : 43
ID : 42
Scope : local
Dragging : 0
Disable release event after dragging: 0
@@ -1853,7 +1801,7 @@ Hotspot m1
Hotspot m0
Attributes
ID : 44
ID : 43
Scope : local
Dragging : 0
Disable release event after dragging: 0
@@ -1884,7 +1832,7 @@ Hotspot m0
Hotspot m3
Attributes
ID : 45
ID : 44
Scope : local
Dragging : 0
Disable release event after dragging: 0
@@ -1971,16 +1919,11 @@ Timer tmSerial
}
if(tInstruction.txt=="entityUpd")
{
// command format: entityUpd,id,icon,name,type,optionalValue
// write id to tId (debug output, but used as variable here, ui elements will be disabled by default)
spstr strCommand.txt,tId.txt,",",1
// id 1
if(tId.txt=="1")
{
// command format: entityUpd[,type,internalName,iconId,displayName,optionalValue]x4
// get Type
spstr strCommand.txt,type1.txt,",",2
spstr strCommand.txt,type1.txt,",",1
// get internal name
spstr strCommand.txt,entn1.txt,",",3
spstr strCommand.txt,entn1.txt,",",2
if(type1.txt=="delete")
{
vis bUp1,0
@@ -1993,10 +1936,14 @@ Timer tmSerial
}else
{
// change icon
spstr strCommand.txt,tTmp.txt,",",4
spstr strCommand.txt,tTmp.txt,",",3
covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tIcon1.txt,sys0,1
vis tIcon1,1
// change icon color
spstr strCommand.txt,tTmp.txt,",",4
covx tTmp.txt,sys0,0,0
tIcon1.pco=sys0
// set name
spstr strCommand.txt,tEntity1.txt,",",5
vis tEntity1,1
@@ -2059,14 +2006,11 @@ Timer tmSerial
// get Text (optional Value)
spstr strCommand.txt,bText1.txt,",",6
}
}
// id2
if(tId.txt=="2")
{
// get Type
spstr strCommand.txt,type2.txt,",",2
spstr strCommand.txt,type2.txt,",",7
// get internal name
spstr strCommand.txt,entn2.txt,",",3
spstr strCommand.txt,entn2.txt,",",8
if(type2.txt=="delete")
{
vis bUp2,0
@@ -2079,12 +2023,16 @@ Timer tmSerial
}else
{
//change icon
spstr strCommand.txt,tTmp.txt,",",4
spstr strCommand.txt,tTmp.txt,",",9
covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tIcon2.txt,sys0,1
vis tIcon2,1
// change icon color
spstr strCommand.txt,tTmp.txt,",",10
covx tTmp.txt,sys0,0,0
tIcon2.pco=sys0
// set name
spstr strCommand.txt,tEntity2.txt,",",5
spstr strCommand.txt,tEntity2.txt,",",11
vis tEntity2,1
}
if(type2.txt=="shutter")
@@ -2103,7 +2051,7 @@ Timer tmSerial
vis btOnOff2,1
vis bText2,0
// get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",6
spstr strCommand.txt,tTmp.txt,",",12
covx tTmp.txt,sys0,0,0
btOnOff2.val=sys0
}
@@ -2115,7 +2063,7 @@ Timer tmSerial
vis btOnOff2,1
vis bText2,0
// get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",6
spstr strCommand.txt,tTmp.txt,",",12
covx tTmp.txt,sys0,0,0
btOnOff2.val=sys0
}
@@ -2130,7 +2078,7 @@ Timer tmSerial
bText2.pco=65535
bText2.pco2=65535
// get Text (optional Value)
spstr strCommand.txt,bText2.txt,",",6
spstr strCommand.txt,bText2.txt,",",12
}
if(type2.txt=="button")
{
@@ -2143,16 +2091,13 @@ Timer tmSerial
bText2.pco=1374
bText2.pco2=1374
// get Text (optional Value)
spstr strCommand.txt,bText2.txt,",",6
}
spstr strCommand.txt,bText2.txt,",",12
}
// id3
if(tId.txt=="3")
{
// get Type
spstr strCommand.txt,type3.txt,",",2
spstr strCommand.txt,type3.txt,",",13
// get internal name
spstr strCommand.txt,entn3.txt,",",3
spstr strCommand.txt,entn3.txt,",",14
if(type3.txt=="delete")
{
vis bUp3,0
@@ -2165,12 +2110,16 @@ Timer tmSerial
}else
{
//change icon
spstr strCommand.txt,tTmp.txt,",",4
spstr strCommand.txt,tTmp.txt,",",15
covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tIcon3.txt,sys0,1
vis tIcon3,1
// change icon color
spstr strCommand.txt,tTmp.txt,",",16
covx tTmp.txt,sys0,0,0
tIcon3.pco=sys0
// set name
spstr strCommand.txt,tEntity3.txt,",",5
spstr strCommand.txt,tEntity3.txt,",",17
vis tEntity3,1
}
if(type3.txt=="shutter")
@@ -2189,7 +2138,7 @@ Timer tmSerial
vis bText3,0
vis btOnOff3,1
// get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",6
spstr strCommand.txt,tTmp.txt,",",18
covx tTmp.txt,sys0,0,0
btOnOff3.val=sys0
}
@@ -2201,7 +2150,7 @@ Timer tmSerial
vis bText3,0
vis btOnOff3,1
// get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",6
spstr strCommand.txt,tTmp.txt,",",18
covx tTmp.txt,sys0,0,0
btOnOff3.val=sys0
}
@@ -2216,7 +2165,7 @@ Timer tmSerial
bText3.pco=65535
bText3.pco2=65535
// get Text (optional Value)
spstr strCommand.txt,bText3.txt,",",6
spstr strCommand.txt,bText3.txt,",",18
}
if(type3.txt=="button")
{
@@ -2229,16 +2178,13 @@ Timer tmSerial
bText3.pco=1374
bText3.pco2=1374
// get Text (optional Value)
spstr strCommand.txt,bText3.txt,",",6
spstr strCommand.txt,bText3.txt,",",18
}
}
// id 2
if(tId.txt=="4")
{
// id4
// get Type
spstr strCommand.txt,type4.txt,",",2
spstr strCommand.txt,type4.txt,",",19
// get internal name
spstr strCommand.txt,entn4.txt,",",3
spstr strCommand.txt,entn4.txt,",",20
if(type4.txt=="delete")
{
vis bUp4,0
@@ -2251,12 +2197,16 @@ Timer tmSerial
}else
{
//change icon
spstr strCommand.txt,tTmp.txt,",",4
spstr strCommand.txt,tTmp.txt,",",21
covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tIcon4.txt,sys0,1
vis tIcon4,1
// change icon color
spstr strCommand.txt,tTmp.txt,",",22
covx tTmp.txt,sys0,0,0
tIcon4.pco=sys0
// set name
spstr strCommand.txt,tEntity4.txt,",",5
spstr strCommand.txt,tEntity4.txt,",",23
vis tEntity4,1
}
if(type4.txt=="shutter")
@@ -2275,7 +2225,7 @@ Timer tmSerial
vis bText4,0
vis btOnOff4,1
// get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",6
spstr strCommand.txt,tTmp.txt,",",24
covx tTmp.txt,sys0,0,0
btOnOff4.val=sys0
}
@@ -2287,7 +2237,7 @@ Timer tmSerial
vis bText4,0
vis btOnOff4,1
// get Button State (optional Value)
spstr strCommand.txt,tTmp.txt,",",6
spstr strCommand.txt,tTmp.txt,",",24
covx tTmp.txt,sys0,0,0
btOnOff4.val=sys0
}
@@ -2302,7 +2252,7 @@ Timer tmSerial
bText4.pco=65535
bText4.pco2=65535
// get Text (optional Value)
spstr strCommand.txt,bText4.txt,",",6
spstr strCommand.txt,bText4.txt,",",24
}
if(type4.txt=="button")
{
@@ -2315,8 +2265,7 @@ Timer tmSerial
bText4.pco=1374
bText4.pco2=1374
// get Text (optional Value)
spstr strCommand.txt,bText4.txt,",",6
}
spstr strCommand.txt,bText4.txt,",",24
}
}
if(tInstruction.txt=="pageType")
@@ -2328,15 +2277,9 @@ Timer tmSerial
spstr strCommand.txt,tTmp.txt,",",2
//save third arg if there's one
spstr strCommand.txt,pageIcons.tTmp2.txt,",",3
if(tId.txt=="cardEntities")
{
//yay, we are already on the correct page
}else
{
//we are going to exit this page with this command, so we have to clear the buffer, so we are not getting into a stupid loop ...
udelete payloadLength-1
bufferPos=0
}
if(tId.txt=="popupLight")
{
pageIcons.tTmp1.txt=tTmp.txt
@@ -2354,10 +2297,18 @@ Timer tmSerial
{
page pageStartup
}
if(tId.txt=="pageNotify")
if(tId.txt=="popupNotify")
{
page popupNotify
}
if(tId.txt=="cardGrid")
{
page cardGrid
}
if(tId.txt=="cardAlarm")
{
page cardAlarm
}
}
if(tInstruction.txt=="time")
{
@@ -2391,20 +2342,11 @@ Timer tmSerial
// next character
bufferPos++
}
if(bufferPos==usize)
{
// copy whole buffer to t1.txt, for debugging
//ucopy t2.txt,0,usize,0
// ucopy n2.val,0,usize,0
// clear whole buffer
//code_c
//bufferPos=0
}
}
Timer tmSleep
Attributes
ID : 37
ID : 36
Scope : local
Period (ms): 1000
Enabled : yes
@@ -2424,7 +2366,7 @@ Timer tmSleep
TouchCap tc0
Attributes
ID : 54
ID : 53
Scope: local
Value: 0

1323
HMI/n2t-out/cardGrid.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -27,25 +27,6 @@ Page cardMedia
vis tTmp,0
vis tId,0
//vis nPageDisp,0
//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
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
//display current page from global var
nPageDisp.val=nPage
Variable (string) strCommand
Attributes
@@ -573,7 +554,7 @@ Button bNext
Font ID : 2
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -627,7 +608,7 @@ Button bPrev
Font ID : 2
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -768,15 +749,9 @@ Timer tmSerial
spstr strCommand.txt,tTmp.txt,",",2
//save third arg if there's one
spstr strCommand.txt,pageIcons.tTmp2.txt,",",3
if(tId.txt=="cardMedia")
{
//yay, we are already on the correct page
}else
{
//we are going to exit this page with this command, so we have to clear the buffer, so we are not getting into a stupid loop ...
udelete payloadLength-1
bufferPos=0
}
if(tId.txt=="popupLight")
{
pageIcons.tTmp1.txt=tTmp.txt
@@ -794,10 +769,18 @@ Timer tmSerial
{
page pageStartup
}
if(tId.txt=="pageNotify")
if(tId.txt=="popupNotify")
{
page popupNotify
}
if(tId.txt=="cardGrid")
{
page cardGrid
}
if(tId.txt=="cardAlarm")
{
page cardAlarm
}
}
// end of user code
udelete payloadLength-1

View File

@@ -40,25 +40,6 @@ Page cardThermo
vis bt6,0
vis bt7,0
vis bt8,0
//page open event
// event,pageOpen,cardThermo,pageNumber
// craft command
// convert pageNumber and write to tTmp
covx nPage,tTmp.txt,0,0
tSend.txt="event,pageOpen,"+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
//display current page from global var
nPageDisp.val=nPage
Variable (string) strCommand
Attributes
@@ -185,7 +166,7 @@ XFloat xTempCurr
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 4
Font ID : 3
Back. Color : 6371
Font Color : 65535
Horizontal Alignment : center
@@ -564,7 +545,7 @@ Button bNext
Font ID : 2
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -614,7 +595,7 @@ Button bDown
Effect Priority : 0
Effect Time : 300
Fill : image
Font ID : 3
Font ID : 0
Background Picture ID (Unpressed) : 7
Back. Picture ID (Pressed) : 7
Horizontal Alignment : center
@@ -670,7 +651,7 @@ Button bUp
Effect Priority : 0
Effect Time : 300
Fill : image
Font ID : 3
Font ID : 0
Background Picture ID (Unpressed) : 9
Back. Picture ID (Pressed) : 9
Horizontal Alignment : center
@@ -728,7 +709,7 @@ Button bPrev
Font ID : 2
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -1518,15 +1499,9 @@ Timer tmSerial
spstr strCommand.txt,tTmp.txt,",",2
//save third arg if there's one
spstr strCommand.txt,pageIcons.tTmp2.txt,",",3
if(tId.txt=="cardThermo")
{
//yay, we are already on the correct page
}else
{
//we are going to exit this page with this command, so we have to clear the buffer, so we are not getting into a stupid loop ...
udelete payloadLength-1
bufferPos=0
}
if(tId.txt=="popupLight")
{
pageIcons.tTmp1.txt=tTmp.txt
@@ -1544,10 +1519,18 @@ Timer tmSerial
{
page pageStartup
}
if(tId.txt=="pageNotify")
if(tId.txt=="popupNotify")
{
page popupNotify
}
if(tId.txt=="cardGrid")
{
page cardGrid
}
if(tId.txt=="cardAlarm")
{
page cardAlarm
}
}
// end of user code
udelete payloadLength-1
@@ -1559,15 +1542,6 @@ Timer tmSerial
// next character
bufferPos++
}
if(bufferPos==usize)
{
// copy whole buffer to t1.txt, for debugging
//ucopy t2.txt,0,usize,0
// ucopy n2.val,0,usize,0
// clear whole buffer
//code_c
//bufferPos=0
}
}
Timer tmSleep

View File

@@ -10,49 +10,57 @@ pageSerialTest
13 Component(s)
48 Line(s) of event code
43 Unique line(s) of event code
pageTest
12 Component(s)
12 Line(s) of event code
12 Unique line(s) of event code
screensaver
25 Component(s)
146 Line(s) of event code
cardMedia
22 Component(s)
210 Line(s) of event code
116 Unique line(s) of event code
popupNotify
17 Component(s)
171 Line(s) of event code
113 Unique line(s) of event code
pageStartup
19 Component(s)
146 Line(s) of event code
111 Unique line(s) of event code
pageSwipeTest
18 Component(s)
62 Line(s) of event code
44 Unique line(s) of event code
popupNotify
15 Component(s)
143 Line(s) of event code
95 Unique line(s) of event code
cardMedia
22 Component(s)
219 Line(s) of event code
114 Unique line(s) of event code
pageStartup
19 Component(s)
140 Line(s) of event code
107 Unique line(s) of event code
pageTest
14 Component(s)
14 Line(s) of event code
14 Unique line(s) of event code
popupShutter
19 Component(s)
148 Line(s) of event code
84 Unique line(s) of event code
popupLight
27 Component(s)
290 Line(s) of event code
149 Unique line(s) of event code
194 Line(s) of event code
106 Unique line(s) of event code
screensaver
25 Component(s)
173 Line(s) of event code
124 Unique line(s) of event code
cardAlarm
28 Component(s)
147 Line(s) of event code
106 Unique line(s) of event code
cardThermo
42 Component(s)
450 Line(s) of event code
220 Unique line(s) of event code
438 Line(s) of event code
221 Unique line(s) of event code
cardEntities
55 Component(s)
824 Line(s) of event code
313 Unique line(s) of event code
54 Component(s)
808 Line(s) of event code
320 Unique line(s) of event code
cardGrid
39 Component(s)
406 Line(s) of event code
224 Unique line(s) of event code
popupLight
27 Component(s)
338 Line(s) of event code
170 Unique line(s) of event code
Total
12 Page(s)
273 Component(s)
2499 Line(s) of event code
670 Unique line(s) of event code
14 Page(s)
343 Component(s)
3172 Line(s) of event code
789 Unique line(s) of event code

View File

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

View File

@@ -42,7 +42,7 @@ Number nCrcRecv
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -72,7 +72,7 @@ Number nCrcCalc
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -102,7 +102,7 @@ Number nIt
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -162,7 +162,7 @@ Text tStatus
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -192,7 +192,7 @@ Text tCmd
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -222,7 +222,7 @@ Text tBuffer
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -252,7 +252,7 @@ Text tDesc
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -298,7 +298,7 @@ Button b0
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 0
Back. Color (Pressed) : 1024
@@ -335,7 +335,7 @@ Button b1
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 0
Back. Color (Pressed) : 1024

View File

@@ -402,7 +402,7 @@ Text tVersion
Horizontal Alignment : center
Vertical Alignment : center
Input Type : character
Text : 4
Text : 11
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
@@ -475,7 +475,7 @@ Button bSendStartup
prints tSend.txt,0
prints crcval,2
Hotspot mSpecial
Hotspot mSpinner
Attributes
ID : 16
Scope : local
@@ -483,10 +483,10 @@ Hotspot mSpecial
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 87
y coordinate : 33
Width : 288
Height : 187
x coordinate : 154
y coordinate : 49
Width : 140
Height : 140
Effect : load
Effect Priority : 0
Effect Time : 300
@@ -577,6 +577,7 @@ Timer tmSerial
}
if(tInstruction.txt=="pageType")
{
dim=100
//command format pageType,specialPageName
//write name of speical page to tId
spstr strCommand.txt,tId.txt,",",1
@@ -604,7 +605,7 @@ Timer tmSerial
{
page pageStartup
}
if(tId.txt=="pageNotify")
if(tId.txt=="popupNotify")
{
page popupNotify
}
@@ -612,6 +613,14 @@ Timer tmSerial
{
page cardMedia
}
if(tId.txt=="cardGrid")
{
page cardGrid
}
if(tId.txt=="cardAlarm")
{
page cardAlarm
}
}
// end of user code
udelete payloadLength-1
@@ -623,15 +632,6 @@ Timer tmSerial
// next character
bufferPos++
}
if(bufferPos==usize)
{
// copy whole buffer to t1.txt, for debugging
//ucopy t2.txt,0,usize,0
// ucopy n2.val,0,usize,0
// clear whole buffer
//code_c
//bufferPos=0
}
}
Timer tmSpinner
@@ -643,7 +643,7 @@ Timer tmSpinner
Events
Timer Event
xpic 154,49,spinner_w.val,140,frame_ptr.val,0,11 // draw the current frame
xpic mSpinner.x,mSpinner.y,spinner_w.val,140,frame_ptr.val,0,11 // draw the current frame
frame_ptr.val+=spinner_w.val%frapic_w.val // advance the pointer to the next frame in the pic resource and roll over at the end
doevents // finish drawing before next timer event triggers
if(frame_ptr.val==1820)

View File

@@ -36,7 +36,7 @@ Number nXS
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -66,7 +66,7 @@ Number nYE
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -96,7 +96,7 @@ Number nYS
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -126,7 +126,7 @@ Number nXE
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -156,7 +156,7 @@ Number nYR
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -186,7 +186,7 @@ Number nXR
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -216,7 +216,7 @@ Text tDesc1
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -246,7 +246,7 @@ Text t2
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -276,7 +276,7 @@ Text tDirection
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -306,7 +306,7 @@ Text t0
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -336,7 +336,7 @@ Text tStatusNew
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -366,7 +366,7 @@ Text t3
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -396,7 +396,7 @@ Text tDirNew
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 5
Font ID : 4
Back. Color : 65535
Font Color : 0
Horizontal Alignment : center
@@ -442,7 +442,7 @@ Button b8
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024

View File

@@ -56,7 +56,7 @@ Button b0
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
@@ -92,7 +92,7 @@ Button b1
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
@@ -128,7 +128,7 @@ Button b2
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
@@ -164,7 +164,7 @@ Button b3
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 0
Back. Color (Pressed) : 1024
@@ -200,7 +200,7 @@ Button b6
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
@@ -236,7 +236,7 @@ Button b4
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
@@ -272,7 +272,7 @@ Button b5
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
@@ -308,7 +308,7 @@ Button b7
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
@@ -344,7 +344,7 @@ Button b8
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
@@ -381,7 +381,7 @@ Button b9
Effect Time : 300
Fill : solid color
Style : 3D auto
Font ID : 5
Font ID : 4
Back. Color : 50712
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
@@ -400,3 +400,75 @@ Button b9
Touch Press Event
page popupNotify
Button b10
Attributes
ID : 12
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 115
y coordinate : 128
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 : alarm
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
page cardAlarm
Button b11
Attributes
ID : 13
Scope : local
Dragging : 0
Disable release event after dragging: 0
Send Component ID : disabled
Opacity : 127
x coordinate : 117
y coordinate : 184
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 : grid
Max. Text Size : 10
Word wrap : disabled
Horizontal Spacing : 0
Vertical Spacing : 0
Events
Touch Press Event
page cardGrid

View File

@@ -28,7 +28,7 @@ Page popupLight
vis tSend,0
vis tTmp,0
vis tInstruction,0
vis tItem,0
vis tId,0
//page open event
// event,pageOpenDetail,typeOfPage,tEntityName
// craft command
@@ -63,7 +63,7 @@ Variable (string) strCommand
ID : 17
Scope : local
Text :
Max. Text Size: 50
Max. Text Size: 100
Variable (string) entn
Attributes
@@ -360,7 +360,7 @@ Text tInstruction
Horizontal Spacing : 0
Vertical Spacing : 0
Text tItem
Text tId
Attributes
ID : 19
Scope : local
@@ -639,7 +639,7 @@ Button b0
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 6371
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -653,7 +653,23 @@ Button b0
Events
Touch Press Event
page cardEntities
//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
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
Button bColor
Attributes
@@ -675,7 +691,7 @@ Button bColor
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 6371
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -849,12 +865,21 @@ Timer tmSerial
spstr strCommand.txt,tInstruction.txt,",",0
if(tInstruction.txt=="entityUpdateDetail")
{
// get Button State
// change icon
spstr strCommand.txt,tTmp.txt,",",1
covx tTmp.txt,sys0,0,0
substr pageIcons.tIcons.txt,tIcon1.txt,sys0,1
vis tIcon1,1
// change icon color
spstr strCommand.txt,tTmp.txt,",",2
covx tTmp.txt,sys0,0,0
tIcon1.pco=sys0
// get Button State
spstr strCommand.txt,tTmp.txt,",",3
covx tTmp.txt,sys0,0,0
btOnOff1.val=sys0
// get Brightness value
spstr strCommand.txt,tTmp.txt,",",2
spstr strCommand.txt,tTmp.txt,",",4
if(tTmp.txt=="disable")
{
vis t1,0
@@ -873,7 +898,7 @@ Timer tmSerial
if(mode.val==1)
{
// get ColorTemp value
spstr strCommand.txt,tTmp.txt,",",3
spstr strCommand.txt,tTmp.txt,",",5
if(tTmp.txt=="unknown")
{
click bColor,1
@@ -895,7 +920,7 @@ Timer tmSerial
}
}
// get ColorWheel value
spstr strCommand.txt,tTmp.txt,",",4
spstr strCommand.txt,tTmp.txt,",",6
if(tTmp.txt!="disable")
{
vis bColor,1
@@ -917,7 +942,6 @@ Timer tmSerial
// get value
spstr strCommand.txt,tTmp.txt,",",1
covx tTmp.txt,dimValue,0,0
dim=dimValue
}
if(tInstruction.txt=="timeout")
{
@@ -929,6 +953,43 @@ Timer tmSerial
udelete payloadLength-1
bufferPos=0
}
if(tInstruction.txt=="pageType")
{
//command format pageType,specialPageName
//write name of speical page to tId
spstr strCommand.txt,tId.txt,",",1
//save second arg if there's one
spstr strCommand.txt,tTmp.txt,",",2
//save third arg if there's one
spstr strCommand.txt,pageIcons.tTmp2.txt,",",3
//we are going to exit this page with this command, so we have to clear the buffer, so we are not getting into a stupid loop ...
udelete payloadLength-1
bufferPos=0
if(tId.txt=="cardEntities")
{
page cardEntities
}
if(tId.txt=="cardMedia")
{
page cardMedia
}
if(tId.txt=="pageStartup")
{
page pageStartup
}
if(tId.txt=="popupNotify")
{
page popupNotify
}
if(tId.txt=="cardGrid")
{
page cardGrid
}
if(tId.txt=="cardAlarm")
{
page cardAlarm
}
}
}
}
}

View File

@@ -25,28 +25,26 @@ Page popupNotify
vis tTmp,0
vis tInstruction,0
vis tId,0
//page open event
// event,pageOpenDetail,typeOfPage,tEntityName
// craft command
tSend.txt="event,pageOpenDetail,notify"
//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
Variable (string) strCommand
Attributes
ID : 8
Scope : local
Text :
Max. Text Size: 500
Max. Text Size: 1000
Variable (string) entn
Attributes
ID : 15
Scope : local
Text :
Max. Text Size: 30
Variable (int32) vaOldSleepT
Attributes
ID : 16
Scope: local
Value: 0
Text tSend
Attributes
@@ -223,7 +221,7 @@ Text tText
Vertical Alignment : top
Input Type : character
Text :
Max. Text Size : 300
Max. Text Size : 500
Word wrap : enabled
Horizontal Spacing : 0
Vertical Spacing : 0
@@ -265,7 +263,7 @@ Button b0
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 6371
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -279,7 +277,24 @@ Button b0
Events
Touch Press Event
page cardEntities
sleepTimeout=vaOldSleepT.val
//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
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
Button b2
Attributes
@@ -315,8 +330,9 @@ Button b2
Events
Touch Press Event
sleepTimeout=vaOldSleepT.val
//craft command
tSend.txt="event,buttonPress,D,D,D,1,notifyAction,yes"
tSend.txt="event,buttonPress,D,D,"+entn.txt+",1,notifyAction,yes"
//send calc crc
btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC
@@ -363,8 +379,9 @@ Button b1
Events
Touch Press Event
sleepTimeout=vaOldSleepT.val
//craft command
tSend.txt="event,buttonPress,D,D,D,1,notifyAction,no"
tSend.txt="event,buttonPress,D,D,"+entn.txt+",1,notifyAction,no"
//send calc crc
btlen tSend.txt,sys0
crcrest 1,0xffff // reset CRC
@@ -451,14 +468,46 @@ Timer tmSerial
spstr strCommand.txt,tInstruction.txt,",",0
if(tInstruction.txt=="entityUpdateDetail")
{
// get entn
spstr strCommand.txt,entn.txt,"|",1
// get Heading
spstr strCommand.txt,tHeading.txt,",",1
spstr strCommand.txt,tHeading.txt,"|",2
// heading color
spstr strCommand.txt,tTmp.txt,"|",3
covx tTmp.txt,sys0,0,0
tHeading.pco=sys0
// get b1
spstr strCommand.txt,b1.txt,",",2
spstr strCommand.txt,b1.txt,"|",4
if(b1.txt!="")
{
vis b1,1
}
// b1 color
spstr strCommand.txt,tTmp.txt,"|",5
covx tTmp.txt,sys0,0,0
b1.pco=sys0
// get b2
spstr strCommand.txt,b2.txt,",",3
spstr strCommand.txt,b2.txt,"|",6
if(b2.txt!="")
{
vis b2,1
}
// b2 color
spstr strCommand.txt,tTmp.txt,"|",7
covx tTmp.txt,sys0,0,0
b2.pco=sys0
// get tText
spstr strCommand.txt,tText.txt,",",4
spstr strCommand.txt,tText.txt,"|",8
// tText color
spstr strCommand.txt,tTmp.txt,"|",9
covx tTmp.txt,sys0,0,0
tText.pco=sys0
//preserve old sleepTimeout
vaOldSleepT.val=sleepTimeout
// sleep timeout
spstr strCommand.txt,tTmp.txt,"|",9
covx tTmp.txt,sys0,0,0
sleepTimeout=sys0
}
if(tInstruction.txt=="time")
{
@@ -475,7 +524,6 @@ Timer tmSerial
// get value
spstr strCommand.txt,tTmp.txt,",",1
covx tTmp.txt,dimValue,0,0
dim=dimValue
}
if(tInstruction.txt=="timeout")
{
@@ -485,20 +533,17 @@ Timer tmSerial
}
if(tInstruction.txt=="pageType")
{
sleepTimeout=vaOldSleepT.val
//command format pageType,specialPageName
//write name of speical page to tId
spstr strCommand.txt,tId.txt,",",1
//save second arg if there's one
spstr strCommand.txt,tTmp.txt,",",2
if(tId.txt=="pageNotify")
{
//yay, we are already on the correct page
}else
{
//save third arg if there's one
spstr strCommand.txt,pageIcons.tTmp2.txt,",",3
//we are going to exit this page with this command, so we have to clear the buffer, so we are not getting into a stupid loop ...
udelete payloadLength-1
bufferPos=0
}
if(tId.txt=="popupLight")
{
pageIcons.tTmp1.txt=tTmp.txt
@@ -516,9 +561,13 @@ Timer tmSerial
{
page pageStartup
}
if(tId.txt=="pageThermo")
if(tId.txt=="cardGrid")
{
page cardThermo
page cardGrid
}
if(tId.txt=="cardAlarm")
{
page cardAlarm
}
}
// end of user code

View File

@@ -28,7 +28,7 @@ Page popupShutter
vis tSend,0
vis tTmp,0
vis tInstruction,0
vis tItem,0
vis tId,0
//page open event
// event,pageOpenDetail,typeOfPage,tEntityName
// craft command
@@ -209,7 +209,7 @@ Text tInstruction
Horizontal Spacing : 0
Vertical Spacing : 0
Text tItem
Text tId
Attributes
ID : 12
Scope : local
@@ -353,7 +353,7 @@ Button b0
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 6371
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -367,7 +367,23 @@ Button b0
Events
Touch Press Event
page cardEntities
//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
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
Button bDown1
Attributes
@@ -389,7 +405,7 @@ Button bDown1
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -443,7 +459,7 @@ Button bStop1
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -497,7 +513,7 @@ Button bUp1
Font ID : 1
Back. Color : 6371
Back. Picture ID (Pressed) : 65535
Back. Color (Pressed) : 1024
Back. Color (Pressed) : 14823
Font Color (Unpressed) : 65535
Font Color (Pressed) : 65535
Horizontal Alignment : center
@@ -615,7 +631,6 @@ Timer tmSerial
// get value
spstr strCommand.txt,tTmp.txt,",",1
covx tTmp.txt,dimValue,0,0
dim=dimValue
}
if(tInstruction.txt=="time")
{
@@ -633,6 +648,48 @@ Timer tmSerial
spstr strCommand.txt,tTmp.txt,",",1
covx tTmp.txt,sleepTimeout,0,0
}
if(tInstruction.txt=="pageType")
{
//command format pageType,specialPageName
//write name of speical page to tId
spstr strCommand.txt,tId.txt,",",1
//save second arg if there's one
spstr strCommand.txt,tTmp.txt,",",2
//save third arg if there's one
spstr strCommand.txt,pageIcons.tTmp2.txt,",",3
//we are going to exit this page with this command, so we have to clear the buffer, so we are not getting into a stupid loop ...
udelete payloadLength-1
bufferPos=0
if(tId.txt=="popupLight")
{
pageIcons.tTmp1.txt=tTmp.txt
page popupLight
}
if(tId.txt=="cardEntities")
{
page cardEntities
}
if(tId.txt=="cardMedia")
{
page cardMedia
}
if(tId.txt=="pageStartup")
{
page pageStartup
}
if(tId.txt=="popupNotify")
{
page popupNotify
}
if(tId.txt=="cardGrid")
{
page cardGrid
}
if(tId.txt=="cardAlarm")
{
page cardAlarm
}
}
// end of user code
udelete payloadLength-1
bufferPos=0

View File

@@ -193,7 +193,7 @@ Text tTime
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 6
Font ID : 5
Back. Color : 0
Font Color : 65535
Horizontal Alignment : center
@@ -283,7 +283,7 @@ Text tMainIcon
Fill : solid color
Style : flat
Associated Keyboard : none
Font ID : 4
Font ID : 3
Back. Color : 0
Font Color : 65535
Horizontal Alignment : center
@@ -666,8 +666,8 @@ Timer tmSerial
spstr strCommand.txt,tInstruction.txt,",",0
if(tInstruction.txt=="wake")
{
dim=100
page originPage.val
//dim=100
click tc0,1
}
if(tInstruction.txt=="dimmode")
{
@@ -725,8 +725,17 @@ Timer tmSerial
//tForecast2Val
spstr strCommand.txt,tForecast2Val.txt,"?",10
}
if(tInstruction.txt=="page")
{
//pagenumber
spstr strCommand.txt,tTmp.txt,",",1
covx tTmp.txt,sys0,0,0
nPage=sys0
//don't send current page number, wake will do
}
if(tInstruction.txt=="pageType")
{
dim=100
//command format pageType,specialPageName
//write name of speical page to tId
spstr strCommand.txt,tId.txt,",",1
@@ -758,10 +767,22 @@ Timer tmSerial
{
page pageStartup
}
if(tId.txt=="pageNotify")
if(tId.txt=="popupNotify")
{
page popupNotify
}
if(tId.txt=="cardGrid")
{
page cardGrid
}
if(tId.txt=="cardEntities")
{
page cardEntities
}
if(tId.txt=="cardAlarm")
{
page cardAlarm
}
}
// end of user code
udelete payloadLength-1
@@ -783,6 +804,23 @@ TouchCap tc0
Events
Touch Press Event
dim=100
page originPage.val
//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
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
//dim=100
//page originPage.val

Binary file not shown.

Binary file not shown.

View File

@@ -9,8 +9,9 @@ NsPanel Lovelace UI is a Firmware for the nextion screen inside of NSPanel in th
## Features
- Entities Page with support for cover, switch, input_boolean, sensor, button, input_button and light
- Detail Pages for Lights (Brightness and Temperature of the Light) and for Covers (Position)
- Entities Page with support for cover, switch, input_boolean, sensor, button, scenes, input_button and light
- Grid Page with support for cover, switch, input_boolean, button, scenes, and light
- Detail Pages for Lights (Brightness, Temperature and Color of the Light) and for Covers (Position)
- Thermostat Page
- Media Player Card
- Screensaver Page with Time, Date and Weather Information
@@ -33,7 +34,7 @@ For more detailed Instructions see the following Sections:
- [How It Works](#how-it-works)
- [Requirements](#requirements)
- [Installation - Home Automation Part](#installation---home-automation-part)
- [Installation - Home Automation Part (Homeassistant)](#installation---home-automation-part-home-assistant)
- [Installing AppDaemon](#installing-appdaemon)
- [Installing Studio Code Server (optional, recommended)](#installing-studio-code-server-optional-recommended)
- [Installing HACS (optional, recommended)](#installing-hacs-optional-recommended)
@@ -42,6 +43,8 @@ For more detailed Instructions see the following Sections:
- [Manually](#manually)
- [Installing Tasmota to your NSPanel](#installing---tasmota-to-your-nspanel)
- [Installation - Home Automation Part (IoBroker)](#installation---home-automation-part-iobroker)
- [Installation - NSPanel Part](#installation-nspanel-part)
- [Flash Tasmota to your NSPanel](#flash-tasmota-to-your-nspanel)
- [Configure Tasmota Template for NSPanel](#configure-tasmota-template-for-nspanel)
@@ -71,9 +74,7 @@ For more details on how the display firmware works see the [README File in the H
- Running [Home Assistant Instance](https://www.home-assistant.io/installation/)
- Installed [MQTT Broker](https://www.home-assistant.io/docs/mqtt/broker) alongside Homeassistant
## Installation - Home Automation Part
### Installing Home Assistant
## Installation - Home Automation Part (Home Assistant)
### Installing AppDaemon
@@ -84,6 +85,13 @@ The easiest way to install it is through Home Assistant's Supervisor Add-on Stor
![hass-add-on-store](doc-pics/hass-add-on-store.png)
#### Add babel package to AppDaemon Container (Optional)
For localisation (date in your local language) you need to add the python package babel to your AppDaemon Installation.
![appdaemon-babel](doc-pics/appdaemon-babel.png)
### Installing Studio Code Server (optional, recommended)
You will need a way to edit the `apps.yaml` config file in the Appdaemon folder.
@@ -136,6 +144,11 @@ Installing the Backend Application manually can be summarized by putting the con
directory of your AppDaemon installation.
## Installation - Home Automation Part (IoBroker)
If you are looking for an ioBroker Integration instead of HomeAssistant take a look into the [Readme](ioBroker/README.md) of the iobroker folder.
Thanks to [britzelpuf](https://github.com/britzelpuf) for this integration.
## Installation - NSPanel Part
This section describes how to free your nspanel from stock firmware and get it ready for Lovelace UI 🎉
@@ -179,8 +192,6 @@ See Tasmota [MQTT Documentation](https://tasmota.github.io/docs/MQTT/) for more
Upload the nspanel.tft from the lastest release to a Webserver (for example www folder of Home Assistant) and execute the following command in Tasmota Console. (Development Version: [tft file from HMI folder](HMI/nspanel.tft))
**Webserver needs to support HTTP Range Header Requests, python2/3 http server doesn't work**
**Webserver must be HTTP, HTTPS is not supported, due to limitations of berry lang on tasmota**
`FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft`
@@ -239,16 +250,19 @@ nspanel-1:
config:
panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT"
panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend"
timeoutScreensaver: 15 #in seconds, values between 5 and 60 are allowed
updateMode: auto-notify # possible values are auto, auto-notify and manual
timeoutScreensaver: 15 #in seconds
#brightnessScreensaver: 10
brightnessScreensaver:
- time: "7:00:00"
value: 10
- time: "23:00:00"
value: 0
locale: "de_DE"
locale: "de_DE" # only used if babel python package is installed
dateFormatBabel: "full" # only used if babel python package is installed
# formatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields
timeFormat: "%H:%M"
dateFormat: "%A, %d. %B %Y"
dateFormat: "%A, %d. %B %Y" # ignored if babel python package is installed
weatherEntity: weather.example
pages:
- type: cardEntities
@@ -264,14 +278,23 @@ nspanel-1:
- button.example_button
- input_button.example_input_button
- light.light_example
- delete # To make sure we don't keep buttons from previous page (read this as 'empty')
- delete # (read this as 'empty')
- type: cardEntities
heading: Example Page 3
items:
- scene.some_scene
- scene.moodlights
- scene.example_scene
- delete
- delete
- delete
- type: cardGrid
heading: Example Page 4
items:
- light.light_example
- button.example_button
- cover.example_cover
- scene.example_scene
- switch.example_switch
- delete
- type: cardThermo
heading: Exmaple Thermostat
item: climate.example_climate
@@ -322,8 +345,7 @@ Since release 1.1 you can update the berry driver directly from the Tasmota Cons
### Flashing of the Display Firmware with FlashNextion doesn't work
1. Make sure to use the [tasmota32-nspanel.bin](https://github.com/tasmota/install/raw/main/firmware/unofficial/tasmota32-nspanel.bin) Tasmota build.
2. Make sure to use an WebServer which supports http range requests like HomeAssistant, apache2 or nginx for exmaple.
3. Make sure to use HTTP and **not HTTPS**
2. Make sure to use HTTP and **not HTTPS**
### My flashing doesn't start at all

View File

@@ -5,16 +5,19 @@ nspanel:
config:
panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT"
panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend"
timeoutScreensaver: 15 #in seconds, values between 5 and 60 are allowed
updateMode: auto-notify # possible values are auto, auto-notify and manual
timeoutScreensaver: 15 #in seconds
#brightnessScreensaver: 10
brightnessScreensaver:
- time: "7:00:00"
value: 10
- time: "23:00:00"
value: 0
locale: "de_DE"
locale: "de_DE" # only used if babel python package is installed
dateFormatBabel: "full" # only used if babel python package is installed
# formatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields
timeFormat: "%H:%M"
dateFormat: "%A, %d. %B %Y"
dateFormat: "%A, %d. %B %Y" # ignored if babel python package is installed
weatherEntity: weather.example
pages:
- type: cardEntities
@@ -30,14 +33,23 @@ nspanel:
- button.example_button
- input_button.example_input_button
- light.light_example
- delete # To make sure we don't keep buttons from previous page (read this as 'empty')
- delete # (read this as 'empty')
- type: cardEntities
heading: Example Page 3
items:
- scene.some_scene
- scene.moodlights
- scene.example_scene
- delete
- delete
- delete
- type: cardGrid
heading: Example Page 4
items:
- light.light_example
- button.example_button
- cover.example_cover
- scene.example_scene
- switch.example_switch
- delete
- type: cardThermo
heading: Exmaple Thermostat
item: climate.example_climate

View File

@@ -0,0 +1,40 @@
import colorsys
import math
def scale(val, src, dst):
"""
Scale the given value from the scale of src to the scale of dst.
"""
return ((val - src[0]) / (src[1]-src[0])) * (dst[1]-dst[0]) + dst[0]
def hsv2rgb(h, s, v):
hsv = colorsys.hsv_to_rgb(h,s,v)
return tuple(round(i * 255) for i in hsv)
def pos_to_color(x, y):
r = 160/2
x = round((x - r) / r * 100) / 100
y = round((r - y) / r * 100) / 100
r = math.sqrt(x*x + y*y)
sat = 0
if (r > 1):
sat = 0
else:
sat = r
hsv = (math.degrees(math.atan2(y, x))%360/360, sat, 1)
rgb = hsv2rgb(hsv[0],hsv[1],hsv[2])
return rgb
def rgb_brightness(rgb_color, brightness):
red = rgb_color[0]/255*brightness
green = rgb_color[1]/255*brightness
blue = rgb_color[2]/255*brightness
return [red, green, blue]
def rgb_dec565(rgb_color):
red = rgb_color[0]
green = rgb_color[1]
blue = rgb_color[2]
# 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.
return ((int(red / 255 * 31) << 11) | (int(green / 255 * 63) << 5) | (int(blue / 255 * 31)))

View File

@@ -0,0 +1,44 @@
icons = {
'window-open': 0,
'lightbulb': 1,
'thermometer': 2,
'gesture-tap-button': 3,
'flash': 4,
'music': 5,
'check-circle-outline': 6,
'close-circle-outline': 7,
'pause': 8,
'play': 9,
'palette': 10,
'alert-circle-outline': 11,
'weather-cloudy': 12,
'weather-fog': 13,
'weather-hail': 14,
'weather-lightning': 15,
'weather-lightning-rainy': 16,
'weather-night': 17,
'weather-partly-cloudy': 18,
'weather-pouring': 19,
'weather-rainy': 20,
'weather-snowy': 21,
'weather-snowy-rainy': 22,
'weather-sunny': 23,
'weather-windy': 24,
'weather-windy-variant': 25,
'water-percent': 26,
'power': 27,
'fire': 28,
'calendar-sync': 29,
'fan': 30,
'snowflake': 31,
'solar-power': 32,
'battery-charging-medium': 33,
'battery-medium': 34,
}
def get_icon_id(ma_name):
if ma_name in icons:
return icons[ma_name]
else:
return icons["alert-circle-outline"]

View File

@@ -1,9 +1,14 @@
import json
import datetime
import hassapi as hass
from helper import scale, pos_to_color, rgb_dec565, rgb_brightness
from icon_mapper import get_icon_id
import math
import colorsys
# check Babel
import importlib
babel_spec = importlib.util.find_spec("babel")
if babel_spec is not None:
import babel.dates
class NsPanelLovelaceUIManager(hass.Hass):
def initialize(self):
@@ -11,6 +16,68 @@ class NsPanelLovelaceUIManager(hass.Hass):
data = self.args["config"]
NsPanelLovelaceUI(self, data)
class Updater:
def __init__(self, nsplui, mode):
self.desired_display_firmware_version = 11
self.desired_display_firmware_url = "http://nspanel.pky.eu/lovelace-ui/github/nspanel-b0027d4.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 NsPanelLovelaceUI:
def __init__(self, api, config):
self.api = api
@@ -26,10 +93,19 @@ class NsPanelLovelaceUI:
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')
if "updateMode" in self.config:
update_mode = self.config["updateMode"]
else:
update_mode = "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)
@@ -37,6 +113,7 @@ class NsPanelLovelaceUI:
# 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
@@ -60,18 +137,24 @@ class NsPanelLovelaceUI:
# send screensaver brightness in case config has changed
self.update_screensaver_brightness(kwargs={"value": self.current_screensaver_brightness})
# send date update in case config has been changed
self.update_date("")
# register callbacks
self.register_callbacks()
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: %s", data, level="DEBUG")
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"
@@ -80,12 +163,14 @@ class NsPanelLovelaceUI:
msg = msg.split(",")
# run action based on received command
# TODO: replace with match case after appdeamon container swiched to python 3.10 - https://pakstech.com/blog/python-switch-case/ - https://www.python.org/dev/peps/pep-0636/
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("")
@@ -97,19 +182,20 @@ class NsPanelLovelaceUI:
# 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
page_type = self.config["pages"][self.current_page_nr]["type"]
self.generate_page(self.current_page_nr, page_type)
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")
# get type of current page
page_type = self.config["pages"][self.current_page_nr]["type"]
# generate commands for current page
self.generate_page(self.current_page_nr, page_type)
self.generate_page(self.current_page_nr)
if msg[1] == "buttonPress":
entity_id = msg[4]
@@ -132,18 +218,24 @@ class NsPanelLovelaceUI:
if msg[1] == "screensaverOpen":
self.update_screensaver_weather("")
def send_mqtt_msg(self,msg):
self.api.log("Send Message from Tasmota: %s", msg) #, level="DEBUG"
self.mqtt.mqtt_publish(self.config["panelSendTopic"], msg)
def update_time(self, kwargs):
time = datetime.datetime.now().strftime(self.config["timeFormat"])
self.send_mqtt_msg("time,{0}".format(time))
self.send_mqtt_msg(f"time,{time}")
def update_date(self, kwargs):
# TODO: implement localization of date
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("date,?{0}".format(date))
self.send_mqtt_msg(f"date,?{date}")
def update_screensaver_brightness(self, kwargs):
self.current_screensaver_brightness = kwargs['value']
@@ -155,95 +247,106 @@ class NsPanelLovelaceUI:
we = self.api.get_entity(self.config["weatherEntity"])
unit = "°C"
# this maps possible states from ha to material design icon names
weathericons = {
'clear-night': 17,
'cloudy': 12,
'exceptional': 11,
'fog': 13,
'hail': 14,
'lightning': 15,
'lightning-rainy': 16,
'partlycloudy': 18,
'pouring': 19,
'rainy': 20,
'snowy': 21,
'snowy-rainy': 22,
'sunny': 23,
'windy': 24,
'windy-variant': 25
'clear-night': 'weather-night',
'cloudy': 'weather-cloudy',
'exceptional': 'alert-circle-outline',
'fog': 'weather-fog',
'hail': 'weather-hail',
'lightning': 'weather-lightning',
'lightning-rainy': 'weather-lightning-rainy',
'partlycloudy': 'weather-partly-cloudy',
'pouring': 'weather-pouring',
'rainy': 'weather-rainy',
'snowy': 'weather-snowy',
'snowy-rainy': 'weather-snowy-rainy',
'sunny': 'weather-sunny',
'windy': 'weather-windy',
'windy-variant': 'weather-windy-variant'
}
o1 = we.attributes.forecast[0]['datetime']
o1 = datetime.datetime.fromisoformat(o1)
o1 = o1.strftime("%a")
i1 = weathericons[we.attributes.forecast[0]['condition']]
o1 = babel.dates.format_date(o1, "E", locale=self.config["locale"])
i1 = get_icon_id(weathericons[we.attributes.forecast[0]['condition']])
u1 = we.attributes.forecast[0]['temperature']
o2 = we.attributes.forecast[1]['datetime']
o2 = datetime.datetime.fromisoformat(o2)
o2 = o2.strftime("%a")
i2 = weathericons[we.attributes.forecast[1]['condition']]
o2 = babel.dates.format_date(o2, "E", locale=self.config["locale"])
i2 = get_icon_id(weathericons[we.attributes.forecast[1]['condition']])
u2 = we.attributes.forecast[1]['temperature']
self.send_mqtt_msg(f"weatherUpdate,?{weathericons[we.state]}?{we.attributes.temperature}{unit}?{26}?{we.attributes.humidity} %?{o1}?{i1}?{u1}?{o2}?{i2}?{u2}")
self.send_mqtt_msg(f"weatherUpdate,?{get_icon_id(weathericons[we.state])}?{we.attributes.temperature}{unit}?{26}?{we.attributes.humidity} %?{o1}?{i1}?{u1}?{o2}?{i2}?{u2}")
def scale(self, val, src, dst):
"""
Scale the given value from the scale of src to the scale of dst.
"""
return ((val - src[0]) / (src[1]-src[0])) * (dst[1]-dst[0]) + dst[0]
def handle_button_press(self, entity_id, btype, optVal=None):
if(btype == "OnOff"):
if(optVal == "1"):
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"):
if btype == "up":
self.api.get_entity(entity_id).call_service("open_cover")
if(btype == "stop"):
if btype == "stop":
self.api.get_entity(entity_id).call_service("stop_cover")
if(btype == "down"):
if btype == "down":
self.api.get_entity(entity_id).call_service("close_cover")
if(btype == "button"):
if(entity_id.startswith('scene')):
if btype == "button":
if entity_id.startswith('scene'):
self.api.get_entity(entity_id).call_service("turn_on")
if entity_id.startswith('light') or entity_id.startswith('switch'):
self.api.get_entity(entity_id).call_service("toggle")
else:
self.api.get_entity(entity_id).call_service("press")
if(btype == "media-next"):
if btype == "media-next":
self.api.get_entity(entity_id).call_service("media_next_track")
if(btype == "media-back"):
if btype == "media-back":
self.api.get_entity(entity_id).call_service("media_previous_track")
if(btype == "media-pause"):
if btype == "media-pause":
self.api.get_entity(entity_id).call_service("media_play_pause")
if(btype == "hvac_action"):
if btype == "hvac_action":
self.api.get_entity(entity_id).call_service("set_hvac_mode", hvac_mode=optVal)
if(btype == "brightnessSlider"):
if btype == "brightnessSlider":
# scale 0-100 to ha brightness range
brightness = int(self.scale(int(optVal),(0,100),(0,255)))
brightness = int(scale(int(optVal),(0,100),(0,255)))
self.api.get_entity(entity_id).call_service("turn_on", brightness=brightness)
if(btype == "colorTempSlider"):
if btype == "colorTempSlider":
entity = self.api.get_entity(entity_id)
#scale 0-100 from slider to color range of lamp
color_val = self.scale(int(optVal), (0, 100), (entity.attributes.min_mireds, entity.attributes.max_mireds))
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"):
if btype == "colorWheel":
self.api.log(optVal)
optVal = optVal.split('|')
color = self.pos_to_color(int(optVal[0]), int(optVal[1]))
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"):
if btype == "positionSlider":
pos = int(optVal)
self.api.get_entity(entity_id).call_service("set_cover_position", position=pos)
if(btype == "volumeSlider"):
if btype == "volumeSlider":
pos = int(optVal)
# HA wants this value between 0 and 1 as float
pos = pos/100
@@ -282,14 +385,14 @@ class NsPanelLovelaceUI:
page_type = current_page_config["type"]
self.api.log("Got state_callback from {0}".format(entity), level="DEBUG")
self.api.log(f"Got state_callback from {entity}", level="DEBUG")
if page_type == "cardEntities":
if page_type in ["cardEntities", "cardGrid"]:
items = current_page_config["items"]
if entity in items:
self.api.log("State change on current page for {0}".format(entity), level="DEBUG")
# send update of the item on page
command = self.generate_entities_item(entity, items.index(entity)+1)
self.api.log(f"State change on current page for {entity}", level="DEBUG")
# send update of the page
command = self.generate_entities_page(items)
self.send_mqtt_msg(command)
if(entity.startswith("cover")):
self.generate_detail_page("popupShutter", entity)
@@ -300,7 +403,7 @@ class NsPanelLovelaceUI:
if page_type == "cardThermo" or page_type == "cardMedia":
if entity == current_page_config["item"]:
self.api.log("State change on current page for {0}".format(entity), level="DEBUG")
self.api.log(f"State change on current page for {entity}", level="DEBUG")
# send update of the whole page
if page_type == "cardThermo":
self.send_mqtt_msg(self.generate_thermo_page(entity))
@@ -310,64 +413,114 @@ class NsPanelLovelaceUI:
return
return
def generate_page(self, page_number):
# get type of current 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")
if page_type == "cardEntities":
# Send page type
self.send_mqtt_msg(f"pageType,{page_type}")
# Set Heading of Page
self.send_mqtt_msg(f"entityUpdHeading,{self.config['pages'][self.current_page_nr]['heading']}")
command = self.generate_entities_page(self.config["pages"][self.current_page_nr]["items"])
self.send_mqtt_msg(command)
# TODO: Call Method for refresh of the item/page of the current entity
if page_type == "cardGrid":
# Send page type
self.send_mqtt_msg(f"pageType,{page_type}")
# Set Heading of Page
self.send_mqtt_msg(f"entityUpdHeading,{self.config['pages'][self.current_page_nr]['heading']}")
def generate_entities_item(self, item, item_nr):
command = self.generate_entities_page(self.config["pages"][self.current_page_nr]["items"])
self.send_mqtt_msg(command)
# type of item is the string before the "." in the item name
if page_type == "cardThermo":
# Send page type
self.send_mqtt_msg(f"pageType,{page_type}")
command = self.generate_thermo_page(self.config["pages"][self.current_page_nr]["item"])
self.send_mqtt_msg(command)
if page_type == "cardMedia":
# Send page type
self.send_mqtt_msg("pageType,{0}".format(page_type))
command = self.generate_media_page(self.config["pages"][self.current_page_nr]["item"])
self.send_mqtt_msg(command)
def generate_entities_item(self, item):
# 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 "entityUpd,{0},{1}".format(item_nr, item_type)
return f",{item_type},,,,,"
if not self.api.entity_exists(item):
return f"entityUpd,{item_nr},text,{item},11,Not found check, apps.yaml"
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":
return "entityUpd,{0},{1},{2},{3},{4}".format(item_nr, "shutter", item, 0, name)
return f",shutter,{item},{get_icon_id('window-open')},17299,{name},"
if item_type == "light":
switch_val = 1 if entity.state == "on" else 0
return "entityUpd,{0},{1},{2},{3},{4},{5}".format(item_nr, item_type, item, 1, name, switch_val)
icon_color = 17299
if "rgb_color" in entity.attributes:
color = entity.attributes.rgb_color
if "brightness" in entity.attributes:
color = rgb_brightness(color, entity.attributes.brightness)
icon_color = rgb_dec565(color)
elif "brightness" in entity.attributes:
color = rgb_brightness([253, 216, 53], entity.attributes.brightness)
icon_color = rgb_dec565(color)
return f",{item_type},{item},{get_icon_id('lightbulb')},{icon_color},{name},{switch_val}"
if item_type == "switch" or item_type == "input_boolean":
switch_val = 1 if entity.state == "on" else 0
icon_id = 4
if item_type == "input_boolean" and switch_val == 1:
icon_id = 6
icon_id = get_icon_id("flash")
if item_type == "input_boolean":
if switch_val == 1:
icon_id = get_icon_id("check-circle-outline")
else:
icon_id = 7
return "entityUpd,{0},{1},{2},{3},{4},{5}".format(item_nr, "switch", item, icon_id, name, switch_val)
icon_id = get_icon_id("close-circle-outline")
return f",switch,{item},{icon_id},17299,{name},{switch_val}"
if item_type == "sensor":
icon_id = 0
unit_of_measurement = ""
# maps ha device classes to material design icons
icon_mapping = {
"temperature": 2,
"power": 4
"temperature": "thermometer",
"power": "flash"
}
if "device_class" in entity.attributes:
if entity.attributes.device_class in icon_mapping:
icon_id = icon_mapping[entity.attributes.device_class]
else:
self.api.log("No Icon found for device_class: %s. Please open a issue on github to report the missing mapping.", entity.attributes.device_class)
icon_id = get_icon_id('alert-circle-outline')
else:
icon_id = get_icon_id('alert-circle-outline')
unit_of_measurement = ""
if "unit_of_measurement" in entity.attributes:
unit_of_measurement = entity.attributes.unit_of_measurement
value = entity.state + " " + unit_of_measurement
return "entityUpd,{0},{1},{2},{3},{4},{5}".format(item_nr, "text", item, icon_id, name, value)
return f",text,{item},{icon_id},17299,{name},{value}"
if item_type == "button" or item_type == "input_button":
return "entityUpd,{0},{1},{2},{3},{4},{5}".format(item_nr, "button", item, 3, name, "PRESS")
return f",button,{item},{get_icon_id('gesture-tap-button')},17299,{name},PRESS"
if item_type == "scene":
return "entityUpd,{0},{1},{2},{3},{4},{5}".format(item_nr, "button", item, 10, name, "ACTIVATE")
return f",button,{item},{get_icon_id('palette')},17299,{name},ACTIVATE"
def generate_entities_page(self, items):
# Get items and construct cmd string
command = "entityUpd"
for item in items:
command += self.generate_entities_item(item)
return command
def get_safe_ha_attribute(self, eattr, attr, default):
return eattr[attr] if attr in eattr else default
@@ -389,30 +542,28 @@ class NsPanelLovelaceUI:
icon_res = ""
hvac_modes = self.get_safe_ha_attribute(entity.attributes, "hvac_modes", [])
for mode in hvac_modes:
icon_id = 11
icon_id = get_icon_id('alert-circle-outline')
color_on = 64512
if mode == "auto":
icon_id = 29
icon_id = get_icon_id("calendar-sync")
color_on = 1024
if mode == "heat":
icon_id = 28
icon_id = get_icon_id("fire")
color_on = 64512
if mode == "off":
icon_id = 27
icon_id = get_icon_id("power")
color_on = 35921
if mode == "cool":
icon_id = 31
icon_id = get_icon_id("snowflake")
color_on = 11487
if mode == "dry":
icon_id = 26
icon_id = get_icon_id("water-percent")
color_on = 60897
if mode == "fan_only":
icon_id = 30
icon_id = get_icon_id("fan")
color_on = 35921
state = 0
if(mode == entity.state):
state = 1
@@ -430,7 +581,7 @@ class NsPanelLovelaceUI:
# uneven
padding_len = int((5-len_hvac_modes)/2)
icon_res = ","*4*padding_len + icon_res + ","*4*padding_len
# uneven use first 5 icons
# use first 5 icons
icon_res = icon_res + ","*4*4
return f"entityUpd,{item},{heading},{current_temp},{dest_temp},{status},{min_temp},{max_temp},{step_temp}{icon_res}"
@@ -438,7 +589,7 @@ class NsPanelLovelaceUI:
def generate_media_page(self, item):
if not self.api.entity_exists(item):
return f"entityUpd,|{item}|Not found|11|Please check your|apps.yaml in AppDaemon|50|11"
return f"entityUpd,|{item}|Not found|{get_icon_id('alert-circle-outline')}|Please check your|apps.yaml in AppDaemon|50|11"
entity = self.api.get_entity(item)
heading = entity.attributes.friendly_name
@@ -446,10 +597,9 @@ class NsPanelLovelaceUI:
title = ""
author = ""
volume = 0
#iconplaypause = 9
if "media_content_type" in entity.attributes:
if entity.attributes.media_content_type == "music":
icon = 5
icon = get_icon_id("music")
if "media_title" in entity.attributes:
title = entity.attributes.media_title
if "media_artist" in entity.attributes:
@@ -458,88 +608,61 @@ class NsPanelLovelaceUI:
volume = int(entity.attributes.volume_level*100)
if entity.state == "playing":
iconplaypause = 8
iconplaypause = get_icon_id("pause")
else:
iconplaypause = 9
iconplaypause = get_icon_id("play")
return f"entityUpd,|{item}|{heading}|{icon}|{title}|{author}|{volume}|{iconplaypause}"
def generate_page(self, page_number, page_type):
self.api.log("Generating page commands for page %i with type %s", self.current_page_nr, page_type, level="DEBUG")
if page_type == "cardEntities":
# Send page type
self.send_mqtt_msg("pageType,{0}".format(page_type))
# Set Heading of Page
self.send_mqtt_msg("entityUpdHeading,{0}".format(self.config["pages"][self.current_page_nr]["heading"]))
# Set Items of Page
current_item_nr = 0
for item in self.config["pages"][self.current_page_nr]["items"]:
current_item_nr += 1
command = self.generate_entities_item(item, current_item_nr)
self.send_mqtt_msg(command)
if page_type == "cardThermo":
# Send page type
self.send_mqtt_msg("pageType,{0}".format(page_type))
command = self.generate_thermo_page(self.config["pages"][self.current_page_nr]["item"])
self.send_mqtt_msg(command)
if page_type == "cardMedia":
# Send page type
self.send_mqtt_msg("pageType,{0}".format(page_type))
command = self.generate_media_page(self.config["pages"][self.current_page_nr]["item"])
self.send_mqtt_msg(command)
def generate_detail_page(self, page_type, entity):
if(page_type == "popupLight"):
if page_type == "popupLight":
entity = self.api.get_entity(entity)
switch_val = 1 if entity.state == "on" else 0
icon_color = 17299
if "rgb_color" in entity.attributes:
color = entity.attributes.rgb_color
if "brightness" in entity.attributes:
color = rgb_brightness(color, entity.attributes.brightness)
icon_color = rgb_dec565(color)
elif "brightness" in entity.attributes:
color = rgb_brightness([253, 216, 53], entity.attributes.brightness)
icon_color = rgb_dec565(color)
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(self.scale(entity.attributes.brightness,(0,255),(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(self.scale(entity.attributes.color_temp,(entity.attributes.min_mireds, entity.attributes.max_mireds),(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"
if "xy" in entity.attributes.supported_color_modes or "rgb" in entity.attributes.supported_color_modes or "rgbw" in entity.attributes.supported_color_modes or "hs" in entity.attributes.supported_color_modes:
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,{switch_val},{brightness},{color_temp},{color}")
self.send_mqtt_msg(f"entityUpdateDetail,{get_icon_id('lightbulb')},{icon_color},{switch_val},{brightness},{color_temp},{color}")
if(page_type == "popupShutter"):
pos = self.api.get_entity(msg[3]).attributes.current_position
if page_type == "popupShutter":
pos = self.api.get_entity(entity).attributes.current_position
# reverse position for slider
pos = 100-pos
self.send_mqtt_msg("entityUpdateDetail,{0}".format(pos))
self.send_mqtt_msg(f"entityUpdateDetail,{pos}")
def hsv2rgb(self, h, s, v):
hsv = colorsys.hsv_to_rgb(h,s,v)
return tuple(round(i * 255) for i in hsv)
def pos_to_color(self, x, y):
r = 160/2
x = round((x - r) / r * 100) / 100
y = round((r - y) / r * 100) / 100
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")
r = math.sqrt(x*x + y*y)
sat = 0
if (r > 1):
sat = 0
else:
sat = r
hsv = (math.degrees(math.atan2(y, x))%360/360, sat, 1)
rgb = self.hsv2rgb(hsv[0],hsv[1],hsv[2])
return rgb

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

After

Width:  |  Height:  |  Size: 236 KiB

24
info.md
View File

@@ -11,16 +11,19 @@ nspanel-1:
config:
panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT"
panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend"
timeoutScreensaver: 15 #in seconds, values between 5 and 60 are allowed
updateMode: auto-notify # possible values are auto, auto-notify and manual
timeoutScreensaver: 15 #in seconds
#brightnessScreensaver: 10
brightnessScreensaver:
- time: "7:00:00"
value: 10
- time: "23:00:00"
value: 0
locale: "de_DE"
locale: "de_DE" # only used if babel python package is installed
dateFormatBabel: "full" # only used if babel python package is installed
# formatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields
timeFormat: "%H:%M"
dateFormat: "%A, %d. %B %Y"
dateFormat: "%A, %d. %B %Y" # ignored if babel python package is installed
weatherEntity: weather.example
pages:
- type: cardEntities
@@ -36,14 +39,23 @@ nspanel-1:
- button.example_button
- input_button.example_input_button
- light.light_example
- delete # To make sure we don't keep buttons from previous page (read this as 'empty')
- delete # (read this as 'empty')
- type: cardEntities
heading: Example Page 3
items:
- scene.some_scene
- scene.moodlights
- scene.example_scene
- delete
- delete
- delete
- type: cardGrid
heading: Example Page 4
items:
- light.light_example
- button.example_button
- cover.example_cover
- scene.example_scene
- switch.example_switch
- delete
- type: cardThermo
heading: Exmaple Thermostat
item: climate.example_climate

View File

@@ -27,41 +27,36 @@ type Config = {
dateFormat: string,
weatherEntity: string | null,
temperatureUnit: string,
batEntity: string,
pvEntity: string,
pages: (PageThermo | PageEntities)[]
leftEntity: string,
leftEntityIcon: number,
leftEntityText: string,
leftEntityUnitText: string | null,
rightEntity: string,
rightEntityIcon: number,
rightEntityText: string,
rightEntityUnitText: string | null,
pages: (PageThermo | PageEntities)[],
button1Page: (PageThermo | PageEntities | null),
button2Page: (PageThermo | PageEntities | null),
}
var subscriptions: any = {};
var pageId = 0;
var config: Config = {
panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT",
panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend",
batEntity: "alias.0.Batterie.ACTUAL",
pvEntity: "alias.0.Pv.ACTUAL",
timeoutScreensaver: 15,
dimmode: 8,
locale: "de_DE",
timeFormat: "%H:%M",
dateFormat: "%A, %d. %B %Y",
weatherEntity: "alias.0.Wetter",
temperatureUnit: "°C",
pages: [
var page1: PageEntities =
{
"type": "cardEntities",
"heading": "Testseite",
"heading": "Haus",
"items": [
"alias.0.Rolladen_Eltern",
"alias.0.Erker",
"alias.0.Küche",
"alias.0.Wand"
]
},
};
var page2: PageEntities =
{
"type": "cardEntities",
"heading": "Strom",
@@ -70,15 +65,64 @@ var config: Config = {
"alias.0.Hausverbrauch",
"alias.0.Pv",
"alias.0.Batterie"
]
};
var button1Page: PageEntities =
{
"type": "cardEntities",
"heading": "Knopf1",
"items": [
"alias.0.Schlafen",
"alias.0.Stern",
"delete",
"delete"
]
};
var button2Page: PageEntities =
{
"type": "cardEntities",
"heading": "Knopf2",
"items": [
"delete",
"delete",
"alias.0.Schlafen",
"alias.0.Stern"
]
},
};
var config: Config = {
panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT",
panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend",
leftEntity: "alias.0.Batterie.ACTUAL",
leftEntityIcon: 34,
leftEntityText: "Batterie",
leftEntityUnitText: "%",
rightEntity: "alias.0.Pv.ACTUAL",
rightEntityIcon: 32,
rightEntityText: "PV",
rightEntityUnitText: "W",
timeoutScreensaver: 15,
dimmode: 8,
locale: "de_DE",
timeFormat: "%H:%M",
dateFormat: "%A, %d. %B %Y",
weatherEntity: "alias.0.Wetter",
temperatureUnit: "°C",
pages: [page1, page2,
{
"type": "cardThermo",
"heading": "Thermostat",
"item": "alias.0.WzNsPanel"
}
]
],
button1Page: button1Page,
button2Page: button2Page
};
schedule("* * * * *", function () {
@@ -88,12 +132,20 @@ schedule("0 * * * *", function () {
SendDate();
});
on([config.pvEntity, config.batEntity], function () {
// Only monitor the extra nodes if one or both are present
var updateArray: string[] = [];
if (config.rightEntity !== null && existsState(config.rightEntity)) {
updateArray.push(config.rightEntity)
}
if (config.leftEntity !== null && existsState(config.leftEntity)) {
updateArray.push(config.leftEntity)
}
if (updateArray.length > 0) {
on(updateArray, function () {
HandleScreensaverUpdate();
})
}
on({ id: config.panelRecvTopic }, function (obj) {
if (obj.state.val.startsWith('\{"CustomRecv":')) {
var json = JSON.parse(obj.state.val);
@@ -127,15 +179,11 @@ function HandleMessage(typ: string, method: string, page: number, words: Array<s
if (method == 'pageOpen' || method == 'startup') {
UnsubscribeWatcher();
var retMsgs: Array<Payload> = [];
if (config.pages[pageId].type == "cardEntities") {
retMsgs = GenerateEntitiesPage(pageId, <PageEntities>config.pages[pageId])
} else if (config.pages[pageId].type == "cardThermo") {
retMsgs = GenerateThermoPage(pageId, <PageThermo>config.pages[pageId])
}
if (method == 'startup')
HandleStartupProcess();
SendToPanel(retMsgs)
GeneratePage(config.pages[pageId]);
}
if (method == 'buttonPress' || method == "tempUpd") {
@@ -145,6 +193,43 @@ function HandleMessage(typ: string, method: string, page: number, words: Array<s
if (method == 'screensaverOpen') {
HandleScreensaver()
}
if (method == 'button1' || method == 'button2') {
HandleHardwareButton(method);
}
}
}
function GeneratePage(page: Page): void {
var retMsgs: Array<Payload> = [];
if (page.type == "cardEntities") {
retMsgs = GenerateEntitiesPage(<PageEntities>config.pages[pageId])
} else if (page.type == "cardThermo") {
retMsgs = GenerateThermoPage(pageId, <PageThermo>config.pages[pageId])
}
SendToPanel(retMsgs)
}
function HandleHardwareButton(method: string): void {
let page: (PageThermo | PageEntities);
if (config.button1Page !== null && method == "button1") {
page = config.button1Page;
}
else if (config.button2Page !== null && method == "button2") {
page = config.button2Page;
}
else {
return;
}
SendToPanel({ payload: "wake" });
switch (page.type) {
case "cardEntities":
SendToPanel(GenerateEntitiesPage(page));
break;
case "cardThermo":
SendToPanel(GenerateThermoPage(0, page));
break;
}
}
@@ -156,14 +241,14 @@ function HandleStartupProcess(): void {
}
function SendDate(): void {
var months = ["Jan", "Feb", "Mar", "Apr", "Mai", "Juni", "Juli", "Aug", "Sep", "Okt", "Nov", "Dez"];
var months = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"];
var days = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"];
var d = new Date();
var day = days[d.getDay()];
var date = d.getDate();
var month = months[d.getMonth()];
var year = d.getFullYear();
var _sendDate = "date,?" + day + " " + date + "." + month + "." + year + "";
var _sendDate = "date,?" + day + " " + date + " " + month + " " + year;
SendToPanel(<Payload>{ payload: _sendDate });
}
@@ -182,31 +267,25 @@ function SendTime(): void {
SendToPanel(<Payload>{ payload: "time," + hr + ":" + min });
}
function GenerateEntitiesPage(pageNum: number, page: PageEntities): Payload[] {
function GenerateEntitiesPage(page: PageEntities): Payload[] {
var out_msgs: Array<Payload> = [];
out_msgs = [{ payload: "pageType,cardEntities" }, { payload: "entityUpdHeading," + config.pages[pageNum].heading }]
out_msgs = [{ payload: "pageType,cardEntities" }, { payload: "entityUpdHeading," + page.heading }]
let pageData = "entityUpd";
page.items.forEach(function (id, i) {
out_msgs.push(CreateEntity(id, i + 1));
pageData += CreateEntity(id, i + 1);
})
out_msgs.push({ payload: pageData });
return out_msgs
}
function CreateEntity(id: string, placeId: number): Payload {
function CreateEntity(id: string, placeId: number): string {
var type = "delete"
var iconId = 0
var name = "FriendlyName"
if (id == "delete") {
return { payload: "entityUpd," + placeId + "," + type };
return ",delete,,,,"
}
// case "button":
// type = "button"
// iconId = 3
// var optVal = "PRESS"
// out_msgs.push({ payload: "entityUpd," + (i + 1) + "," + type + "," + id + "," + iconId + "," + name + "," + optVal })
// break
// ioBroker
if (existsObject(id)) {
let o = getObject(id)
@@ -228,8 +307,8 @@ function CreateEntity(id: string, placeId: number): Payload {
var optVal = "0"
if (val === true || val === "true")
optVal = "1"
return { payload: "entityUpd," + placeId + "," + type + "," + id + "," + iconId + "," + name + "," + optVal }
break
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," + optVal
case "dimmer":
type = "light"
iconId = 1
@@ -244,13 +323,13 @@ function CreateEntity(id: string, placeId: number): Payload {
}
if (val === true || val === "true")
optVal = "1"
return { payload: "entityUpd," + placeId + "," + type + "," + id + "," + iconId + "," + name + "," + optVal }
break
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," + optVal
case "blind":
type = "shutter"
iconId = 0
return { payload: "entityUpd," + placeId + "," + type + "," + id + "," + iconId + "," + name }
break
return "," + type + "," + id + "," + iconId + "," + "17299," + name + ","
case "info":
case "value.temperature":
type = "text"
@@ -266,19 +345,27 @@ function CreateEntity(id: string, placeId: number): Payload {
}
if (o.common.role == "value.temperature") {
iconId = 2
iconId = 2;
optVal += config.temperatureUnit;
}
else {
optVal += GetUnitOfMeasurement(id + ".ACTUAL");
}
return { payload: "entityUpd," + placeId + "," + type + "," + id + "," + iconId + "," + name + "," + optVal }
break
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," + optVal;
case "button":
type = "button";
iconId = 3;
var optVal = "PRESS";
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," + optVal;
default:
break
return ",delete,,,,"
}
}
return { payload: "entityUpd," + placeId + "," + type };
return ",delete,,,,"
}
function RegisterEntityWatcher(id: string, entityId: string, placeId: number): void {
@@ -286,7 +373,7 @@ function RegisterEntityWatcher(id: string, entityId: string, placeId: number): v
return;
}
subscriptions[id] = (on({ id: id, change: 'any' }, function (data) {
SendToPanel(CreateEntity(entityId, placeId));
GeneratePage(config.pages[pageId]);
}))
}
@@ -332,7 +419,6 @@ function GenerateThermoPage(pageNum: number, page: PageThermo): Payload[] {
if (existsState(id + ".SET"))
destTemp = parseInt(getState(id + ".SET").val) * 10;
let status = ""
if (existsState(id + ".MODE"))
status = destTemp = getState(id + ".MODE").val;
@@ -373,6 +459,8 @@ function HandleButtonEvent(words): void {
setState(id + ".STOP", true)
if (words[6] == "down")
setState(id + ".CLOSE", true)
if (words[6] == "button")
setState(id + ".SET", true)
if (words[6] == "positionSlider")
setState(id + ".SET", parseInt(words[7]))
@@ -396,16 +484,15 @@ function GenerateDetailPage(type: string, entityId: string): Payload[] {
if (existsObject(id)) {
var o = getObject(id)
var val = null;
let icon = 1;
if (type == "popupLight") {
let switchVal = "0"
if (o.common.role == "light") {
if (existsState(id + ".GET"))
{
if (existsState(id + ".GET")) {
val = getState(id + ".GET").val;
RegisterDetailEntityWatcher(id + ".GET", id, type);
}
else if (existsState(id + ".SET"))
{
else if (existsState(id + ".SET")) {
val = getState(id + ".SET").val;
RegisterDetailEntityWatcher(id + ".SET", id, type);
}
@@ -413,18 +500,16 @@ function GenerateDetailPage(type: string, entityId: string): Payload[] {
if (val)
switchVal = "1"
out_msgs.push({ payload: "entityUpdateDetail," + switchVal + ",disable,disable,disable" })
out_msgs.push({ payload: "entityUpdateDetail," + icon + "," + "17299," + switchVal + ",disable,disable,disable" })
}
if (o.common.role == "dimmer") {
if (existsState(id + ".ON_ACTUAL"))
{
if (existsState(id + ".ON_ACTUAL")) {
val = getState(id + ".ON_ACTUAL").val;
RegisterDetailEntityWatcher(id + ".ON_ACTUAL", id, type);
}
else if (existsState(id + ".ON_SET"))
{
else if (existsState(id + ".ON_SET")) {
val = getState(id + ".ON_SET").val;
RegisterDetailEntityWatcher(id + ".ON_SET", id, type);
}
@@ -432,31 +517,25 @@ function GenerateDetailPage(type: string, entityId: string): Payload[] {
if (val === true || val === "true")
switchVal = "1"
let brightness = 0;
if (existsState(id + ".ACTUAL"))
{
if (existsState(id + ".ACTUAL")) {
brightness = Math.trunc(scale(getState(id + ".ACTUAL").val, 0, 100, 0, 100))
RegisterDetailEntityWatcher(id + ".ACTUAL", id, type);
}
let colortemp = "disable"
//let attr_support_color = attr.supported_color_modes
//if (attr_support_color.includes("color_temp"))
// colortemp = Math.trunc(scale(attr.color_temp, attr.min_mireds, attr.max_mireds, 0, 100))
out_msgs.push({ payload: "entityUpdateDetail," + switchVal + "," + brightness + "," + colortemp })
out_msgs.push({ payload: "entityUpdateDetail," + icon + "," + "17299," + switchVal + "," + brightness + "," + colortemp })
}
}
if (type == "popupShutter") {
if (existsState(id + ".ACTUAL"))
val = getState(id + ".ACTUAL").val;
else if (existsState(id + ".SET"))
val = getState(id + ".SET").val;
out_msgs.push({ payload: "entityUpdateDetail," + val })
}
}
@@ -483,41 +562,112 @@ function HandleScreensaverUpdate(): void {
if (config.weatherEntity != null && existsObject(config.weatherEntity)) {
var icon = getState(config.weatherEntity + ".ICON").val;
let temperature: string = getState(config.weatherEntity + ".TEMP").val;
let temperature: string =
existsState(config.weatherEntity + ".ACTUAL") ? getState(config.weatherEntity + ".ACTUAL").val :
existsState(config.weatherEntity + ".TEMP") ? getState(config.weatherEntity + ".TEMP").val: "null";
let humidity = getState(config.weatherEntity + ".HUMIDITY").val;
let u1 = getState(config.batEntity).val;
let u2 = getState(config.pvEntity).val;
SendToPanel(<Payload>{ payload: "weatherUpdate,?" + GetAccuWeatherIcon(parseInt(icon)) + "?" + temperature.toString() + " " + config.temperatureUnit + "?26?" + humidity + " %?Batterie?4?" + u1 + "%?PV?23?" + u2 + "W" })
let payloadString =
"weatherUpdate,?" + GetAccuWeatherIcon(parseInt(icon)) + "?"
+ temperature + " " + config.temperatureUnit + "?26?"
+ humidity + " %?" ;
if(existsState(config.leftEntity))
{
let u1 = getState(config.leftEntity).val;
payloadString += config.leftEntityText + "?" + config.leftEntityIcon + "?" + u1 + " " + config.leftEntityUnitText + "?";
}
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});
}
}
function GetAccuWeatherIcon(icon: number): number {
switch (icon) {
case 6: // stark bewölkt
case 38:
return 12;
break;
case 1: // Sonnig
case 2:
case 3:
return 23;
case 12: // pouring
return 19;
case 18: // rainy
return 20;
case 32: // windig
return 24;
case 33: // klar
case 34:
return 17;
case 35: // partlycloudy
return 18;
case 24: // Ice
case 30: // Hot
case 31: // Cold
return 11; // exceptional
case 7: // Cloudy
case 8: // Dreary (Overcast)
case 38: // Mostly Cloudy
return 12; // cloudy
case 11: // fog
return 13;
return 13; // fog
case 25: // Sleet
return 14; // Hail
case 15: // T-Storms
return 15; // lightning
case 16: // Mostly Cloudy w/ T-Storms
case 17: // Partly Sunny w/ T-Storms
case 41: // Partly Cloudy w/ T-Storms
case 42: // Mostly Cloudy w/ T-Storms
return 16; // lightning-rainy
case 33: // Clear
case 34: // Mostly Clear
case 37: // Hazy Moonlight
return 17;
case 3: // Partly Sunny
case 4: // Intermittent Clouds
case 6: // Mostly Cloudy
case 35: // Partly Cloudy
case 36: // Intermittent Clouds
return 18; // partlycloudy
case 18: // pouring
return 19; // pouring
case 12: // Showers
case 13: // Mostly Cloudy w/ Showers
case 14: // Partly Sunny w/ Showers
case 26: // Freezing Rain
case 39: // Partly Cloudy w/ Showers
case 40: // Mostly Cloudy w/ Showers
return 20; // rainy
case 19: // Flurries
case 20: // Mostly Cloudy w/ Flurries
case 21: // Partly Sunny w/ Flurries
case 22: // Snow
case 23: // Mostly Cloudy w/ Snow
case 43: // Mostly Cloudy w/ Flurries
case 44: // Mostly Cloudy w/ Snow
return 21; // snowy
case 29: // Rain and Snow
return 22; // snowy-rainy
case 1: // Sunny
case 2: // Mostly Sunny
case 5: // Hazy Sunshine
return 23; // sunny
case 32: // windy
return 24; // windy
default:
return 1;
break;
}
}

144
ioBroker/README.md Normal file
View File

@@ -0,0 +1,144 @@
# NSPanel ioBroker Integration
## Features
- Thermostat Card
- Entity Card (Temperature, Switches and sensors, the script tries to figure the unit of measurement automatically)
- Detail Card (only switch and normal dimmer)
- Live update (when value was changed in the backend and the page is currently open)
- Screensaver Page with Time, Date and Weather Information.
## Requirements
- ioBroker
- MQTT Broker/Client
- Javascript
- devices (default)
- all devices needs to be defined in the devices panel
- supported device roles are light, dimmer, blind, thermostat
## Note
Currently the names are pulled from the objects data field common.name.de.
If you use a different language please search and replace the "common.name.de" with your language.
You can find this in the device raw settings.
## Installation
- Import this script into the ioBroker javascript instance and choose Typescript.
- Make sure the version of the adapter is not to old.
- Find the config variable and update to your needs.
- The format strings are not used right now.
- Make sure your device is connected with the mqtt instance. I didn't get it working with the sonoff adapter, but I didn't tried it too long.
- Create a state with a mqtt client or create one per hand. The mqtt adapter will not create the state CustomSend
- you only need to send a dummy message to cmnd/<yourPanel>/CustomSend
- then the state will be created
## Update the screensaver string
The screensaver string which is send to the display looks something like this:
weatherUpdate,?23?11 °C?26?54%?Batterie?4?12 %?PV?23?123W
All fields are seperated by a question mark. In detail the fields are:
weatherUpdate,?Icon?Text?Icon (default humidity)?Text next to the last icon?Text for the left icon on the right side?Icon?Text under the icon?Text for the right icon on the left side?Icon?Text under the icon
See the icons currently usable in the following table:
[Icon Table](../HMI#icons-ids)
You can change the string and devices in the config object.
## Buttons
If you like you can add special pages for the buttons, but there is a problem currently which will open the last page again. But if you press the button again, the correct page will open.
First you need to add this rule to Tasmota:
```
Rule2 on Button1#state do Publish tele/%topic%/RESULT {"CustomRecv":"event,button1"} endon on Button2#state do Publish tele/%topic%/RESULT {"CustomRecv":"event,button2"} endon
Rule2
```
## The config element in the script which needs to be configured
```
var config: Config = {
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.
leftEntity: "alias.0.Batterie.ACTUAL", // This is a state will be displayed on the left side.
leftEntityIcon: 34, // This is a icon which will be displayed on the left side.
leftEntityText: "Batterie", // The label for the left side.
leftEntityUnitText: "%", // The unit which will be appendon the left side.
rightEntity: "alias.0.Pv.ACTUAL", // The same but for the right side.
rightEntityIcon: 32,
rightEntityText: "PV",
rightEntityUnitText: "W",
timeoutScreensaver: 15, // Timeout for screensaver
dimmode: 8, // Display dim
locale: "de_DE", // not used right now
timeFormat: "%H:%M", // not used right now
dateFormat: "%A, %d. %B %Y", // not used right now
weatherEntity: "alias.0.Wetter",
temperatureUnit: "°C", // Unit to append on temperature sensors
pages: [
{
"type": "cardEntities", // card type (cardEntities, cardThermo)
"heading": "Testseite", // heading
"items": [ // items array (up to 4 on cardEntities, 1 for cardThermo)
"alias.0.Rolladen_Eltern", // device which must be configured in the device panel. Use only the folder for the device, not the set, get states ...
"alias.0.Erker",
"alias.0.Küche",
"alias.0.Wand"
]
},
{
"type": "cardEntities",
"heading": "Strom",
"items": [
"alias.0.Netz",
"alias.0.Hausverbrauch",
"alias.0.Pv",
"alias.0.Batterie"
]
},
{
"type": "cardThermo",
"heading": "Thermostat",
"item": "alias.0.WzNsPanel" // Needs to be a thermostat in the device panel
}
],
button1Page: button1Page, // A cardEntities, cardThermo or nothing. This will be opened when pressing button1
button2Page: button2Page // you guess it
};
```
If you want you can create dedicated objects, so you don't need to declare them again. Then you can use tehm in the pages array and button pages.
```
var button1Page: PageEntities =
{
"type": "cardEntities",
"heading": "Knopf1",
"items": [
"alias.0.Schlafen",
"alias.0.Stern",
"delete",
"delete"
]
};
```
Pages array can look like this:
```
pages: [
button1Page,
{
"type": "cardEntities",
"heading": "Strom",
"items": [
"alias.0.Netz",
"alias.0.Hausverbrauch",
"alias.0.Pv",
"alias.0.Batterie"
]
}]
```

View File

@@ -1,5 +1,44 @@
# Nextion Berry Driver
This berry driver is intended for the usage with a custom HMI/TFT firmware on nspanel and is a customisted version form [peepshow-21's ns-flash](https://github.com/peepshow-21/ns-flash)
It adds the following commands to Tasmota:
- `Nextion Payload`
Send's normal Nextion Commands to the Screen (suffixed by 0xFFFFFF)
- `CustomSend Payload`
Send's normal Custom Commands to the Screen in the following format:
`55 BB [payload length] [payload] [crc] [crc]`
- `FlashNextion URL`
Start's flashing a tft file to the nextion screen via Nextion Upload Protocol 1.2
Webserver must be reachable via HTTP
Example: `FlashNextion http://192.168.75.30:8123/local/nspanel.tft`
- `GetDriverVersion`
Returns the version currently defined in the berry script
- `UpdateDriverVersion URL`
Downloads the autoexec.be script from the specified URL and loads it.
Besides the commands, serial input will be published on 'RESULT' Topic, depending on the input in one of the following formats:
- `{"CustomRecv":%s}`
- `{"nextion":%s}`
# Nextion Berry Driver Legacy Range (Old version with HTTP Range Method)
This berry driver is intended for the usage with a custom HMI/TFT firmware on nspanel.
It adds the following commands to Tasmota:

View File

@@ -1,388 +0,0 @@
# Sonoff NSPanel Tasmota Lovelace UI Berry Driver | code by joBr99
# based on;
# Sonoff NSPanel Tasmota (Nextion with Flashing) driver | code by peepshow-21
# based on;
# Sonoff NSPanel Tasmota driver v0.47 | code by blakadder and s-hadinger
# Example Flash
# FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft
# FlashNextion http://nspanel.pky.eu/lui.tft
class Nextion : Driver
static VERSION = "1.1.3"
static header = bytes('55BB')
static flash_block_size = 4096
var flash_mode
var flash_size
var flash_written
var flash_buff
var flash_offset
var awaiting_offset
var tcp
var ser
var last_per
def split_55(b)
var ret = []
var s = size(b)
var i = s-2 # start from last-1
while i > 0
if b[i] == 0x55 && b[i+1] == 0xBB
ret.push(b[i..s-1]) # push last msg to list
b = b[(0..i-1)] # write the rest back to b
end
i -= 1
end
ret.push(b)
return ret
end
def crc16(data, poly)
if !poly poly = 0xA001 end
# CRC-16 MODBUS HASHING ALGORITHM
var crc = 0xFFFF
for i:0..size(data)-1
crc = crc ^ data[i]
for j:0..7
if crc & 1
crc = (crc >> 1) ^ poly
else
crc = crc >> 1
end
end
end
return crc
end
# encode using custom protocol 55 BB [payload length] [payload length] [payload] [crc] [crc]
def encode(payload)
var b = bytes()
b += self.header
b.add(size(payload), 2) # add size as 2 bytes, little endian
b += bytes().fromstring(payload)
var msg_crc = self.crc16(b)
b.add(msg_crc, 2) # crc 2 bytes, little endian
return b
end
def encodenx(payload)
var b = bytes().fromstring(payload)
b += bytes('FFFFFF')
return b
end
def sendnx(payload)
import string
var payload_bin = self.encodenx(payload)
self.ser.write(payload_bin)
log(string.format("NXP: Nextion command sent = %s",str(payload_bin)), 3)
end
def send(payload)
var payload_bin = self.encode(payload)
if self.flash_mode==1
log("NXP: skipped command becuase still flashing", 3)
else
self.ser.write(payload_bin)
log("NXP: payload sent = " + str(payload_bin), 3)
end
end
def write_to_nextion(b)
self.ser.write(b)
end
def screeninit()
log("NXP: Screen Initialized")
self.sendnx("recmod=1")
end
def write_block()
import string
log("FLH: Read block",3)
while size(self.flash_buff)<self.flash_block_size && self.tcp.connected()
if self.tcp.available()>0
self.flash_buff += self.tcp.readbytes()
else
tasmota.delay(50)
log("FLH: Wait for available...",3)
end
end
log("FLH: Buff size "+str(size(self.flash_buff)),3)
var to_write
if size(self.flash_buff)>self.flash_block_size
to_write = self.flash_buff[0..self.flash_block_size-1]
self.flash_buff = self.flash_buff[self.flash_block_size..]
else
to_write = self.flash_buff
self.flash_buff = bytes()
end
log("FLH: Writing "+str(size(to_write)),3)
var per = (self.flash_written*100)/self.flash_size
if (self.last_per!=per)
self.last_per = per
tasmota.publish_result(string.format("{\"Flashing\":{\"complete\": %d}}",per), "RESULT")
end
if size(to_write)>0
self.flash_written += size(to_write)
if self.flash_offset==0 || self.flash_written>self.flash_offset
self.ser.write(to_write)
self.flash_offset = 0
else
tasmota.set_timer(10,/->self.write_block())
end
end
log("FLH: Total "+str(self.flash_written),3)
if (self.flash_written==self.flash_size)
log("FLH: Flashing complete")
self.flash_mode = 0
end
end
def every_100ms()
import string
if self.ser.available() > 0
var msg = self.ser.read()
if size(msg) > 0
log(string.format("NXP: Received Raw = %s",str(msg)), 3)
if (self.flash_mode==1)
var strv = msg[0..-4].asstring()
if string.find(strv,"comok 2")>=0
log("FLH: Send (High Speed) flash start")
self.sendnx(string.format("whmi-wris %d,115200,res0",self.flash_size))
elif size(msg)==1 && msg[0]==0x08
log("FLH: Waiting offset...",3)
self.awaiting_offset = 1
elif size(msg)==4 && self.awaiting_offset==1
self.awaiting_offset = 0
self.flash_offset = msg.get(0,4)
log("FLH: Flash offset marker "+str(self.flash_offset),3)
self.write_block()
elif size(msg)==1 && msg[0]==0x05
self.write_block()
else
log("FLH: Something has gone wrong flashing display firmware ["+str(msg)+"]",2)
end
else
var msg_list = self.split_55(msg)
for i:0..size(msg_list)-1
msg = msg_list[i]
if size(msg) > 0
if msg == bytes('000000FFFFFF88FFFFFF')
self.screeninit()
elif size(msg)>=2 && msg[0]==0x55 && msg[1]==0xBB
var jm = string.format("{\"CustomRecv\":\"%s\"}",msg[4..-3].asstring())
tasmota.publish_result(jm, "RESULT")
elif msg[0]==0x07 && size(msg)==1 # BELL/Buzzer
tasmota.cmd("buzzer 1,1")
else
var jm = string.format("{\"nextion\":\"%s\"}",str(msg[0..-4]))
tasmota.publish_result(jm, "RESULT")
end
end
end
end
end
end
end
def begin_nextion_flash()
self.flash_written = 0
self.awaiting_offset = 0
self.flash_offset = 0
self.sendnx('DRAKJHSUYDGBNCJHGJKSHBDN')
self.sendnx('recmod=0')
self.sendnx('recmod=0')
self.flash_mode = 1
self.sendnx("connect")
end
def open_url(url)
import string
var host
var port
var s1 = string.split(url,7)[1]
var i = string.find(s1,":")
var sa
if i<0
port = 80
i = string.find(s1,"/")
sa = string.split(s1,i)
host = sa[0]
else
sa = string.split(s1,i)
host = sa[0]
s1 = string.split(sa[1],1)[1]
i = string.find(s1,"/")
sa = string.split(s1,i)
port = int(sa[0])
end
var get = sa[1]
log(string.format("FLH: host: %s, port: %s, get: %s",host,port,get))
self.tcp = tcpclient()
self.tcp.connect(host,port)
log("FLH: Connected:"+str(self.tcp.connected()),3)
var get_req = "GET "+get+" HTTP/1.0\r\n"
get_req += string.format("HOST: %s:%s\r\n\r\n",host,port)
self.tcp.write(get_req)
var a = self.tcp.available()
i = 1
while a==0 && i<5
tasmota.delay(100*i)
tasmota.yield()
i += 1
log("FLH: Retry "+str(i),3)
a = self.tcp.available()
end
if a==0
log("FLH: Nothing available to read!",3)
return
end
var b = self.tcp.readbytes()
i = 0
var end_headers = false;
var headers
while i<size(b) && headers==nil
if b[i..(i+3)]==bytes().fromstring("\r\n\r\n")
headers = b[0..(i+3)].asstring()
self.flash_buff = b[(i+4)..]
else
i += 1
end
end
#print(headers)
# check http respose for code 200
var tag = "200 OK"
i = string.find(headers,tag)
if (i>0)
log("FLH: HTTP Respose is 200 OK",3)
else
log("FLH: HTTP Respose is not 200 OK",3)
print(headers)
return
end
# check http respose for content-length
tag = "Content-Length: "
i = string.find(headers,tag)
if (i>0)
var i2 = string.find(headers,"\r\n",i)
var s = headers[i+size(tag)..i2-1]
self.flash_size=int(s)
end
if self.flash_size==0
log("FLH: No size header, counting ...",3)
self.flash_size = size(self.flash_buff)
#print("counting start ...")
while self.tcp.connected()
while self.tcp.available()>0
self.flash_size += size(self.tcp.readbytes())
end
tasmota.delay(50)
end
#print("counting end ...",self.flash_size)
self.tcp.close()
self.open_url(url)
else
log("FLH: Size found in header, skip count",3)
end
log("FLH: Flash file size: "+str(self.flash_size),3)
end
def flash_nextion(url)
self.flash_size = 0
self.open_url(url)
self.begin_nextion_flash()
end
def version_number(str)
import string
var i1 = string.find(str,".",0)
var i2 = string.find(str,".",i1+1)
var num = int(str[0..i1-1])*10000+int(str[i1+1..i2-1])*100+int(str[i2+1..])
return num
end
def init()
log("NXP: Initializing Driver")
self.ser = serial(17, 16, 115200, serial.SERIAL_8N1)
self.flash_mode = 0
end
end
var nextion = Nextion()
tasmota.add_driver(nextion)
def get_current_version(cmd, idx, payload, payload_json)
import string
var version_of_this_script = 2
var jm = string.format("{\"nlui_driver_version\":\"%s\"}", version_of_this_script)
tasmota.publish_result(jm, "RESULT")
end
tasmota.add_cmd('GetDriverVersion', get_current_version)
def update_berry_driver(cmd, idx, payload, payload_json)
def task()
import string
var cl = webclient()
cl.begin(payload)
var r = cl.GET()
if r == 200
print("Sucessfully downloaded nspanel-lovelace-ui berry driver")
else
print("Error while downloading nspanel-lovelace-ui berry driver")
end
r = cl.write_file("autoexec.be")
if r < 0
print("Error while writeing nspanel-lovelace-ui berry driver")
else
print("Scucessfully written nspanel-lovelace-ui berry driver")
var s = load('autoexec.be')
if s == true
var jm = string.format("{\"nlui_driver_update\":\"%s\"}", "succeeded")
tasmota.publish_result(jm, "RESULT")
else
var jm = string.format("{\"nlui_driver_update\":\"%s\"}", "failed")
tasmota.publish_result(jm, "RESULT")
end
end
end
tasmota.set_timer(0,task)
tasmota.resp_cmnd_done()
end
tasmota.add_cmd('UpdateDriverVersion', update_berry_driver)
def flash_nextion(cmd, idx, payload, payload_json)
def task()
nextion.flash_nextion(payload)
end
tasmota.set_timer(0,task)
tasmota.resp_cmnd_done()
end
def send_cmd(cmd, idx, payload, payload_json)
nextion.sendnx(payload)
tasmota.resp_cmnd_done()
end
def send_cmd2(cmd, idx, payload, payload_json)
nextion.send(payload)
tasmota.resp_cmnd_done()
end
tasmota.add_cmd('Nextion', send_cmd)
tasmota.add_cmd('CustomSend', send_cmd2)
tasmota.add_cmd('FlashNextion', flash_nextion)

View File

@@ -0,0 +1,409 @@
# Nextion Serial Protocol driver by joBr99 + nextion upload protocol 1.2 (the fast one yay) implementation using http range and tcpclient
# based on;
# Sonoff NSPanel Tasmota driver v0.47 | code by blakadder and s-hadinger
class TftDownloader
var tcp
var host
var port
var file
var s
var b
var tft_file_size
var current_chunk
var current_chunk_start
var download_range
def init(host, port, file, download_range)
self.tft_file_size = 0
self.host = host
self.port = port
self.file = file
self.download_range = download_range #32768
end
def download_chunk(b_start, b_length)
import string
self.tcp = tcpclient()
self.tcp.connect(self.host, self.port)
print("connected:", self.tcp.connected())
self.s = "GET " + self.file + " HTTP/1.0\r\n"
self.s += "HOST: " + self.host + "\r\n"
self.s += string.format("Range: bytes=%d-%d\r\n", b_start, (b_start+b_length-1))
print(string.format("Downloading Byte %d - %d", b_start, (b_start+b_length-1)))
self.s += "\r\n"
self.tcp.write(self.s)
#read one char after another until we reached end of http header
var end_of_header = false
var header = ""
while !end_of_header
if self.tcp.available() > 0
header += self.tcp.read(1)
if(string.find(header, '\r\n\r\n') != -1)
end_of_header = true
end
end
end
var content_length = 0
# check for 206 status code
if(string.find(header, '206 Partial Content') != -1)
# download was sucessful
else
print("Error while downloading")
print(header)
return nil
end
# convert header to list
header = string.split(header, '\r\n')
for i : header.iter()
#print(i)
if(string.find(i, 'Content-Range:') != -1)
if self.tft_file_size == 0
print(i)
self.tft_file_size = number(string.split(i, '/')[1])
end
end
if(string.find(i, 'Content-Length:') != -1)
content_length = number(string.split(i, 16)[1])
end
end
#print(content_length)
# read bytes until content_length is reached
var content = bytes()
while content.size() != content_length
if self.tcp.available() > 0
content += self.tcp.readbytes()
end
end
#print(content.size())
return content
end
def get_file_size()
self.download_chunk(0, 1)
return self.tft_file_size
end
# returns the next 4096 bytes after pos of the tft file
def next_chunk(pos)
if(self.current_chunk == nil)
print("current chunk empty")
self.current_chunk = self.download_chunk(pos, self.download_range)
self.current_chunk_start = pos
end
if(pos < self.current_chunk_start)
print("Requested pos is below start point of chunk in memory, not implemented")
end
if(pos >= (self.current_chunk_start+self.download_range))
print("Requested pos is after the end of chunk in memory, downloading new range")
self.current_chunk = self.download_chunk(pos, self.download_range)
self.current_chunk_start = pos
end
var start_within_current_chunk = pos - self.current_chunk_start
return self.current_chunk[start_within_current_chunk..(start_within_current_chunk+4095)]
end
end
class Nextion : Driver
var ser
var flash_size
var flash_mode
var flash_version
var flash_skip
var flash_current_byte
var tftd
var progress_percentage_last
static header = bytes('55BB')
def init()
log("NSP: Initializing Driver")
self.ser = serial(17, 16, 115200, serial.SERIAL_8N1)
self.flash_mode = 0
self.flash_version = 1
self.flash_skip = false
tasmota.add_driver(self)
end
def crc16(data, poly)
if !poly poly = 0xA001 end
# CRC-16 MODBUS HASHING ALGORITHM
var crc = 0xFFFF
for i:0..size(data)-1
crc = crc ^ data[i]
for j:0..7
if crc & 1
crc = (crc >> 1) ^ poly
else
crc = crc >> 1
end
end
end
return crc
end
def split_55(b)
var ret = []
var s = size(b)
var i = s-2 # start from last-1
while i > 0
if b[i] == 0x55 && b[i+1] == 0xBB
ret.push(b[i..s-1]) # push last msg to list
b = b[(0..i-1)] # write the rest back to b
end
i -= 1
end
ret.push(b)
return ret
end
# encode using custom protocol 55 BB [payload length] [payload length] [payload] [crc] [crc]
def encode(payload)
var b = bytes()
b += self.header
b.add(size(payload), 2) # add size as 2 bytes, little endian
b += bytes().fromstring(payload)
var msg_crc = self.crc16(b)
b.add(msg_crc, 2) # crc 2 bytes, little endian
return b
end
# send a nextion payload
def encodenx(payload)
var b = bytes().fromstring(payload)
b += bytes('FFFFFF')
return b
end
def sendnx(payload)
var payload_bin = self.encodenx(payload)
self.ser.write(payload_bin)
print("NSP: Sent =", payload_bin)
log("NSP: Nextion command sent = " + str(payload_bin), 3)
end
def send(payload)
var payload_bin = self.encode(payload)
if self.flash_mode==1
log("NSP: skipped command becuase still flashing", 3)
else
self.ser.write(payload_bin)
log("NSP: payload sent = " + str(payload_bin), 3)
end
end
def start_flash(url)
import string
var host
var port
var s1 = string.split(url,7)[1]
var i = string.find(s1,":")
var sa
if i<0
port = 80
i = string.find(s1,"/")
sa = string.split(s1,i)
host = sa[0]
else
sa = string.split(s1,i)
host = sa[0]
s1 = string.split(sa[1],1)[1]
i = string.find(s1,"/")
sa = string.split(s1,i)
port = int(sa[0])
end
var file = sa[1]
#print(host,port,file)
self.tftd = TftDownloader(host, port, file, 32768)
# get size of tft file
self.flash_size = self.tftd.get_file_size()
self.flash_mode = 1
self.sendnx('DRAKJHSUYDGBNCJHGJKSHBDN')
self.sendnx('recmod=0')
self.sendnx('recmod=0')
self.sendnx("connect")
self.sendnx("connect")
self.flash_current_byte = 0
end
def write_chunk(b_start)
var chunk = self.tftd.next_chunk(b_start)
#import string
#print(string.format("Sending Byte %d - %d with size of %d", b_start, b_start+4095, chunk.size()))
self.ser.write(chunk)
return chunk.size()
end
def flash_nextion()
import string
var x = self.write_chunk(self.flash_current_byte)
self.flash_current_byte = self.flash_current_byte + x
var progress_percentage = (self.flash_current_byte*100/self.flash_size)
if (self.progress_percentage_last!=progress_percentage)
print(string.format("Flashing Progress ( %d / %d ) [ %d ]", self.flash_current_byte, self.flash_size, progress_percentage))
self.progress_percentage_last = progress_percentage
tasmota.publish_result(string.format("{\"Flashing\":{\"complete\": %d}}",progress_percentage), "RESULT")
end
if (self.flash_current_byte==self.flash_size)
log("NSP: Flashing complete")
self.flash_mode = 0
end
tasmota.yield()
end
def every_100ms()
import string
if self.ser.available() > 0
var msg = self.ser.read()
if size(msg) > 0
print("NSP: Received Raw =", msg)
if self.flash_mode==1
var str = msg[0..-4].asstring()
log(str, 3)
# TODO: add check for firmware versions < 126 and send proto 1.1 command for thoose
if (string.find(str,"comok 2")==0)
if self.flash_version==1
log("NSP: Flashing 1.1")
self.sendnx(string.format("whmi-wri %d,115200,1",self.flash_size)) # Nextion Upload Protocol 1.1
else
log("NSP: Flashing 1.2")
self.sendnx(string.format("whmi-wris %d,115200,1",self.flash_size)) # Nextion Upload Protocol 1.2
end
# skip to byte (upload protocol 1.2)
elif (size(msg)==1 && msg[0]==0x08)
self.flash_skip = true
print("rec 0x08")
elif (size(msg)==4 && self.flash_skip)
var skip_to_byte = msg[0..4].get(0,4)
if(skip_to_byte == 0)
print("don't skip, offset is 0")
else
print("skip to ", skip_to_byte)
self.flash_current_byte = skip_to_byte
end
self.flash_nextion()
# send next 4096 bytes (proto 1.1/1.2)
elif (size(msg)==1 && msg[0]==0x05)
print("rec 0x05")
self.flash_nextion()
end
else
# Recive messages using custom protocol 55 BB [payload length] [payload length] [payload] [crc] [crc]
if msg[0..1] == self.header
var lst = self.split_55(msg)
for i:0..size(lst)-1
msg = lst[i]
#var j = msg[2]+2
var j = size(msg) - 3
msg = msg[4..j]
if size(msg) > 2
var jm = string.format("{\"CustomRecv\":\"%s\"}",msg.asstring())
tasmota.publish_result(jm, "RESULT")
end
end
elif msg == bytes('000000FFFFFF88FFFFFF')
log("NSP: Screen Initialized")
else
var jm = string.format("{\"nextion\":\"%s\"}",str(msg[0..-4]))
tasmota.publish_result(jm, "RESULT")
end
end
end
end
end
end
def get_current_version(cmd, idx, payload, payload_json)
import string
var version_of_this_script = 2
var jm = string.format("{\"nlui_driver_version\":\"%s\"}", version_of_this_script)
tasmota.publish_result(jm, "RESULT")
end
tasmota.add_cmd('GetDriverVersion', get_current_version)
def update_berry_driver(cmd, idx, payload, payload_json)
def task()
import string
var cl = webclient()
cl.begin(payload)
var r = cl.GET()
if r == 200
print("Sucessfully downloaded nspanel-lovelace-ui berry driver")
else
print("Error while downloading nspanel-lovelace-ui berry driver")
end
r = cl.write_file("autoexec.be")
if r < 0
print("Error while writeing nspanel-lovelace-ui berry driver")
else
print("Scucessfully written nspanel-lovelace-ui berry driver")
var s = load('autoexec.be')
if s == true
var jm = string.format("{\"nlui_driver_update\":\"%s\"}", "succeeded")
tasmota.publish_result(jm, "RESULT")
else
var jm = string.format("{\"nlui_driver_update\":\"%s\"}", "failed")
tasmota.publish_result(jm, "RESULT")
end
end
end
tasmota.set_timer(0,task)
tasmota.resp_cmnd_done()
end
tasmota.add_cmd('UpdateDriverVersion', update_berry_driver)
var nextion = Nextion()
def flash_nextion(cmd, idx, payload, payload_json)
def task()
nextion.flash_version = 1
nextion.start_flash(payload)
end
tasmota.set_timer(0,task)
tasmota.resp_cmnd_done()
end
tasmota.add_cmd('FlashNextion', flash_nextion)
def flash_nextion_1_2(cmd, idx, payload, payload_json)
def task()
nextion.flash_version = 2
nextion.start_flash(payload)
end
tasmota.set_timer(0,task)
tasmota.resp_cmnd_done()
end
tasmota.add_cmd('FlashNextionFast', flash_nextion_1_2)
def send_cmd(cmd, idx, payload, payload_json)
nextion.sendnx(payload)
tasmota.resp_cmnd_done()
end
tasmota.add_cmd('Nextion', send_cmd)
def send_cmd2(cmd, idx, payload, payload_json)
nextion.send(payload)
tasmota.resp_cmnd_done()
end
tasmota.add_cmd('CustomSend', send_cmd2)

View File

@@ -1,138 +1,43 @@
# Nextion Serial Protocol driver by joBr99 + nextion upload protocol 1.2 (the fast one yay) implementation using http range and tcpclient
# Sonoff NSPanel Tasmota Lovelace UI Berry Driver | code by joBr99
# based on;
# Sonoff NSPanel Tasmota (Nextion with Flashing) driver | code by peepshow-21
# based on;
# Sonoff NSPanel Tasmota driver v0.47 | code by blakadder and s-hadinger
class TftDownloader
var tcp
var host
var port
var file
var s
var b
var tft_file_size
var current_chunk
var current_chunk_start
var download_range
def init(host, port, file, download_range)
self.tft_file_size = 0
self.host = host
self.port = port
self.file = file
self.download_range = download_range #32768
end
def download_chunk(b_start, b_length)
import string
self.tcp = tcpclient()
self.tcp.connect(self.host, self.port)
print("connected:", self.tcp.connected())
self.s = "GET " + self.file + " HTTP/1.0\r\n"
self.s += "HOST: " + self.host + "\r\n"
self.s += string.format("Range: bytes=%d-%d\r\n", b_start, (b_start+b_length-1))
print(string.format("Downloading Byte %d - %d", b_start, (b_start+b_length-1)))
self.s += "\r\n"
self.tcp.write(self.s)
#read one char after another until we reached end of http header
var end_of_header = false
var header = ""
while !end_of_header
if self.tcp.available() > 0
header += self.tcp.read(1)
if(string.find(header, '\r\n\r\n') != -1)
end_of_header = true
end
end
end
var content_length = 0
# check for 206 status code
if(string.find(header, '206 Partial Content') != -1)
# download was sucessful
else
print("Error while downloading")
print(header)
return nil
end
# convert header to list
header = string.split(header, '\r\n')
for i : header.iter()
#print(i)
if(string.find(i, 'Content-Range:') != -1)
if self.tft_file_size == 0
print(i)
self.tft_file_size = number(string.split(i, '/')[1])
end
end
if(string.find(i, 'Content-Length:') != -1)
content_length = number(string.split(i, 16)[1])
end
end
#print(content_length)
# read bytes until content_length is reached
var content = bytes()
while content.size() != content_length
if self.tcp.available() > 0
content += self.tcp.readbytes()
end
end
#print(content.size())
return content
end
def get_file_size()
self.download_chunk(0, 1)
return self.tft_file_size
end
# returns the next 4096 bytes after pos of the tft file
def next_chunk(pos)
if(self.current_chunk == nil)
print("current chunk empty")
self.current_chunk = self.download_chunk(pos, self.download_range)
self.current_chunk_start = pos
end
if(pos < self.current_chunk_start)
print("Requested pos is below start point of chunk in memory, not implemented")
end
if(pos >= (self.current_chunk_start+self.download_range))
print("Requested pos is after the end of chunk in memory, downloading new range")
self.current_chunk = self.download_chunk(pos, self.download_range)
self.current_chunk_start = pos
end
var start_within_current_chunk = pos - self.current_chunk_start
return self.current_chunk[start_within_current_chunk..(start_within_current_chunk+4095)]
end
end
# Example Flash
# FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft
# FlashNextion http://nspanel.pky.eu/lui.tft
class Nextion : Driver
var ser
var flash_size
var flash_mode
var flash_version
var flash_skip
var flash_current_byte
var tftd
var progress_percentage_last
static VERSION = "1.1.3"
static header = bytes('55BB')
def init()
log("NSP: Initializing Driver")
self.ser = serial(17, 16, 115200, serial.SERIAL_8N1)
self.flash_mode = 0
self.flash_version = 1
self.flash_skip = false
tasmota.add_driver(self)
static flash_block_size = 4096
var flash_mode
var flash_size
var flash_written
var flash_buff
var flash_offset
var awaiting_offset
var tcp
var ser
var last_per
def split_55(b)
var ret = []
var s = size(b)
var i = s-2 # start from last-1
while i > 0
if b[i] == 0x55 && b[i+1] == 0xBB
ret.push(b[i..s-1]) # push last msg to list
b = b[(0..i-1)] # write the rest back to b
end
i -= 1
end
ret.push(b)
return ret
end
def crc16(data, poly)
@@ -152,21 +57,6 @@ class Nextion : Driver
return crc
end
def split_55(b)
var ret = []
var s = size(b)
var i = s-2 # start from last-1
while i > 0
if b[i] == 0x55 && b[i+1] == 0xBB
ret.push(b[i..s-1]) # push last msg to list
b = b[(0..i-1)] # write the rest back to b
end
i -= 1
end
ret.push(b)
return ret
end
# encode using custom protocol 55 BB [payload length] [payload length] [payload] [crc] [crc]
def encode(payload)
var b = bytes()
@@ -178,7 +68,6 @@ class Nextion : Driver
return b
end
# send a nextion payload
def encodenx(payload)
var b = bytes().fromstring(payload)
b += bytes('FFFFFF')
@@ -186,23 +75,135 @@ class Nextion : Driver
end
def sendnx(payload)
import string
var payload_bin = self.encodenx(payload)
self.ser.write(payload_bin)
print("NSP: Sent =", payload_bin)
log("NSP: Nextion command sent = " + str(payload_bin), 3)
log(string.format("NXP: Nextion command sent = %s",str(payload_bin)), 3)
end
def send(payload)
var payload_bin = self.encode(payload)
if self.flash_mode==1
log("NSP: skipped command becuase still flashing", 3)
log("NXP: skipped command becuase still flashing", 3)
else
self.ser.write(payload_bin)
log("NSP: payload sent = " + str(payload_bin), 3)
log("NXP: payload sent = " + str(payload_bin), 3)
end
end
def start_flash(url)
def write_to_nextion(b)
self.ser.write(b)
end
def screeninit()
log("NXP: Screen Initialized")
self.sendnx("recmod=1")
end
def write_block()
import string
log("FLH: Read block",3)
while size(self.flash_buff)<self.flash_block_size && self.tcp.connected()
if self.tcp.available()>0
self.flash_buff += self.tcp.readbytes()
else
tasmota.delay(50)
log("FLH: Wait for available...",3)
end
end
log("FLH: Buff size "+str(size(self.flash_buff)),3)
var to_write
if size(self.flash_buff)>self.flash_block_size
to_write = self.flash_buff[0..self.flash_block_size-1]
self.flash_buff = self.flash_buff[self.flash_block_size..]
else
to_write = self.flash_buff
self.flash_buff = bytes()
end
log("FLH: Writing "+str(size(to_write)),3)
var per = (self.flash_written*100)/self.flash_size
if (self.last_per!=per)
self.last_per = per
tasmota.publish_result(string.format("{\"Flashing\":{\"complete\": %d}}",per), "RESULT")
end
if size(to_write)>0
self.flash_written += size(to_write)
if self.flash_offset==0 || self.flash_written>self.flash_offset
self.ser.write(to_write)
self.flash_offset = 0
else
tasmota.set_timer(10,/->self.write_block())
end
end
log("FLH: Total "+str(self.flash_written),3)
if (self.flash_written==self.flash_size)
log("FLH: Flashing complete")
self.flash_mode = 0
end
end
def every_100ms()
import string
if self.ser.available() > 0
var msg = self.ser.read()
if size(msg) > 0
log(string.format("NXP: Received Raw = %s",str(msg)), 3)
if (self.flash_mode==1)
var strv = msg[0..-4].asstring()
if string.find(strv,"comok 2")>=0
log("FLH: Send (High Speed) flash start")
self.sendnx(string.format("whmi-wris %d,115200,res0",self.flash_size))
elif size(msg)==1 && msg[0]==0x08
log("FLH: Waiting offset...",3)
self.awaiting_offset = 1
elif size(msg)==4 && self.awaiting_offset==1
self.awaiting_offset = 0
self.flash_offset = msg.get(0,4)
log("FLH: Flash offset marker "+str(self.flash_offset),3)
self.write_block()
elif size(msg)==1 && msg[0]==0x05
self.write_block()
else
log("FLH: Something has gone wrong flashing display firmware ["+str(msg)+"]",2)
end
else
var msg_list = self.split_55(msg)
for i:0..size(msg_list)-1
msg = msg_list[i]
if size(msg) > 0
if msg == bytes('000000FFFFFF88FFFFFF')
self.screeninit()
elif size(msg)>=2 && msg[0]==0x55 && msg[1]==0xBB
var jm = string.format("{\"CustomRecv\":\"%s\"}",msg[4..-3].asstring())
tasmota.publish_result(jm, "RESULT")
elif msg[0]==0x07 && size(msg)==1 # BELL/Buzzer
tasmota.cmd("buzzer 1,1")
else
var jm = string.format("{\"nextion\":\"%s\"}",str(msg[0..-4]))
tasmota.publish_result(jm, "RESULT")
end
end
end
end
end
end
end
def begin_nextion_flash()
self.flash_written = 0
self.awaiting_offset = 0
self.flash_offset = 0
self.sendnx('DRAKJHSUYDGBNCJHGJKSHBDN')
self.sendnx('recmod=0')
self.sendnx('recmod=0')
self.flash_mode = 1
self.sendnx("connect")
end
def open_url(url)
import string
var host
var port
@@ -222,115 +223,109 @@ class Nextion : Driver
sa = string.split(s1,i)
port = int(sa[0])
end
var file = sa[1]
#print(host,port,file)
var get = sa[1]
log(string.format("FLH: host: %s, port: %s, get: %s",host,port,get))
self.tcp = tcpclient()
self.tcp.connect(host,port)
log("FLH: Connected:"+str(self.tcp.connected()),3)
var get_req = "GET "+get+" HTTP/1.0\r\n"
get_req += string.format("HOST: %s:%s\r\n\r\n",host,port)
self.tcp.write(get_req)
var a = self.tcp.available()
i = 1
while a==0 && i<5
tasmota.delay(100*i)
tasmota.yield()
i += 1
log("FLH: Retry "+str(i),3)
a = self.tcp.available()
end
if a==0
log("FLH: Nothing available to read!",3)
return
end
var b = self.tcp.readbytes()
i = 0
var end_headers = false;
var headers
while i<size(b) && headers==nil
if b[i..(i+3)]==bytes().fromstring("\r\n\r\n")
headers = b[0..(i+3)].asstring()
self.flash_buff = b[(i+4)..]
else
i += 1
end
end
#print(headers)
# check http respose for code 200
var tag = "200 OK"
i = string.find(headers,tag)
if (i>0)
log("FLH: HTTP Respose is 200 OK",3)
else
log("FLH: HTTP Respose is not 200 OK",3)
print(headers)
return
end
# check http respose for content-length
tag = "Content-Length: "
i = string.find(headers,tag)
if (i>0)
var i2 = string.find(headers,"\r\n",i)
var s = headers[i+size(tag)..i2-1]
self.flash_size=int(s)
end
if self.flash_size==0
log("FLH: No size header, counting ...",3)
self.flash_size = size(self.flash_buff)
#print("counting start ...")
while self.tcp.connected()
while self.tcp.available()>0
self.flash_size += size(self.tcp.readbytes())
end
tasmota.delay(50)
end
#print("counting end ...",self.flash_size)
self.tcp.close()
self.open_url(url)
else
log("FLH: Size found in header, skip count",3)
end
log("FLH: Flash file size: "+str(self.flash_size),3)
self.tftd = TftDownloader(host, port, file, 32768)
# get size of tft file
self.flash_size = self.tftd.get_file_size()
self.flash_mode = 1
self.sendnx('DRAKJHSUYDGBNCJHGJKSHBDN')
self.sendnx('recmod=0')
self.sendnx('recmod=0')
self.sendnx("connect")
self.sendnx("connect")
self.flash_current_byte = 0
end
def write_chunk(b_start)
var chunk = self.tftd.next_chunk(b_start)
#import string
#print(string.format("Sending Byte %d - %d with size of %d", b_start, b_start+4095, chunk.size()))
self.ser.write(chunk)
return chunk.size()
def flash_nextion(url)
self.flash_size = 0
self.open_url(url)
self.begin_nextion_flash()
end
def flash_nextion()
def version_number(str)
import string
var x = self.write_chunk(self.flash_current_byte)
self.flash_current_byte = self.flash_current_byte + x
var progress_percentage = (self.flash_current_byte*100/self.flash_size)
if (self.progress_percentage_last!=progress_percentage)
print(string.format("Flashing Progress ( %d / %d ) [ %d ]", self.flash_current_byte, self.flash_size, progress_percentage))
self.progress_percentage_last = progress_percentage
tasmota.publish_result(string.format("{\"Flashing\":{\"complete\": %d}}",progress_percentage), "RESULT")
var i1 = string.find(str,".",0)
var i2 = string.find(str,".",i1+1)
var num = int(str[0..i1-1])*10000+int(str[i1+1..i2-1])*100+int(str[i2+1..])
return num
end
if (self.flash_current_byte==self.flash_size)
log("NSP: Flashing complete")
def init()
log("NXP: Initializing Driver")
self.ser = serial(17, 16, 115200, serial.SERIAL_8N1)
self.flash_mode = 0
end
tasmota.yield()
end
def every_100ms()
import string
if self.ser.available() > 0
var msg = self.ser.read()
if size(msg) > 0
print("NSP: Received Raw =", msg)
if self.flash_mode==1
var str = msg[0..-4].asstring()
log(str, 3)
# TODO: add check for firmware versions < 126 and send proto 1.1 command for thoose
if (string.find(str,"comok 2")==0)
if self.flash_version==1
log("NSP: Flashing 1.1")
self.sendnx(string.format("whmi-wri %d,115200,1",self.flash_size)) # Nextion Upload Protocol 1.1
else
log("NSP: Flashing 1.2")
self.sendnx(string.format("whmi-wris %d,115200,1",self.flash_size)) # Nextion Upload Protocol 1.2
end
var nextion = Nextion()
# skip to byte (upload protocol 1.2)
elif (size(msg)==1 && msg[0]==0x08)
self.flash_skip = true
print("rec 0x08")
elif (size(msg)==4 && self.flash_skip)
var skip_to_byte = msg[0..4].get(0,4)
if(skip_to_byte == 0)
print("don't skip, offset is 0")
else
print("skip to ", skip_to_byte)
self.flash_current_byte = skip_to_byte
end
self.flash_nextion()
# send next 4096 bytes (proto 1.1/1.2)
elif (size(msg)==1 && msg[0]==0x05)
print("rec 0x05")
self.flash_nextion()
end
else
# Recive messages using custom protocol 55 BB [payload length] [payload length] [payload] [crc] [crc]
if msg[0..1] == self.header
var lst = self.split_55(msg)
for i:0..size(lst)-1
msg = lst[i]
#var j = msg[2]+2
var j = size(msg) - 3
msg = msg[4..j]
if size(msg) > 2
var jm = string.format("{\"CustomRecv\":\"%s\"}",msg.asstring())
tasmota.publish_result(jm, "RESULT")
end
end
elif msg == bytes('000000FFFFFF88FFFFFF')
log("NSP: Screen Initialized")
else
var jm = string.format("{\"nextion\":\"%s\"}",str(msg[0..-4]))
tasmota.publish_result(jm, "RESULT")
end
end
end
end
end
end
tasmota.add_driver(nextion)
def get_current_version(cmd, idx, payload, payload_json)
import string
var version_of_this_script = 2
var version_of_this_script = 3
var jm = string.format("{\"nlui_driver_version\":\"%s\"}", version_of_this_script)
tasmota.publish_result(jm, "RESULT")
end
@@ -352,7 +347,7 @@ def update_berry_driver(cmd, idx, payload, payload_json)
if r < 0
print("Error while writeing nspanel-lovelace-ui berry driver")
else
print("Scucessfully written nspanel-lovelace-ui berry driver")
print("Sucessfully written nspanel-lovelace-ui berry driver")
var s = load('autoexec.be')
if s == true
var jm = string.format("{\"nlui_driver_update\":\"%s\"}", "succeeded")
@@ -370,40 +365,24 @@ end
tasmota.add_cmd('UpdateDriverVersion', update_berry_driver)
var nextion = Nextion()
def flash_nextion(cmd, idx, payload, payload_json)
def task()
nextion.flash_version = 1
nextion.start_flash(payload)
nextion.flash_nextion(payload)
end
tasmota.set_timer(0,task)
tasmota.resp_cmnd_done()
end
tasmota.add_cmd('FlashNextion', flash_nextion)
def flash_nextion_1_2(cmd, idx, payload, payload_json)
def task()
nextion.flash_version = 2
nextion.start_flash(payload)
end
tasmota.set_timer(0,task)
tasmota.resp_cmnd_done()
end
tasmota.add_cmd('FlashNextionFast', flash_nextion_1_2)
def send_cmd(cmd, idx, payload, payload_json)
nextion.sendnx(payload)
tasmota.resp_cmnd_done()
end
tasmota.add_cmd('Nextion', send_cmd)
def send_cmd2(cmd, idx, payload, payload_json)
nextion.send(payload)
tasmota.resp_cmnd_done()
end
tasmota.add_cmd('Nextion', send_cmd)
tasmota.add_cmd('CustomSend', send_cmd2)
tasmota.add_cmd('FlashNextion', flash_nextion)