From d418d7bdd88ac07fa264d9b52c9e95093b6c5717 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 11 Dec 2020 15:13:52 +0100 Subject: [PATCH 1/7] Fix diacritics in TEMPLATE.md --- TEMPLATES.md | 57 +++++++++------------------------------------------- 1 file changed, 9 insertions(+), 48 deletions(-) diff --git a/TEMPLATES.md b/TEMPLATES.md index 0da198365..265b3ffa8 100644 --- a/TEMPLATES.md +++ b/TEMPLATES.md @@ -5,7 +5,6 @@ Find below the available templates as of December 2020. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) ## Aromatherapy Diffuser - ``` Asakuki 500ml {"NAME":"Oil Diffuser","GPIO":[1,1,1,1,1,1,0,0,1,1,1,224,225,0],"FLAG":0,"BASE":18} BlitzWolf BW-FUN3 400ml {"NAME":"Generic","GPIO":[1,1,1,1,1,1,1,1,1,1,1,1,1,0],"FLAG":0,"BASE":54} @@ -19,13 +18,11 @@ Wood Grain 550ML {"NAME":"MY-KCL01800FB","GPIO":[1,1,1,1,1,1,0,0,1,1 ``` ## Bluetooth Bridge - ``` Arlec Smart Home Hub {"NAME":"Arlec Hub","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} ``` ## Bulb Socket - ``` Blitzwolf E27 {"NAME":"Blitzwolf BW-LT30","GPIO":[32,0,0,0,224,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} Elegant Choice E27/E26 {"NAME":"name","GPIO":[0,0,0,0,0,0,0,0,0,0,0,224,0,0],"FLAG":0,"BASE":18} @@ -34,7 +31,6 @@ SmartBase E0260 {"NAME":"SmartBaseE0260","GPIO":[0,0,0,0,320,0,0,0, ``` ## CCT - ``` AICase 800lm {"NAME":"AICase Smart L","GPIO":[0,0,0,0,0,416,0,0,0,417,0,0,0,0],"FLAG":0,"BASE":18} Ajax Online 380lm {"NAME":"AjaxOnline","GPIO":[32,0,0,0,0,416,0,0,417,0,0,0,0,0],"FLAG":0,"BASE":38} @@ -74,7 +70,7 @@ Hykker SL-0392 650lm {"NAME":"Hykker 7W","GPIO":[0,0,0,0,0,416,0,0,417,0 Iotton 9W 700lm {"NAME":"Iotton Light","GPIO":[0,0,0,0,416,417,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} iView 10W 1050lm {"NAME":"iView ISB1000-D","GPIO":[0,0,0,0,0,416,0,0,0,417,0,0,0,0],"FLAG":0,"BASE":18} Kogan 10W Cool & Warm White 1050lm {"NAME":"Kogan 10W CCT","GPIO":[0,0,0,0,0,416,0,0,0,417,0,0,0,0],"FLAG":0,"BASE":48} -Kogan 4.5W 330lm 110? {"NAME":"Kogan White/Wa","GPIO":[0,0,0,0,0,416,0,0,417,0,0,0,0,0],"FLAG":0,"BASE":18} +Kogan 4.5W 330lm 110° {"NAME":"Kogan White/Wa","GPIO":[0,0,0,0,0,416,0,0,417,0,0,0,0,0],"FLAG":0,"BASE":18} Kogan 5W {"NAME":"Kogan Co/Wa","GPIO":[0,0,0,0,0,416,0,0,0,417,0,0,0,0],"FLAG":0,"BASE":18} Laser 10W 1000lm {"NAME":"Laser 10W CCT","GPIO":[0,0,0,0,0,416,0,0,0,417,0,0,0,0],"FLAG":0,"BASE":48} Laser 10W 1000lm {"NAME":"Laster 10W CCT","GPIO":[0,0,0,0,0,416,0,0,0,417,0,0,0,0],"FLAG":0,"BASE":18} @@ -101,7 +97,7 @@ Nedis A60 800lm {"NAME":"WIFILW10WTE27","GPIO":[0,0,0,0,0,416,0,0,4 Nedis C10 350lm {"NAME":"WIFILW10WTE14","GPIO":[0,0,0,0,0,416,0,0,0,417,0,0,0,0],"FLAG":0,"BASE":18} Nedis G125 5.5W 350lm Twisted Filament {"NAME":"WIFILF10GDG125","GPIO":[0,0,0,0,0,0,0,0,417,0,416,0,0,0],"FLAG":0,"BASE":18} Nedis PAR16 330lm {"NAME":"Nedis WIFILW30","GPIO":[0,0,0,0,0,416,0,0,417,0,0,0,0,0],"FLAG":0,"BASE":18} -Nedis PAR16 4.5W 330lm 110? {"NAME":"WIFILW30","GPIO":[0,0,0,0,0,416,0,0,417,0,0,0,0,0],"FLAG":0,"BASE":18} +Nedis PAR16 4.5W 330lm 110° {"NAME":"WIFILW30","GPIO":[0,0,0,0,0,416,0,0,417,0,0,0,0,0],"FLAG":0,"BASE":18} Philips Zhirui Candle 250lm {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,417,0,0,416,0,0],"FLAG":0,"BASE":48} Phillips Zhirui 450lm {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,417,0,0,416,0,0],"FLAG":0,"BASE":48} Polux ST64 5.5W 470lm {"NAME":"basic","GPIO":[0,0,0,0,0,0,0,0,417,0,416,0,0,0],"FLAG":0,"BASE":18} @@ -114,14 +110,13 @@ Spectrum Smart 5W 410lm Candle {"NAME":"lightbulb","GPIO":[0,0,0,0,0,0,0,0,417, Status 9W 806lm {"NAME":"Status Smart","GPIO":[0,0,0,0,0,0,0,0,417,0,416,0,0,0],"FLAG":0,"BASE":18} Swisstone SH 330 806lm {"NAME":"SwisstoneSH330","GPIO":[0,0,0,0,2912,416,0,0,417,2976,2944,0,0,0],"FLAG":0,"BASE":18} Treatlife A19 9W 800lm {"NAME":"Treatlife SL20","GPIO":[0,0,0,0,0,416,0,0,0,417,0,0,0,0],"FLAG":0,"BASE":18} -V-Tac PAR16 4.5W 300lm 110? {"NAME":"V-TAC VT-5174","GPIO":[0,0,0,0,0,0,0,0,417,0,416,0,0,0],"FLAG":0,"BASE":18} +V-Tac PAR16 4.5W 300lm 110° {"NAME":"V-TAC VT-5174","GPIO":[0,0,0,0,0,0,0,0,417,0,416,0,0,0],"FLAG":0,"BASE":18} Vestaiot BR30 800lm {"NAME":"Vesta BR30 CCT","GPIO":[0,0,0,0,0,416,0,0,0,417,0,0,0,0],"FLAG":0,"BASE":18} Wipro Garnet NS9100 810lm {"NAME":"WiproSmartBulb","GPIO":[0,0,0,0,417,0,0,0,416,0,0,0,0,0],"FLAG":0,"BASE":18} Wyze WLPA19 A19 800lm {"NAME":"Wyze Bulb","GPIO":[0,0,0,0,0,0,0,0,0,416,417,0,0,0],"FLAG":0,"BASE":48} ``` ## Ceiling Light - ``` BAZZ 14" RGBCCT {"NAME":"WF19129W","GPIO":[0,0,0,0,416,419,0,0,417,420,418,0,0,0],"FLAG":0,"BASE":18} BlitzWolf 24W {"NAME":"BW-LT20","GPIO":[0,0,0,0,0,416,0,0,0,417,0,0,0,1],"FLAG":0,"BASE":18} @@ -144,7 +139,6 @@ Verve Design Hana 24W CCT {"NAME":"Verve ACL03HA","GPIO":[0,0,0,0,0,0,0,0,417 ``` ## Contact Sensor - ``` D06 {"NAME":"D06 Door Sensor","GPIO":[0,3200,0,3232,224,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} Digoo DG-ZXD21 Door Detector {"NAME":"Digoo ZXD21","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} @@ -154,7 +148,6 @@ Zemismart Door Window {"NAME":"Zemismart","GPIO":[1,2272,1,2304,1,1,0,0,1 ``` ## Curtain Switch - ``` Anccy {"NAME":"Anccy Shutter","GPIO":[544,0,289,34,226,33,0,0,32,224,290,225,288,0],"FLAG":0,"BASE":18} Anccy Relax {"NAME":"Tuya Shutter","GPIO":[544,0,290,161,225,34,0,0,32,224,289,226,288,0],"FLAG":0,"BASE":18} @@ -177,7 +170,6 @@ Zemismart {"NAME":"Zemismart","GPIO":[544,0,0,162,290,161,0,0 ``` ## DIY - ``` Adafruit HUZZAH {"NAME":"Huzzah","GPIO":[32,0,320,0,1,1,0,0,1,1,1,1,1,0],"FLAG":0,"BASE":18} ESP-01 Module {"NAME":"ESP01","GPIO":[1,1,1,1,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} @@ -195,7 +187,6 @@ Yison ESP-01/ESP-202 Development Board {"NAME":"Yison Dev Board","GPIO":[259,54 ``` ## Dimmable - ``` Aisirer 9W 806lm {"NAME":"Aisirer 9W","GPIO":[0,0,0,0,0,416,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} Aisirer 9W 806lm {"NAME":"AISIRER E26","GPIO":[0,0,0,0,0,416,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} @@ -262,7 +253,6 @@ Xiaomi Philips MUE4088RT {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,0, ``` ## Dimmer - ``` 3A Smart Home HGZB-04D {"NAME":"HGZB-4D","GPIO":[1,1,1,1,1,1,0,0,1,1,290,1,1,0],"FLAG":0,"BASE":54} Acenx SD03 {"NAME":"SD03","GPIO":[34,33,0,323,576,322,0,0,321,416,320,96,256,0],"FLAG":0,"BASE":73} @@ -303,7 +293,6 @@ Zemismart KS-7011 {"NAME":"KS-7011 Dimmer","GPIO":[1,2272,1,2304,1,1, ``` ## Downlight - ``` 3A 12W RGBW {"NAME":"RGBWSpot","GPIO":[0,0,0,0,416,419,0,0,417,452,418,0,0,0],"FLAG":0,"BASE":18} Arlec Smart 9W CCT {"NAME":"Arlec ALD092CHA","GPIO":[0,0,0,0,419,420,0,0,416,418,417,0,0,0],"FLAG":0,"BASE":18} @@ -327,14 +316,12 @@ Zemismart 6" 14W RGBCCT {"NAME":"ZemiDownLight6","GPIO":[0,0,0,0,416,419,0, ``` ## Energy Meter - ``` Hiking Single Phase 65A Din Rail {"NAME":"hiking dds2382wifi","GPIO":[0,2272,0,2304,0,0,0,0,0,0,320,0,32,0],"FLAG":0,"BASE":1} ZMAi-90 Digital {"NAME":"ZMAi-90","GPIO":[0,3200,0,3232,0,0,0,0,224,64,0,0,0,0],"FLAG":0,"BASE":18} ``` ## Fan - ``` Anko HEGSM40 {"NAME":"Anko HEGSM40","GPIO":[0,0,0,0,0,0,0,0,0,2304,0,2272,0,0],"FLAG":0,"BASE":54} Arlec Smart 45cm Smart DC Wall {"NAME":"Arlec 45cm Fan","GPIO":[0,0,0,0,0,0,0,0,0,2304,0,2272,0,0],"FLAG":0,"BASE":54} @@ -342,7 +329,7 @@ BrilliantSmart 99111 {"NAME":"Brilliant Fan","GPIO":[0,2272,0,2304,0,0,0 Geek Aire AF1s {"NAME":"Geek Aire Fan","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} Goldair SleepSmart GCPF315 {"NAME":"Goldair Fan","GPIO":[0,0,0,0,0,0,0,0,0,2304,0,2272,0,0],"FLAG":0,"BASE":54} Lucci Connect Remote Control {"NAME":"Lucci Fan","GPIO":[0,0,0,0,0,0,0,0,0,2304,0,2272,0,0],"FLAG":0,"BASE":54} -Sichler Haushaltsger?te Column {"NAME":"Sichler Fan","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} +Sichler Haushaltsgeräte Column {"NAME":"Sichler Fan","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} Sonoff IFan02 {"NAME":"Sonoff iFan02","GPIO":[32,1,0,1,226,225,33,34,224,320,35,227,0,0],"FLAG":0,"BASE":44} Sonoff IFan03 {"NAME":"SonoffiFan03","GPIO":[32,3200,0,3232,0,0,256,512,226,320,225,227,0,0],"FLAG":0,"BASE":71} Technical Pro FXA16 {"NAME":"FXA16 Fan","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} @@ -350,20 +337,17 @@ Zemismart Bladeless {"NAME":"Bladeless Fan","GPIO":[1,2272,1,2304,1,1,0 ``` ## Gas Sensor - ``` Natural Gas (CH4) Alarm {"NAME":"PA-210WYS","GPIO":[1,2272,1,2304,1,1,0,0,1,1,1,1,1,0],"FLAG":0,"BASE":54} ``` ## Heater - ``` Klarstein Bornholm Smart 2000W {"NAME":"Klarstein Bornholm","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} Kogan 1500W Panel {"NAME":"Kogan Panel Heater","GPIO":[0,0,0,0,0,0,0,0,0,2304,0,2272,0,0],"FLAG":0,"BASE":54} ``` ## IR Bridge - ``` A1 Universal Remote Control {"NAME":"A1 IR Bridge","GPIO":[1,1,1,1,320,1088,0,0,0,32,1056,0,0,0],"FLAG":0,"BASE":62} Alfawise KS1 {"NAME":"KS1","GPIO":[1,1792,32,1824,32,1088,0,0,320,0,1056,0,0,4704],"FLAG":0,"BASE":62} @@ -389,7 +373,6 @@ YTF Universal Remote {"NAME":"YTF IR Bridge","GPIO":[1,1,1,1,320,1088,0, ``` ## Kettle - ``` Anko 1.7L Cordless Water {"NAME":"Anko Kettle","GPIO":[1,1,1,1,1,1,0,0,1,2304,1,2272,1,0],"FLAG":0,"BASE":54} Kogan 1.7L Smart Glass {"NAME":"Kogan Kettle","GPIO":[1,2272,1,2304,1,1,0,0,1,1,1,1,1,0],"FLAG":0,"BASE":54} @@ -397,7 +380,6 @@ ProfiCook PC-WKS 1167G 1.5L {"NAME":"PC-WKS 1167G","GPIO":[0,2272,0,2304,0,0,0, ``` ## LED Controller - ``` Anncoe C350 RGB {"NAME":"TUYA LED","GPIO":[0,0,0,0,0,417,0,0,418,32,416,0,0,0],"FLAG":0,"BASE":18} Anncoe C350 RGBW {"NAME":"TUYA LED","GPIO":[0,0,0,0,0,417,0,0,418,32,416,419,0,0],"FLAG":0,"BASE":18} @@ -438,7 +420,6 @@ ZJ-WF-ESP-A v1.1 {"NAME":"RGB2","GPIO":[0,0,0,0,0,0,0,0,417,416,418, ``` ## LED Strip - ``` Arlec Smart 2m LED Colour Changing Strip Light {"NAME":"Arlec ALD233AH","GPIO":[0,0,0,0,416,419,0,0,417,0,418,0,0,0],"FLAG":0,"BASE":18} B.K. Licht 2m RGB {"NAME":"RGBW-Strip","GPIO":[0,0,0,0,416,32,0,0,417,0,418,0,0,0],"FLAG":0,"BASE":18} @@ -487,7 +468,6 @@ Zemismart 3m Extendable RGBW {"NAME":"Zemismart LED","GPIO":[0,0,0,0,417,416,0, ``` ## Light - ``` Arlec Smart 10W LED Bunker {"NAME":"DetaBulkhead","GPIO":[0,0,0,0,0,0,0,0,0,0,416,0,0,0],"FLAG":0,"BASE":18} Arlec Smart 15W Security Floodlight {"NAME":"ArlecFlood","GPIO":[0,0,0,0,0,0,0,0,0,0,416,0,0,1],"FLAG":0,"BASE":18} @@ -520,7 +500,6 @@ Wipro Next 20W Smart LED Batten (White) {"NAME":"WIPROBatten","GPIO":[0,0,0,0,0 ``` ## Miscellaneous - ``` Alfawise Air Purifier {"NAME":"alfawise P2","GPIO":[1,2272,1,2304,1,1,0,0,1,1,1,1,1,0],"FLAG":0,"BASE":54} BlitzWolf Air Fryer {"NAME":"Bw-AF1","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} @@ -535,7 +514,6 @@ Sonoff RM433 RF Remote Controller {"NAME":"REQUIRES RF DEVICE"} ``` ## Motion Sensor - ``` DP-WP001 PIR {"NAME":"TUYA PIR","GPIO":[1,2272,1,2304,1,1,0,0,1,1,1,1,1,0],"FLAG":0,"BASE":54} Lenovo Rechargable PIR Motion {"NAME":"Lenovo PIR","GPIO":[1,2272,1,2304,1,1,0,0,1,1,1,1,1,0],"FLAG":0,"BASE":54} @@ -543,7 +521,6 @@ Mirabella Genio I002576 {"NAME":"GenioPir","GPIO":[32,2272,0,2304,0,0,0,0,0 ``` ## Motor - ``` Zemismart BCM300D-TY {"NAME":"Zemistart_Curt","GPIO":[0,0,0,0,0,0,0,0,0,2304,0,2272,0,0],"FLAG":0,"BASE":54} Zemismart Blinds Controller "Not available" @@ -552,7 +529,6 @@ Zemismart Updated RF Remote Roller Shade {"NAME":"Zemismart M515EGB","GPIO":[1, ``` ## Multisensor - ``` AZ-Envy Environmental Development Board {"NAME":"AZ Envy","GPIO":[0,0,288,0,640,608,0,0,0,0,0,0,0,4704],"FLAG":0,"BASE":18} NEO Coolcam Siren with Temperature and Humidity {"NAME":"Neo Siren 3in1","GPIO":[1,2272,1,2304,1,1,0,0,1,1,1,1,1,0],"FLAG":0,"BASE":54} @@ -560,7 +536,6 @@ Sonoff SC {"NAME":"Sonoff SC","GPIO":[32,3200,1,3232,0,0,0,0, ``` ## Outdoor Plug - ``` Acenx SOP04-US Dual {"NAME":"SOP04-US Dual","GPIO":[1,1,1,1,320,321,0,0,224,32,225,1,1,0],"FLAG":0,"BASE":18} Aicliv 3 Outlet {"NAME":"AICLIV SOP03US","GPIO":[0,0,0,226,321,0,0,0,224,33,225,0,0,0],"FLAG":0,"BASE":18} @@ -620,7 +595,6 @@ WOOX R4052 {"NAME":"WOOX R4052","GPIO":[32,0,0,0,0,0,0,0,224,3 ``` ## Plug - ``` 2nice SP111 {"NAME":"2NICE SP111","GPIO":[320,0,321,0,0,0,0,0,0,32,0,224,0,4736],"FLAG":0,"BASE":18} 2nice UP111 {"NAME":"2NICE UP111","GPIO":[0,576,0,32,2720,2656,0,0,2624,320,224,0,0,0],"FLAG":0,"BASE":18} @@ -911,7 +885,7 @@ Maxcio W-US003 {"NAME":"W-US003","GPIO":[1,32,1,1,1,1,0,0,1,225,22 Maxcio YX-DE02 {"NAME":"Maxcio DE02","GPIO":[0,32,0,224,320,225,0,0,416,417,418,0,0,0],"FLAG":0,"BASE":18} Maxcio YX-DE04 {"NAME":"Maxcio YX-DE04","GPIO":[1,32,1,224,320,419,0,0,416,417,418,1,1,4704],"FLAG":0,"BASE":18} MaxKare XKJJ-0218 {"NAME":"MaxKare XKJJ-0","GPIO":[0,0,0,0,33,2688,0,0,224,32,2656,225,2592,0],"FLAG":0,"BASE":18} -Maxus Brio Head 16 {"NAME":"Brio-W-Head16","GPIO":[0,0,320,0,0,2720,0,0,2624,32,2656,224,0,0],"FLAG":0,"BASE":18} +Maxus Brio Head 16A {"NAME":"Brio-W-Head16","GPIO":[0,0,320,0,0,2720,0,0,2624,32,2656,224,0,0],"FLAG":0,"BASE":18} Medion Life+ S85225 {"NAME":"Medion","GPIO":[0,0,0,32,2720,2656,0,0,2624,320,224,0,0,0],"FLAG":0,"BASE":52} Merkury Innovations 4 Outlets {"NAME":"MI-WW119-199W","GPIO":[320,3200,0,3232,225,32,0,0,224,226,227,0,0,0],"FLAG":0,"BASE":18} Merkury MI-WW101-199 {"NAME":"merkury WW101","GPIO":[0,0,0,0,0,0,0,0,320,64,0,224,0,0],"FLAG":0,"BASE":18} @@ -1106,7 +1080,6 @@ ZSP-001 {"NAME":"ZSP-001","GPIO":[32,1,1,1,2688,2656,0,0,25 ``` ## Power Strip - ``` A0F0 ZLD-44EU-W {"NAME":"AOFO-4AC-4USB","GPIO":[0,320,0,32,225,224,0,0,226,227,260,0,0,4704],"FLAG":0,"BASE":18} Acenx 3AC+3USB {"NAME":"ACENX 3-Outlet","GPIO":[320,291,290,289,0,224,0,0,226,227,225,0,32,0],"FLAG":0,"BASE":18} @@ -1206,13 +1179,11 @@ ZLD64-EU-W {"NAME":"ZLD64-EU-W","GPIO":[0,320,0,32,225,224,0,0 ``` ## RF Bridge - ``` Sonoff RF Bridge 433 {"NAME":"Sonoff Bridge","GPIO":[32,3200,1,3232,1,1,0,0,1,320,1,0,0,0],"FLAG":0,"BASE":25} ``` ## RGB - ``` Cairondin 7W 500lm {"NAME":"Cairondin","GPIO":[32,0,0,0,0,0,0,0,0,3008,0,3040,0,0],"FLAG":0,"BASE":27} Deltaco SH-LE27RGB 810lm {"NAME":"SH-LE27RGB","GPIO":[0,0,0,0,417,416,0,0,420,418,419,0,0,0],"FLAG":0,"BASE":18} @@ -1226,7 +1197,6 @@ Wipro Garnet NS7001 480lm {"NAME":"WiproSmartBulb","GPIO":[0,0,0,0,416,419,0, ``` ## RGBCCT - ``` Aigital LE13 800lm {"NAME":"Aigital 9W RGB","GPIO":[0,0,0,0,420,417,0,0,418,0,419,416,0,0],"FLAG":0,"BASE":18} Aisirer 10W 1000lm {"NAME":"Aisirer RGBCW","GPIO":[160,0,0,0,0,0,0,0,0,4032,4064,0,0,0],"FLAG":0,"BASE":18} @@ -1356,7 +1326,7 @@ Teckin SB50 v3 A19 800lm {"NAME":"Teckin SB50v3","GPIO":[0,0,0,0,416,419,0,0 Teckin SB53 1300lm {"NAME":"Teckin SB53","GPIO":[0,0,0,0,416,419,0,0,417,420,418,0,0,0],"FLAG":0,"BASE":18} Treatlife A19 8W 650lm {"NAME":"Treatlife RGBW","GPIO":[0,0,0,0,417,416,0,0,420,418,419,0,0,0],"FLAG":0,"BASE":18} V-TAC 10W 806lm {"NAME":"V-TAC VT-5119","GPIO":[0,0,0,0,4032,0,0,0,0,0,4064,0,0,0],"FLAG":0,"BASE":18} -V-Tac PAR16 4.5W 400lm 100? {"NAME":"V-TAC VT5164","GPIO":[0,0,0,0,0,0,0,0,4064,0,4032,0,0,0],"FLAG":0,"BASE":18} +V-Tac PAR16 4.5W 400lm 100° {"NAME":"V-TAC VT5164","GPIO":[0,0,0,0,0,0,0,0,4064,0,4032,0,0,0],"FLAG":0,"BASE":18} Vizia 5W GU10 {"NAME":"Vizia RGBWW","GPIO":[0,0,0,0,419,420,0,0,417,418,416,0,0,1],"FLAG":0,"BASE":18} Wipro Garnet 9W 810lm {"NAME":"Wipro","GPIO":[0,0,0,0,416,419,0,0,417,420,418,0,0,0],"FLAG":0,"BASE":18} WiZ BR30 13.8W 750lm {"NAME":"WiZ RGBCCT PAR30","GPIO":[0,0,0,0,419,0,0,0,417,420,418,416,0,0],"FLAG":0,"BASE":48} @@ -1367,7 +1337,6 @@ ZZHXON 600lm {"NAME":"E27_RGB_Bulb","GPIO":[0,0,0,0,419,420,0,0, ``` ## RGBW - ``` 3Stone EBE-QPW36 1050lm {"NAME":"3STONE","GPIO":[0,0,0,0,2944,2912,0,0,416,2976,0,0,0,1],"FLAG":0,"BASE":18} Accewit 7W 650lm {"NAME":"Accewit Bulb","GPIO":[0,0,0,0,0,417,0,0,418,0,419,416,0,0],"FLAG":0,"BASE":18} @@ -1436,7 +1405,7 @@ Kainsy 600lm {"NAME":"KAINSY","GPIO":[32,0,0,0,3008,3040,0,0,0,0 Kkmoon 9W 800lm {"NAME":"KKMOON V21","GPIO":[0,0,0,0,419,0,0,0,417,418,416,0,0,0],"FLAG":0,"BASE":18} Koaanw 650lm {"NAME":"KOAANW Bulb","GPIO":[0,0,0,0,3008,3040,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} Kogan 10W Ambient 1050lm {"NAME":"Kogan RGB","GPIO":[0,0,0,0,2912,416,0,0,0,0,2944,0,0,0],"FLAG":0,"BASE":18} -Kogan 4.5W 330lm 110? {"NAME":"Kogan_GU10","GPIO":[0,0,0,0,418,419,0,0,416,0,417,0,0,0],"FLAG":0,"BASE":18} +Kogan 4.5W 330lm 110° {"NAME":"Kogan_GU10","GPIO":[0,0,0,0,418,419,0,0,416,0,417,0,0,0],"FLAG":0,"BASE":18} Kogan Ambient Candle {"NAME":"Kogan_E14","GPIO":[0,0,0,0,416,419,0,0,417,0,418,0,0,0],"FLAG":0,"BASE":18} Kuled 800lm {"NAME":"KULED 60W RGB","GPIO":[0,0,0,0,418,419,0,0,416,0,417,0,0,4704],"FLAG":0,"BASE":18} Laideyi 7W {"NAME":"7W-E14-RGBW-La","GPIO":[0,0,0,0,417,416,0,0,418,0,419,0,0,0],"FLAG":0,"BASE":18} @@ -1530,7 +1499,6 @@ Zilotek A19 800lm {"NAME":"Zilotek RGBW","GPIO":[0,0,0,0,2912,416,0,0 ``` ## Relay - ``` Anmbest 2 Channel Inching Self-locking Switch Module {"NAME":"Generic","GPIO":[32,1,1,1,1,225,33,0,224,320,0,0,0,0],"FLAG":0,"BASE":1} Athom 10A {"NAME":"Athom CB0110A","GPIO":[0,0,0,0,320,0,0,0,224,32,0,0,0,0],"FLAG":0,"BASE":1} @@ -1566,20 +1534,18 @@ Sonoff SV {"NAME":"Sonoff SV","GPIO":[32,1,0,1,1,1,0,0,224,32 ``` ## Smoke Sensor - ``` Nedis Smoke Detector {"NAME":"Nedis Smoke","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} Smoke Alarm {"NAME":"YG400A","GPIO":[1,2272,1,2304,1,1,0,0,1,1,1,1,1,0],"FLAG":0,"BASE":54} ``` ## Switch - ``` 3 Way Smart Light {"NAME":"Nexete KS-602F 3-Way","GPIO":[1,1,1,1,1,1,0,0,1,1,1,1,1,0],"FLAG":0,"BASE":54} 3A Smart Home {"NAME":"3A Smart Home ","GPIO":[288,0,291,33,225,34,0,0,32,224,290,226,289,0],"FLAG":0,"BASE":18} AGL 2 Gang {"NAME":"AGL WiFi 02","GPIO":[0,0,544,0,0,33,0,0,225,224,0,0,32,0],"FLAG":0,"BASE":18} AGL 3 Gang {"NAME":"AGL WiFi 03","GPIO":[0,0,544,0,34,33,0,0,225,224,226,0,32,0],"FLAG":0,"BASE":18} -AGL M?dulo Rel? 01 Canal {"NAME":"AGL-Basic","GPIO":[0,1,0,0,224,32,0,0,0,0,320,0,0,0],"FLAG":0,"BASE":18} +AGL Módulo Relé 01 Canal {"NAME":"AGL-Basic","GPIO":[0,1,0,0,224,32,0,0,0,0,320,0,0,0],"FLAG":0,"BASE":18} Albohes 2 Channel {"NAME":"Albohes SH-08","GPIO":[0,3200,33,3232,321,320,0,0,224,544,32,0,225,1],"FLAG":0,"BASE":18} Aoycocr SW1 {"NAME":"Aoycocr SW1","GPIO":[576,1,321,1,1,1,1,1,320,32,1,224,1,1],"FLAG":0,"BASE":18} Athom 1 Gang {"NAME":"Athom SW011EU","GPIO":[576,0,0,32,0,0,0,0,0,224,288,0,0,0],"FLAG":0,"BASE":1} @@ -1735,7 +1701,7 @@ Moes WS-US3-W 3 Gang {"NAME":"Tuya Moes 3 Ch","GPIO":[544,0,290,33,225,3 Moes WT02S {"NAME":"Moes WT02S","GPIO":[0,0,0,0,320,576,0,0,224,160,0,0,0,1],"FLAG":0,"BASE":18} MoesHouse RF433 3 Gang {"NAME":"WS-EUB3-WR","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} MoKo Scene Life {"NAME":"Moko Smart Swi","GPIO":[576,0,0,0,418,417,0,0,320,0,416,224,0,0],"FLAG":0,"BASE":18} -MoKo Smart Life {"NAME":"Moko Switch","GPIO":[321,0,0,32,224,0,0,0,0,0,288,0,0,0],"FLAG":0,"BASE":59} +MoKo Smart Life {"NAME":"Moko Switch (Single)","GPIO":[544,0,0,32,224,0,0,0,0,0,320,0,0,0],"FLAG":0,"BASE":59} NaamaSmart KS602 {"NAME":"KS-602","GPIO":[32,0,0,0,0,0,0,0,224,576,0,0,0,0],"FLAG":0,"BASE":18} Nedis Dual {"NAME":"SM-SW102U-2","GPIO":[576,0,0,33,225,0,0,0,32,224,0,0,0,4704],"FLAG":0,"BASE":18} Nexete DS-123 {"NAME":"DS-123","GPIO":[544,321,1,32,224,33,0,0,1,225,320,1,1,0],"FLAG":0,"BASE":18} @@ -1873,7 +1839,6 @@ ZUCZUG 3 Gang {"NAME":"2ph105626a x3","GPIO":[0,288,0,32,34,33,0, ``` ## Temperature Sensor - ``` DS18B20 ESP01 DIY {"NAME":"ESP-01-01S-DS18B20-v1.0","GPIO":[1,1,1312,1,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} ESP01 DHT11 DIY {"NAME":"ESP01S DHT11","GPIO":[1,1,1184,1,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} @@ -1882,7 +1847,6 @@ Shelly Add-on {"NAME":"Shelly 1 Temp ","GPIO":[1344,0,0,1312,224, ``` ## Valve - ``` Garden Water Timer BQ05 {"NAME":"BQ05","GPIO":[32,0,0,0,0,0,0,0,224,544,0,0,0,4704],"FLAG":0,"BASE":18} Hoenyzy DN20 3/4 {"NAME":"DN20 Valve","GPIO":[0,0,0,0,0,0,0,0,32,224,0,0,0,0],"FLAG":0,"BASE":18} @@ -1893,7 +1857,6 @@ Owfeel EN71 {"NAME":"SmartValve","GPIO":[224,0,0,0,0,0,0,0,32,2 ``` ## Wall Outlet - ``` Aseer THWFS01 {"NAME":"ASEER-THWFS01","GPIO":[320,33,544,323,2720,2656,0,0,2624,225,321,224,32,0],"FLAG":0,"BASE":18} Bestten LO-2-W {"NAME":"BESTTEN LO-2-W","GPIO":[0,0,0,0,576,32,0,0,224,0,0,0,0,0],"FLAG":0,"BASE":18} @@ -1926,14 +1889,12 @@ Vigica VGSPK00815 {"NAME":"VIGICA outlet","GPIO":[32,1,1,1,1,225,33,1 ``` ## Water Sensor - ``` W06 {"NAME":"W06 Water Sensor","GPIO":[0,3200,0,3232,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} Y09 {"NAME":"Y09","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} ``` ## Zigbee Bridge - ``` Sonoff ZBBridge {"NAME":"Sonoff ZbBridge","GPIO":[320,3552,0,3584,5312,0,0,0,640,576,608,0,32,0],"FLAG":0,"BASE":75} ``` From 056493740bfd131c3ee687222c5866279f12db2c Mon Sep 17 00:00:00 2001 From: Alexander Kabakaev Date: Sat, 12 Dec 2020 10:35:57 +0100 Subject: [PATCH 2/7] show relay state in prometheus metrics --- tasmota/xsns_75_prometheus.ino | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tasmota/xsns_75_prometheus.ino b/tasmota/xsns_75_prometheus.ino index cea6b64ee..503291cd2 100644 --- a/tasmota/xsns_75_prometheus.ino +++ b/tasmota/xsns_75_prometheus.ino @@ -75,6 +75,11 @@ void HandleMetrics(void) WSContentSend_P(PSTR("# TYPE energy_power_kilowatts_total counter\nenergy_power_kilowatts_total %s\n"), parameter); #endif + for (uint32_t device = 0; device < TasmotaGlobal.devices_present; device++) { + power_t mask = 1 << device; + WSContentSend_P(PSTR("# TYPE relay%d_state gauge\nrelay%d_state %d\n"), device+1, device+1, (TasmotaGlobal.power & mask)); + } + /* // Alternative method using the complete sensor JSON data // For prometheus it may need to be decoded to # TYPE messages From 1558f0c7315ffc69bc251d44207db86a42d0c24e Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sat, 12 Dec 2020 19:05:47 +0100 Subject: [PATCH 3/7] Zigbee add visual map of network --- CHANGELOG.md | 1 + tasmota/xdrv_01_webserver.ino | 12 ++ tasmota/xdrv_23_zigbee_1_headers.ino | 4 + tasmota/xdrv_23_zigbee_2_devices.ino | 6 + ...no => xdrv_23_zigbee_7_0_statemachine.ino} | 0 tasmota/xdrv_23_zigbee_7_5_map.ino | 180 ++++++++++++++++++ tasmota/xdrv_23_zigbee_8_parsers.ino | 25 ++- tasmota/xdrv_23_zigbee_A_impl.ino | 109 +++++++++-- 8 files changed, 323 insertions(+), 14 deletions(-) rename tasmota/{xdrv_23_zigbee_7_statemachine.ino => xdrv_23_zigbee_7_0_statemachine.ino} (100%) create mode 100644 tasmota/xdrv_23_zigbee_7_5_map.ino diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a64d5f62..9a9ce16b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. - Zigbee better support for Tuya Protocol (#10074) - Support for SPI connected MFRC522 13.56MHz rfid card reader (#9916) - Letsencrypt R3 in addition to X3 CA (#10086) +- Zigbee add visual map of network ### Breaking Changed - KNX DPT9 (16-bit float) to DPT14 (32-bit float) by Adrian Scillato (#9811, #9888) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index e9ae48e78..7e74f2e89 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1661,6 +1661,18 @@ bool HandleRootStatusRefresh(void) ExecuteWebCommand(svalue, SRC_WEBGUI); } #endif // USE_SONOFF_RF +#ifdef USE_ZIGBEE + WebGetArg("zbj", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR("ZbPermitJoin")); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + WebGetArg("zbr", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR("ZbMap")); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } +#endif // USE_ZIGBEE WSContentBegin(200, CT_HTML); WSContentSend_P(PSTR("{t}")); XsnsCall(FUNC_WEB_SENSOR); diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino index 04448711c..33ca5381e 100644 --- a/tasmota/xdrv_23_zigbee_1_headers.ino +++ b/tasmota/xdrv_23_zigbee_1_headers.ino @@ -90,6 +90,10 @@ public: bool recv_until = false; // ignore all messages until the received frame fully matches bool eeprom_present = false; // is the ZBBridge EEPROM present? bool eeprom_ready = false; // is the ZBBridge EEPROM formatted and ready? + // Zigbee mapping + bool mapping_in_progress = false; // is there a mapping in progress + bool mapping_ready = false; // do we have mapping information ready + uint32_t mapping_end_time = 0; uint8_t on_error_goto = ZIGBEE_LABEL_ABORT; // on error goto label, 99 default to abort uint8_t on_timeout_goto = ZIGBEE_LABEL_ABORT; // on timeout goto label, 99 default to abort diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index 3c6137bc5..8532e5da8 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -717,6 +717,7 @@ public: // sequence number for Zigbee frames uint16_t shortaddr; // unique key if not null, or unspecified if null uint8_t seqNumber; + bool is_router; // flag used by ZbMap to distibguish routers from end-devices bool hidden; bool reachable; // Light information for Hue integration integration, last known values @@ -742,6 +743,7 @@ public: attr_list(), shortaddr(_shortaddr), seqNumber(0), + is_router(false), hidden(false), reachable(false), data(), @@ -768,6 +770,10 @@ public: inline bool getReachable(void) const { return reachable; } inline bool getPower(uint8_t ep =0) const; + inline bool isRouter(void) const { return is_router; } + inline bool isCoordinator(void) const { return 0x0000 == shortaddr; } + inline void setRouter(bool router) { is_router = router; } + inline void setLQI(uint8_t _lqi) { lqi = _lqi; } inline void setBatteryPercent(uint8_t bp) { batterypercent = bp; } diff --git a/tasmota/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_0_statemachine.ino similarity index 100% rename from tasmota/xdrv_23_zigbee_7_statemachine.ino rename to tasmota/xdrv_23_zigbee_7_0_statemachine.ino diff --git a/tasmota/xdrv_23_zigbee_7_5_map.ino b/tasmota/xdrv_23_zigbee_7_5_map.ino new file mode 100644 index 000000000..17c79d5e5 --- /dev/null +++ b/tasmota/xdrv_23_zigbee_7_5_map.ino @@ -0,0 +1,180 @@ +/* + xdrv_23_zigbee_7_5_map.ino - zigbee support for Tasmota + + Copyright (C) 2020 Theo Arends and Stephan Hadinger + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_ZIGBEE + +class Z_Mapper_Edge { +public: + + // enum Edge_Type : uint8_t { + // Unknown = 0x00, + // Parent = 0x01, // node_1 is parent of node_2 + // Child = 0x02, // node_1 is child of node_2 + // Sibling = 0x03, // both nodes are siblings + // }; + + Z_Mapper_Edge(void) : + node_1(BAD_SHORTADDR), + node_2(BAD_SHORTADDR), + lqi(0x00) + // edge_type(Unknown) + {} + + // Z_Mapper_Edge(uint16_t node_a, uint16_t node_b, uint8_t _lqi, Edge_Type _type) : + Z_Mapper_Edge(uint16_t node_a, uint16_t node_b, uint8_t _lqi) : + node_1(BAD_SHORTADDR), + node_2(BAD_SHORTADDR), + lqi(_lqi) + // edge_type(_type) + { + setEdges(node_a, node_b); + } + + void setEdges(uint16_t node_a, uint16_t node_b); + + bool sameEdge(const Z_Mapper_Edge & edge2) const; + + // Edge_Type Z_Mapper_Edge_Type_Reverse(Edge_Type _type) { + // switch (_type) { + // case Parent: return Child; + // case Child: return Parent; + // default: return _type; + // } + // } + + // we always orientate the edge from with shortaddresses in ascending order + // invariant: node_1 < node_2 + uint16_t node_1; + uint16_t node_2; + + uint8_t lqi; + // Edge_Type edge_type; +}; + +// +// Handles the mapping of Zigbee devices +// +class Z_Mapper { +public: + Z_Mapper(void) : + edges() + {} + + void reset(void) { edges.reset(); } + + Z_Mapper_Edge & findEdge(const Z_Mapper_Edge & edge2); + bool addEdge(const Z_Mapper_Edge & edge2); + + void dumpInternals(void) const; + + LList edges; + +}; + +// global +Z_Mapper zigbee_mapper; + +/*********************************************************************************************\ + * Implementation for Z_Mapper_Edge +\*********************************************************************************************/ +void Z_Mapper_Edge::setEdges(uint16_t node_a, uint16_t node_b) { + if (node_a < node_b) { + node_1 = node_a; + node_2 = node_b; + } else if (node_a > node_b) { + node_1 = node_b; + node_2 = node_a; + } else { + // do nothing + } +} + +bool Z_Mapper_Edge::sameEdge(const Z_Mapper_Edge & edge2) const { + return (node_1 == edge2.node_1) && (node_2 == edge2.node_2); +} + +/*********************************************************************************************\ + * Implementation for Z_Mapper +\*********************************************************************************************/ +Z_Mapper_Edge & Z_Mapper::findEdge(const Z_Mapper_Edge & edge2) { + if ((edge2.node_1 == BAD_SHORTADDR) || (edge2.node_2 == BAD_SHORTADDR)) { return *(Z_Mapper_Edge*)nullptr; } + for (auto & edge : edges) { + if (edge2.sameEdge(edge)) { + return edge; + } + } + return *(Z_Mapper_Edge*)nullptr; +} + +bool Z_Mapper::addEdge(const Z_Mapper_Edge & edge2) { + if ((edge2.node_1 == BAD_SHORTADDR) || (edge2.node_2 == BAD_SHORTADDR)) { return false; } + Z_Mapper_Edge & cur_edge = findEdge(edge2); + if (&cur_edge == nullptr) { + edges.addHead(edge2); + } else { + //upgrade fields + if (edge2.lqi > cur_edge.lqi) { + cur_edge.lqi = edge2.lqi; + } + // if (cur_edge.edge_type == Z_Mapper_Edge::Unknown) { + // cur_edge.edge_type = edge2.edge_type; + // } else if ((edge2.edge_type == Z_Mapper_Edge::Parent) || (edge2.edge_type == Z_Mapper_Edge::Child)) { + // // Parent or Child always has priority over Sibling + // cur_edge.edge_type = edge2.edge_type; + // } + } + return true; +} + +void Z_Mapper::dumpInternals(void) const { + WSContentSend_P(PSTR("nodes:[" "{id:\"0x0000\",label:\"Coordinator\",group:\"o\",title:\"0x0000\"}")); + for (const auto & device : zigbee_devices.getDevices()) { + WSContentSend_P(PSTR(",{id:\"0x%04X\",group:\"%c\",title:\"0x%04X\",label:\""), + device.shortaddr, device.isRouter() ? 'r' : 'e', device.shortaddr); + + const char *fname = device.friendlyName; + if (fname != nullptr) { + WSContentSend_P(PSTR("%s"), fname); + } else { + WSContentSend_P(PSTR("0x%04X"), device.shortaddr); + } + WSContentSend_P("\"}"); + } + WSContentSend_P(PSTR("],")); + + WSContentSend_P(PSTR("edges:[")); + for (auto & edge : edges) { + uint32_t lqi_color = 0x000; + // if (edge.lqi >= 192) { + // lqi_color = 0x364; + // } else if (edge.lqi >= 128) { + // lqi_color = 0x346; + // } else if (edge.lqi > 0) { + // lqi_color = 0xd56; + // } + char hex[8]; + snprintf(hex, sizeof(hex), PSTR("%d"), edge.lqi); + + WSContentSend_P("{from:\"0x%04X\",to:\"0x%04X\",label:\"%s\",color:\"#%03X\"},", + edge.node_1, edge.node_2, (edge.lqi > 0) ? hex : "", lqi_color); + } + WSContentSend_P(PSTR("],")); +} + +#endif // USE_ZIGBEE diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index f9c8019b9..d97aa8335 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -229,7 +229,7 @@ void Z_Send_State_or_Map(uint16_t shortaddr, uint8_t index, uint16_t zdo_cmd) { // This callback is registered to send ZbMap(s) to each device one at a time void Z_Map(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { if (BAD_SHORTADDR != shortaddr) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "sending `ZnMap 0x%04X`"), shortaddr); + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "sending `ZbMap 0x%04X`"), shortaddr); #ifdef USE_ZIGBEE_ZNP Z_Send_State_or_Map(shortaddr, value, ZDO_MGMT_LQI_REQ); #endif // USE_ZIGBEE_ZNP @@ -238,6 +238,8 @@ void Z_Map(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t end #endif // USE_ZIGBEE_EZSP } else { AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "ZbMap done")); + zigbee.mapping_in_progress = false; + zigbee.mapping_ready = true; } } /*********************************************************************************************\ @@ -1110,6 +1112,27 @@ int32_t Z_Mgmt_Lqi_Bind_Rsp(int32_t res, const class SBuffer &buf, boolean lqi) TrueFalseNull(m_permitjoin & 0x02), m_depth, m_lqi); + + // detect any router + Z_Device & device = zigbee_devices.findShortAddr(m_shortaddr); + if (device.valid()) { + if ((m_dev_type & 0x03) == 1) { // it is a router + device.setRouter(true); + } + } + + // Add information to zigbee mapper + // Z_Mapper_Edge::Edge_Type edge_type; + // switch ((m_dev_type & 0x70) >> 4) { + // case 0: edge_type = Z_Mapper_Edge::Parent; break; + // case 1: edge_type = Z_Mapper_Edge::Child; break; + // case 2: edge_type = Z_Mapper_Edge::Sibling; break; + // default: edge_type = Z_Mapper_Edge::Unknown; break; + + // } + // Z_Mapper_Edge edge(m_shortaddr, shortaddr, m_lqi, edge_type); + Z_Mapper_Edge edge(m_shortaddr, shortaddr, m_lqi); + zigbee_mapper.addEdge(edge); } ResponseAppend_P(PSTR("]}}")); diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index 1b3aad1c7..f7d6fbdc7 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -1052,6 +1052,26 @@ void CmndZbBindState(void) { CmndZbBindState_or_Map(false); } +void ZigbeeMapAllDevices(void) { + // we can't abort a mapping in progress + if (zigbee.mapping_in_progress) { return; } + // defer sending ZbMap to each device + zigbee_mapper.reset(); // clear all data in Zigbee mapper + + const static uint32_t DELAY_ZBMAP = 2000; // wait for 1s between commands + uint32_t wait_ms = DELAY_ZBMAP; + zigbee.mapping_in_progress = true; // mark mapping in progress + + zigbee_devices.setTimer(0x0000, 0, 0 /*wait_ms*/, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map); + for (const auto & device : zigbee_devices.getDevices()) { + zigbee_devices.setTimer(device.shortaddr, 0, wait_ms, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map); + wait_ms += DELAY_ZBMAP; + } + wait_ms += DELAY_ZBMAP*2; + zigbee_devices.setTimer(BAD_SHORTADDR, 0, wait_ms, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map); + zigbee.mapping_end_time = wait_ms + millis(); +} + // // Command `ZbMap` // `ZbMap` as index if it does not fit. If default, `1` starts at the beginning @@ -1061,15 +1081,7 @@ void CmndZbMap(void) { RemoveSpace(XdrvMailbox.data); if (strlen(XdrvMailbox.data) == 0) { - // defer sending ZbMap to each device - const static uint32_t DELAY_ZBMAP = 2000; // wait for 1s between commands - uint32_t wait_ms = DELAY_ZBMAP; - zigbee_devices.setTimer(0x0000, 0, 0 /*wait_ms*/, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map); - for (const auto & device : zigbee_devices.getDevices()) { - zigbee_devices.setTimer(device.shortaddr, 0, wait_ms, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map); - wait_ms += DELAY_ZBMAP; - } - zigbee_devices.setTimer(BAD_SHORTADDR, 0, wait_ms, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map); + ZigbeeMapAllDevices(); ResponseCmndDone(); } else { CmndZbBindState_or_Map(true); @@ -1317,8 +1329,8 @@ void CmndZbSave(void) { case -10: { // reinit EEPROM ZFS::erase(); - break; } + break; #endif default: saveZigbeeDevices(); @@ -1698,6 +1710,16 @@ extern "C" { } } // extern "C" +#define WEB_HANDLE_ZB_MAP "Zigbee Map" +#define WEB_HANDLE_ZB_PERMIT_JOIN "Zigbee Permit Join" +#define WEB_HANDLE_ZB_MAP_REFRESH "Zigbee Map Refresh" +const char HTTP_BTN_ZB_BUTTONS[] PROGMEM = + "" + "

" + "
"; +const char HTTP_AUTO_REFRESH_PAGE[] PROGMEM = ""; +const char HTTP_BTN_ZB_MAP_REFRESH[] PROGMEM = "

"; + void ZigbeeShow(bool json) { if (json) { @@ -1879,11 +1901,67 @@ void ZigbeeShow(bool json) } } - WSContentSend_P(PSTR("{t}")); // Terminate current multi column table and open new table + WSContentSend_P(PSTR("{t}

")); // Terminate current multi column table and open new table + if (zigbee.permit_end_time) { + // PermitJoin in progress + WSContentSend_P(PSTR("

[ Devices allowed to join ]

")); // Terminate current multi column table and open new table + } #endif } } +// Web handler to refresh the map, the redirect to show map +void ZigbeeMapRefresh(void) { + if ((!zigbee.init_phase) && (!zigbee.mapping_in_progress)) { + ZigbeeMapAllDevices(); + } + Webserver->sendHeader("Location","/zbm"); // Add a header to respond with a new location for the browser to go to the home page again + Webserver->send(302); +} + +// Display a graphical representation of the Zigbee map using vis.js network +void ZigbeeShowMap(void) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Zigbee Mapper")); + + // if no map, then launch a new mapping + if ((!zigbee.init_phase) && (!zigbee.mapping_ready) && (!zigbee.mapping_in_progress)) { + ZigbeeMapAllDevices(); + } + + WSContentStart_P(PSTR("Tasmota Zigbee Mapping")); + WSContentSendStyle(); + + if (zigbee.init_phase) { + WSContentSend_P(PSTR("Zigbee not started")); + } else if (zigbee.mapping_in_progress) { + int32_t mapping_remaining = 1 + (zigbee.mapping_end_time - millis()) / 1000; + if (mapping_remaining < 0) { mapping_remaining = 0; } + WSContentSend_P(PSTR("Mapping in progress (%d s. remaining)"), mapping_remaining); + WSContentSend_P(HTTP_AUTO_REFRESH_PAGE); + } else if (!zigbee.mapping_ready) { + WSContentSend_P(PSTR("No mapping")); + } else { + WSContentSend_P(PSTR( + "" + "
" + "" + )); + WSContentSend_P(HTTP_BTN_ZB_MAP_REFRESH); + } + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -1920,12 +1998,17 @@ bool Xdrv23(uint8_t function) case FUNC_WEB_SENSOR: ZigbeeShow(false); break; -#ifdef USE_ZIGBEE_EZSP // GUI xmodem case FUNC_WEB_ADD_HANDLER: +#ifdef USE_ZIGBEE_EZSP WebServer_on(PSTR("/" WEB_HANDLE_ZIGBEE_XFER), HandleZigbeeXfer); - break; #endif // USE_ZIGBEE_EZSP + WebServer_on(PSTR("/zbm"), ZigbeeShowMap, HTTP_GET); // add web handler for Zigbee map + WebServer_on(PSTR("/zbr"), ZigbeeMapRefresh, HTTP_GET); // add web handler for Zigbee map refresh + break; + case FUNC_WEB_ADD_MAIN_BUTTON: + WSContentSend_P(HTTP_BTN_ZB_BUTTONS); + break; #endif // USE_WEBSERVER case FUNC_PRE_INIT: ZigbeeInit(); From 5f1a24370fd8ac24cff01975a9fa50e701acef6e Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Sat, 12 Dec 2020 13:32:14 -0600 Subject: [PATCH 4/7] Support power tap and hold; increase hold from .5 to .75 seconds --- tasmota/xdrv_35_pwm_dimmer.ino | 54 ++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index 823055c83..dc9fe0bfe 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -76,6 +76,7 @@ bool tap_handled = false; bool invert_power_button_bri_direction = false; bool button_pressed[3] = { false, false, false }; bool button_held[3]; +bool button_unprocessed[3] = { false, false, false }; #ifdef USE_PWM_DIMMER_REMOTE struct remote_pwm_dimmer remote_pwm_dimmers[MAX_PWM_DIMMER_KEYS]; struct remote_pwm_dimmer * active_remote_pwm_dimmer; @@ -284,8 +285,16 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed) if (pressed) { uint32_t now = millis(); - // If this is about the power button, ... - if (is_power_button) { + // If the button was pressed and released but was not processed by support_button because the + // button interval had not elapsed, + if (button_unprocessed[button_index]) { + mqtt_trigger = 5; + if (!active_remote_pwm_dimmer) mqtt_trigger += button_index; + button_hold_time[button_index] = now + 750; + } + + // Otherwise, if this is about the power button, ... + else if (is_power_button) { // If we're not ignoring the power button and no other buttons are pressed, ... if (!ignore_power_button && buttons_pressed == 1) { @@ -325,8 +334,8 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed) // If the up or down button was tapped while holding the power button before this, handle // the operation below. if (button_tapped) { - handle_tap = true; - button_hold_time[button_index] = now + 500; + handle_tap = ignore_power_button = true; + button_hold_time[button_index] = now + 750; } // Otherwise, if the power is on and remote mode is enabled, adjust the brightness. Set the @@ -568,7 +577,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed) // If the up or down button was tapped while holding the power button and the up or down button // is being held or was just released after not being held, handle the operation. if (handle_tap) { - ignore_power_button = tap_handled = true; + tap_handled = true; // If the down button was tapped while holding the power button, send a device group update to // select the previous/next fixed color. @@ -591,9 +600,10 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed) #endif // USE_DEVICE_GROUPS ; } - // If the down button was tapped while holding the power button, publish an MQTT Event Trigger#. + // If the up button was tapped while holding the power button, publish an MQTT Event Trigger#. else { - mqtt_trigger = (is_down_button ? 3 : 4); + mqtt_trigger = 3; + if (is_down_button) mqtt_trigger = 4; } } @@ -739,7 +749,15 @@ bool Xdrv35(uint8_t function) // increment the buttons pressed count. if (!button_pressed[button_index]) { button_pressed[button_index] = true; - button_hold_time[button_index] = now + (button_index == power_button_index ? 500 : 250); + uint32_t hold_delay = 250; + if (button_index == power_button_index) { +#ifdef USE_PWM_DIMMER_REMOTE + if (!(active_remote_pwm_dimmer ? active_remote_pwm_dimmer->power_on : TasmotaGlobal.power)) hold_delay = 500; +#else // USE_PWM_DIMMER_REMOTE + if (!TasmotaGlobal.power) hold_delay = 500; +#endif // USE_PWM_DIMMER_REMOTE + } + button_hold_time[button_index] = now + hold_delay; buttons_pressed++; if (buttons_pressed > 1) multibutton_in_progress = true; @@ -796,6 +814,16 @@ bool Xdrv35(uint8_t function) // Set a timer so FUNC_ANY_KEY ignores the button if support_button winds up sending a // key because of this. ignore_any_key_time = now + 500; + + // If a multi-button operation is in progress or the button was pressed, released and + // then held, tell support_button that we've handled it. + result = true; + Button.press_counter[button_index] = 0; + if (buttons_pressed == 0) multibutton_in_progress = false; + button_unprocessed[button_index] = false; + } + else { + button_unprocessed[button_index] = true; } // If the power button was just released, clear the flags associated with it. @@ -806,12 +834,6 @@ bool Xdrv35(uint8_t function) } button_held[button_index] = false; } - - // If a multi-button operation is in progress, tell support_button that we've handled it. - if (multibutton_in_progress) { - result = true; - if (buttons_pressed == 0) multibutton_in_progress = false; - } } break; @@ -819,7 +841,9 @@ bool Xdrv35(uint8_t function) { uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; // 0 = Off, 1 = On, 2 = Toggle, 3 = Hold, 10,11,12,13 and 14 for Button Multipress if ((state == 2 || state == 10) && ignore_any_key_time < millis()) { - PWMDimmerHandleButton((XdrvMailbox.payload & 0xFF) - 1, false); + uint32_t button_index = (XdrvMailbox.payload & 0xFF) - 1; + button_unprocessed[button_index] = false; + PWMDimmerHandleButton(button_index, false); } } break; From e1391acaba7cc8fdab34c350544583adc46de01f Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Sat, 12 Dec 2020 15:09:49 -0600 Subject: [PATCH 5/7] Wrap remote dimmer reference in ifdef --- tasmota/xdrv_35_pwm_dimmer.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index dc9fe0bfe..c54d071f1 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -289,7 +289,9 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed) // button interval had not elapsed, if (button_unprocessed[button_index]) { mqtt_trigger = 5; +#ifdef USE_PWM_DIMMER_REMOTE if (!active_remote_pwm_dimmer) mqtt_trigger += button_index; +#endif // USE_PWM_DIMMER_REMOTE button_hold_time[button_index] = now + 750; } From fe3bef037c284ef2c2cf9b2a8dc2f0f2009eb0fc Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sun, 13 Dec 2020 07:31:10 +0100 Subject: [PATCH 6/7] fix pin overrides --- tasmota/xdrv_42_i2s_audio.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_42_i2s_audio.ino b/tasmota/xdrv_42_i2s_audio.ino index 568989fb3..6f82b63bc 100644 --- a/tasmota/xdrv_42_i2s_audio.ino +++ b/tasmota/xdrv_42_i2s_audio.ino @@ -90,16 +90,16 @@ AudioGeneratorTalkie *talkie = nullptr; #define TWATCH_DAC_IIS_DOUT 3 #endif // ESP8266 #ifdef ESP32 -#undef TWATCH_DAC_IIS_BCK -#undef TWATCH_DAC_IIS_WS -#undef TWATCH_DAC_IIS_DOUT #ifndef TWATCH_DAC_IIS_BCK +#undef TWATCH_DAC_IIS_BCK #define TWATCH_DAC_IIS_BCK 26 #endif #ifndef TWATCH_DAC_IIS_WS +#undef TWATCH_DAC_IIS_WS #define TWATCH_DAC_IIS_WS 25 #endif #ifndef TWATCH_DAC_IIS_DOUT +#undef TWATCH_DAC_IIS_DOUT #define TWATCH_DAC_IIS_DOUT 33 #endif #endif // ESP32 From c50256f2b30140d7d88d2f9ef134e113c1932fc6 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sun, 13 Dec 2020 07:32:09 +0100 Subject: [PATCH 7/7] add pwm and alt_eeprom --- tasmota/xdrv_10_scripter.ino | 186 +++++++++++++++++++++++++++++------ 1 file changed, 157 insertions(+), 29 deletions(-) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 75bffaec3..d2049af81 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -108,7 +108,11 @@ uint32_t DecodeLightId(uint32_t hue_id); #pragma message "script 24c256 file option used" #else //#warning "EEP_SCRIPT_SIZE also needs USE_24C256" +#if EEP_SCRIPT_SIZE==SPI_FLASH_SEC_SIZE #pragma message "internal eeprom script buffer used" +#else +#pragma message "internal compressed eeprom script buffer used" +#endif //#define USE_24C256 #endif #endif // EEP_SCRIPT_SIZE @@ -119,7 +123,7 @@ uint32_t DecodeLightId(uint32_t hue_id); #endif // USE_UNISHOX_COMPRESSION -#ifdef USE_SCRIPT_COMPRESSION +//#ifdef USE_SCRIPT_COMPRESSION #include #define SCRIPT_COMPRESS compressor.unishox_compress @@ -127,7 +131,8 @@ uint32_t DecodeLightId(uint32_t hue_id); #ifndef UNISHOXRSIZE #define UNISHOXRSIZE 2560 #endif -#endif // USE_SCRIPT_COMPRESSION + +//#endif // USE_SCRIPT_COMPRESSION #ifndef STASK_PRIO #define STASK_PRIO 1 @@ -158,6 +163,51 @@ void Script_ticker4_end(void) { } #endif +// EEPROM MACROS +// i2c eeprom + +#if defined(ALT_EEPROM) && !defined(ESP32) +#undef EEP_WRITE +#undef EEP_READ +#undef EEP_INIT +#define EEP_WRITE(A,B,C) alt_eeprom_writeBytes(A, B, (uint8_t*)C); +#define EEP_READ(A,B,C) alt_eeprom_readBytes(A, B, (uint8_t*)C); +#define EEP_INIT(A) alt_eeprom_init(A) + +#if EEP_SCRIPT_SIZE>6500 +#undef EEP_SCRIPT_SIZE +#define EEP_SCRIPT_SIZE 6500 +#endif + +uint32_t eeprom_block; + +// these support only one 4 k block below EEPROM this steals 4k of application area +uint32_t alt_eeprom_init(uint32_t size) { + //EEPROM.begin(size); + eeprom_block = (uint32_t)&_FS_end - 0x40200000 - SPI_FLASH_SEC_SIZE; + return 1; +} + +void alt_eeprom_writeBytes(uint32_t adr, uint32_t len, uint8_t *buf) { + uint32_t *lwp=(uint32_t*)buf; + ESP.flashEraseSector(eeprom_block / SPI_FLASH_SEC_SIZE); + ESP.flashWrite(eeprom_block , lwp, SPI_FLASH_SEC_SIZE); +} + +void alt_eeprom_readBytes(uint32_t adr, uint32_t len, uint8_t *buf) { + uint32_t *lwp=(uint32_t*)buf; + ESP.flashRead(eeprom_block , lwp, SPI_FLASH_SEC_SIZE); +} +#else +#undef EEP_WRITE +#undef EEP_READ +#undef EEP_INIT +#define EEP_WRITE(A,B,C) eeprom_writeBytes(A, B, (uint8_t*)C); +#define EEP_READ(A,B,C) eeprom_readBytes(A, B, (uint8_t*)C); +#define EEP_INIT(A) eeprom_init(A) +#endif // ALT_EEPROM + + #if defined(LITTLEFS_SCRIPT_SIZE) || (USE_SCRIPT_FATFS==-1) #ifdef ESP32 @@ -516,10 +566,7 @@ void RulesTeleperiod(void) { if (bitRead(Settings.rule_enabled, 0) && TasmotaGlobal.mqtt_data[0]) Run_Scripter(">T", 2, TasmotaGlobal.mqtt_data); } -// EEPROM MACROS -// i2c eeprom -#define EEP_WRITE(A,B,C) eeprom_writeBytes(A, B, (uint8_t*)C); -#define EEP_READ(A,B,C) eeprom_readBytes(A, B, (uint8_t*)C); + #define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++; @@ -3734,22 +3781,45 @@ void esp32_beep(int32_t freq ,uint32_t len) { xTimerChangePeriod( beep_th, ticks, 10); } } +#endif // ESP32 -void esp32_pwm(int32_t value) { +uint8_t pwmpin[5]; + +void esp_pwm(int32_t value, uint32 freq, uint32_t channel) { + if (channel < 1 || channel > 3) channel = 1; +#ifdef ESP32 + channel+=7; if (value < 0) { if (value <= -64) value = 0; - ledcSetup(7, 4000, 10); - ledcAttachPin(-value, 7); - ledcWrite(7, 0); + // set range to 10 bit + ledcSetup(channel, freq, 10); + ledcAttachPin(-value, channel); + ledcWrite(channel, 0); } else { if (value > 1023) { value = 1023; } - ledcWrite(7, value); + ledcWrite(channel, value); } +#else + // esp8266 default to range 0-1023 + channel-=1; + if (value < 0) { + if (value <= -64) value = 0; + pwmpin[channel] = -value; + pinMode(pwmpin[channel], OUTPUT); + analogWriteFreq(freq); + analogWrite(pwmpin[channel], 0); + } else { + if (value > 1023) { + value = 1023; + } + analogWrite(pwmpin[channel],value); + } +#endif // ESP32 } -#endif // ESP32 + //#define IFTHEN_DEBUG @@ -4164,14 +4234,34 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonParserObject *jo) { lp++; goto next_line; } - else if (!strncmp(lp, "pwm(", 4)) { - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); +#endif //ESP32 + + else if (!strncmp(lp, "pwm", 3)) { + lp += 3; + uint8_t channel = 1; + if (*(lp+1)=='(') { + channel = *lp & 7; + if (channel > 5) { + channel = 5; + } + lp += 2; + } else { + if (*lp=='(') { + lp++; + } else { + goto next_line; + } + } + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); SCRIPT_SKIP_SPACES - esp32_pwm(fvar); + float fvar1=4000; + if (*lp!=')') { + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); + } + esp_pwm(fvar, fvar1, channel); lp++; goto next_line; } -#endif //ESP32 else if (!strncmp(lp, "wcs", 3)) { lp+=4; // skip one space after cmd @@ -5116,7 +5206,16 @@ void SaveScript(void) { #ifdef EEP_SCRIPT_SIZE if (glob_script_mem.flags&1) { +#if EEP_SCRIPT_SIZE==SPI_FLASH_SEC_SIZE EEP_WRITE(0, EEP_SCRIPT_SIZE, glob_script_mem.script_ram); +#else + char *ucs; + ucs = (char*)calloc(SPI_FLASH_SEC_SIZE + 4, 1); + if (!script_compress(ucs,EEP_SCRIPT_SIZE-1)) { + EEP_WRITE(0, EEP_SCRIPT_SIZE, ucs); + } + if (ucs) free(ucs); +#endif } #endif // EEP_SCRIPT_SIZE @@ -5198,6 +5297,21 @@ void ScriptSaveSettings(void) { SaveScriptEnd(); } +// +uint32_t script_compress(char *dest, uint32_t size) { + //AddLog_P(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram)); + uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), dest, size); + if (len_compressed > 0) { + dest[len_compressed] = 0; + AddLog_P(LOG_LEVEL_INFO,PSTR("script compressed to %d bytes = %d %%"),len_compressed,len_compressed * 100 / strlen(glob_script_mem.script_ram)); + return 0; + } else { + AddLog_P(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed); + return 1; + } +} +//#endif // USE_SCRIPT_COMPRESSION + void SaveScriptEnd(void) { #ifdef USE_SCRIPT_GLOBVARS @@ -5212,20 +5326,11 @@ void SaveScriptEnd(void) { } #ifdef USE_SCRIPT_COMPRESSION - //AddLog_P(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram)); - uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), Settings.rules[0], MAX_SCRIPT_SIZE-1); - if (len_compressed > 0) { - Settings.rules[0][len_compressed] = 0; - AddLog_P(LOG_LEVEL_INFO,PSTR("script compressed to %d bytes = %d %%"),len_compressed,len_compressed * 100 / strlen(glob_script_mem.script_ram)); - } else { - AddLog_P(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed); - } + script_compress(Settings.rules[0],MAX_SCRIPT_SIZE-1); #endif // USE_SCRIPT_COMPRESSION if (bitRead(Settings.rule_enabled, 0)) { - - int16_t res = Init_Scripter(); if (res) { AddLog_P(LOG_LEVEL_INFO, PSTR("script init error: %d"), res); @@ -6990,7 +7095,7 @@ exgc: WSContentSend_PD("['"); char lbl[16]; if (todflg>=0) { - sprintf(lbl, "%d", todflg / divflg); + sprintf(lbl, "%d:%02d", todflg / divflg, (todflg % divflg) * (60 / divflg) ); todflg++; if (todflg >= entries) { todflg = 0; @@ -7395,9 +7500,10 @@ bool Xdrv10(uint8_t function) #endif //USE_BUTTON_EVENT #ifdef EEP_SCRIPT_SIZE - if (eeprom_init(EEP_SCRIPT_SIZE)) { - // found 32kb eeprom + if (EEP_INIT(EEP_SCRIPT_SIZE)) { + // found 32kb eeprom, char *script; +#if EEP_SCRIPT_SIZE==SPI_FLASH_SEC_SIZE script = (char*)calloc(EEP_SCRIPT_SIZE + 4, 1); if (!script) break; glob_script_mem.script_ram = script; @@ -7407,6 +7513,28 @@ bool Xdrv10(uint8_t function) memset(script, EEP_SCRIPT_SIZE, 0); } script[EEP_SCRIPT_SIZE - 1] = 0; +#else + char *ucs; + ucs = (char*)calloc(SPI_FLASH_SEC_SIZE + 4, 1); + if (!ucs) break; + EEP_READ(0, SPI_FLASH_SEC_SIZE, ucs); + if (*ucs==0xff) { + memset(ucs, SPI_FLASH_SEC_SIZE, 0); + } + ucs[SPI_FLASH_SEC_SIZE - 1] = 0; + + script = (char*)calloc(EEP_SCRIPT_SIZE + 4, 1); + if (!script) break; + glob_script_mem.script_ram = script; + glob_script_mem.script_size = EEP_SCRIPT_SIZE; + + int32_t len_decompressed; + len_decompressed = SCRIPT_DECOMPRESS(ucs, strlen(ucs), glob_script_mem.script_ram, glob_script_mem.script_size); + if (len_decompressed>0) glob_script_mem.script_ram[len_decompressed] = 0; + + if (ucs) free(ucs); + +#endif // use rules storage for permanent vars glob_script_mem.script_pram = (uint8_t*)Settings.rules[0]; glob_script_mem.script_pram_size = MAX_SCRIPT_SIZE;