mirror of https://github.com/arendst/Tasmota.git
Merge branch 'development' into pre-release-9.2.0
This commit is contained in:
commit
198ec55473
|
@ -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)
|
||||
|
|
57
TEMPLATES.md
57
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}
|
||||
```
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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("]}}"));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue