Merge branch 'development' into pre-release-9.2.0

This commit is contained in:
Theo Arends 2020-12-13 12:17:35 +01:00
commit 198ec55473
13 changed files with 538 additions and 109 deletions

View File

@ -21,6 +21,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)

View File

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

View File

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

View File

@ -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 <unishox.h>
#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;

View File

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

View File

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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<Z_Mapper_Edge> 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

View File

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

View File

@ -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<x>` 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 =
"<button onclick='la(\"&zbj=1\");'>" WEB_HANDLE_ZB_PERMIT_JOIN "</button>"
"<p></p>"
"<form action='zbm' method='get'><button>" WEB_HANDLE_ZB_MAP "</button></form>";
const char HTTP_AUTO_REFRESH_PAGE[] PROGMEM = "<script>setTimeout(function(){location.reload();},1990);</script>";
const char HTTP_BTN_ZB_MAP_REFRESH[] PROGMEM = "<p></p><form action='zbr' method='get'><button>" WEB_HANDLE_ZB_MAP_REFRESH "</button></form>";
void ZigbeeShow(bool json)
{
if (json) {
@ -1879,11 +1901,67 @@ void ZigbeeShow(bool json)
}
}
WSContentSend_P(PSTR("</table>{t}")); // Terminate current multi column table and open new table
WSContentSend_P(PSTR("</table>{t}<p></p>")); // Terminate current multi column table and open new table
if (zigbee.permit_end_time) {
// PermitJoin in progress
WSContentSend_P(PSTR("<p><b>[ <span style='color:#080;'>Devices allowed to join</span> ]</b></p>")); // 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(
"<script type=\"text/javascript\" src=\"https://unpkg.com/vis-network/standalone/umd/vis-network.min.js\"></script>"
"<div id=\"mynetwork\" style=\"background-color:#fff;width:800px;height:400px;border:1px solid lightgray;resize:both;\"></div>"
"<script type=\"text/javascript\">"
"var container=document.getElementById(\"mynetwork\");"
"var options={groups:{o:{shape:\"circle\",color:\"#d55\"},r:{shape:\"box\",color:\"#fb7\"},e:{shape:\"ellipse\",color:\"#adf\"}}};"
"var data={"
));
zigbee_mapper.dumpInternals();
WSContentSend_P(PSTR(
"};"
"var network=new vis.Network(container,data,options);</script>"
));
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();

View File

@ -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,18 @@ 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;
#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;
}
// 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 +336,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 +579,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 +602,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 +751,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 +816,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 +836,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 +843,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;

View File

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

View File

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