diff --git a/.github/workflows/CI_github_ESP32.yml b/.github/workflows/CI_github_ESP32.yml index cc9af6f19..64fbd39b2 100644 --- a/.github/workflows/CI_github_ESP32.yml +++ b/.github/workflows/CI_github_ESP32.yml @@ -17,8 +17,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32 tasmota32-webcam: @@ -34,8 +33,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-webcam tasmota32-minimal: @@ -51,8 +49,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-minimal tasmota32-lite: runs-on: ubuntu-latest @@ -67,8 +64,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-lite tasmota32-knx: runs-on: ubuntu-latest @@ -83,8 +79,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-knx tasmota32-sensors: @@ -100,8 +95,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-sensors tasmota32-display: runs-on: ubuntu-latest @@ -116,8 +110,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-display tasmota32-ir: runs-on: ubuntu-latest @@ -132,8 +125,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-ir tasmota32-BG: runs-on: ubuntu-latest @@ -148,8 +140,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-BG tasmota32-BR: @@ -165,8 +156,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-BR tasmota32-CN: runs-on: ubuntu-latest @@ -181,8 +171,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-CN tasmota32-CZ: runs-on: ubuntu-latest @@ -197,8 +186,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-CZ tasmota32-DE: runs-on: ubuntu-latest @@ -213,8 +201,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-DE tasmota32-ES: @@ -230,8 +217,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-ES tasmota32-FR: runs-on: ubuntu-latest @@ -246,8 +232,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-FR tasmota32-GR: runs-on: ubuntu-latest @@ -262,8 +247,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-GR tasmota32-HE: runs-on: ubuntu-latest @@ -278,8 +262,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-HE tasmota32-HU: @@ -295,8 +278,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-HU tasmota32-IT: runs-on: ubuntu-latest @@ -311,8 +293,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-IT tasmota32-KO: runs-on: ubuntu-latest @@ -327,8 +308,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-KO tasmota32-NL: runs-on: ubuntu-latest @@ -343,8 +323,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-NL tasmota32-PL: @@ -360,8 +339,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-PL tasmota32-PT: runs-on: ubuntu-latest @@ -376,8 +354,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-PT tasmota32-RO: runs-on: ubuntu-latest @@ -392,8 +369,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-RO tasmota32-RU: runs-on: ubuntu-latest @@ -408,8 +384,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-RU tasmota32-SE: @@ -425,8 +400,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-SE tasmota32-SK: runs-on: ubuntu-latest @@ -441,8 +415,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-SK tasmota32-TR: runs-on: ubuntu-latest @@ -457,8 +430,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-TR tasmota32-TW: runs-on: ubuntu-latest @@ -473,8 +445,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-TW tasmota32-UK: @@ -490,6 +461,5 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-UK diff --git a/.github/workflows/Tasmota_build.yml b/.github/workflows/Tasmota_build.yml index 5d5665715..4a890b89d 100644 --- a/.github/workflows/Tasmota_build.yml +++ b/.github/workflows/Tasmota_build.yml @@ -750,8 +750,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32 - uses: actions/upload-artifact@v2 with: @@ -774,8 +773,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-minimal - uses: actions/upload-artifact@v2 with: @@ -798,8 +796,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-lite - uses: actions/upload-artifact@v2 with: @@ -822,8 +819,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-webcam - uses: actions/upload-artifact@v2 with: @@ -846,8 +842,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-knx - uses: actions/upload-artifact@v2 with: @@ -870,8 +865,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-sensors - uses: actions/upload-artifact@v2 with: @@ -894,8 +888,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-display - uses: actions/upload-artifact@v2 with: @@ -918,8 +911,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-ir - uses: actions/upload-artifact@v2 with: @@ -942,8 +934,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-ircustom - uses: actions/upload-artifact@v2 with: @@ -966,8 +957,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-BG - uses: actions/upload-artifact@v2 with: @@ -990,8 +980,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-BR - uses: actions/upload-artifact@v2 with: @@ -1014,8 +1003,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-CN - uses: actions/upload-artifact@v2 with: @@ -1038,8 +1026,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-CZ - uses: actions/upload-artifact@v2 with: @@ -1062,8 +1049,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-DE - uses: actions/upload-artifact@v2 with: @@ -1086,8 +1072,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-ES - uses: actions/upload-artifact@v2 with: @@ -1110,8 +1095,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-FR - uses: actions/upload-artifact@v2 with: @@ -1134,8 +1118,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-GR - uses: actions/upload-artifact@v2 with: @@ -1158,8 +1141,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-HE - uses: actions/upload-artifact@v2 with: @@ -1182,8 +1164,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-HU - uses: actions/upload-artifact@v2 with: @@ -1206,8 +1187,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-IT - uses: actions/upload-artifact@v2 with: @@ -1230,8 +1210,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-KO - uses: actions/upload-artifact@v2 with: @@ -1254,8 +1233,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-NL - uses: actions/upload-artifact@v2 with: @@ -1278,8 +1256,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-PL - uses: actions/upload-artifact@v2 with: @@ -1302,8 +1279,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-PT - uses: actions/upload-artifact@v2 with: @@ -1326,8 +1302,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-RO - uses: actions/upload-artifact@v2 with: @@ -1350,8 +1325,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-RU - uses: actions/upload-artifact@v2 with: @@ -1374,8 +1348,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-SE - uses: actions/upload-artifact@v2 with: @@ -1398,8 +1371,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-SK - uses: actions/upload-artifact@v2 with: @@ -1422,8 +1394,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-TR - uses: actions/upload-artifact@v2 with: @@ -1446,8 +1417,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-TW - uses: actions/upload-artifact@v2 with: @@ -1470,8 +1440,7 @@ jobs: platformio upgrade --dev platformio update - name: Run PlatformIO - run: | - mv -f platformio_override_sample.ini platformio_override.ini + run: | platformio run -e tasmota32-UK - uses: actions/upload-artifact@v2 with: diff --git a/I2CDEVICES.md b/I2CDEVICES.md index 457116347..5d60c5fb4 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -74,4 +74,5 @@ Index | Define | Driver | Device | Address(es) | Description 49 | USE_VEML6075 | xsns_70 | VEML6075 | 0x10 | UVA/UVB/UVINDEX Sensor 50 | USE_VEML7700 | xsns_71 | VEML7700 | 0x10 | Ambient light intensity sensor 51 | USE_MCP9808 | xsns_72 | MCP9808 | 0x18 - 0x1F | Temperature sensor - 52 | USE_HP303B | xsns_73 | HP303B | 0x76 - 0x77 | Pressure and temperature sensor \ No newline at end of file + 52 | USE_HP303B | xsns_73 | HP303B | 0x76 - 0x77 | Pressure and temperature sensor + 53 | USE_MLX90640 | xdrv_84 | MLX90640 | 0x33 | IR array temperature sensor \ No newline at end of file diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 796435d03..9b3740986 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -47,7 +47,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - **tasmota-zbbridge.bin** = The dedicated Sonoff Zigbee Bridge version. - **tasmota-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**. -Binaries for ESP8266 based devices can be downloaded from http://ota.tasmota.com/tasmota/release. Binaries for ESP32 based devices can be downloaded from http://ota.tasmota.com/tasmota32/release. The base links can be used for OTA upgrades like ``OtaUrl http://ota.tasmota.com/tasmota/release/tasmota.bin`` +The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota/release for ESP8266 or http://ota.tasmota.com/tasmota32/release for ESP32. The links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota/release/tasmota.bin`` [List](MODULES.md) of embedded modules. @@ -59,5 +59,8 @@ Binaries for ESP8266 based devices can be downloaded from http://ota.tasmota.com - Fix energy total counters (#9263, #9266) - Fix crash in ``ZbRestore`` +- Fix reset BMP sensors when executing command ``SaveData`` and define USE_DEEPSLEEP enabled (#9300) - Add new shutter modes (#9244) - Add ``#define USE_MQTT_AWS_IOT_LIGHT`` for password based AWS IoT authentication +- Add Zigbee auto-config when pairing +- Add support for MLX90640 IR array temperature sensor by Christian Baars diff --git a/lib/mlx90640-library/MLX90640_API.cpp b/lib/mlx90640-library/MLX90640_API.cpp new file mode 100644 index 000000000..87d871530 --- /dev/null +++ b/lib/mlx90640-library/MLX90640_API.cpp @@ -0,0 +1,1640 @@ +/** + * @copyright (C) 2017 Melexis N.V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +void ExtractVDDParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractPTATParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractGainParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractTgcParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractResolutionParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractKsTaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractKsToParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractAlphaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractOffsetParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractKtaPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractKvPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractCPParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractCILCParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +int ExtractDeviatingPixels(uint16_t *eeData, paramsMLX90640 *mlx90640); +int CheckAdjacentPixels(uint16_t pix1, uint16_t pix2); +float GetMedian(float *values, int n); +int IsPixelBad(uint16_t pixel,paramsMLX90640 *params); +int ValidateFrameData(uint16_t *frameData); +int ValidateAuxData(uint16_t *auxData); +int MLX90640_I2CRead(uint8_t addr, uint32_t reg, uint16_t len, uint16_t *reg_data); +int MLX90640_I2CWrite(uint8_t _deviceAddress, unsigned int writeAddress, uint16_t data); + +// I2C +#define I2C_BUFFER_LENGTH 128 + +int MLX90640_I2CRead(uint8_t addr, uint32_t reg, uint16_t len, uint16_t *reg_data){ + int bytesRemaining = len * 2; + int dataSpot = 0; //Start at beginning of array + while (bytesRemaining > 0) + { + Wire.beginTransmission(addr); + Wire.write(reg >> 8); //MSB + Wire.write(reg & 0xFF); //LSB + if (Wire.endTransmission(false) != 0) //Do not release bus + { + return (0); //Sensor did not ACK + } + int numberOfBytesToRead = bytesRemaining; + if (numberOfBytesToRead > I2C_BUFFER_LENGTH) numberOfBytesToRead = I2C_BUFFER_LENGTH; + Wire.requestFrom((int)addr, numberOfBytesToRead); + if (Wire.available()) + { + for (uint32_t x = 0 ; x < numberOfBytesToRead / 2; x++) + { + reg_data[dataSpot] = Wire.read() << 8; //MSB + reg_data[dataSpot] |= Wire.read(); //LSB + dataSpot++; + } + } + bytesRemaining -= numberOfBytesToRead; + reg += numberOfBytesToRead / 2; + } + return (0); //Success +} + +int MLX90640_I2CWrite(uint8_t _deviceAddress, unsigned int writeAddress, uint16_t data) +{ + Wire.beginTransmission((uint8_t)_deviceAddress); + Wire.write(writeAddress >> 8); //MSB + Wire.write(writeAddress & 0xFF); //LSB + Wire.write(data >> 8); //MSB + Wire.write(data & 0xFF); //LSB + if (Wire.endTransmission() != 0) + { + //Sensor did not ACK + return (-1); + } + uint16_t dataCheck; + MLX90640_I2CRead(_deviceAddress, writeAddress, 1, &dataCheck); + if (dataCheck != data) + { + return -2; + } + return (0); //Success +} + +int MLX90640_DumpEE(uint8_t slaveAddr, uint16_t *eeData) +{ + return MLX90640_I2CRead(slaveAddr, 0x2400, 832, eeData); +} + +int MLX90640_SynchFrame(uint8_t slaveAddr) +{ + uint16_t dataReady = 0; + uint16_t statusRegister; + int error = 1; + + error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030); + if(error == -1) + { + return error; + } + + while(dataReady == 0) + { + error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister); + if(error != 0) + { + return error; + } + dataReady = statusRegister & 0x0008; + } + + return 0; +} + +// int MLX90640_TriggerMeasurement(uint8_t slaveAddr) // ATM not used in Tasmota +// { +// int error = 1; +// uint16_t ctrlReg; + +// error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &ctrlReg); + +// if ( error != 0) +// { +// return error; +// } + +// ctrlReg |= 0x8000; +// error = MLX90640_I2CWrite(slaveAddr, 0x800D, ctrlReg); + +// if ( error != 0) +// { +// return error; +// } + +// // error = MLX90640_I2CGeneralReset(); + +// // if ( error != 0) +// // { +// // return error; +// // } + +// error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &ctrlReg); + +// if ( error != 0) +// { +// return error; +// } + +// if ((ctrlReg & 0x8000) != 0) +// { +// return -9; +// } + +// return 0; +// } + +int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData) +{ + uint16_t dataReady = 0; + uint16_t controlRegister1; + uint16_t statusRegister; + int error = 1; + uint16_t data[64]; + uint8_t cnt = 0; + + while(dataReady == 0) + { + error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister); + if(error != 0) + { + return error; + } + dataReady = statusRegister & 0x0008; + } + + error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030); + if(error == -1) + { + return error; + } + + error = MLX90640_I2CRead(slaveAddr, 0x0400, 768, frameData); + if(error != 0) + { + return error; + } + + error = MLX90640_I2CRead(slaveAddr, 0x0700, 64, data); + if(error != 0) + { + return error; + } + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + frameData[832] = controlRegister1; + frameData[833] = statusRegister & 0x0001; + + if(error != 0) + { + return error; + } + + error = ValidateAuxData(data); + if(error == 0) + { + for(cnt=0; cnt<64; cnt++) + { + frameData[cnt+768] = data[cnt]; + } + } + + error = ValidateFrameData(frameData); + if (error != 0) + { + return error; + } + + return frameData[833]; +} + +int ValidateFrameData(uint16_t *frameData) +{ + uint8_t line = 0; + + for(int i=0; i<768; i+=32) + { + if((frameData[i] == 0x7FFF) && (line%2 == frameData[833])) return -8; + line = line + 1; + } + + return 0; +} + +int ValidateAuxData(uint16_t *auxData) +{ + + if(auxData[0] == 0x7FFF) return -8; + + for(int i=8; i<19; i++) + { + if(auxData[i] == 0x7FFF) return -8; + } + + for(int i=20; i<23; i++) + { + if(auxData[i] == 0x7FFF) return -8; + } + + for(int i=24; i<33; i++) + { + if(auxData[i] == 0x7FFF) return -8; + } + + for(int i=40; i<51; i++) + { + if(auxData[i] == 0x7FFF) return -8; + } + + for(int i=52; i<55; i++) + { + if(auxData[i] == 0x7FFF) return -8; + } + + for(int i=56; i<64; i++) + { + if(auxData[i] == 0x7FFF) return -8; + } + + return 0; + +} + +int MLX90640_ExtractParameters(uint16_t *eeData, paramsMLX90640 *mlx90640, int _chunk) // Tasmota +{ + int error = 0; + switch(_chunk){ + case 0: + ExtractVDDParameters(eeData, mlx90640); + ExtractPTATParameters(eeData, mlx90640); + ExtractGainParameters(eeData, mlx90640); + ExtractTgcParameters(eeData, mlx90640); + ExtractResolutionParameters(eeData, mlx90640); + ExtractKsTaParameters(eeData, mlx90640); + ExtractKsToParameters(eeData, mlx90640); + break; + case 1: + ExtractCPParameters(eeData, mlx90640); + ExtractAlphaParameters(eeData, mlx90640); + break; + case 2: + ExtractOffsetParameters(eeData, mlx90640); + break; + case 3: + ExtractKtaPixelParameters(eeData, mlx90640); + break; + case 4: + ExtractKvPixelParameters(eeData, mlx90640); + break; + case 5: + ExtractCILCParameters(eeData, mlx90640); + error = ExtractDeviatingPixels(eeData, mlx90640); + break; + } + return error; +} + +//------------------------------------------------------------------------------ + +int MLX90640_SetResolution(uint8_t slaveAddr, uint8_t resolution) +{ + uint16_t controlRegister1; + int value; + int error; + + value = (resolution & 0x03) << 10; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + + if(error == 0) + { + value = (controlRegister1 & 0xF3FF) | value; + error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); + } + + return error; +} + +//------------------------------------------------------------------------------ + +int MLX90640_GetCurResolution(uint8_t slaveAddr) +{ + uint16_t controlRegister1; + int resolutionRAM; + int error; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + if(error != 0) + { + return error; + } + resolutionRAM = (controlRegister1 & 0x0C00) >> 10; + + return resolutionRAM; +} + +//------------------------------------------------------------------------------ + +int MLX90640_SetRefreshRate(uint8_t slaveAddr, uint8_t refreshRate) +{ + uint16_t controlRegister1; + int value; + int error; + + value = (refreshRate & 0x07)<<7; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + if(error == 0) + { + value = (controlRegister1 & 0xFC7F) | value; + error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); + } + + return error; +} + +//------------------------------------------------------------------------------ + +int MLX90640_GetRefreshRate(uint8_t slaveAddr) +{ + uint16_t controlRegister1; + int refreshRate; + int error; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + if(error != 0) + { + return error; + } + refreshRate = (controlRegister1 & 0x0380) >> 7; + + return refreshRate; +} + +//------------------------------------------------------------------------------ + +int MLX90640_SetInterleavedMode(uint8_t slaveAddr) +{ + uint16_t controlRegister1; + int value; + int error; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + + if(error == 0) + { + value = (controlRegister1 & 0xEFFF); + error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); + } + + return error; +} + +//------------------------------------------------------------------------------ + +int MLX90640_SetChessMode(uint8_t slaveAddr) +{ + uint16_t controlRegister1; + int value; + int error; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + + if(error == 0) + { + value = (controlRegister1 | 0x1000); + error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); + } + + return error; +} + +//------------------------------------------------------------------------------ + +int MLX90640_GetCurMode(uint8_t slaveAddr) +{ + uint16_t controlRegister1; + int modeRAM; + int error; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + if(error != 0) + { + return error; + } + modeRAM = (controlRegister1 & 0x1000) >> 12; + + return modeRAM; +} + +//------------------------------------------------------------------------------ +void MLX90640_CalculateTo(uint16_t *frameData, const paramsMLX90640 *params, float emissivity, float tr, float *result, uint8_t _part) +{ + float vdd; + float ta; + float ta4; + float tr4; + float taTr; + float gain; + float irDataCP[2]; + float irData; + float alphaCompensated; + uint8_t mode; + int8_t ilPattern; + int8_t chessPattern; + int8_t pattern; + int8_t conversionPattern; + float Sx; + float To; + float alphaCorrR[4]; + int8_t range; + uint16_t subPage; + float ktaScale; + float kvScale; + float alphaScale; + float kta; + float kv; + + subPage = frameData[833]; + vdd = MLX90640_GetVdd(frameData, params); + ta = MLX90640_GetTa(frameData, params); + + ta4 = (ta + 273.15); + ta4 = ta4 * ta4; + ta4 = ta4 * ta4; + tr4 = (tr + 273.15); + tr4 = tr4 * tr4; + tr4 = tr4 * tr4; + taTr = tr4 - (tr4-ta4)/emissivity; + + ktaScale = pow(2,(double)params->ktaScale); + kvScale = pow(2,(double)params->kvScale); + alphaScale = pow(2,(double)params->alphaScale); + + alphaCorrR[0] = 1 / (1 + params->ksTo[0] * 40); + alphaCorrR[1] = 1 ; + alphaCorrR[2] = (1 + params->ksTo[1] * params->ct[2]); + alphaCorrR[3] = alphaCorrR[2] * (1 + params->ksTo[2] * (params->ct[3] - params->ct[2])); + +//------------------------- Gain calculation ----------------------------------- + gain = frameData[778]; + if(gain > 32767) + { + gain = gain - 65536; + } + + gain = params->gainEE / gain; + +//------------------------- To calculation ------------------------------------- + mode = (frameData[832] & 0x1000) >> 5; + + irDataCP[0] = frameData[776]; + irDataCP[1] = frameData[808]; + for( int i = 0; i < 2; i++) + { + if(irDataCP[i] > 32767) + { + irDataCP[i] = irDataCP[i] - 65536; + } + irDataCP[i] = irDataCP[i] * gain; + } + irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); + if( mode == params->calibrationModeEE) + { + irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); + } + else + { + irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); + } + + uint32_t _offset = _part*(768/2); + for( int pixelNumber = _offset; pixelNumber < (_offset+(768/2)); pixelNumber++) + { + ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2; + chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2); + conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern); + + if(mode == 0) + { + pattern = ilPattern; + } + else + { + pattern = chessPattern; + } + + if(pattern == frameData[833]) + { + irData = frameData[pixelNumber]; + if(irData > 32767) + { + irData = irData - 65536; + } + irData = irData * gain; + + kta = params->kta[pixelNumber]/ktaScale; + kv = params->kv[pixelNumber]/kvScale; + irData = irData - params->offset[pixelNumber]*(1 + kta*(ta - 25))*(1 + kv*(vdd - 3.3)); + + if(mode != params->calibrationModeEE) + { + irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern; + } + + irData = irData - params->tgc * irDataCP[subPage]; + irData = irData / emissivity; + + alphaCompensated = SCALEALPHA*alphaScale/params->alpha[pixelNumber]; + alphaCompensated = alphaCompensated*(1 + params->KsTa * (ta - 25)); + + Sx = alphaCompensated * alphaCompensated * alphaCompensated * (irData + alphaCompensated * taTr); + Sx = sqrt(sqrt(Sx)) * params->ksTo[1]; + + To = sqrt(sqrt(irData/(alphaCompensated * (1 - params->ksTo[1] * 273.15) + Sx) + taTr)) - 273.15; + + if(To < params->ct[1]) + { + range = 0; + } + else if(To < params->ct[2]) + { + range = 1; + } + else if(To < params->ct[3]) + { + range = 2; + } + else + { + range = 3; + } + + To = sqrt(sqrt(irData / (alphaCompensated * alphaCorrR[range] * (1 + params->ksTo[range] * (To - params->ct[range]))) + taTr)) - 273.15; + + result[pixelNumber] = To; + } + } +} + +//------------------------------------------------------------------------------ + +// void MLX90640_GetImage(uint16_t *frameData, const paramsMLX90640 *params, float *result) +// { +// float vdd; +// float ta; +// float gain; +// float irDataCP[2]; +// float irData; +// float alphaCompensated; +// uint8_t mode; +// int8_t ilPattern; +// int8_t chessPattern; +// int8_t pattern; +// int8_t conversionPattern; +// float image; +// uint16_t subPage; +// float ktaScale; +// float kvScale; +// float kta; +// float kv; + +// subPage = frameData[833]; +// vdd = MLX90640_GetVdd(frameData, params); +// ta = MLX90640_GetTa(frameData, params); + +// ktaScale = pow(2,(double)params->ktaScale); +// kvScale = pow(2,(double)params->kvScale); + +// //------------------------- Gain calculation ----------------------------------- +// gain = frameData[778]; +// if(gain > 32767) +// { +// gain = gain - 65536; +// } + +// gain = params->gainEE / gain; + +// //------------------------- Image calculation ------------------------------------- +// mode = (frameData[832] & 0x1000) >> 5; + +// irDataCP[0] = frameData[776]; +// irDataCP[1] = frameData[808]; +// for( int i = 0; i < 2; i++) +// { +// if(irDataCP[i] > 32767) +// { +// irDataCP[i] = irDataCP[i] - 65536; +// } +// irDataCP[i] = irDataCP[i] * gain; +// } +// irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); +// if( mode == params->calibrationModeEE) +// { +// irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); +// } +// else +// { +// irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); +// } + +// for( int pixelNumber = 0; pixelNumber < 768; pixelNumber++) +// { +// ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2; +// chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2); +// conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern); + +// if(mode == 0) +// { +// pattern = ilPattern; +// } +// else +// { +// pattern = chessPattern; +// } + +// if(pattern == frameData[833]) +// { +// irData = frameData[pixelNumber]; +// if(irData > 32767) +// { +// irData = irData - 65536; +// } +// irData = irData * gain; + +// kta = params->kta[pixelNumber]/ktaScale; +// kv = params->kv[pixelNumber]/kvScale; +// irData = irData - params->offset[pixelNumber]*(1 + kta*(ta - 25))*(1 + kv*(vdd - 3.3)); + +// if(mode != params->calibrationModeEE) +// { +// irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern; +// } + +// irData = irData - params->tgc * irDataCP[subPage]; + +// alphaCompensated = params->alpha[pixelNumber]; + +// image = irData*alphaCompensated; + +// result[pixelNumber] = image; +// } +// } +// } + +//------------------------------------------------------------------------------ + +float MLX90640_GetVdd(uint16_t *frameData, const paramsMLX90640 *params) +{ + float vdd; + float resolutionCorrection; + + int resolutionRAM; + + vdd = frameData[810]; + if(vdd > 32767) + { + vdd = vdd - 65536; + } + resolutionRAM = (frameData[832] & 0x0C00) >> 10; + resolutionCorrection = pow(2, (double)params->resolutionEE) / pow(2, (double)resolutionRAM); + vdd = (resolutionCorrection * vdd - params->vdd25) / params->kVdd + 3.3; + + return vdd; +} + +//------------------------------------------------------------------------------ + +float MLX90640_GetTa(uint16_t *frameData, const paramsMLX90640 *params) +{ + float ptat; + float ptatArt; + float vdd; + float ta; + + vdd = MLX90640_GetVdd(frameData, params); + + ptat = frameData[800]; + if(ptat > 32767) + { + ptat = ptat - 65536; + } + + ptatArt = frameData[768]; + if(ptatArt > 32767) + { + ptatArt = ptatArt - 65536; + } + ptatArt = (ptat / (ptat * params->alphaPTAT + ptatArt)) * pow(2, (double)18); + + ta = (ptatArt / (1 + params->KvPTAT * (vdd - 3.3)) - params->vPTAT25); + ta = ta / params->KtPTAT + 25; + + return ta; +} + +//------------------------------------------------------------------------------ + +int MLX90640_GetSubPageNumber(uint16_t *frameData) +{ + return frameData[833]; + +} + +//------------------------------------------------------------------------------ +void MLX90640_BadPixelsCorrection(uint16_t *pixels, float *to, int mode, paramsMLX90640 *params) +{ + float ap[4]; + uint8_t pix; + uint8_t line; + uint8_t column; + + pix = 0; + while(pixels[pix] != 0xFFFF) + { + line = pixels[pix]>>5; + column = pixels[pix] - (line<<5); + + if(mode == 1) + { + if(line == 0) + { + if(column == 0) + { + to[pixels[pix]] = to[33]; + } + else if(column == 31) + { + to[pixels[pix]] = to[62]; + } + else + { + to[pixels[pix]] = (to[pixels[pix]+31] + to[pixels[pix]+33])/2.0; + } + } + else if(line == 23) + { + if(column == 0) + { + to[pixels[pix]] = to[705]; + } + else if(column == 31) + { + to[pixels[pix]] = to[734]; + } + else + { + to[pixels[pix]] = (to[pixels[pix]-33] + to[pixels[pix]-31])/2.0; + } + } + else if(column == 0) + { + to[pixels[pix]] = (to[pixels[pix]-31] + to[pixels[pix]+33])/2.0; + } + else if(column == 31) + { + to[pixels[pix]] = (to[pixels[pix]-33] + to[pixels[pix]+31])/2.0; + } + else + { + ap[0] = to[pixels[pix]-33]; + ap[1] = to[pixels[pix]-31]; + ap[2] = to[pixels[pix]+31]; + ap[3] = to[pixels[pix]+33]; + to[pixels[pix]] = GetMedian(ap,4); + } + } + else + { + if(column == 0) + { + to[pixels[pix]] = to[pixels[pix]+1]; + } + else if(column == 1 || column == 30) + { + to[pixels[pix]] = (to[pixels[pix]-1]+to[pixels[pix]+1])/2.0; + } + else if(column == 31) + { + to[pixels[pix]] = to[pixels[pix]-1]; + } + else + { + if(IsPixelBad(pixels[pix]-2,params) == 0 && IsPixelBad(pixels[pix]+2,params) == 0) + { + ap[0] = to[pixels[pix]+1] - to[pixels[pix]+2]; + ap[1] = to[pixels[pix]-1] - to[pixels[pix]-2]; + if(fabs(ap[0]) > fabs(ap[1])) + { + to[pixels[pix]] = to[pixels[pix]-1] + ap[1]; + } + else + { + to[pixels[pix]] = to[pixels[pix]+1] + ap[0]; + } + } + else + { + to[pixels[pix]] = (to[pixels[pix]-1]+to[pixels[pix]+1])/2.0; + } + } + } + pix = pix + 1; + } +} + +//------------------------------------------------------------------------------ + +void ExtractVDDParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int16_t kVdd; + int16_t vdd25; + + kVdd = eeData[51]; + + kVdd = (eeData[51] & 0xFF00) >> 8; + if(kVdd > 127) + { + kVdd = kVdd - 256; + } + kVdd = 32 * kVdd; + vdd25 = eeData[51] & 0x00FF; + vdd25 = ((vdd25 - 256) << 5) - 8192; + + mlx90640->kVdd = kVdd; + mlx90640->vdd25 = vdd25; +} + +//------------------------------------------------------------------------------ + +void ExtractPTATParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + float KvPTAT; + float KtPTAT; + int16_t vPTAT25; + float alphaPTAT; + + KvPTAT = (eeData[50] & 0xFC00) >> 10; + if(KvPTAT > 31) + { + KvPTAT = KvPTAT - 64; + } + KvPTAT = KvPTAT/4096; + + KtPTAT = eeData[50] & 0x03FF; + if(KtPTAT > 511) + { + KtPTAT = KtPTAT - 1024; + } + KtPTAT = KtPTAT/8; + + vPTAT25 = eeData[49]; + + alphaPTAT = (eeData[16] & 0xF000) / pow(2, (double)14) + 8.0f; + + mlx90640->KvPTAT = KvPTAT; + mlx90640->KtPTAT = KtPTAT; + mlx90640->vPTAT25 = vPTAT25; + mlx90640->alphaPTAT = alphaPTAT; +} + +//------------------------------------------------------------------------------ + +void ExtractGainParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int16_t gainEE; + + gainEE = eeData[48]; + if(gainEE > 32767) + { + gainEE = gainEE -65536; + } + + mlx90640->gainEE = gainEE; +} + +//------------------------------------------------------------------------------ + +void ExtractTgcParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + float tgc; + tgc = eeData[60] & 0x00FF; + if(tgc > 127) + { + tgc = tgc - 256; + } + tgc = tgc / 32.0f; + + mlx90640->tgc = tgc; +} + +//------------------------------------------------------------------------------ + +void ExtractResolutionParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + uint8_t resolutionEE; + resolutionEE = (eeData[56] & 0x3000) >> 12; + + mlx90640->resolutionEE = resolutionEE; +} + +//------------------------------------------------------------------------------ + +void ExtractKsTaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + float KsTa; + KsTa = (eeData[60] & 0xFF00) >> 8; + if(KsTa > 127) + { + KsTa = KsTa -256; + } + KsTa = KsTa / 8192.0f; + + mlx90640->KsTa = KsTa; +} + +//------------------------------------------------------------------------------ + +void ExtractKsToParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int KsToScale; + int8_t step; + + step = ((eeData[63] & 0x3000) >> 12) * 10; + + mlx90640->ct[0] = -40; + mlx90640->ct[1] = 0; + mlx90640->ct[2] = (eeData[63] & 0x00F0) >> 4; + mlx90640->ct[3] = (eeData[63] & 0x0F00) >> 8; + + mlx90640->ct[2] = mlx90640->ct[2]*step; + mlx90640->ct[3] = mlx90640->ct[2] + mlx90640->ct[3]*step; + mlx90640->ct[4] = 400; + + KsToScale = (eeData[63] & 0x000F) + 8; + KsToScale = 1 << KsToScale; + + mlx90640->ksTo[0] = eeData[61] & 0x00FF; + mlx90640->ksTo[1] = (eeData[61] & 0xFF00) >> 8; + mlx90640->ksTo[2] = eeData[62] & 0x00FF; + mlx90640->ksTo[3] = (eeData[62] & 0xFF00) >> 8; + + for(int i = 0; i < 4; i++) + { + if(mlx90640->ksTo[i] > 127) + { + mlx90640->ksTo[i] = mlx90640->ksTo[i] - 256; + } + mlx90640->ksTo[i] = mlx90640->ksTo[i] / KsToScale; + } + + mlx90640->ksTo[4] = -0.0002; +} + +//------------------------------------------------------------------------------ + +void ExtractAlphaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int accRow[24]; + int accColumn[32]; + int p = 0; + int alphaRef; + uint8_t alphaScale; + uint8_t accRowScale; + uint8_t accColumnScale; + uint8_t accRemScale; + float alphaTemp[768]; + float temp; + + + accRemScale = eeData[32] & 0x000F; + accColumnScale = (eeData[32] & 0x00F0) >> 4; + accRowScale = (eeData[32] & 0x0F00) >> 8; + alphaScale = ((eeData[32] & 0xF000) >> 12) + 30; + alphaRef = eeData[33]; + + for(int i = 0; i < 6; i++) + { + p = i * 4; + accRow[p + 0] = (eeData[34 + i] & 0x000F); + accRow[p + 1] = (eeData[34 + i] & 0x00F0) >> 4; + accRow[p + 2] = (eeData[34 + i] & 0x0F00) >> 8; + accRow[p + 3] = (eeData[34 + i] & 0xF000) >> 12; + } + + for(int i = 0; i < 24; i++) + { + if (accRow[i] > 7) + { + accRow[i] = accRow[i] - 16; + } + } + + for(int i = 0; i < 8; i++) + { + p = i * 4; + accColumn[p + 0] = (eeData[40 + i] & 0x000F); + accColumn[p + 1] = (eeData[40 + i] & 0x00F0) >> 4; + accColumn[p + 2] = (eeData[40 + i] & 0x0F00) >> 8; + accColumn[p + 3] = (eeData[40 + i] & 0xF000) >> 12; + } + + for(int i = 0; i < 32; i ++) + { + if (accColumn[i] > 7) + { + accColumn[i] = accColumn[i] - 16; + } + } + + for(int i = 0; i < 24; i++) + { + for(int j = 0; j < 32; j ++) + { + p = 32 * i +j; + alphaTemp[p] = (eeData[64 + p] & 0x03F0) >> 4; + if (alphaTemp[p] > 31) + { + alphaTemp[p] = alphaTemp[p] - 64; + } + alphaTemp[p] = alphaTemp[p]*(1 << accRemScale); + alphaTemp[p] = (alphaRef + (accRow[i] << accRowScale) + (accColumn[j] << accColumnScale) + alphaTemp[p]); + alphaTemp[p] = alphaTemp[p] / pow(2,(double)alphaScale); + alphaTemp[p] = alphaTemp[p] - mlx90640->tgc * (mlx90640->cpAlpha[0] + mlx90640->cpAlpha[1])/2; + alphaTemp[p] = SCALEALPHA/alphaTemp[p]; + } + } + + temp = alphaTemp[0]; + for(int i = 1; i < 768; i++) + { + if (alphaTemp[i] > temp) + { + temp = alphaTemp[i]; + } + } + + alphaScale = 0; + while(temp < 32767.4) + { + temp = temp*2; + alphaScale = alphaScale + 1; + } + + for(int i = 0; i < 768; i++) + { + temp = alphaTemp[i] * pow(2,(double)alphaScale); + mlx90640->alpha[i] = (temp + 0.5); + + } + + mlx90640->alphaScale = alphaScale; + +} + +//------------------------------------------------------------------------------ + +void ExtractOffsetParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int occRow[24]; + int occColumn[32]; + int p = 0; + int16_t offsetRef; + uint8_t occRowScale; + uint8_t occColumnScale; + uint8_t occRemScale; + + + occRemScale = (eeData[16] & 0x000F); + occColumnScale = (eeData[16] & 0x00F0) >> 4; + occRowScale = (eeData[16] & 0x0F00) >> 8; + offsetRef = eeData[17]; + if (offsetRef > 32767) + { + offsetRef = offsetRef - 65536; + } + + for(int i = 0; i < 6; i++) + { + p = i * 4; + occRow[p + 0] = (eeData[18 + i] & 0x000F); + occRow[p + 1] = (eeData[18 + i] & 0x00F0) >> 4; + occRow[p + 2] = (eeData[18 + i] & 0x0F00) >> 8; + occRow[p + 3] = (eeData[18 + i] & 0xF000) >> 12; + } + + for(int i = 0; i < 24; i++) + { + if (occRow[i] > 7) + { + occRow[i] = occRow[i] - 16; + } + } + + for(int i = 0; i < 8; i++) + { + p = i * 4; + occColumn[p + 0] = (eeData[24 + i] & 0x000F); + occColumn[p + 1] = (eeData[24 + i] & 0x00F0) >> 4; + occColumn[p + 2] = (eeData[24 + i] & 0x0F00) >> 8; + occColumn[p + 3] = (eeData[24 + i] & 0xF000) >> 12; + } + + for(int i = 0; i < 32; i ++) + { + if (occColumn[i] > 7) + { + occColumn[i] = occColumn[i] - 16; + } + } + + for(int i = 0; i < 24; i++) + { + for(int j = 0; j < 32; j ++) + { + p = 32 * i +j; + mlx90640->offset[p] = (eeData[64 + p] & 0xFC00) >> 10; + if (mlx90640->offset[p] > 31) + { + mlx90640->offset[p] = mlx90640->offset[p] - 64; + } + mlx90640->offset[p] = mlx90640->offset[p]*(1 << occRemScale); + mlx90640->offset[p] = (offsetRef + (occRow[i] << occRowScale) + (occColumn[j] << occColumnScale) + mlx90640->offset[p]); + } + } +} + +//------------------------------------------------------------------------------ + +void ExtractKtaPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int p = 0; + int8_t KtaRC[4]; + int8_t KtaRoCo; + int8_t KtaRoCe; + int8_t KtaReCo; + int8_t KtaReCe; + uint8_t ktaScale1; + uint8_t ktaScale2; + uint8_t split; + float ktaTemp[768]; + float temp; + + KtaRoCo = (eeData[54] & 0xFF00) >> 8; + if (KtaRoCo > 127) + { + KtaRoCo = KtaRoCo - 256; + } + KtaRC[0] = KtaRoCo; + + KtaReCo = (eeData[54] & 0x00FF); + if (KtaReCo > 127) + { + KtaReCo = KtaReCo - 256; + } + KtaRC[2] = KtaReCo; + + KtaRoCe = (eeData[55] & 0xFF00) >> 8; + if (KtaRoCe > 127) + { + KtaRoCe = KtaRoCe - 256; + } + KtaRC[1] = KtaRoCe; + + KtaReCe = (eeData[55] & 0x00FF); + if (KtaReCe > 127) + { + KtaReCe = KtaReCe - 256; + } + KtaRC[3] = KtaReCe; + + ktaScale1 = ((eeData[56] & 0x00F0) >> 4) + 8; + ktaScale2 = (eeData[56] & 0x000F); + + for(int i = 0; i < 24; i++) + { + for(int j = 0; j < 32; j ++) + { + p = 32 * i +j; + split = 2*(p/32 - (p/64)*2) + p%2; + ktaTemp[p] = (eeData[64 + p] & 0x000E) >> 1; + if (ktaTemp[p] > 3) + { + ktaTemp[p] = ktaTemp[p] - 8; + } + ktaTemp[p] = ktaTemp[p] * (1 << ktaScale2); + ktaTemp[p] = KtaRC[split] + ktaTemp[p]; + ktaTemp[p] = ktaTemp[p] / pow(2,(double)ktaScale1); + //ktaTemp[p] = ktaTemp[p] * mlx90640->offset[p]; + } + } + + temp = fabs(ktaTemp[0]); + for(int i = 1; i < 768; i++) + { + if (fabs(ktaTemp[i]) > temp) + { + temp = fabs(ktaTemp[i]); + } + } + + ktaScale1 = 0; + while(temp < 63.4) + { + temp = temp*2; + ktaScale1 = ktaScale1 + 1; + } + + for(int i = 0; i < 768; i++) + { + temp = ktaTemp[i] * pow(2,(double)ktaScale1); + if (temp < 0) + { + mlx90640->kta[i] = (temp - 0.5); + } + else + { + mlx90640->kta[i] = (temp + 0.5); + } + + } + + mlx90640->ktaScale = ktaScale1; +} + + +//------------------------------------------------------------------------------ + +void ExtractKvPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int p = 0; + int8_t KvT[4]; + int8_t KvRoCo; + int8_t KvRoCe; + int8_t KvReCo; + int8_t KvReCe; + uint8_t kvScale; + uint8_t split; + float kvTemp[768]; + float temp; + + KvRoCo = (eeData[52] & 0xF000) >> 12; + if (KvRoCo > 7) + { + KvRoCo = KvRoCo - 16; + } + KvT[0] = KvRoCo; + + KvReCo = (eeData[52] & 0x0F00) >> 8; + if (KvReCo > 7) + { + KvReCo = KvReCo - 16; + } + KvT[2] = KvReCo; + + KvRoCe = (eeData[52] & 0x00F0) >> 4; + if (KvRoCe > 7) + { + KvRoCe = KvRoCe - 16; + } + KvT[1] = KvRoCe; + + KvReCe = (eeData[52] & 0x000F); + if (KvReCe > 7) + { + KvReCe = KvReCe - 16; + } + KvT[3] = KvReCe; + + kvScale = (eeData[56] & 0x0F00) >> 8; + + + for(int i = 0; i < 24; i++) + { + for(int j = 0; j < 32; j ++) + { + p = 32 * i +j; + split = 2*(p/32 - (p/64)*2) + p%2; + kvTemp[p] = KvT[split]; + kvTemp[p] = kvTemp[p] / pow(2,(double)kvScale); + //kvTemp[p] = kvTemp[p] * mlx90640->offset[p]; + } + } + + temp = fabs(kvTemp[0]); + for(int i = 1; i < 768; i++) + { + if (fabs(kvTemp[i]) > temp) + { + temp = fabs(kvTemp[i]); + } + } + + kvScale = 0; + while(temp < 63.4) + { + temp = temp*2; + kvScale = kvScale + 1; + } + + for(int i = 0; i < 768; i++) + { + temp = kvTemp[i] * pow(2,(double)kvScale); + if (temp < 0) + { + mlx90640->kv[i] = (temp - 0.5); + } + else + { + mlx90640->kv[i] = (temp + 0.5); + } + + } + + mlx90640->kvScale = kvScale; +} + +//------------------------------------------------------------------------------ + +void ExtractCPParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + float alphaSP[2]; + int16_t offsetSP[2]; + float cpKv; + float cpKta; + uint8_t alphaScale; + uint8_t ktaScale1; + uint8_t kvScale; + + alphaScale = ((eeData[32] & 0xF000) >> 12) + 27; + + offsetSP[0] = (eeData[58] & 0x03FF); + if (offsetSP[0] > 511) + { + offsetSP[0] = offsetSP[0] - 1024; + } + + offsetSP[1] = (eeData[58] & 0xFC00) >> 10; + if (offsetSP[1] > 31) + { + offsetSP[1] = offsetSP[1] - 64; + } + offsetSP[1] = offsetSP[1] + offsetSP[0]; + + alphaSP[0] = (eeData[57] & 0x03FF); + if (alphaSP[0] > 511) + { + alphaSP[0] = alphaSP[0] - 1024; + } + alphaSP[0] = alphaSP[0] / pow(2,(double)alphaScale); + + alphaSP[1] = (eeData[57] & 0xFC00) >> 10; + if (alphaSP[1] > 31) + { + alphaSP[1] = alphaSP[1] - 64; + } + alphaSP[1] = (1 + alphaSP[1]/128) * alphaSP[0]; + + cpKta = (eeData[59] & 0x00FF); + if (cpKta > 127) + { + cpKta = cpKta - 256; + } + ktaScale1 = ((eeData[56] & 0x00F0) >> 4) + 8; + mlx90640->cpKta = cpKta / pow(2,(double)ktaScale1); + + cpKv = (eeData[59] & 0xFF00) >> 8; + if (cpKv > 127) + { + cpKv = cpKv - 256; + } + kvScale = (eeData[56] & 0x0F00) >> 8; + mlx90640->cpKv = cpKv / pow(2,(double)kvScale); + + mlx90640->cpAlpha[0] = alphaSP[0]; + mlx90640->cpAlpha[1] = alphaSP[1]; + mlx90640->cpOffset[0] = offsetSP[0]; + mlx90640->cpOffset[1] = offsetSP[1]; +} + +//------------------------------------------------------------------------------ + +void ExtractCILCParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + float ilChessC[3]; + uint8_t calibrationModeEE; + + calibrationModeEE = (eeData[10] & 0x0800) >> 4; + calibrationModeEE = calibrationModeEE ^ 0x80; + + ilChessC[0] = (eeData[53] & 0x003F); + if (ilChessC[0] > 31) + { + ilChessC[0] = ilChessC[0] - 64; + } + ilChessC[0] = ilChessC[0] / 16.0f; + + ilChessC[1] = (eeData[53] & 0x07C0) >> 6; + if (ilChessC[1] > 15) + { + ilChessC[1] = ilChessC[1] - 32; + } + ilChessC[1] = ilChessC[1] / 2.0f; + + ilChessC[2] = (eeData[53] & 0xF800) >> 11; + if (ilChessC[2] > 15) + { + ilChessC[2] = ilChessC[2] - 32; + } + ilChessC[2] = ilChessC[2] / 8.0f; + + mlx90640->calibrationModeEE = calibrationModeEE; + mlx90640->ilChessC[0] = ilChessC[0]; + mlx90640->ilChessC[1] = ilChessC[1]; + mlx90640->ilChessC[2] = ilChessC[2]; +} + +//------------------------------------------------------------------------------ + +int ExtractDeviatingPixels(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + uint16_t pixCnt = 0; + uint16_t brokenPixCnt = 0; + uint16_t outlierPixCnt = 0; + int warn = 0; + int i; + + for(pixCnt = 0; pixCnt<5; pixCnt++) + { + mlx90640->brokenPixels[pixCnt] = 0xFFFF; + mlx90640->outlierPixels[pixCnt] = 0xFFFF; + } + + pixCnt = 0; + while (pixCnt < 768 && brokenPixCnt < 5 && outlierPixCnt < 5) + { + if(eeData[pixCnt+64] == 0) + { + mlx90640->brokenPixels[brokenPixCnt] = pixCnt; + brokenPixCnt = brokenPixCnt + 1; + } + else if((eeData[pixCnt+64] & 0x0001) != 0) + { + mlx90640->outlierPixels[outlierPixCnt] = pixCnt; + outlierPixCnt = outlierPixCnt + 1; + } + + pixCnt = pixCnt + 1; + + } + + if(brokenPixCnt > 4) + { + warn = -3; + } + else if(outlierPixCnt > 4) + { + warn = -4; + } + else if((brokenPixCnt + outlierPixCnt) > 4) + { + warn = -5; + } + else + { + for(pixCnt=0; pixCntbrokenPixels[pixCnt],mlx90640->brokenPixels[i]); + if(warn != 0) + { + return warn; + } + } + } + + for(pixCnt=0; pixCntoutlierPixels[pixCnt],mlx90640->outlierPixels[i]); + if(warn != 0) + { + return warn; + } + } + } + + for(pixCnt=0; pixCntbrokenPixels[pixCnt],mlx90640->outlierPixels[i]); + if(warn != 0) + { + return warn; + } + } + } + + } + + + return warn; + +} + +//------------------------------------------------------------------------------ + + int CheckAdjacentPixels(uint16_t pix1, uint16_t pix2) + { + int pixPosDif; + + pixPosDif = pix1 - pix2; + if(pixPosDif > -34 && pixPosDif < -30) + { + return -6; + } + if(pixPosDif > -2 && pixPosDif < 2) + { + return -6; + } + if(pixPosDif > 30 && pixPosDif < 34) + { + return -6; + } + + return 0; + } + +//------------------------------------------------------------------------------ + +float GetMedian(float *values, int n) + { + float temp; + + for(int i=0; ioutlierPixels[i] || pixel == params->brokenPixels[i]) + { + return 1; + } + } + + return 0; +} + +//------------------------------------------------------------------------------ diff --git a/lib/mlx90640-library/MLX90640_API.h b/lib/mlx90640-library/MLX90640_API.h new file mode 100644 index 000000000..efbcdff5b --- /dev/null +++ b/lib/mlx90640-library/MLX90640_API.h @@ -0,0 +1,74 @@ +/** + * @copyright (C) 2017 Melexis N.V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _MLX90640_API_H_ +#define _MLX90640_API_H_ + +#include + +#define SCALEALPHA 0.000001 + +typedef struct + { + int16_t kVdd; + int16_t vdd25; + float KvPTAT; + float KtPTAT; + uint16_t vPTAT25; + float alphaPTAT; + int16_t gainEE; + float tgc; + float cpKv; + float cpKta; + uint8_t resolutionEE; + uint8_t calibrationModeEE; + float KsTa; + float ksTo[5]; + int16_t ct[5]; + uint16_t alpha[768]; + uint8_t alphaScale; + int16_t offset[768]; + int8_t kta[768]; + uint8_t ktaScale; + int8_t kv[768]; + uint8_t kvScale; + float cpAlpha[2]; + int16_t cpOffset[2]; + float ilChessC[3]; + uint16_t brokenPixels[5]; + uint16_t outlierPixels[5]; + } paramsMLX90640; + + int MLX90640_DumpEE(uint8_t slaveAddr, uint16_t *eeData); + int MLX90640_SynchFrame(uint8_t slaveAddr); + // int MLX90640_TriggerMeasurement(uint8_t slaveAddr); + int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData); + int MLX90640_ExtractParameters(uint16_t *eeData, paramsMLX90640 *mlx90640,int _chunk); + float MLX90640_GetVdd(uint16_t *frameData, const paramsMLX90640 *params); + float MLX90640_GetTa(uint16_t *frameData, const paramsMLX90640 *params); + // void MLX90640_GetImage(uint16_t *frameData, const paramsMLX90640 *params, float *result); + void MLX90640_CalculateTo(uint16_t *frameData, const paramsMLX90640 *params, float emissivity, float tr, float *result, uint8_t _part); + int MLX90640_SetResolution(uint8_t slaveAddr, uint8_t resolution); + int MLX90640_GetCurResolution(uint8_t slaveAddr); + int MLX90640_SetRefreshRate(uint8_t slaveAddr, uint8_t refreshRate); + int MLX90640_GetRefreshRate(uint8_t slaveAddr); + int MLX90640_GetSubPageNumber(uint16_t *frameData); + int MLX90640_GetCurMode(uint8_t slaveAddr); + int MLX90640_SetInterleavedMode(uint8_t slaveAddr); + int MLX90640_SetChessMode(uint8_t slaveAddr); + void MLX90640_BadPixelsCorrection(uint16_t *pixels, float *to, int mode, paramsMLX90640 *params); + +#endif diff --git a/pio/gzip-firmware.py b/pio/gzip-firmware.py index 43af1f933..248bb5a02 100644 --- a/pio/gzip-firmware.py +++ b/pio/gzip-firmware.py @@ -6,7 +6,7 @@ import gzip OUTPUT_DIR = "build_output{}".format(os.path.sep) def bin_gzip(source, target, env): - variant = str(target[0]).split(os.path.sep)[1] + variant = str(target[0]).split(os.path.sep)[2] # create string with location and file names based on variant bin_file = "{}firmware{}{}.bin".format(OUTPUT_DIR, os.path.sep, variant) diff --git a/pio/name-firmware.py b/pio/name-firmware.py index 1490ecc5c..1c79056de 100644 --- a/pio/name-firmware.py +++ b/pio/name-firmware.py @@ -5,7 +5,7 @@ import shutil OUTPUT_DIR = "build_output{}".format(os.path.sep) def bin_map_copy(source, target, env): - variant = str(target[0]).split(os.path.sep)[1] + variant = str(target[0]).split(os.path.sep)[2] # check if output directories exist and create if necessary if not os.path.isdir(OUTPUT_DIR): diff --git a/platformio.ini b/platformio.ini index ecf7d41ab..a0c4d82b5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,18 +7,9 @@ ; Please visit documentation for the other options and examples ; http://docs.platformio.org/en/stable/projectconf.html -[platformio] -description = Provide ESP8266 based devices with Web, MQTT and OTA firmware -src_dir = tasmota -build_dir = .pioenvs -workspace_dir = .pioenvs -build_cache_dir = .cache -extra_configs = platformio_tasmota32.ini - platformio_tasmota_env.ini - platformio_tasmota_env32.ini - platformio_override.ini -; *** Build/upload environment +; *** Tasmota build variant selection +[build_envs] default_envs = ; *** Uncomment by deleting ";" in the line(s) below to select version(s) ; tasmota @@ -53,10 +44,21 @@ default_envs = ; tasmota-TW ; tasmota-UK ; +; *** Selection for Tasmota ESP32 is done in platformio_tasmota32.ini +; ; *** alternatively can be done in: platformio_override.ini ; *** See example: platformio_override_sample.ini ; ********************************************************************* +[platformio] +description = Provide ESP8266 / ESP32 based devices with Web, MQTT and OTA firmware +src_dir = tasmota +build_cache_dir = .cache +extra_configs = platformio_tasmota32.ini + platformio_tasmota_env.ini + platformio_tasmota_env32.ini + platformio_override.ini +default_envs = ${build_envs.default_envs} [common] framework = arduino diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 549f2e333..739ec2338 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -1,6 +1,44 @@ ; *** BETA ESP32 Tasmota version *** ; *** expect the unexpected. Some features not working!!! *** +[platformio] + +; *** Tasmota build variant selection +default_envs = ${build_envs.default_envs} +; *** Uncomment by deleting ";" in the line(s) below to select version(s) +; tasmota32 +; tasmota32-webcam +; tasmota32-minimal +; tasmota32-lite +; tasmota32-knx +; tasmota32-sensors +; tasmota32-display +; tasmota32-ir +; tasmota32-ircustom +; tasmota32-BG +; tasmota32-BR +; tasmota32-CN +; tasmota32-CZ +; tasmota32-DE +; tasmota32-ES +; tasmota32-FR +; tasmota32-GR +; tasmota32-HE +; tasmota32-HU +; tasmota32-IT +; tasmota32-KO +; tasmota32-NL +; tasmota32-PL +; tasmota32-PT +; tasmota32-RO +; tasmota32-RU +; tasmota32-SE +; tasmota32-SK +; tasmota32-TR +; tasmota32-TW +; tasmota32-UK + + [common32] platform = espressif32@2.0.0 platform_packages = tool-esptoolpy@1.20800.0 diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index faaa2ae17..5c0d36fd2 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -6,8 +6,11 @@ - Fix energy total counters (#9263, #9266) - Fix crash in ``ZbRestore`` +- Fix reset BMP sensors when executing command ``SaveData`` and define USE_DEEPSLEEP enabled (#9300) - Add new shutter modes (#9244) - Add ``#define USE_MQTT_AWS_IOT_LIGHT`` for password based AWS IoT authentication +- Add Zigbee auto-config when pairing +- Add support for MLX90640 IR array temperature sensor by Christian Baars ### 8.5.0 20200907 diff --git a/tasmota/WiFiClientSecureLightBearSSL.cpp b/tasmota/WiFiClientSecureLightBearSSL.cpp index d85373688..f0a6bcfbb 100755 --- a/tasmota/WiFiClientSecureLightBearSSL.cpp +++ b/tasmota/WiFiClientSecureLightBearSSL.cpp @@ -874,10 +874,8 @@ extern "C" { // we support only P256 EC curve for AWS IoT, no EC curve for Letsencrypt unless forced br_ssl_engine_set_ec(&cc->eng, &br_ec_p256_m15); // TODO #endif -#ifdef USE_MQTT_AWS_IOT_LIGHT static const char * alpn_mqtt = "mqtt"; br_ssl_engine_set_protocol_names(&cc->eng, &alpn_mqtt, 1); -#endif } } diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 961a82e10..f2673bda6 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -558,6 +558,7 @@ // #define USE_VEML7700 // [I2cDriver50] Enable VEML7700 Ambient Light sensor (I2C addresses 0x10) (+4k5 code) // #define USE_MCP9808 // [I2cDriver51] Enable MCP9808 temperature sensor (I2C addresses 0x18 - 0x1F) (+0k9 code) // #define USE_HP303B // [I2cDriver52] Enable HP303B temperature and pressure sensor (I2C address 0x76 or 0x77) (+6k2 code) +// #define USE_MLX90640 // [I2cDriver53] Enable MLX90640 IR array temperature sensor (I2C address 0x33) (+20k code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/tasmota/settings.h b/tasmota/settings.h index 97cefd392..ba436a495 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -129,8 +129,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t virtual_ct_cw : 1; // bit 25 (v8.4.0.1) - SetOption107 - Virtual CT Channel - signals whether the hardware white is cold CW (true) or warm WW (false) uint32_t teleinfo_rawdata : 1; // bit 26 (v8.4.0.2) - SetOption108 - enable Teleinfo + Tasmota Energy device (0) or Teleinfo raw data only (1) uint32_t alexa_gen_1 : 1; // bit 27 (v8.4.0.3) - SetOption109 - Alexa gen1 mode - if you only have Echo Dot 2nd gen devices - uint32_t buzzer_freq_mode : 1; // bit 28 (v8.4.0.3) - SetOption110 - SetOption110 - Use frequency output for buzzer pin instead of on/off signal - uint32_t spare29 : 1; // bit 29 + uint32_t zb_disable_autobind : 1; // bit 28 (v8.5.0.1) - SetOption110 - disable Zigbee auto-config when pairing new devices + uint32_t buzzer_freq_mode : 1; // bit 29 (v8.5.0.1) - SetOption111 - Use frequency output for buzzer pin instead of on/off signal uint32_t spare30 : 1; // bit 30 uint32_t spare31 : 1; // bit 31 }; diff --git a/tasmota/support.ino b/tasmota/support.ino index 8d4044906..eddffeab6 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -2006,3 +2006,27 @@ String Decompress(const char * compressed, size_t uncompressed_size) { } #endif // USE_UNISHOX_COMPRESSION + +/*********************************************************************************************\ + * High entropy hardware random generator + * Thanks to DigitalAlchemist +\*********************************************************************************************/ +// Based on code from https://raw.githubusercontent.com/espressif/esp-idf/master/components/esp32/hw_random.c +uint32_t HwRandom(void) { +#if ESP8266 + // https://web.archive.org/web/20160922031242/http://esp8266-re.foogod.com/wiki/Random_Number_Generator + #define _RAND_ADDR 0x3FF20E44UL +#else // ESP32 + #define _RAND_ADDR 0x3FF75144UL +#endif + static uint32_t last_ccount = 0; + uint32_t ccount; + uint32_t result = 0; + do { + ccount = ESP.getCycleCount(); + result ^= *(volatile uint32_t *)_RAND_ADDR; + } while (ccount - last_ccount < 64); + last_ccount = ccount; + return result ^ *(volatile uint32_t *)_RAND_ADDR; +#undef _RAND_ADDR +} diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index d7f8328d3..50da89faa 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -601,8 +601,9 @@ void GetFeatures(void) #ifdef USE_I2S_AUDIO feature6 |= 0x00800000; // xdrv_42_i2s_audio.ino #endif - -// feature6 |= 0x01000000; +#ifdef USE_MLX90640 + feature6 |= 0x01000000; // xdrv_43_mlx90640.ino +#endif // feature6 |= 0x02000000; // feature6 |= 0x04000000; // feature6 |= 0x08000000; diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 32a914f8f..944165eef 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -254,6 +254,229 @@ enum ProgramSelectablePins { GPIO_USER, // User configurable needs to be 255 GPIO_MAX }; +/* +// Indexed by UserSelectablePins to convert legacy (8-bit) GPIOs +const uint16_t kGpioConvert[] PROGMEM = { + GPIO_NONE, + AGPIO(GPIO_DHT11), // DHT11 + AGPIO(GPIO_DHT22), // DHT21, DHT22, AM2301, AM2302, AM2321 + AGPIO(GPIO_SI7021), // iTead SI7021 + AGPIO(GPIO_DSB), // Single wire DS18B20 or DS18S20 + AGPIO(GPIO_I2C_SCL), // I2C SCL + AGPIO(GPIO_I2C_SDA), // I2C SDA + AGPIO(GPIO_WS2812), // WS2812 Led string + AGPIO(GPIO_IRSEND), // IR remote + AGPIO(GPIO_SWT1), // Switch + AGPIO(GPIO_SWT1) +1, + AGPIO(GPIO_SWT1) +2, + AGPIO(GPIO_SWT1) +3, + AGPIO(GPIO_SWT1) +4, + AGPIO(GPIO_SWT1) +5, + AGPIO(GPIO_SWT1) +6, + AGPIO(GPIO_SWT1) +7, + AGPIO(GPIO_KEY1), // Button + AGPIO(GPIO_KEY1) +1, + AGPIO(GPIO_KEY1) +2, + AGPIO(GPIO_KEY1) +3, + AGPIO(GPIO_REL1), // Relay + AGPIO(GPIO_REL1) +1, + AGPIO(GPIO_REL1) +2, + AGPIO(GPIO_REL1) +3, + AGPIO(GPIO_REL1) +4, + AGPIO(GPIO_REL1) +5, + AGPIO(GPIO_REL1) +6, + AGPIO(GPIO_REL1) +7, + AGPIO(GPIO_REL1_INV), // Relay inverted + AGPIO(GPIO_REL1_INV) +1, + AGPIO(GPIO_REL1_INV) +2, + AGPIO(GPIO_REL1_INV) +3, + AGPIO(GPIO_REL1_INV) +4, + AGPIO(GPIO_REL1_INV) +5, + AGPIO(GPIO_REL1_INV) +6, + AGPIO(GPIO_REL1_INV) +7, + AGPIO(GPIO_PWM1), // PWM + AGPIO(GPIO_PWM1) +1, + AGPIO(GPIO_PWM1) +2, + AGPIO(GPIO_PWM1) +3, + AGPIO(GPIO_PWM1) +4, + AGPIO(GPIO_CNTR1), // Counter + AGPIO(GPIO_CNTR1) +1, + AGPIO(GPIO_CNTR1) +2, + AGPIO(GPIO_CNTR1) +3, + AGPIO(GPIO_PWM1_INV), // PWM inverted + AGPIO(GPIO_PWM1_INV) +1, + AGPIO(GPIO_PWM1_INV) +2, + AGPIO(GPIO_PWM1_INV) +3, + AGPIO(GPIO_PWM1_INV) +4, + AGPIO(GPIO_IRRECV), // IR receive + AGPIO(GPIO_LED1), // Led + AGPIO(GPIO_LED1) +1, + AGPIO(GPIO_LED1) +2, + AGPIO(GPIO_LED1) +3, + AGPIO(GPIO_LED1_INV), // Led inverted + AGPIO(GPIO_LED1_INV) +1, + AGPIO(GPIO_LED1_INV) +2, + AGPIO(GPIO_LED1_INV) +3, + AGPIO(GPIO_MHZ_TXD), // MH-Z19 Serial interface + AGPIO(GPIO_MHZ_RXD), + AGPIO(GPIO_PZEM0XX_TX), // PZEM0XX Serial interface + AGPIO(GPIO_PZEM004_RX), // PZEM004T Serial interface + AGPIO(GPIO_SAIR_TX), // SenseAir Serial interface + AGPIO(GPIO_SAIR_RX), // SenseAir Serial interface + AGPIO(GPIO_SPI_CS), // SPI Chip Select + AGPIO(GPIO_SPI_DC), // SPI Data Direction + AGPIO(GPIO_BACKLIGHT), // Display backlight control + AGPIO(GPIO_PMS5003_RX), // Plantower PMS5003 Serial interface + AGPIO(GPIO_SDS0X1_RX), // Nova Fitness SDS011 Serial interface + AGPIO(GPIO_SBR_TX), // Serial Bridge Serial interface + AGPIO(GPIO_SBR_RX), // Serial Bridge Serial interface + AGPIO(GPIO_SR04_TRIG), // SR04 Tri/TXgger pin + AGPIO(GPIO_SR04_ECHO), // SR04 Ech/RXo pin + AGPIO(GPIO_SDM120_TX), // SDM120 Serial interface + AGPIO(GPIO_SDM120_RX), // SDM120 Serial interface + AGPIO(GPIO_SDM630_TX), // SDM630 Serial interface + AGPIO(GPIO_SDM630_RX), // SDM630 Serial interface + AGPIO(GPIO_TM16CLK), // TM1638 Clock + AGPIO(GPIO_TM16DIO), // TM1638 Data I/O + AGPIO(GPIO_TM16STB), // TM1638 Strobe + AGPIO(GPIO_SWT1_NP), // Switch no pullup + AGPIO(GPIO_SWT1_NP) +1, + AGPIO(GPIO_SWT1_NP) +2, + AGPIO(GPIO_SWT1_NP) +3, + AGPIO(GPIO_SWT1_NP) +4, + AGPIO(GPIO_SWT1_NP) +5, + AGPIO(GPIO_SWT1_NP) +6, + AGPIO(GPIO_SWT1_NP) +7, + AGPIO(GPIO_KEY1_NP), // Button no pullup + AGPIO(GPIO_KEY1_NP) +1, + AGPIO(GPIO_KEY1_NP) +2, + AGPIO(GPIO_KEY1_NP) +3, + AGPIO(GPIO_CNTR1_NP), // Counter no pullup + AGPIO(GPIO_CNTR1_NP) +1, + AGPIO(GPIO_CNTR1_NP) +2, + AGPIO(GPIO_CNTR1_NP) +3, + AGPIO(GPIO_PZEM016_RX), // PZEM-014,016 Serial Modbus interface + AGPIO(GPIO_PZEM017_RX), // PZEM-003,017 Serial Modbus interface + AGPIO(GPIO_MP3_DFR562), // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface + AGPIO(GPIO_SDS0X1_TX), // Nova Fitness SDS011 Serial interface + AGPIO(GPIO_HX711_SCK), // HX711 Load Cell clock + AGPIO(GPIO_HX711_DAT), // HX711 Load Cell data + AGPIO(GPIO_TX2X_TXD_BLACK), // TX20/TX23 Transmission Pin + AGPIO(GPIO_RFSEND), // RF transmitter + AGPIO(GPIO_RFRECV), // RF receiver + AGPIO(GPIO_TUYA_TX), // Tuya Serial interface + AGPIO(GPIO_TUYA_RX), // Tuya Serial interface + AGPIO(GPIO_MGC3130_XFER), + AGPIO(GPIO_MGC3130_RESET), + AGPIO(GPIO_SSPI_MISO), // Software SPI Master Input Client Output + AGPIO(GPIO_SSPI_MOSI), // Software SPI Master Output Client Input + AGPIO(GPIO_SSPI_SCLK), // Software SPI Serial Clock + AGPIO(GPIO_SSPI_CS), // Software SPI Chip Select + AGPIO(GPIO_SSPI_DC), // Software SPI Data or Command + AGPIO(GPIO_RF_SENSOR), // Rf receiver with sensor decoding + AGPIO(GPIO_AZ_TXD), // AZ-Instrument 7798 CO2 datalogger Serial interface + AGPIO(GPIO_AZ_RXD), // AZ-Instrument 7798 CO2 datalogger Serial interface + AGPIO(GPIO_MAX31855CS), // MAX31855 Serial interface + AGPIO(GPIO_MAX31855CLK), // MAX31855 Serial interface + AGPIO(GPIO_MAX31855DO), // MAX31855 Serial interface + AGPIO(GPIO_KEY1_INV), // Button inverted + AGPIO(GPIO_KEY1_INV) +1, + AGPIO(GPIO_KEY1_INV) +2, + AGPIO(GPIO_KEY1_INV) +3, + AGPIO(GPIO_KEY1_INV_NP), // Button inverted no pullup + AGPIO(GPIO_KEY1_INV_NP) +1, + AGPIO(GPIO_KEY1_INV_NP) +2, + AGPIO(GPIO_KEY1_INV_NP) +3, + AGPIO(GPIO_NRG_SEL), // HLW8012/HLJ-01 Sel output (1 = Voltage) + AGPIO(GPIO_NRG_SEL_INV), // HLW8012/HLJ-01 Sel output (0 = Voltage) + AGPIO(GPIO_NRG_CF1), // HLW8012/HLJ-01 CF1 voltage / current + AGPIO(GPIO_HLW_CF), // HLW8012 CF power + AGPIO(GPIO_HJL_CF), // HJL-01/BL0937 CF power + AGPIO(GPIO_MCP39F5_TX), // MCP39F501 Serial interface (Shelly2) + AGPIO(GPIO_MCP39F5_RX), // MCP39F501 Serial interface (Shelly2) + AGPIO(GPIO_MCP39F5_RST), // MCP39F501 Reset (Shelly2) + AGPIO(GPIO_PN532_TXD), // PN532 HSU Tx + AGPIO(GPIO_PN532_RXD), // PN532 HSU Rx + AGPIO(GPIO_SM16716_CLK), // SM16716 CLOCK + AGPIO(GPIO_SM16716_DAT), // SM16716 DATA + AGPIO(GPIO_SM16716_SEL), // SM16716 SELECT + AGPIO(GPIO_DI), // my92x1 PWM input + AGPIO(GPIO_DCKI), // my92x1 CLK input + AGPIO(GPIO_CSE7766_TX), // CSE7766 Serial interface (S31 and Pow R2) + AGPIO(GPIO_CSE7766_RX), // CSE7766 Serial interface (S31 and Pow R2) + AGPIO(GPIO_ARIRFRCV), // AriLux RF Receive input + AGPIO(GPIO_TXD), // Serial interface + AGPIO(GPIO_RXD), // Serial interface + AGPIO(GPIO_ROT1A), // Rotary A Pin + AGPIO(GPIO_ROT1B), // Rotary B Pin + AGPIO(GPIO_ROT1A) +1, // Rotary A Pin + AGPIO(GPIO_ROT1B) +1, // Rotary B Pin + AGPIO(GPIO_HRE_CLOCK), + AGPIO(GPIO_HRE_DATA), + AGPIO(GPIO_ADE7953_IRQ), // ADE7953 IRQ + AGPIO(GPIO_LEDLNK), // Link led + AGPIO(GPIO_LEDLNK_INV), // Inverted link led + AGPIO(GPIO_ARIRFSEL), // Arilux RF Receive input selected + AGPIO(GPIO_BUZZER), // Buzzer + AGPIO(GPIO_BUZZER_INV), // Inverted buzzer + AGPIO(GPIO_OLED_RESET), // OLED Display Reset + AGPIO(GPIO_SOLAXX1_TX), // Solax Inverter tx pin + AGPIO(GPIO_SOLAXX1_RX), // Solax Inverter rx pin + AGPIO(GPIO_ZIGBEE_TX), // Zigbee Serial interface + AGPIO(GPIO_ZIGBEE_RX), // Zigbee Serial interface + AGPIO(GPIO_RDM6300_RX), + AGPIO(GPIO_IBEACON_TX), + AGPIO(GPIO_IBEACON_RX), + AGPIO(GPIO_A4988_DIR), // A4988 direction pin + AGPIO(GPIO_A4988_STP), // A4988 step pin + AGPIO(GPIO_A4988_ENA), // A4988 enabled pin + AGPIO(GPIO_A4988_MS1), // A4988 microstep pin1 + AGPIO(GPIO_A4988_MS2), // A4988 microstep pin2 + AGPIO(GPIO_A4988_MS3), // A4988 microstep pin3 + AGPIO(GPIO_DDS2382_TX), // DDS2382 Serial interface + AGPIO(GPIO_DDS2382_RX), // DDS2382 Serial interface + AGPIO(GPIO_DDSU666_TX), // DDSU666 Serial interface + AGPIO(GPIO_DDSU666_RX), // DDSU666 Serial interface + AGPIO(GPIO_SM2135_CLK), // SM2135 CLOCK + AGPIO(GPIO_SM2135_DAT), // SM2135 DATA + AGPIO(GPIO_DEEPSLEEP), + AGPIO(GPIO_EXS_ENABLE), // EXS MCU Enable + AGPIO(GPIO_TASMOTACLIENT_TXD), // Tasmota Client TX + AGPIO(GPIO_TASMOTACLIENT_RXD), // Tasmota Client RX + AGPIO(GPIO_TASMOTACLIENT_RST), // Tasmota Client Reset + AGPIO(GPIO_TASMOTACLIENT_RST_INV), // Tasmota Client Reset Inverted + AGPIO(GPIO_HPMA_RX), // Honeywell HPMA115S0 Serial interface + AGPIO(GPIO_HPMA_TX), // Honeywell HPMA115S0 Serial interface + AGPIO(GPIO_GPS_RX), // GPS serial interface + AGPIO(GPIO_GPS_TX), // GPS serial interface + AGPIO(GPIO_DSB_OUT), // Pseudo Single wire DS18B20 or DS18S20 + AGPIO(GPIO_DHT11_OUT), // Pseudo Single wire DHT11, DHT21, DHT22, AM2301, AM2302, AM2321 + AGPIO(GPIO_HM10_RX), // GPS serial interface + AGPIO(GPIO_HM10_TX), // GPS serial interface + AGPIO(GPIO_LE01MR_RX), // F7F LE-01MR energy meter rx pin + AGPIO(GPIO_LE01MR_TX), // F7F LE-01MR energy meter tx pin + AGPIO(GPIO_CC1101_GDO0), // CC1101 pin for RX + AGPIO(GPIO_CC1101_GDO2), // CC1101 pin for RX + AGPIO(GPIO_HRXL_RX), + AGPIO(GPIO_ELECTRIQ_MOODL_TX), + AGPIO(GPIO_AS3935), // AS3935 IRQ Pin + AGPIO(GPIO_PMS5003_TX), // Plantower PMS5003 Serial interface + AGPIO(GPIO_BOILER_OT_RX), + AGPIO(GPIO_BOILER_OT_TX), + AGPIO(GPIO_WINDMETER_SPEED), + AGPIO(GPIO_BL0940_RX), // BL0940 Serial interface + AGPIO(GPIO_TCP_TX), // TCP Serial bridge + AGPIO(GPIO_TCP_RX), // TCP Serial bridge + AGPIO(GPIO_TELEINFO_RX), + AGPIO(GPIO_TELEINFO_ENABLE), + AGPIO(GPIO_LMT01), // LMT01, count pulses on GPIO + AGPIO(GPIO_IEM3000_TX), // IEM3000 Serial interface + AGPIO(GPIO_IEM3000_RX), // IEM3000 Serial interface + AGPIO(GPIO_ZIGBEE_RST), // Zigbee reset + AGPIO(GPIO_DYP_RX) +}; +*/ + // Text in webpage Module Parameters and commands GPIOS and GPIO const char kSensorNames[] PROGMEM = D_SENSOR_NONE "|" @@ -1032,1065 +1255,1065 @@ const uint8_t kModuleTemplateList[MAXMODULE] PROGMEM = { \*********************************************************************************************/ const mytmplt8266 kModules8266[TMP_MAXMODULE_8285] PROGMEM = { - { // SONOFF_BASIC - Sonoff Basic (ESP8266) - AGPIO(GPIO_KEY1), // GPIO00 Button - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_USER), // GPIO02 Only available on newer Sonoff Basic R2 V1 - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_USER), // GPIO04 Optional sensor - 0, // GPIO05 - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1), // GPIO12 Red Led and Relay (0 = Off, 1 = On) - AGPIO(GPIO_LED1_INV), // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status - AGPIO(GPIO_USER), // GPIO14 Optional sensor - 0, // GPIO15 - 0, // GPIO16 - 0 // ADC0 Analog input + { // SONOFF_BASIC - Sonoff Basic (ESP8266) + GPIO_KEY1, // GPIO00 Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Only available on newer Sonoff Basic R2 V1 + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_USER, // GPIO04 Optional sensor + 0, // GPIO05 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status + GPIO_USER, // GPIO14 Optional sensor + 0, // GPIO15 + 0, // GPIO16 + 0 // ADC0 Analog input }, - { // SONOFF_SV - Sonoff SV (ESP8266) - AGPIO(GPIO_KEY1), // GPIO00 Button - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor + { // SONOFF_SV - Sonoff SV (ESP8266) + GPIO_KEY1, // GPIO00 Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor 0, - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_USER), // GPIO04 Optional sensor - AGPIO(GPIO_USER), // GPIO05 Optional sensor - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1), // GPIO12 Red Led and Relay (0 = Off, 1 = On) - AGPIO(GPIO_LED1_INV), // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status - AGPIO(GPIO_USER), // GPIO14 Optional sensor + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_USER, // GPIO04 Optional sensor + GPIO_USER, // GPIO05 Optional sensor + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status + GPIO_USER, // GPIO14 Optional sensor 0, 0, - AGPIO(ADC0_USER) // ADC0 Analog input + ADC0_USER // ADC0 Analog input }, - { // SONOFF_DUAL - Sonoff Dual (ESP8266) - AGPIO(GPIO_USER), // GPIO00 Pad - AGPIO(GPIO_TXD), // GPIO01 Relay control + { // SONOFF_DUAL - Sonoff Dual (ESP8266) + GPIO_USER, // GPIO00 Pad + GPIO_TXD, // GPIO01 Relay control 0, - AGPIO(GPIO_RXD), // GPIO03 Relay control - AGPIO(GPIO_USER), // GPIO04 Optional sensor + GPIO_RXD, // GPIO03 Relay control + GPIO_USER, // GPIO04 Optional sensor 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 0, - AGPIO(GPIO_LED1_INV), // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - AGPIO(GPIO_USER), // GPIO14 Optional sensor + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + GPIO_USER, // GPIO14 Optional sensor 0, 0, 0 }, - { // SONOFF_POW - Sonoff Pow (ESP8266 - HLW8012) - AGPIO(GPIO_KEY1), // GPIO00 Button + { // SONOFF_POW - Sonoff Pow (ESP8266 - HLW8012) + GPIO_KEY1, // GPIO00 Button 0, 0, 0, 0, - AGPIO(GPIO_NRG_SEL), // GPIO05 HLW8012 Sel output (1 = Voltage) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1), // GPIO12 Red Led and Relay (0 = Off, 1 = On) - AGPIO(GPIO_NRG_CF1), // GPIO13 HLW8012 CF1 voltage / current - AGPIO(GPIO_HLW_CF), // GPIO14 HLW8012 CF power - AGPIO(GPIO_LED1), // GPIO15 Blue Led (0 = On, 1 = Off) - Link and Power status + GPIO_NRG_SEL, // GPIO05 HLW8012 Sel output (1 = Voltage) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_NRG_CF1, // GPIO13 HLW8012 CF1 voltage / current + GPIO_HLW_CF, // GPIO14 HLW8012 CF power + GPIO_LED1, // GPIO15 Blue Led (0 = On, 1 = Off) - Link and Power status 0, 0 }, - { // SONOFF_LED - Sonoff LED (ESP8266) - AGPIO(GPIO_KEY1), // GPIO00 Button + { // SONOFF_LED - Sonoff LED (ESP8266) + GPIO_KEY1, // GPIO00 Button 0, 0, 0, - AGPIO(GPIO_USER), // GPIO04 Optional sensor (PWM3 Green) - AGPIO(GPIO_USER), // GPIO05 Optional sensor (PWM2 Red) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_PWM1), // GPIO12 Cold light (PWM0 Cold) - AGPIO(GPIO_LED1_INV), // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - AGPIO(GPIO_PWM1) +1, // GPIO14 Warm light (PWM1 Warm) - AGPIO(GPIO_USER), // GPIO15 Optional sensor (PWM4 Blue) + GPIO_USER, // GPIO04 Optional sensor (PWM3 Green) + GPIO_USER, // GPIO05 Optional sensor (PWM2 Red) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM1, // GPIO12 Cold light (PWM0 Cold) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + GPIO_PWM2, // GPIO14 Warm light (PWM1 Warm) + GPIO_USER, // GPIO15 Optional sensor (PWM4 Blue) 0, 0 }, - { // ELECTRODRAGON - ElectroDragon IoT Relay Board (ESP8266) - AGPIO(GPIO_KEY1) +1, // GPIO00 Button 2 - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_KEY1), // GPIO02 Button 1 - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_USER), // GPIO04 Optional sensor - AGPIO(GPIO_USER), // GPIO05 Optional sensor - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1) +1, // GPIO12 Red Led and Relay 2 (0 = Off, 1 = On) - AGPIO(GPIO_REL1), // GPIO13 Red Led and Relay 1 (0 = Off, 1 = On) - AGPIO(GPIO_USER), // GPIO14 Optional sensor - AGPIO(GPIO_USER), // GPIO15 Optional sensor - AGPIO(GPIO_LED1), // GPIO16 Green/Blue Led (1 = On, 0 = Off) - Link and Power status - AGPIO(ADC0_USER) // ADC0 A0 Analog input + { // ELECTRODRAGON - ElectroDragon IoT Relay Board (ESP8266) + GPIO_KEY2, // GPIO00 Button 2 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_KEY1, // GPIO02 Button 1 + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_USER, // GPIO04 Optional sensor + GPIO_USER, // GPIO05 Optional sensor + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL2, // GPIO12 Red Led and Relay 2 (0 = Off, 1 = On) + GPIO_REL1, // GPIO13 Red Led and Relay 1 (0 = Off, 1 = On) + GPIO_USER, // GPIO14 Optional sensor + GPIO_USER, // GPIO15 Optional sensor + GPIO_LED1, // GPIO16 Green/Blue Led (1 = On, 0 = Off) - Link and Power status + ADC0_USER // ADC0 A0 Analog input }, - { // EXS_RELAY - ES-Store Latching relay(s) (ESP8266) - // https://ex-store.de/ESP8266-WiFi-Relay-V31 - // V3.1 Module Pin 1 VCC 3V3, Module Pin 6 GND - // https://ex-store.de/2-Kanal-WiFi-WLan-Relay-V5-Blackline-fuer-Unterputzmontage - AGPIO(GPIO_USER), // GPIO00 V3.1 Module Pin 8 - V5.0 Module Pin 4 - AGPIO(GPIO_USER), // GPIO01 UART0_TXD V3.1 Module Pin 2 - V5.0 Module Pin 3 - AGPIO(GPIO_USER), // GPIO02 V3.1 Module Pin 7 - AGPIO(GPIO_USER), // GPIO03 UART0_RXD V3.1 Module Pin 3 - AGPIO(GPIO_USER), // GPIO04 V3.1 Module Pin 10 - V5.0 Module Pin 2 - AGPIO(GPIO_USER), // GPIO05 V3.1 Module Pin 9 - V5.0 Module Pin 1 - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1), // GPIO12 Relay1 ( 1 = Off) - AGPIO(GPIO_REL1) +1, // GPIO13 Relay1 ( 1 = On) - AGPIO(GPIO_USER), // GPIO14 V3.1 Module Pin 5 - V5.0 GPIO_REL3_INV Relay2 ( 1 = Off) - AGPIO(GPIO_LED1), // GPIO15 V5.0 LED1 - Link and Power status - AGPIO(GPIO_USER), // GPIO16 V3.1 Module Pin 4 - V5.0 GPIO_REL4_INV Relay2 ( 1 = On) + { // EXS_RELAY - ES-Store Latching relay(s) (ESP8266) + // https://ex-store.de/ESP8266-WiFi-Relay-V31 + // V3.1 Module Pin 1 VCC 3V3, Module Pin 6 GND + // https://ex-store.de/2-Kanal-WiFi-WLan-Relay-V5-Blackline-fuer-Unterputzmontage + GPIO_USER, // GPIO00 V3.1 Module Pin 8 - V5.0 Module Pin 4 + GPIO_USER, // GPIO01 UART0_TXD V3.1 Module Pin 2 - V5.0 Module Pin 3 + GPIO_USER, // GPIO02 V3.1 Module Pin 7 + GPIO_USER, // GPIO03 UART0_RXD V3.1 Module Pin 3 + GPIO_USER, // GPIO04 V3.1 Module Pin 10 - V5.0 Module Pin 2 + GPIO_USER, // GPIO05 V3.1 Module Pin 9 - V5.0 Module Pin 1 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Relay1 ( 1 = Off) + GPIO_REL2, // GPIO13 Relay1 ( 1 = On) + GPIO_USER, // GPIO14 V3.1 Module Pin 5 - V5.0 GPIO_REL3_INV Relay2 ( 1 = Off) + GPIO_LED1, // GPIO15 V5.0 LED1 - Link and Power status + GPIO_USER, // GPIO16 V3.1 Module Pin 4 - V5.0 GPIO_REL4_INV Relay2 ( 1 = On) 0 }, - { // WION - Indoor Tap (ESP8266) - // https://www.amazon.com/gp/product/B00ZYLUBJU/ref=s9_acsd_al_bw_c_x_3_w - AGPIO(GPIO_USER), // GPIO00 Optional sensor (pm clock) + { // WION - Indoor Tap (ESP8266) + // https://www.amazon.com/gp/product/B00ZYLUBJU/ref=s9_acsd_al_bw_c_x_3_w + GPIO_USER, // GPIO00 Optional sensor (pm clock) 0, - AGPIO(GPIO_LED1), // GPIO02 Green Led (1 = On, 0 = Off) - Link and Power status + GPIO_LED1, // GPIO02 Green Led (1 = On, 0 = Off) - Link and Power status 0, 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_USER), // GPIO12 Optional sensor (pm data) - AGPIO(GPIO_KEY1), // GPIO13 Button + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 Optional sensor (pm data) + GPIO_KEY1, // GPIO13 Button 0, - AGPIO(GPIO_REL1), // GPIO15 Relay (0 = Off, 1 = On) + GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) 0, 0 }, - { // SONOFF_DEV - Sonoff Dev (ESP8266) - AGPIO(GPIO_KEY1), // GPIO00 E-FW Button - AGPIO(GPIO_USER), // GPIO01 TX Serial RXD and Optional sensor + { // SONOFF_DEV - Sonoff Dev (ESP8266) + GPIO_KEY1, // GPIO00 E-FW Button + GPIO_USER, // GPIO01 TX Serial RXD and Optional sensor 0, // GPIO02 - AGPIO(GPIO_USER), // GPIO03 RX Serial TXD and Optional sensor - AGPIO(GPIO_USER), // GPIO04 Optional sensor - AGPIO(GPIO_USER), // GPIO05 Optional sensor - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_USER), // GPIO12 - AGPIO(GPIO_USER), // GPIO13 BLUE LED - AGPIO(GPIO_USER), // GPIO14 Optional sensor - 0, // GPIO15 - 0, // GPIO16 - AGPIO(ADC0_USER) // ADC0 A0 Analog input + GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor + GPIO_USER, // GPIO04 Optional sensor + GPIO_USER, // GPIO05 Optional sensor + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 + GPIO_USER, // GPIO13 BLUE LED + GPIO_USER, // GPIO14 Optional sensor + 0, // GPIO15 + 0, // GPIO16 + ADC0_USER // ADC0 A0 Analog input }, - { // H801 - Lixada H801 Wifi (ESP8266) - AGPIO(GPIO_USER), // GPIO00 E-FW Button - AGPIO(GPIO_LED1), // GPIO01 Green LED - Link and Power status - AGPIO(GPIO_USER), // GPIO02 TX and Optional sensor - Pin next to TX on the PCB - AGPIO(GPIO_USER), // GPIO03 RX and Optional sensor - Pin next to GND on the PCB - AGPIO(GPIO_PWM1) +4, // GPIO04 W2 - PWM5 - AGPIO(GPIO_LED1_INV) +1, // GPIO05 Red LED - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_PWM1) +2, // GPIO12 Blue - AGPIO(GPIO_PWM1) +1, // GPIO13 Green - AGPIO(GPIO_PWM1) +3, // GPIO14 W1 - PWM4 - AGPIO(GPIO_PWM1), // GPIO15 Red + { // H801 - Lixada H801 Wifi (ESP8266) + GPIO_USER, // GPIO00 E-FW Button + GPIO_LED1, // GPIO01 Green LED - Link and Power status + GPIO_USER, // GPIO02 TX and Optional sensor - Pin next to TX on the PCB + GPIO_USER, // GPIO03 RX and Optional sensor - Pin next to GND on the PCB + GPIO_PWM5, // GPIO04 W2 - PWM5 + GPIO_LED2_INV, // GPIO05 Red LED + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM3, // GPIO12 Blue + GPIO_PWM2, // GPIO13 Green + GPIO_PWM4, // GPIO14 W1 - PWM4 + GPIO_PWM1, // GPIO15 Red 0, 0 }, - { // SONOFF_SC - onoff SC (ESP8266) - AGPIO(GPIO_KEY1), // GPIO00 Button - AGPIO(GPIO_TXD), // GPIO01 RXD to ATMEGA328P - AGPIO(GPIO_USER), // GPIO02 Optional sensor - AGPIO(GPIO_RXD), // GPIO03 TXD to ATMEGA328P + { // SONOFF_SC - onoff SC (ESP8266) + GPIO_KEY1, // GPIO00 Button + GPIO_TXD, // GPIO01 RXD to ATMEGA328P + GPIO_USER, // GPIO02 Optional sensor + GPIO_RXD, // GPIO03 TXD to ATMEGA328P 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 0, - AGPIO(GPIO_LED1_INV), // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status + GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status 0, 0, 0, 0 }, - { // SONOFF_BN - Sonoff BN-SZ01 Ceiling led (ESP8285) + { // SONOFF_BN - Sonoff BN-SZ01 Ceiling led (ESP8285) 0, 0, 0, 0, 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_PWM1), // GPIO12 Light - AGPIO(GPIO_LED1_INV), // GPIO13 Red Led (0 = On, 1 = Off) - Link and Power status + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM1, // GPIO12 Light + GPIO_LED1_INV, // GPIO13 Red Led (0 = On, 1 = Off) - Link and Power status 0, 0, 0, 0 }, - { // HUAFAN_SS - Hua Fan Smart Socket (ESP8266) - like Sonoff Pow - AGPIO(GPIO_LEDLNK_INV), // GPIO00 Blue Led (0 = On, 1 = Off) - Link status + { // HUAFAN_SS - Hua Fan Smart Socket (ESP8266) - like Sonoff Pow + GPIO_LEDLNK_INV, // GPIO00 Blue Led (0 = On, 1 = Off) - Link status 0, 0, - AGPIO(GPIO_LED1_INV), // GPIO03 Red Led (0 = On, 1 = Off) - Power status - AGPIO(GPIO_KEY1), // GPIO04 Button - AGPIO(GPIO_REL1_INV), // GPIO05 Relay (0 = On, 1 = Off) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_NRG_CF1), // GPIO12 HLW8012 CF1 voltage / current - AGPIO(GPIO_NRG_SEL), // GPIO13 HLW8012 Sel output (1 = Voltage) - AGPIO(GPIO_HLW_CF), // GPIO14 HLW8012 CF power + GPIO_LED1_INV, // GPIO03 Red Led (0 = On, 1 = Off) - Power status + GPIO_KEY1, // GPIO04 Button + GPIO_REL1_INV, // GPIO05 Relay (0 = On, 1 = Off) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_CF1, // GPIO12 HLW8012 CF1 voltage / current + GPIO_NRG_SEL, // GPIO13 HLW8012 Sel output (1 = Voltage) + GPIO_HLW_CF, // GPIO14 HLW8012 CF power 0, 0, 0 }, - { // SONOFF_BRIDGE - Sonoff RF Bridge 433 (ESP8285) - AGPIO(GPIO_KEY1), // GPIO00 Button - AGPIO(GPIO_TXD), // GPIO01 RF bridge control - AGPIO(GPIO_USER), // GPIO02 Optional sensor - AGPIO(GPIO_RXD), // GPIO03 RF bridge control - AGPIO(GPIO_USER), // GPIO04 Optional sensor - AGPIO(GPIO_USER), // GPIO05 Optional sensor - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_USER), // GPIO12 Optional sensor - AGPIO(GPIO_LED1_INV), // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - AGPIO(GPIO_USER), // GPIO14 Optional sensor + { // SONOFF_BRIDGE - Sonoff RF Bridge 433 (ESP8285) + GPIO_KEY1, // GPIO00 Button + GPIO_TXD, // GPIO01 RF bridge control + GPIO_USER, // GPIO02 Optional sensor + GPIO_RXD, // GPIO03 RF bridge control + GPIO_USER, // GPIO04 Optional sensor + GPIO_USER, // GPIO05 Optional sensor + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 Optional sensor + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + GPIO_USER, // GPIO14 Optional sensor 0, 0, 0 }, - { // SONOFF_B1 - Sonoff B1 (ESP8285 - my9231) - AGPIO(GPIO_KEY1), // GPIO00 Pad - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor pad - AGPIO(GPIO_USER), // GPIO02 Optional sensor SDA pad - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor pad + { // SONOFF_B1 - Sonoff B1 (ESP8285 - my9231) + GPIO_KEY1, // GPIO00 Pad + GPIO_USER, // GPIO01 Serial RXD and Optional sensor pad + GPIO_USER, // GPIO02 Optional sensor SDA pad + GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_DI), // GPIO12 my9231 DI + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_DI, // GPIO12 my9231 DI 0, - AGPIO(GPIO_DCKI), // GPIO14 my9231 DCKI + GPIO_DCKI, // GPIO14 my9231 DCKI 0, 0, 0 }, - { // AILIGHT - Ai-Thinker RGBW led (ESP8266 - my9291) - AGPIO(GPIO_KEY1), // GPIO00 Pad - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor pad - AGPIO(GPIO_USER), // GPIO02 Optional sensor SDA pad - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor pad + { // AILIGHT - Ai-Thinker RGBW led (ESP8266 - my9291) + GPIO_KEY1, // GPIO00 Pad + GPIO_USER, // GPIO01 Serial RXD and Optional sensor pad + GPIO_USER, // GPIO02 Optional sensor SDA pad + GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 0, - AGPIO(GPIO_DI), // GPIO13 my9291 DI + GPIO_DI, // GPIO13 my9291 DI 0, - AGPIO(GPIO_DCKI), // GPIO15 my9291 DCKI + GPIO_DCKI, // GPIO15 my9291 DCKI 0, 0 }, - { // SONOFF_T11 - Sonoff T1 1CH (ESP8285) - AGPIO(GPIO_KEY1), // GPIO00 Button 1 - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_USER), // GPIO02 Optional Sensor (J3 Pin 5) - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor + { // SONOFF_T11 - Sonoff T1 1CH (ESP8285) + GPIO_KEY1, // GPIO00 Button 1 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional Sensor (J3 Pin 5) + GPIO_USER, // GPIO03 Serial TXD and Optional sensor 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1), // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) - AGPIO(GPIO_LED1_INV), // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status 0, 0, 0, 0 }, - { // SUPLA1 - Supla Espablo (ESP8266) - // http://www.wykop.pl/ramka/3325399/diy-supla-do-puszki-instalacyjnej-podtynkowej-supla-org/ - 0, // GPIO00 Flash jumper - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor + { // SUPLA1 - Supla Espablo (ESP8266) + // http://www.wykop.pl/ramka/3325399/diy-supla-do-puszki-instalacyjnej-podtynkowej-supla-org/ + 0, // GPIO00 Flash jumper + GPIO_USER, // GPIO01 Serial RXD and Optional sensor #ifdef USE_DS18x20 - AGPIO(GPIO_DSB), // GPIO02 DS18B20 sensor + GPIO_DSB, // GPIO02 DS18B20 sensor #else - AGPIO(GPIO_USER), // GPIO02 Optional sensor + GPIO_USER, // GPIO02 Optional sensor #endif - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_KEY1), // GPIO04 Button 1 - AGPIO(GPIO_REL1), // GPIO05 Relay 1 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_USER), // GPIO12 Optional sensor - AGPIO(GPIO_REL1) +1, // GPIO13 Relay 2 (0 = Off, 1 = On) - AGPIO(GPIO_USER), // GPIO14 Optional sensor + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_KEY1, // GPIO04 Button 1 + GPIO_REL1, // GPIO05 Relay 1 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 Optional sensor + GPIO_REL2, // GPIO13 Relay 2 (0 = Off, 1 = On) + GPIO_USER, // GPIO14 Optional sensor 0, - AGPIO(GPIO_LED1), // GPIO16 Led (1 = On, 0 = Off) - Link and Power status - AGPIO(ADC0_USER) // ADC0 A0 Analog input + GPIO_LED1, // GPIO16 Led (1 = On, 0 = Off) - Link and Power status + ADC0_USER // ADC0 A0 Analog input }, - { // WITTY - Witty Cloud Dev Board (ESP8266) - // https://www.aliexpress.com/item/ESP8266-serial-WIFI-Witty-cloud-Development-Board-ESP-12F-module-MINI-nodemcu/32643464555.html - AGPIO(GPIO_USER), // GPIO00 D3 flash push button on interface board - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_LED1_INV), // GPIO02 D4 Blue Led (0 = On, 1 = Off) on ESP-12F - Link and Power status - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_KEY1), // GPIO04 D2 push button on ESP-12F board - AGPIO(GPIO_USER), // GPIO05 D1 optional sensor - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_PWM1) +1, // GPIO12 D6 RGB LED Green - AGPIO(GPIO_PWM1) +2, // GPIO13 D7 RGB LED Blue - AGPIO(GPIO_USER), // GPIO14 D5 optional sensor - AGPIO(GPIO_PWM1), // GPIO15 D8 RGB LED Red - AGPIO(GPIO_USER), // GPIO16 D0 optional sensor - AGPIO(ADC0_USER) // ADC0 A0 Light sensor / Requires USE_ADC_VCC in user_config.h to be disabled + { // WITTY - Witty Cloud Dev Board (ESP8266) + // https://www.aliexpress.com/item/ESP8266-serial-WIFI-Witty-cloud-Development-Board-ESP-12F-module-MINI-nodemcu/32643464555.html + GPIO_USER, // GPIO00 D3 flash push button on interface board + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_LED1_INV, // GPIO02 D4 Blue Led (0 = On, 1 = Off) on ESP-12F - Link and Power status + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_KEY1, // GPIO04 D2 push button on ESP-12F board + GPIO_USER, // GPIO05 D1 optional sensor + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM2, // GPIO12 D6 RGB LED Green + GPIO_PWM3, // GPIO13 D7 RGB LED Blue + GPIO_USER, // GPIO14 D5 optional sensor + GPIO_PWM1, // GPIO15 D8 RGB LED Red + GPIO_USER, // GPIO16 D0 optional sensor + ADC0_USER // ADC0 A0 Light sensor / Requires USE_ADC_VCC in user_config.h to be disabled }, - { // YUNSHAN - Yunshan Wifi Relay (ESP8266) - // https://www.ebay.com/p/Esp8266-220v-10a-Network-Relay-WiFi-Module/1369583381 - // Schematics and Info https://ucexperiment.wordpress.com/2016/12/18/yunshan-esp8266-250v-15a-acdc-network-wifi-relay-module/ - 0, // GPIO00 Flash jumper - Module Pin 8 - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - Module Pin 2 - AGPIO(GPIO_LED1_INV), // GPIO02 Blue Led (0 = On, 1 = Off) on ESP-12F - Module Pin 7 - Link and Power status - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - Module Pin 3 - AGPIO(GPIO_REL1), // GPIO04 Red Led and Relay (0 = Off, 1 = On) - Module Pin 10 - AGPIO(GPIO_KEY1), // GPIO05 Blue Led and OptoCoupler input - Module Pin 9 - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) + { // YUNSHAN - Yunshan Wifi Relay (ESP8266) + // https://www.ebay.com/p/Esp8266-220v-10a-Network-Relay-WiFi-Module/1369583381 + // Schematics and Info https://ucexperiment.wordpress.com/2016/12/18/yunshan-esp8266-250v-15a-acdc-network-wifi-relay-module/ + 0, // GPIO00 Flash jumper - Module Pin 8 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor - Module Pin 2 + GPIO_LED1_INV, // GPIO02 Blue Led (0 = On, 1 = Off) on ESP-12F - Module Pin 7 - Link and Power status + GPIO_USER, // GPIO03 Serial TXD and Optional sensor - Module Pin 3 + GPIO_REL1, // GPIO04 Red Led and Relay (0 = Off, 1 = On) - Module Pin 10 + GPIO_KEY1, // GPIO05 Blue Led and OptoCoupler input - Module Pin 9 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 0, 0, 0, 0, 0, 0 }, - { // MAGICHOME - Magic Home (aka Flux-light) (ESP8266) and Arilux LC10 (ESP8285) - // https://www.aliexpress.com/item/Magic-Home-Mini-RGB-RGBW-Wifi-Controller-For-Led-Strip-Panel-light-Timing-Function-16million-colors/32686853650.html + { // MAGICHOME - Magic Home (aka Flux-light) (ESP8266) and Arilux LC10 (ESP8285) + // https://www.aliexpress.com/item/Magic-Home-Mini-RGB-RGBW-Wifi-Controller-For-Led-Strip-Panel-light-Timing-Function-16million-colors/32686853650.html 0, - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_LED1_INV), // GPIO02 Blue onboard LED - Link and Power status - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_ARIRFRCV), // GPIO04 IR or RF receiver (optional) (Arilux LC10) - AGPIO(GPIO_PWM1) +1, // GPIO05 RGB LED Green - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_PWM1) +2, // GPIO12 RGB LED Blue - AGPIO(GPIO_USER), // GPIO13 RGBW LED White (optional - set to PWM4 for Cold White or Warm White as used on Arilux LC10) - AGPIO(GPIO_PWM1), // GPIO14 RGB LED Red - AGPIO(GPIO_ARIRFSEL), // GPIO15 RF receiver control (Arilux LC10) + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_LED1_INV, // GPIO02 Blue onboard LED - Link and Power status + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional) (Arilux LC10) + GPIO_PWM2, // GPIO05 RGB LED Green + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM3, // GPIO12 RGB LED Blue + GPIO_USER, // GPIO13 RGBW LED White (optional - set to PWM4 for Cold White or Warm White as used on Arilux LC10) + GPIO_PWM1, // GPIO14 RGB LED Red + GPIO_ARIRFSEL, // GPIO15 RF receiver control (Arilux LC10) 0, 0 }, - { // LUANIHVIO - ESP8266_HVIO - // https://luani.de/projekte/esp8266-hvio/ - 0, // GPIO00 Flash jumper - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_USER), // GPIO02 Optional sensor / I2C SDA pad - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_REL1), // GPIO04 Relay 1 (0 = Off, 1 = On) - AGPIO(GPIO_REL1) +1, // GPIO05 Relay 2 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_SWT1), // GPIO12 External input 1 (0 = On, 1 = Off) - AGPIO(GPIO_SWT1) +1, // GPIO13 External input 2 (0 = On, 1 = Off) - AGPIO(GPIO_USER), // GPIO14 Optional sensor / I2C SCL pad - AGPIO(GPIO_LED1), // GPIO15 Led (1 = On, 0 = Off) - Link and Power status + { // LUANIHVIO - ESP8266_HVIO + // https://luani.de/projekte/esp8266-hvio/ + 0, // GPIO00 Flash jumper + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional sensor / I2C SDA pad + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_REL1, // GPIO04 Relay 1 (0 = Off, 1 = On) + GPIO_REL2, // GPIO05 Relay 2 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_SWT1, // GPIO12 External input 1 (0 = On, 1 = Off) + GPIO_SWT2, // GPIO13 External input 2 (0 = On, 1 = Off) + GPIO_USER, // GPIO14 Optional sensor / I2C SCL pad + GPIO_LED1, // GPIO15 Led (1 = On, 0 = Off) - Link and Power status 0, - AGPIO(ADC0_USER) // ADC0 A0 Analog input + ADC0_USER // ADC0 A0 Analog input }, - { // KMC_70011 - KMC 70011 - // https://www.amazon.com/KMC-Timing-Monitoring-Network-125V-240V/dp/B06XRX2GTQ - AGPIO(GPIO_KEY1), // GPIO00 Button + { // KMC_70011 - KMC 70011 + // https://www.amazon.com/KMC-Timing-Monitoring-Network-125V-240V/dp/B06XRX2GTQ + GPIO_KEY1, // GPIO00 Button 0, 0, 0, - AGPIO(GPIO_HLW_CF), // GPIO04 HLW8012 CF power - AGPIO(GPIO_NRG_CF1), // GPIO05 HLW8012 CF1 voltage / current - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_NRG_SEL), // GPIO12 HLW8012 SEL (1 = Voltage) - AGPIO(GPIO_LED1_INV), // GPIO13 Green Led - Link and Power status - AGPIO(GPIO_REL1), // GPIO14 Relay + GPIO_HLW_CF, // GPIO04 HLW8012 CF power + GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 voltage / current + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL, // GPIO12 HLW8012 SEL (1 = Voltage) + GPIO_LED1_INV, // GPIO13 Green Led - Link and Power status + GPIO_REL1, // GPIO14 Relay 0, 0, 0 }, - { // ARILUX_LC01 - Arilux AL-LC01 (ESP8285) - // https://www.banggood.com/nl/ARILUX-AL-LC01-Super-Mini-LED-WIFI-Smart-RGB-Controller-For-RGB-LED-Strip-Light-DC-9-12V-p-1058603.html - // (PwmFrequency 1111Hz) - AGPIO(GPIO_KEY1), // GPIO00 Optional Button - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_ARIRFSEL), // GPIO02 RF receiver control - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_ARIRFRCV), // GPIO04 IR or RF receiver (optional) - AGPIO(GPIO_PWM1), // GPIO05 RGB LED Red - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_PWM1) +1, // GPIO12 RGB LED Green - AGPIO(GPIO_PWM1) +2, // GPIO13 RGB LED Blue - AGPIO(GPIO_USER), // GPIO14 RGBW LED White (optional - set to PWM4 for Cold White or Warm White) + { // ARILUX_LC01 - Arilux AL-LC01 (ESP8285) + // https://www.banggood.com/nl/ARILUX-AL-LC01-Super-Mini-LED-WIFI-Smart-RGB-Controller-For-RGB-LED-Strip-Light-DC-9-12V-p-1058603.html + // (PwmFrequency 1111Hz) + GPIO_KEY1, // GPIO00 Optional Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_ARIRFSEL, // GPIO02 RF receiver control + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional) + GPIO_PWM1, // GPIO05 RGB LED Red + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM2, // GPIO12 RGB LED Green + GPIO_PWM3, // GPIO13 RGB LED Blue + GPIO_USER, // GPIO14 RGBW LED White (optional - set to PWM4 for Cold White or Warm White) 0, 0, 0 }, - { // ARILUX_LC11 - Arilux AL-LC11 (ESP8266) - // https://www.banggood.com/nl/ARILUX-AL-LC11-Super-Mini-LED-WIFI-APP-Controller-RF-Remote-Control-For-RGBWW-LED-Strip-DC9-28V-p-1085112.html - // (PwmFrequency 540Hz) - AGPIO(GPIO_KEY1), // GPIO00 Optional Button - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_ARIRFSEL), // GPIO02 RF receiver control - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_PWM1) +1, // GPIO04 RGB LED Green - AGPIO(GPIO_PWM1), // GPIO05 RGB LED Red - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_PWM1) +4, // GPIO12 RGBCW LED Warm - AGPIO(GPIO_PWM1) +3, // GPIO13 RGBW LED Cold - AGPIO(GPIO_PWM1) +2, // GPIO14 RGB LED Blue - AGPIO(GPIO_ARIRFRCV), // GPIO15 RF receiver input + { // ARILUX_LC11 - Arilux AL-LC11 (ESP8266) + // https://www.banggood.com/nl/ARILUX-AL-LC11-Super-Mini-LED-WIFI-APP-Controller-RF-Remote-Control-For-RGBWW-LED-Strip-DC9-28V-p-1085112.html + // (PwmFrequency 540Hz) + GPIO_KEY1, // GPIO00 Optional Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_ARIRFSEL, // GPIO02 RF receiver control + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_PWM2, // GPIO04 RGB LED Green + GPIO_PWM1, // GPIO05 RGB LED Red + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM5, // GPIO12 RGBCW LED Warm + GPIO_PWM4, // GPIO13 RGBW LED Cold + GPIO_PWM3, // GPIO14 RGB LED Blue + GPIO_ARIRFRCV, // GPIO15 RF receiver input 0, 0 }, - { // ARILUX_LC06 - Arilux AL-LC06 (ESP8285) - // https://www.banggood.com/ARILUX-AL-LC06-LED-WIFI-Smartphone-Controller-Romote-5-Channels-DC12-24V-For-RGBWW-Strip-light-p-1061476.html - AGPIO(GPIO_KEY1), // GPIO00 Optional Button - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_USER), // GPIO02 Empty pad - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_USER), // GPIO04 W2 - PWM5 + { // ARILUX_LC06 - Arilux AL-LC06 (ESP8285) + // https://www.banggood.com/ARILUX-AL-LC06-LED-WIFI-Smartphone-Controller-Romote-5-Channels-DC12-24V-For-RGBWW-Strip-light-p-1061476.html + GPIO_KEY1, // GPIO00 Optional Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Empty pad + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_USER, // GPIO04 W2 - PWM5 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_PWM1) +1, // GPIO12 RGB LED Green - AGPIO(GPIO_PWM1) +2, // GPIO13 RGB LED Blue - AGPIO(GPIO_PWM1), // GPIO14 RGB LED Red - AGPIO(GPIO_USER), // GPIO15 RGBW LED White + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM2, // GPIO12 RGB LED Green + GPIO_PWM3, // GPIO13 RGB LED Blue + GPIO_PWM1, // GPIO14 RGB LED Red + GPIO_USER, // GPIO15 RGBW LED White 0, 0 }, - { // ZENGGE_ZF_WF017 - Zenggee ZJ-WF017-A (ESP12S)) - // https://www.ebay.com/p/Smartphone-Android-IOS-WiFi-Music-Controller-for-RGB-5050-3528-LED-Strip-Light/534446632?_trksid=p2047675.l2644 - AGPIO(GPIO_KEY1), // GPIO00 Optional Button + { // ZENGGE_ZF_WF017 - Zenggee ZJ-WF017-A (ESP12S)) + // https://www.ebay.com/p/Smartphone-Android-IOS-WiFi-Music-Controller-for-RGB-5050-3528-LED-Strip-Light/534446632?_trksid=p2047675.l2644 + GPIO_KEY1, // GPIO00 Optional Button 0, - AGPIO(GPIO_USER), // GPIO02 Empty pad + GPIO_USER, // GPIO02 Empty pad 0, - AGPIO(GPIO_USER), // GPIO04 W2 - PWM5 + GPIO_USER, // GPIO04 W2 - PWM5 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_PWM1) +1, // GPIO12 RGB LED Green - AGPIO(GPIO_PWM1), // GPIO13 RGB LED Red - AGPIO(GPIO_PWM1) +2, // GPIO14 RGB LED Blue + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM2, // GPIO12 RGB LED Green + GPIO_PWM1, // GPIO13 RGB LED Red + GPIO_PWM3, // GPIO14 RGB LED Blue 0, 0, 0 }, - { // SONOFF_POW_R2 - Sonoff Pow R2 (ESP8285 - CSE7766) - AGPIO(GPIO_KEY1), // GPIO00 Button - AGPIO(GPIO_CSE7766_TX), // GPIO01 Serial RXD 4800 baud 8E1 CSE7766 energy sensor + { // SONOFF_POW_R2 - Sonoff Pow R2 (ESP8285 - CSE7766) + GPIO_KEY1, // GPIO00 Button + GPIO_CSE7766_TX, // GPIO01 Serial RXD 4800 baud 8E1 CSE7766 energy sensor 0, - AGPIO(GPIO_CSE7766_RX), // GPIO03 Serial TXD + GPIO_CSE7766_RX, // GPIO03 Serial TXD 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1), // GPIO12 Red Led and Relay (0 = Off, 1 = On) - AGPIO(GPIO_LED1_INV), // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status 0, 0, 0, 0 }, - { // BLITZWOLF_BWSHP - BlitzWolf BW-SHP2 and BW-SHP6 (ESP8285 - BL0937 or HJL-01 Energy Monitoring) - // https://www.banggood.com/BlitzWolf-BW-SHP2-Smart-WIFI-Socket-EU-Plug-220V-16A-Work-with-Amazon-Alexa-Google-Assistant-p-1292899.html - // https://www.amazon.de/Steckdose-Homecube-intelligente-Verbrauchsanzeige-funktioniert/dp/B076Q2LKHG/ref=sr_1_fkmr0_1 - // https://www.amazon.de/Intelligente-Stromverbrauch-Fernsteurung-Schaltbare-Energieklasse/dp/B076WZQS4S/ref=sr_1_1 - // https://www.aliexpress.com/store/product/BlitzWolf-BW-SHP6-EU-Plug-Metering-Version-WIFI-Smart-Socket-220V-240V-10A-Work-with-Amazon/1965360_32945504669.html - AGPIO(GPIO_LED1_INV), // GPIO00 Red Led (1 = On, 0 = Off) - Power status - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_LEDLNK_INV), // GPIO02 Blue Led (1 = On, 0 = Off) - Link status - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor + { // BLITZWOLF_BWSHP - BlitzWolf BW-SHP2 and BW-SHP6 (ESP8285 - BL0937 or HJL-01 Energy Monitoring) + // https://www.banggood.com/BlitzWolf-BW-SHP2-Smart-WIFI-Socket-EU-Plug-220V-16A-Work-with-Amazon-Alexa-Google-Assistant-p-1292899.html + // https://www.amazon.de/Steckdose-Homecube-intelligente-Verbrauchsanzeige-funktioniert/dp/B076Q2LKHG/ref=sr_1_fkmr0_1 + // https://www.amazon.de/Intelligente-Stromverbrauch-Fernsteurung-Schaltbare-Energieklasse/dp/B076WZQS4S/ref=sr_1_1 + // https://www.aliexpress.com/store/product/BlitzWolf-BW-SHP6-EU-Plug-Metering-Version-WIFI-Smart-Socket-220V-240V-10A-Work-with-Amazon/1965360_32945504669.html + GPIO_LED1_INV, // GPIO00 Red Led (1 = On, 0 = Off) - Power status + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_LEDLNK_INV, // GPIO02 Blue Led (1 = On, 0 = Off) - Link status + GPIO_USER, // GPIO03 Serial TXD and Optional sensor 0, - AGPIO(GPIO_HJL_CF), // GPIO05 BL0937 or HJL-01 CF power - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_NRG_SEL_INV), // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) - AGPIO(GPIO_KEY1), // GPIO13 Button - AGPIO(GPIO_NRG_CF1), // GPIO14 BL0937 or HJL-01 CF1 current / voltage - AGPIO(GPIO_REL1), // GPIO15 Relay (0 = Off, 1 = On) + GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_KEY1, // GPIO13 Button + GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage + GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) 0, 0 }, - { // SHELLY1 - Shelly1 Open Source (ESP8266 - 2MB) - https://shelly.cloud/shelly1-open-source/ - AGPIO(GPIO_USER), // GPIO00 - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC - AGPIO(GPIO_USER), // GPIO01 Serial RXD - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC + { // SHELLY1 - Shelly1 Open Source (ESP8266 - 2MB) - https://shelly.cloud/shelly1-open-source/ + GPIO_USER, // GPIO00 - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC + GPIO_USER, // GPIO01 Serial RXD - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC 0, - AGPIO(GPIO_USER), // GPIO03 Serial TXD - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC - AGPIO(GPIO_REL1), // GPIO04 Relay (0 = Off, 1 = On) - AGPIO(GPIO_SWT1_NP), // GPIO05 SW pin - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO03 Serial TXD - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC + GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) + GPIO_SWT1_NP, // GPIO05 SW pin + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 0, 0, 0, 0, 0, 0 }, - { // SHELLY2 - Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ + { // SHELLY2 - Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ 0, - AGPIO(GPIO_MCP39F5_TX), // GPIO01 MCP39F501 Serial input + GPIO_MCP39F5_TX, // GPIO01 MCP39F501 Serial input 0, - AGPIO(GPIO_MCP39F5_RX), // GPIO03 MCP39F501 Serial output - AGPIO(GPIO_REL1), // GPIO04 - AGPIO(GPIO_REL1) +1, // GPIO05 - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_SWT1), // GPIO12 + GPIO_MCP39F5_RX, // GPIO03 MCP39F501 Serial output + GPIO_REL1, // GPIO04 + GPIO_REL2, // GPIO05 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_SWT1, // GPIO12 0, - AGPIO(GPIO_SWT1) +1, // GPIO14 - AGPIO(GPIO_MCP39F5_RST), // GPIO15 MCP39F501 Reset + GPIO_SWT2, // GPIO14 + GPIO_MCP39F5_RST, // GPIO15 MCP39F501 Reset 0, 0 }, - { // PHILIPS - Xiaomi Philips bulb (ESP8266) + { // PHILIPS - Xiaomi Philips bulb (ESP8266) 0, 0, 0, 0, 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_PWM1) +1, // GPIO12 cold/warm light + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM2, // GPIO12 cold/warm light 0, 0, - AGPIO(GPIO_PWM1), // GPIO15 light intensity + GPIO_PWM1, // GPIO15 light intensity 0, 0 }, - { // NEO_COOLCAM - Neo Coolcam (ESP8266) - // https://www.banggood.com/NEO-COOLCAM-WiFi-Mini-Smart-Plug-APP-Remote-Control-Timing-Smart-Socket-EU-Plug-p-1288562.html?cur_warehouse=CN + { // NEO_COOLCAM - Neo Coolcam (ESP8266) + // https://www.banggood.com/NEO-COOLCAM-WiFi-Mini-Smart-Plug-APP-Remote-Control-Timing-Smart-Socket-EU-Plug-p-1288562.html?cur_warehouse=CN 0, 0, 0, 0, - AGPIO(GPIO_LED1_INV), // GPIO04 Red Led (0 = On, 1 = Off) - Link and Power status + GPIO_LED1_INV, // GPIO04 Red Led (0 = On, 1 = Off) - Link and Power status 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1), // GPIO12 Red Led and Relay (0 = Off, 1 = On) - AGPIO(GPIO_KEY1), // GPIO13 Button + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_KEY1, // GPIO13 Button 0, 0, 0, 0 }, - { // ESP_SWITCH - Michael Haustein 4 channel wall switch (ESP07 = ESP8266) - // Use rules for further actions like - rule on power1#state do publish cmnd/other_device/power %value% endon - AGPIO(GPIO_KEY1) +1, // GPIO00 Button 2 - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_REL1_INV) +2, // GPIO02 Yellow Led 3 (0 = On, 1 = Off) - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_KEY1), // GPIO04 Button 1 - AGPIO(GPIO_REL1_INV) +1, // GPIO05 Red Led 2 (0 = On, 1 = Off) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1_INV) +3, // GPIO12 Blue Led 4 (0 = On, 1 = Off) - AGPIO(GPIO_KEY1) +3, // GPIO13 Button 4 - AGPIO(GPIO_KEY1) +2, // GPIO14 Button 3 - AGPIO(GPIO_LED1), // GPIO15 Optional sensor - AGPIO(GPIO_REL1_INV), // GPIO16 Green Led 1 (0 = On, 1 = Off) + { // ESP_SWITCH - Michael Haustein 4 channel wall switch (ESP07 = ESP8266) + // Use rules for further actions like - rule on power1#state do publish cmnd/other_device/power %value% endon + GPIO_KEY2, // GPIO00 Button 2 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_REL3_INV, // GPIO02 Yellow Led 3 (0 = On, 1 = Off) + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_KEY1, // GPIO04 Button 1 + GPIO_REL2_INV, // GPIO05 Red Led 2 (0 = On, 1 = Off) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL4_INV, // GPIO12 Blue Led 4 (0 = On, 1 = Off) + GPIO_KEY4, // GPIO13 Button 4 + GPIO_KEY3, // GPIO14 Button 3 + GPIO_LED1, // GPIO15 Optional sensor + GPIO_REL1_INV, // GPIO16 Green Led 1 (0 = On, 1 = Off) 0 }, - { // OBI - OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko/p/2291706 - AGPIO(GPIO_USER), // GPIO00 - AGPIO(GPIO_USER), // GPIO01 Serial RXD + { // OBI - OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko/p/2291706 + GPIO_USER, // GPIO00 + GPIO_USER, // GPIO01 Serial RXD 0, - AGPIO(GPIO_USER), // GPIO03 Serial TXD - AGPIO(GPIO_LED1), // GPIO04 Blue LED - Link and Power status - AGPIO(GPIO_REL1), // GPIO05 (Relay OFF, but used as Relay Switch) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_LED1) +2, // GPIO12 (Relay ON, but set to LOW, so we can switch with GPIO05) - AGPIO(GPIO_USER), // GPIO13 - AGPIO(GPIO_KEY1), // GPIO14 Button + GPIO_USER, // GPIO03 Serial TXD + GPIO_LED1, // GPIO04 Blue LED - Link and Power status + GPIO_REL1, // GPIO05 (Relay OFF, but used as Relay Switch) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_LED3, // GPIO12 (Relay ON, but set to LOW, so we can switch with GPIO05) + GPIO_USER, // GPIO13 + GPIO_KEY1, // GPIO14 Button 0, - AGPIO(GPIO_USER), // GPIO16 - AGPIO(ADC0_USER) // ADC0 A0 Analog input + GPIO_USER, // GPIO16 + ADC0_USER // ADC0 A0 Analog input }, - { // TECKIN - https://www.amazon.de/gp/product/B07D5V139R + { // TECKIN - https://www.amazon.de/gp/product/B07D5V139R 0, - AGPIO(GPIO_KEY1), // GPIO01 Serial TXD and Button + GPIO_KEY1, // GPIO01 Serial TXD and Button 0, - AGPIO(GPIO_LED1_INV), // GPIO03 Serial RXD and Red Led (0 = On, 1 = Off) - Power status - AGPIO(GPIO_HJL_CF), // GPIO04 BL0937 or HJL-01 CF power - AGPIO(GPIO_NRG_CF1), // GPIO05 BL0937 or HJL-01 CF1 current / voltage - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_NRG_SEL_INV), // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) - AGPIO(GPIO_LEDLNK_INV), // GPIO13 Blue Led (0 = On, 1 = Off) - Link status - AGPIO(GPIO_REL1), // GPIO14 Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO03 Serial RXD and Red Led (0 = On, 1 = Off) - Power status + GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_LEDLNK_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link status + GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) 0, 0, 0 }, - { // APLIC_WDP303075 - Aplic WDP 303075 (ESP8285 - HLW8012 Energy Monitoring) - // https://www.amazon.de/dp/B07CNWVNJ2 + { // APLIC_WDP303075 - Aplic WDP 303075 (ESP8285 - HLW8012 Energy Monitoring) + // https://www.amazon.de/dp/B07CNWVNJ2 0, 0, 0, - AGPIO(GPIO_KEY1), // GPIO03 Button - AGPIO(GPIO_HLW_CF), // GPIO04 HLW8012 CF power - AGPIO(GPIO_NRG_CF1), // GPIO05 HLW8012 CF1 current / voltage - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_NRG_SEL_INV), // GPIO12 HLW8012 CF Sel output (0 = Voltage) - AGPIO(GPIO_LED1_INV), // GPIO13 LED (0 = On, 1 = Off) - Link and Power status - AGPIO(GPIO_REL1), // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On ) + GPIO_KEY1, // GPIO03 Button + GPIO_HLW_CF, // GPIO04 HLW8012 CF power + GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 current / voltage + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage) + GPIO_LED1_INV, // GPIO13 LED (0 = On, 1 = Off) - Link and Power status + GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On ) 0, 0, 0 }, - { // TUYA_DIMMER - Tuya MCU device (ESP8266 w/ separate MCU) - // https://www.amazon.com/gp/product/B07CTNSZZ8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1 - AGPIO(GPIO_USER), // Virtual Button (controlled by MCU) - AGPIO(GPIO_USER), // GPIO01 MCU serial control - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), // GPIO03 MCU serial control - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), // GPIO14 Green Led - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), + { // TUYA_DIMMER - Tuya MCU device (ESP8266 w/ separate MCU) + // https://www.amazon.com/gp/product/B07CTNSZZ8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1 + GPIO_USER, // Virtual Button (controlled by MCU) + GPIO_USER, // GPIO01 MCU serial control + GPIO_USER, + GPIO_USER, // GPIO03 MCU serial control + GPIO_USER, + GPIO_USER, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, + GPIO_USER, + GPIO_USER, // GPIO14 Green Led + GPIO_USER, + GPIO_USER, 0 }, - { // GOSUND - https://www.amazon.de/gp/product/B0777BWS1P + { // GOSUND - https://www.amazon.de/gp/product/B0777BWS1P 0, - AGPIO(GPIO_LEDLNK_INV), // GPIO01 Serial RXD and LED1 (blue) inv - Link status + GPIO_LEDLNK_INV, // GPIO01 Serial RXD and LED1 (blue) inv - Link status 0, - AGPIO(GPIO_KEY1), // GPIO03 Serial TXD and Button - AGPIO(GPIO_HJL_CF), // GPIO04 BL0937 or HJL-01 CF power - AGPIO(GPIO_NRG_CF1), // GPIO05 BL0937 or HJL-01 CF1 current / voltage - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_NRG_SEL_INV), // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) - AGPIO(GPIO_LED1_INV), // GPIO13 LED2 (red) inv - Power status - AGPIO(GPIO_REL1), // GPIO14 Relay (0 = Off, 1 = On) + GPIO_KEY1, // GPIO03 Serial TXD and Button + GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_LED1_INV, // GPIO13 LED2 (red) inv - Power status + GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) 0, 0, 0 }, - { // ARMTRONIX_DIMMERS - ARMTRONIX Dimmer, one or two channel (ESP8266 w/ separate MCU dimmer) - // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-two-triac-board/ - // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-esp8266-one-triac-board-alexaecho/ - AGPIO(GPIO_USER), - AGPIO(GPIO_TXD), // GPIO01 MCU serial control - AGPIO(GPIO_USER), - AGPIO(GPIO_RXD), // GPIO03 MCU serial control - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), + { // ARMTRONIX_DIMMERS - ARMTRONIX Dimmer, one or two channel (ESP8266 w/ separate MCU dimmer) + // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-two-triac-board/ + // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-esp8266-one-triac-board-alexaecho/ + GPIO_USER, + GPIO_TXD, // GPIO01 MCU serial control + GPIO_USER, + GPIO_RXD, // GPIO03 MCU serial control + GPIO_USER, + GPIO_USER, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, + GPIO_USER, + GPIO_USER, + GPIO_USER, + GPIO_USER, 0 }, - { // SK03_TUYA - Outdoor smart plug with power monitoring HLW8012 chip - https://www.amazon.com/gp/product/B07CG7MBPV - AGPIO(GPIO_KEY1), // GPIO00 Button + { // SK03_TUYA - Outdoor smart plug with power monitoring HLW8012 chip - https://www.amazon.com/gp/product/B07CG7MBPV + GPIO_KEY1, // GPIO00 Button 0, 0, 0, - AGPIO(GPIO_HLW_CF), // GPIO04 HLW8012 CF power - AGPIO(GPIO_NRG_CF1), // GPIO05 HLW8012 CF1 current / voltage - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_NRG_SEL_INV), // GPIO12 HLW8012 CF Sel output (0 = Voltage) - AGPIO(GPIO_LED1_INV), // GPIO13 Red Led (0 = On, 1 = Off) - Power status - AGPIO(GPIO_LEDLNK_INV), // GPIO14 Blue Led (0 = On, 1 = Off) - Link status - AGPIO(GPIO_REL1), // GPIO15 Relay (0 = Off, 1 = On) + GPIO_HLW_CF, // GPIO04 HLW8012 CF power + GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 current / voltage + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage) + GPIO_LED1_INV, // GPIO13 Red Led (0 = On, 1 = Off) - Power status + GPIO_LEDLNK_INV, // GPIO14 Blue Led (0 = On, 1 = Off) - Link status + GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) 0, 0 }, - { // PS_16_DZ - PS-16-DZ Dimmer (ESP8266 w/ separate Nuvoton MCU dimmer) - // https://www.aliexpress.com/item/SM-Smart-WIFI-Wall-Dimmer-Light-Switch-US-Ewelink-APP-Remote-Control-Wi-Fi-Wirele-Work/32871151902.html - AGPIO(GPIO_USER), - AGPIO(GPIO_TXD), // GPIO01 MCU serial control - AGPIO(GPIO_USER), - AGPIO(GPIO_RXD), // GPIO03 MCU serial control - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_USER), - AGPIO(GPIO_LED1), // GPIO13 WiFi LED - Link and Power status - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), - AGPIO(GPIO_USER), + { // PS_16_DZ - PS-16-DZ Dimmer (ESP8266 w/ separate Nuvoton MCU dimmer) + // https://www.aliexpress.com/item/SM-Smart-WIFI-Wall-Dimmer-Light-Switch-US-Ewelink-APP-Remote-Control-Wi-Fi-Wirele-Work/32871151902.html + GPIO_USER, + GPIO_TXD, // GPIO01 MCU serial control + GPIO_USER, + GPIO_RXD, // GPIO03 MCU serial control + GPIO_USER, + GPIO_USER, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, + GPIO_LED1, // GPIO13 WiFi LED - Link and Power status + GPIO_USER, + GPIO_USER, + GPIO_USER, 0 }, - { // TECKIN_US - Teckin SP20 US with Energy Monitoring - // https://www.amazon.com/Outlet-Compatible-Monitoring-Function-Required/dp/B079Q5W22B - // https://www.amazon.com/Outlet-ZOOZEE-Monitoring-Function-Compatible/dp/B07J2LR5KN - AGPIO(GPIO_LED1_INV), // GPIO00 Red Led (1 = On, 0 = Off) - Power status + { // TECKIN_US - Teckin SP20 US with Energy Monitoring + // https://www.amazon.com/Outlet-Compatible-Monitoring-Function-Required/dp/B079Q5W22B + // https://www.amazon.com/Outlet-ZOOZEE-Monitoring-Function-Compatible/dp/B07J2LR5KN + GPIO_LED1_INV, // GPIO00 Red Led (1 = On, 0 = Off) - Power status 0, - AGPIO(GPIO_LEDLNK_INV), // GPIO02 Blue Led (1 = On, 0 = Off) - Link status + GPIO_LEDLNK_INV, // GPIO02 Blue Led (1 = On, 0 = Off) - Link status 0, - AGPIO(GPIO_REL1), // GPIO04 Relay (0 = Off, 1 = On) - AGPIO(GPIO_HJL_CF), // GPIO05 BL0937 or HJL-01 CF power - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_NRG_SEL_INV), // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) - AGPIO(GPIO_KEY1), // GPIO13 Button - AGPIO(GPIO_NRG_CF1), // GPIO14 BL0937 or HJL-01 CF1 current / voltage + GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) + GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_KEY1, // GPIO13 Button + GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage 0, 0, 0 }, - { // MANZOKU_EU_4 - "MANZOKU" labeled power strip, EU version - // https://www.amazon.de/Steckdosenleiste-AOFO-Mehrfachsteckdose-Überspannungsschutz-Sprachsteuerung/dp/B07GBSD11P/ - // https://www.amazon.de/Steckdosenleiste-Geekbes-USB-Anschluss-Kompatibel-gesteuert/dp/B078W23BW9/ - 0, // GPIO00 - 0, // GPIO01 Serial RXD + { // MANZOKU_EU_4 - "MANZOKU" labeled power strip, EU version + // https://www.amazon.de/Steckdosenleiste-AOFO-Mehrfachsteckdose-Überspannungsschutz-Sprachsteuerung/dp/B07GBSD11P/ + // https://www.amazon.de/Steckdosenleiste-Geekbes-USB-Anschluss-Kompatibel-gesteuert/dp/B078W23BW9/ + 0, // GPIO00 + 0, // GPIO01 Serial RXD 0, - AGPIO(GPIO_KEY1), // GPIO03 Serial TXD + Button - AGPIO(GPIO_REL1) +1, // GPIO04 Relay 2 - AGPIO(GPIO_REL1), // GPIO05 Relay 1 - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1) +2, // GPIO12 Relay 3 - AGPIO(GPIO_REL1) +3, // GPIO13 Relay 4 - AGPIO(GPIO_USER), // GPIO14 + GPIO_KEY1, // GPIO03 Serial TXD + Button + GPIO_REL2, // GPIO04 Relay 2 + GPIO_REL1, // GPIO05 Relay 1 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL3, // GPIO12 Relay 3 + GPIO_REL4, // GPIO13 Relay 4 + GPIO_USER, // GPIO14 0, - AGPIO(GPIO_USER), // GPIO16 + GPIO_USER, // GPIO16 0 }, - { // OBI2 - OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko-2-stueck-weiss/p/4077673 - 0, // GPIO00 - 0, // GPIO01 Serial RXD + { // OBI2 - OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko-2-stueck-weiss/p/4077673 + 0, // GPIO00 + 0, // GPIO01 Serial RXD 0, - 0, // GPIO03 Serial TXD - AGPIO(GPIO_REL1), // GPIO04 Relay 1 - AGPIO(GPIO_KEY1), // GPIO05 Button - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_LEDLNK_INV), // GPIO12 Green LED - Link status - AGPIO(GPIO_LED1), // GPIO13 Red LED - Power status + 0, // GPIO03 Serial TXD + GPIO_REL1, // GPIO04 Relay 1 + GPIO_KEY1, // GPIO05 Button + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_LEDLNK_INV, // GPIO12 Green LED - Link status + GPIO_LED1, // GPIO13 Red LED - Power status 0, 0, 0, 0 }, - { // YTF_IR_BRIDGE - https://www.aliexpress.com/item/Tuya-universal-Smart-IR-Hub-remote-control-Voice-Control-AC-TV-Work-With-Alexa-Google-Home/32951202513.html - AGPIO(GPIO_USER), // GPIO00 - AGPIO(GPIO_USER), // GPIO01 Serial RXD - AGPIO(GPIO_USER), // GPIO02 - AGPIO(GPIO_USER), // GPIO03 Serial TXD - AGPIO(GPIO_LED1_INV), // GPIO04 Blue Led - Link status - AGPIO(GPIO_IRRECV), // GPIO05 IR Receiver - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - 0, // GPIO12 - AGPIO(GPIO_KEY1), // GPIO13 Button - AGPIO(GPIO_IRSEND), // GPIO14 IR Transmitter + { // YTF_IR_BRIDGE - https://www.aliexpress.com/item/Tuya-universal-Smart-IR-Hub-remote-control-Voice-Control-AC-TV-Work-With-Alexa-Google-Home/32951202513.html + GPIO_USER, // GPIO00 + GPIO_USER, // GPIO01 Serial RXD + GPIO_USER, // GPIO02 + GPIO_USER, // GPIO03 Serial TXD + GPIO_LED1_INV, // GPIO04 Blue Led - Link status + GPIO_IRRECV, // GPIO05 IR Receiver + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + 0, // GPIO12 + GPIO_KEY1, // GPIO13 Button + GPIO_IRSEND, // GPIO14 IR Transmitter 0, 0, 0 }, - { // DIGOO - Digoo DG-SP202 - // https://www.banggood.com/DIGOO-DG-SP202-Dual-EU-Plug-Smart-WIFI-Socket-Individual-Controllable-Energy-Monitor-Remote-Control-Timing-Smart-Home-Outlet-let-p-1375323.html - AGPIO(GPIO_KEY1), // GPIO00 Button1 - 0, // GPIO01 Serial RXD - 0, // GPIO02 - 0, // GPIO03 Serial TXD - AGPIO(GPIO_HJL_CF), // GPIO04 BL0937 or HJL-01 CF power - AGPIO(GPIO_NRG_CF1), // GPIO05 BL0937 or HJL-01 CF1 current / voltage - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_NRG_SEL_INV), // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) - AGPIO(GPIO_LED1), // GPIO13 Blue Leds - Link Status - AGPIO(GPIO_REL1) +1, // GPIO14 Relay2 (0 = Off, 1 = On) and Red Led - AGPIO(GPIO_REL1), // GPIO15 Relay1 (0 = Off, 1 = On) and Red Led - AGPIO(GPIO_KEY1_NP) +1, // GPIO16 Button2, externally pulled up + { // DIGOO - Digoo DG-SP202 + // https://www.banggood.com/DIGOO-DG-SP202-Dual-EU-Plug-Smart-WIFI-Socket-Individual-Controllable-Energy-Monitor-Remote-Control-Timing-Smart-Home-Outlet-let-p-1375323.html + GPIO_KEY1, // GPIO00 Button1 + 0, // GPIO01 Serial RXD + 0, // GPIO02 + 0, // GPIO03 Serial TXD + GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_LED1, // GPIO13 Blue Leds - Link Status + GPIO_REL2, // GPIO14 Relay2 (0 = Off, 1 = On) and Red Led + GPIO_REL1, // GPIO15 Relay1 (0 = Off, 1 = On) and Red Led + GPIO_KEY2_NP, // GPIO16 Button2, externally pulled up 0 }, - { // KA10 - SMANERGY KA10 (ESP8285 - BL0937 Energy Monitoring) - https://www.amazon.es/dp/B07MBTCH2Y - 0, // GPIO00 - AGPIO(GPIO_LEDLNK_INV), // GPIO01 Blue LED - Link status - 0, // GPIO02 - AGPIO(GPIO_KEY1), // GPIO03 Button - AGPIO(GPIO_HJL_CF), // GPIO04 BL0937 CF power - AGPIO(GPIO_NRG_CF1), // GPIO05 BL0937 CF1 voltage / current - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_NRG_SEL_INV), // GPIO12 BL0937 Sel output (1 = Voltage) - AGPIO(GPIO_LED1), // GPIO13 Red LED - Power status - AGPIO(GPIO_REL1), // GPIO14 Relay 1 + { // KA10 - SMANERGY KA10 (ESP8285 - BL0937 Energy Monitoring) - https://www.amazon.es/dp/B07MBTCH2Y + 0, // GPIO00 + GPIO_LEDLNK_INV, // GPIO01 Blue LED - Link status + 0, // GPIO02 + GPIO_KEY1, // GPIO03 Button + GPIO_HJL_CF, // GPIO04 BL0937 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 CF1 voltage / current + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage) + GPIO_LED1, // GPIO13 Red LED - Power status + GPIO_REL1, // GPIO14 Relay 1 0, 0, 0 }, - { // ZX2820 - AGPIO(GPIO_KEY1), // GPIO00 Button + { // ZX2820 + GPIO_KEY1, // GPIO00 Button 0, 0, 0, - AGPIO(GPIO_HLW_CF), // GPIO04 HLW8012 CF power - AGPIO(GPIO_NRG_CF1), // GPIO05 HLW8012 CF1 voltage / current - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_NRG_SEL_INV), // GPIO12 HLW8012 SEL (0 = Voltage) - AGPIO(GPIO_LED1_INV), // GPIO13 Green Led - Link and Power status - AGPIO(GPIO_REL1), // GPIO14 Relay + GPIO_HLW_CF, // GPIO04 HLW8012 CF power + GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 voltage / current + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 HLW8012 SEL (0 = Voltage) + GPIO_LED1_INV, // GPIO13 Green Led - Link and Power status + GPIO_REL1, // GPIO14 Relay 0, 0, 0 }, - { // MI_DESK_LAMP - Mi LED Desk Lamp - https://www.mi.com/global/smartlamp/ + { // MI_DESK_LAMP - Mi LED Desk Lamp - https://www.mi.com/global/smartlamp/ 0, 0, - AGPIO(GPIO_KEY1), // GPIO02 Button + GPIO_KEY1, // GPIO02 Button 0, - AGPIO(GPIO_PWM1), // GPIO04 Cold White - AGPIO(GPIO_PWM1) +1, // GPIO05 Warm White - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_ROT1A), // GPIO12 Rotary switch A pin - AGPIO(GPIO_ROT1B), // GPIO13 Rotary switch B pin + GPIO_PWM1, // GPIO04 Cold White + GPIO_PWM2, // GPIO05 Warm White + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_ROT1A, // GPIO12 Rotary switch A pin + GPIO_ROT1B, // GPIO13 Rotary switch B pin 0, 0, 0, 0 }, - { // SP10 - Tuya SP10 (BL0937 Energy Monitoring) - // https://www.aliexpress.com/item/Smart-Mini-WiFi-Plug-Outlet-Switch-Work-With-ForEcho-Alexa-Google-Home-Remote-EU-Smart-Socket/32963670423.html - 0, // GPIO00 - AGPIO(GPIO_PWM1), // GPIO01 Nightlight - 0, // GPIO02 - AGPIO(GPIO_KEY1), // GPIO03 Button - AGPIO(GPIO_HJL_CF), // GPIO04 BL0937 CF power - AGPIO(GPIO_NRG_CF1), // GPIO05 BL0937 CF1 voltage / current - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_NRG_SEL_INV), // GPIO12 BL0937 Sel output (1 = Voltage) - AGPIO(GPIO_LED1), // GPIO13 Blue LED - Link status - AGPIO(GPIO_REL1), // GPIO14 Relay and red LED + { // SP10 - Tuya SP10 (BL0937 Energy Monitoring) + // https://www.aliexpress.com/item/Smart-Mini-WiFi-Plug-Outlet-Switch-Work-With-ForEcho-Alexa-Google-Home-Remote-EU-Smart-Socket/32963670423.html + 0, // GPIO00 + GPIO_PWM1, // GPIO01 Nightlight + 0, // GPIO02 + GPIO_KEY1, // GPIO03 Button + GPIO_HJL_CF, // GPIO04 BL0937 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 CF1 voltage / current + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage) + GPIO_LED1, // GPIO13 Blue LED - Link status + GPIO_REL1, // GPIO14 Relay and red LED 0, 0, 0 }, - { // WAGA - WAGA life CHCZ02MB (HJL-01 Energy Monitoring) - // https://www.ebay.com/itm/332595697006 - AGPIO(GPIO_LED1_INV), // GPIO00 Red LED - 0, // GPIO01 Serial RXD - 0, // GPIO02 - AGPIO(GPIO_NRG_SEL_INV), // GPIO03 HJL-01 Sel output (1 = Voltage) - 0, // GPIO04 - AGPIO(GPIO_HJL_CF), // GPIO05 HJL-01 CF power - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1), // GPIO12 Relay - AGPIO(GPIO_KEY1), // GPIO13 Button - AGPIO(GPIO_NRG_CF1), // GPIO14 HJL-01 CF1 voltage / current - AGPIO(GPIO_LEDLNK_INV), // GPIO15 Blue LED - Link status + { // WAGA - WAGA life CHCZ02MB (HJL-01 Energy Monitoring) + // https://www.ebay.com/itm/332595697006 + GPIO_LED1_INV, // GPIO00 Red LED + 0, // GPIO01 Serial RXD + 0, // GPIO02 + GPIO_NRG_SEL_INV, // GPIO03 HJL-01 Sel output (1 = Voltage) + 0, // GPIO04 + GPIO_HJL_CF, // GPIO05 HJL-01 CF power + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Relay + GPIO_KEY1, // GPIO13 Button + GPIO_NRG_CF1, // GPIO14 HJL-01 CF1 voltage / current + GPIO_LEDLNK_INV, // GPIO15 Blue LED - Link status 0, 0 }, - { // SYF05 - Sunyesmart SYF05 (a.k.a. Fcmila) = TYWE3S + SM16726 - // Also works with Merkury 904 RGBW Bulbs with 13 set to GPIO_SM16716_SEL - // https://www.flipkart.com/fc-mila-bxav-xs-ad-smart-bulb/p/itmf85zgs45fzr7n - // https://docs.tuya.com/en/hardware/WiFi-module/wifi-e3s-module.html - // http://www.datasheet-pdf.com/PDF/SM16716-Datasheet-Sunmoon-932771 - AGPIO(GPIO_USER), // GPIO00 N.C. - 0, // GPIO01 Serial RXD - AGPIO(GPIO_USER), // GPIO02 N.C. - 0, // GPIO03 Serial TXD - AGPIO(GPIO_SM16716_CLK), // GPIO04 SM16716 Clock - AGPIO(GPIO_PWM1), // GPIO05 White - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_USER), // GPIO12 Alt. White on some devices - AGPIO(GPIO_USER), // GPIO13 SM16716 Enable on some devices - AGPIO(GPIO_SM16716_DAT), // GPIO14 SM16716 Data - 0, // GPIO15 wired to GND - AGPIO(GPIO_USER), // GPIO16 N.C. - AGPIO(ADC0_USER) // ADC0 A0 Analog input + { // SYF05 - Sunyesmart SYF05 (a.k.a. Fcmila) = TYWE3S + SM16726 + // Also works with Merkury 904 RGBW Bulbs with 13 set to GPIO_SM16716_SEL + // https://www.flipkart.com/fc-mila-bxav-xs-ad-smart-bulb/p/itmf85zgs45fzr7n + // https://docs.tuya.com/en/hardware/WiFi-module/wifi-e3s-module.html + // http://www.datasheet-pdf.com/PDF/SM16716-Datasheet-Sunmoon-932771 + GPIO_USER, // GPIO00 N.C. + 0, // GPIO01 Serial RXD + GPIO_USER, // GPIO02 N.C. + 0, // GPIO03 Serial TXD + GPIO_SM16716_CLK, // GPIO04 SM16716 Clock + GPIO_PWM1, // GPIO05 White + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 Alt. White on some devices + GPIO_USER, // GPIO13 SM16716 Enable on some devices + GPIO_SM16716_DAT, // GPIO14 SM16716 Data + 0, // GPIO15 wired to GND + GPIO_USER, // GPIO16 N.C. + ADC0_USER // ADC0 A0 Analog input }, - { // EXS_DIMMER - EX-Store WiFi Dimmer v4, two channel (ESP8266 w/ separate MCU dimmer) - // https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A - // https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A-ESP8266-V12-Stift-und-Buchsenleisten + { // EXS_DIMMER - EX-Store WiFi Dimmer v4, two channel (ESP8266 w/ separate MCU dimmer) + // https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A + // https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A-ESP8266-V12-Stift-und-Buchsenleisten 0, - AGPIO(GPIO_TXD), // GPIO01 MCU serial control - AGPIO(GPIO_LEDLNK), // GPIO02 LED Link - AGPIO(GPIO_RXD), // GPIO03 MCU serial control - AGPIO(GPIO_USER), // GPIO04 - AGPIO(GPIO_USER), // GPIO05 - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_USER), // GPIO12 - AGPIO(GPIO_EXS_ENABLE), // GPIO13 EXS MCU Enable - AGPIO(GPIO_USER), // GPIO14 - 0, // GPIO15 + GPIO_TXD, // GPIO01 MCU serial control + GPIO_LEDLNK, // GPIO02 LED Link + GPIO_RXD, // GPIO03 MCU serial control + GPIO_USER, // GPIO04 + GPIO_USER, // GPIO05 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 + GPIO_EXS_ENABLE, // GPIO13 EXS MCU Enable + GPIO_USER, // GPIO14 + 0, // GPIO15 0, 0 }, - { // PWM_DIMMER - Support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM - // dimmer switches. The brightness of the load for these dimmers is - // controlled by a PWM GPIO pin. There are typically power, up & down - // buttons and 4 LED's. Examples are: - // https://www.amazon.com/dp/B07FXYSVR1 - // https://www.amazon.com/dp/B07V26Q3VD - // https://www.amazon.com/dp/B07K67D43J - // https://www.amazon.com/dp/B07TTGFWFM - AGPIO(GPIO_KEY1) +2, // GPIO00 Up button - AGPIO(GPIO_KEY1) +1, // GPIO01 Down button - 0, // GPIO02 - AGPIO(GPIO_LED1_INV) +3, // GPIO03 Level 5 LED - AGPIO(GPIO_LEDLNK_INV), // GPIO04 LED Link - AGPIO(GPIO_LED1_INV) +2, // GPIO05 Level 4 LED - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_LED1_INV) +1, // GPIO12 Level 3 LED - AGPIO(GPIO_PWM1), // GPIO13 Dimmer PWM - AGPIO(GPIO_LED1_INV), // GPIO12 Level 2 LED - AGPIO(GPIO_KEY1_INV), // GPIO15 Power button - AGPIO(GPIO_REL1_INV), // GPIO16 Power relay/Level 1 LED + { // PWM_DIMMER - Support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM + // dimmer switches. The brightness of the load for these dimmers is + // controlled by a PWM GPIO pin. There are typically power, up & down + // buttons and 4 LED's. Examples are: + // https://www.amazon.com/dp/B07FXYSVR1 + // https://www.amazon.com/dp/B07V26Q3VD + // https://www.amazon.com/dp/B07K67D43J + // https://www.amazon.com/dp/B07TTGFWFM + GPIO_KEY3, // GPIO00 Up button + GPIO_KEY2, // GPIO01 Down button + 0, // GPIO02 + GPIO_LED4_INV, // GPIO03 Level 5 LED + GPIO_LEDLNK_INV, // GPIO04 LED Link + GPIO_LED3_INV, // GPIO05 Level 4 LED + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_LED2_INV, // GPIO12 Level 3 LED + GPIO_PWM1, // GPIO13 Dimmer PWM + GPIO_LED1_INV, // GPIO12 Level 2 LED + GPIO_KEY1_INV, // GPIO15 Power button + GPIO_REL1_INV, // GPIO16 Power relay/Level 1 LED 0 }, - { // SONOFF_ZB_BRIDGE - Sonoff Zigbee Bridge (ESP8266) - AGPIO(GPIO_LED1_INV), // GPIO00 Green Led (0 = On, 1 = Off) - Traffic between ESP and EFR - AGPIO(GPIO_ZIGBEE_TX), // GPIO01 Zigbee Serial control - 0, // GPIO02 - AGPIO(GPIO_ZIGBEE_RX), // GPIO03 Zigbee Serial control - AGPIO(GPIO_ZIGBEE_RST), // GPIO04 Zigbee Reset - 0, // GPIO05 EFR32 Bootloader mode (drive Low for Gecko Bootloader, inactive or high for Zigbee EmberZNet) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_I2C_SDA), // GPIO12 I2C SDA - connected to 512KB EEPROM - AGPIO(GPIO_LEDLNK_INV), // GPIO13 Blue Led (0 = On, 1 = Off) - Link status - AGPIO(GPIO_I2C_SCL), // GPIO14 I2C SCL - connected to 512KB EEPROM - 0, // GPIO15 connected to IO15 pad, also used for logging - AGPIO(GPIO_KEY1), // GPIO16 Button + { // SONOFF_ZB_BRIDGE - Sonoff Zigbee Bridge (ESP8266) + GPIO_LED1_INV, // GPIO00 Green Led (0 = On, 1 = Off) - Traffic between ESP and EFR + GPIO_ZIGBEE_TX, // GPIO01 Zigbee Serial control + 0, // GPIO02 + GPIO_ZIGBEE_RX, // GPIO03 Zigbee Serial control + GPIO_ZIGBEE_RST, // GPIO04 Zigbee Reset + 0, // GPIO05 EFR32 Bootloader mode (drive Low for Gecko Bootloader, inactive or high for Zigbee EmberZNet) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_I2C_SDA, // GPIO12 I2C SDA - connected to 512KB EEPROM + GPIO_LEDLNK_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link status + GPIO_I2C_SCL, // GPIO14 I2C SCL - connected to 512KB EEPROM + 0, // GPIO15 connected to IO15 pad, also used for logging + GPIO_KEY1, // GPIO16 Button 0 } }; @@ -2100,113 +2323,113 @@ const mytmplt8266 kModules8266[TMP_MAXMODULE_8285] PROGMEM = { \*********************************************************************************************/ const mytmplt kModules8285[TMP_MAXMODULE_8266 - TMP_WEMOS] PROGMEM = { - { // WEMOS - Any ESP8266/ESP8285 device like WeMos and NodeMCU hardware (ESP8266) - AGPIO(GPIO_USER), // GPIO00 D3 Wemos Button Shield - AGPIO(GPIO_USER), // GPIO01 TX Serial RXD - AGPIO(GPIO_USER), // GPIO02 D4 Wemos DHT Shield - AGPIO(GPIO_USER), // GPIO03 RX Serial TXD and Optional sensor - AGPIO(GPIO_USER), // GPIO04 D2 Wemos I2C SDA - AGPIO(GPIO_USER), // GPIO05 D1 Wemos I2C SCL / Wemos Relay Shield (0 = Off, 1 = On) / Wemos WS2812B RGB led Shield - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - AGPIO(GPIO_USER), // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - AGPIO(GPIO_USER), // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_USER), // GPIO12 D6 - AGPIO(GPIO_USER), // GPIO13 D7 - AGPIO(GPIO_USER), // GPIO14 D5 - AGPIO(GPIO_USER), // GPIO15 D8 - AGPIO(GPIO_USER), // GPIO16 D0 Wemos Wake - AGPIO(ADC0_USER) // ADC0 A0 Analog input + { // WEMOS - Any ESP8266/ESP8285 device like WeMos and NodeMCU hardware (ESP8266) + GPIO_USER, // GPIO00 D3 Wemos Button Shield + GPIO_USER, // GPIO01 TX Serial RXD + GPIO_USER, // GPIO02 D4 Wemos DHT Shield + GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor + GPIO_USER, // GPIO04 D2 Wemos I2C SDA + GPIO_USER, // GPIO05 D1 Wemos I2C SCL / Wemos Relay Shield (0 = Off, 1 = On) / Wemos WS2812B RGB led Shield + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_USER, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + GPIO_USER, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 D6 + GPIO_USER, // GPIO13 D7 + GPIO_USER, // GPIO14 D5 + GPIO_USER, // GPIO15 D8 + GPIO_USER, // GPIO16 D0 Wemos Wake + ADC0_USER // ADC0 A0 Analog input }, - { // SONOFF_4CH - Sonoff 4CH (ESP8285) - AGPIO(GPIO_KEY1), // GPIO00 Button 1 - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_USER), // GPIO02 Optional sensor - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_REL1) +2, // GPIO04 Sonoff 4CH Red Led and Relay 3 (0 = Off, 1 = On) - AGPIO(GPIO_REL1) +1, // GPIO05 Sonoff 4CH Red Led and Relay 2 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - AGPIO(GPIO_KEY1) +1, // GPIO09 Button 2 - AGPIO(GPIO_KEY1) +2, // GPIO10 Button 3 - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1), // GPIO12 Red Led and Relay 1 (0 = Off, 1 = On) - Link and Power status - AGPIO(GPIO_LED1_INV), // GPIO13 Blue Led (0 = On, 1 = Off) - AGPIO(GPIO_KEY1) +3, // GPIO14 Button 4 - AGPIO(GPIO_REL1) +3, // GPIO15 Red Led and Relay 4 (0 = Off, 1 = On) + { // SONOFF_4CH - Sonoff 4CH (ESP8285) + GPIO_KEY1, // GPIO00 Button 1 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional sensor + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_REL3, // GPIO04 Sonoff 4CH Red Led and Relay 3 (0 = Off, 1 = On) + GPIO_REL2, // GPIO05 Sonoff 4CH Red Led and Relay 2 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_KEY2, // GPIO09 Button 2 + GPIO_KEY3, // GPIO10 Button 3 + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay 1 (0 = Off, 1 = On) - Link and Power status + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) + GPIO_KEY4, // GPIO14 Button 4 + GPIO_REL4, // GPIO15 Red Led and Relay 4 (0 = Off, 1 = On) 0, 0 }, - { // SONOFF_T12 - Sonoff T1 2CH (ESP8285) - AGPIO(GPIO_KEY1), // GPIO00 Button 1 - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_USER), // GPIO02 Optional Sensor (J3 Pin 5) - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor + { // SONOFF_T12 - Sonoff T1 2CH (ESP8285) + GPIO_KEY1, // GPIO00 Button 1 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional Sensor (J3 Pin 5) + GPIO_USER, // GPIO03 Serial TXD and Optional sensor 0, - AGPIO(GPIO_REL1) +1, // GPIO05 Blue Led and Relay 2 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - AGPIO(GPIO_KEY1) +1, // GPIO09 Button 2 - 0, // GPIO10 - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1), // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) - AGPIO(GPIO_LED1_INV), // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + GPIO_REL2, // GPIO05 Blue Led and Relay 2 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_KEY2, // GPIO09 Button 2 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status 0, 0, 0, 0 }, - { // SONOFF_T13 - Sonoff T1 3CH (ESP8285) - AGPIO(GPIO_KEY1), // GPIO00 Button 1 - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor - AGPIO(GPIO_USER), // GPIO02 Optional Sensor (J3 Pin 5) - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor - AGPIO(GPIO_REL1) +2, // GPIO04 Blue Led and Relay 3 (0 = Off, 1 = On) - AGPIO(GPIO_REL1) +1, // GPIO05 Blue Led and Relay 2 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - AGPIO(GPIO_KEY1) +1, // GPIO09 Button 2 - AGPIO(GPIO_KEY1) +2, // GPIO10 Button 3 - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1), // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) - AGPIO(GPIO_LED1_INV), // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + { // SONOFF_T13 - Sonoff T1 3CH (ESP8285) + GPIO_KEY1, // GPIO00 Button 1 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional Sensor (J3 Pin 5) + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_REL3, // GPIO04 Blue Led and Relay 3 (0 = Off, 1 = On) + GPIO_REL2, // GPIO05 Blue Led and Relay 2 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_KEY2, // GPIO09 Button 2 + GPIO_KEY3, // GPIO10 Button 3 + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status 0, 0, 0, 0 }, - { // SONOFF_DUAL_R2 - Sonoff Dual R2 (ESP8285) - AGPIO(GPIO_USER), // GPIO00 Button 0 on header (0 = On, 1 = Off) - AGPIO(GPIO_USER), // GPIO01 Serial RXD and Optional sensor + { // SONOFF_DUAL_R2 - Sonoff Dual R2 (ESP8285) + GPIO_USER, // GPIO00 Button 0 on header (0 = On, 1 = Off) + GPIO_USER, // GPIO01 Serial RXD and Optional sensor 0, - AGPIO(GPIO_USER), // GPIO03 Serial TXD and Optional sensor + GPIO_USER, // GPIO03 Serial TXD and Optional sensor 0, - AGPIO(GPIO_REL1) +1, // GPIO05 Relay 2 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - AGPIO(GPIO_USER), // GPIO09 Button 1 on header (0 = On, 1 = Off) - AGPIO(GPIO_KEY1), // GPIO10 Button on casing - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1), // GPIO12 Relay 1 (0 = Off, 1 = On) - AGPIO(GPIO_LED1_INV), // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + GPIO_REL2, // GPIO05 Relay 2 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_USER, // GPIO09 Button 1 on header (0 = On, 1 = Off) + GPIO_KEY1, // GPIO10 Button on casing + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Relay 1 (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status 0, 0, 0, 0 }, - { // SONOFF_IFAN03 - Sonoff iFan03 (ESP8285) - AGPIO(GPIO_KEY1), // GPIO00 WIFI_KEY0 Button 1 - AGPIO(GPIO_TXD), // GPIO01 ESP_TXD Serial RXD connection to P0.5 of RF microcontroller - 0, // GPIO02 ESP_LOG - AGPIO(GPIO_RXD), // GPIO03 ESP_RXD Serial TXD connection to P0.4 of RF microcontroller - 0, // GPIO04 DEBUG_RX - 0, // GPIO05 DEBUG_TX - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - AGPIO(GPIO_REL1_INV), // GPIO09 WIFI_O0 Relay 1 (0 = Off, 1 = On) controlling the light - AGPIO(GPIO_BUZZER_INV), // GPIO10 WIFI_O4 Buzzer (0 = Off, 1 = On) - // GPIO11 (SD_CMD Flash) - AGPIO(GPIO_REL1) +2, // GPIO12 WIFI_O2 Relay 3 (0 = Off, 1 = On) controlling the fan - AGPIO(GPIO_LED1_INV), // GPIO13 WIFI_CHK Blue Led on PCA (0 = On, 1 = Off) - Link and Power status - AGPIO(GPIO_REL1) +1, // GPIO14 WIFI_O1 Relay 2 (0 = Off, 1 = On) controlling the fan - AGPIO(GPIO_REL1) +3, // GPIO15 WIFI_O3 Relay 4 (0 = Off, 1 = On) controlling the fan + { // SONOFF_IFAN03 - Sonoff iFan03 (ESP8285) + GPIO_KEY1, // GPIO00 WIFI_KEY0 Button 1 + GPIO_TXD, // GPIO01 ESP_TXD Serial RXD connection to P0.5 of RF microcontroller + 0, // GPIO02 ESP_LOG + GPIO_RXD, // GPIO03 ESP_RXD Serial TXD connection to P0.4 of RF microcontroller + 0, // GPIO04 DEBUG_RX + 0, // GPIO05 DEBUG_TX + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_REL1_INV, // GPIO09 WIFI_O0 Relay 1 (0 = Off, 1 = On) controlling the light + GPIO_BUZZER_INV, // GPIO10 WIFI_O4 Buzzer (0 = Off, 1 = On) + // GPIO11 (SD_CMD Flash) + GPIO_REL3, // GPIO12 WIFI_O2 Relay 3 (0 = Off, 1 = On) controlling the fan + GPIO_LED1_INV, // GPIO13 WIFI_CHK Blue Led on PCA (0 = On, 1 = Off) - Link and Power status + GPIO_REL2, // GPIO14 WIFI_O1 Relay 2 (0 = Off, 1 = On) controlling the fan + GPIO_REL4, // GPIO15 WIFI_O3 Relay 4 (0 = Off, 1 = On) controlling the fan 0, 0 } }; diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index bcd71005f..58fd04c2c 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -57,7 +57,7 @@ struct MQTT { uint8_t initial_connection_state = 2; // MQTT connection messages state bool connected = false; // MQTT virtual connection status bool allowed = false; // MQTT enabled and parameters valid - bool tls_private_key = false; // MQTT require a private key before connecting + bool mqtt_tls = false; // MQTT TLS is enabled } Mqtt; #ifdef USE_MQTT_TLS @@ -149,22 +149,24 @@ void MqttInit(void) // Turn on TLS for port 8883 (TLS) and 8884 (TLS, client certificate) Settings.flag4.mqtt_tls = true; } + Mqtt.mqtt_tls = Settings.flag4.mqtt_tls; // this flag should not change even if we change the SetOption (until reboot) // Detect AWS IoT and set default parameters String host = String(SettingsText(SET_MQTT_HOST)); if (host.indexOf(".iot.") && host.endsWith(".amazonaws.com")) { // look for ".iot." and ".amazonaws.com" in the domain name Settings.flag4.mqtt_no_retain = true; - // Mqtt.tls_private_key = true; } - if (Settings.flag4.mqtt_tls) { + if (Mqtt.mqtt_tls) { tlsClient = new BearSSL::WiFiClientSecure_light(1024,1024); #ifdef USE_MQTT_AWS_IOT loadTlsDir(); // load key and certificate data from Flash - tlsClient->setClientECCert(AWS_IoT_Client_Certificate, - AWS_IoT_Private_Key, - 0xFFFF /* all usages, don't care */, 0); + if ((nullptr != AWS_IoT_Private_Key) && (nullptr != AWS_IoT_Client_Certificate)) { + tlsClient->setClientECCert(AWS_IoT_Client_Certificate, + AWS_IoT_Private_Key, + 0xFFFF /* all usages, don't care */, 0); + } #endif #ifdef USE_MQTT_TLS_CA_CERT @@ -578,8 +580,8 @@ void MqttReconnect(void) } #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) // don't enable MQTT for AWS IoT if Private Key or Certificate are not set - if (Settings.flag4.mqtt_tls && Mqtt.tls_private_key) { - if (!AWS_IoT_Private_Key || !AWS_IoT_Client_Certificate) { + if (Mqtt.mqtt_tls) { + if (0 == strlen(SettingsText(SET_MQTT_PWD))) { // we anticipate that an empty password does not make sense with TLS. This avoids failed connections Mqtt.allowed = false; } } @@ -614,7 +616,7 @@ void MqttReconnect(void) if (MqttClient.connected()) { MqttClient.disconnect(); } #ifdef USE_MQTT_TLS - if (Settings.flag4.mqtt_tls) { + if (Mqtt.mqtt_tls) { tlsClient->stop(); } else { EspClient = WiFiClient(); // Wifi Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497) @@ -632,10 +634,12 @@ void MqttReconnect(void) MqttClient.setCallback(MqttDataHandler); #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) // re-assign private keys in case it was updated in between - if (Settings.flag4.mqtt_tls) { - tlsClient->setClientECCert(AWS_IoT_Client_Certificate, - AWS_IoT_Private_Key, - 0xFFFF /* all usages, don't care */, 0); + if (Mqtt.mqtt_tls) { + if ((nullptr != AWS_IoT_Private_Key) && (nullptr != AWS_IoT_Client_Certificate)) { + tlsClient->setClientECCert(AWS_IoT_Client_Certificate, + AWS_IoT_Private_Key, + 0xFFFF /* all usages, don't care */, 0); + } } #endif MqttClient.setServer(SettingsText(SET_MQTT_HOST), Settings.mqtt_port); @@ -645,7 +649,7 @@ void MqttReconnect(void) bool allow_all_fingerprints; bool learn_fingerprint1; bool learn_fingerprint2; - if (Settings.flag4.mqtt_tls) { + if (Mqtt.mqtt_tls) { allow_all_fingerprints = false; learn_fingerprint1 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[0], 0x00); learn_fingerprint2 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[1], 0x00); @@ -658,16 +662,18 @@ void MqttReconnect(void) #endif bool lwt_retain = Settings.flag4.mqtt_no_retain ? false : true; // no retained last will if "no_retain" #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - if (Settings.flag4.mqtt_tls && Mqtt.tls_private_key) { - // If we require private key then we should null user/pwd - mqtt_user = nullptr; - mqtt_pwd = nullptr; + if (Mqtt.mqtt_tls) { + if ((nullptr != AWS_IoT_Private_Key) && (nullptr != AWS_IoT_Client_Certificate)) { + // if private key is there, we remove user/pwd + mqtt_user = nullptr; + mqtt_pwd = nullptr; + } } #endif if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, lwt_retain, mqtt_data, MQTT_CLEAN_SESSION)) { #ifdef USE_MQTT_TLS - if (Settings.flag4.mqtt_tls) { + if (Mqtt.mqtt_tls) { AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connected in %d ms, max ThunkStack used %d"), millis() - mqtt_connect_time, tlsClient->getMaxThunkStackUse()); if (!tlsClient->getMFLNStatus()) { @@ -739,7 +745,7 @@ void MqttReconnect(void) MqttConnected(); } else { #ifdef USE_MQTT_TLS - if (Settings.flag4.mqtt_tls) { + if (Mqtt.mqtt_tls) { AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connection error: %d"), tlsClient->getLastError()); } #endif @@ -1311,7 +1317,7 @@ void HandleMqttConfiguration(void) SettingsText(SET_MQTT_HOST), Settings.mqtt_port, #ifdef USE_MQTT_TLS - Settings.flag4.mqtt_tls ? " checked" : "", // SetOption102 - Enable MQTT TLS + Mqtt.mqtt_tls ? " checked" : "", // SetOption102 - Enable MQTT TLS #endif // USE_MQTT_TLS Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, SettingsText(SET_MQTT_CLIENT)); WSContentSend_P(HTTP_FORM_MQTT2, @@ -1346,7 +1352,7 @@ void MqttSaveSettings(void) WebGetArg("ml", tmp, sizeof(tmp)); Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); #ifdef USE_MQTT_TLS - Settings.flag4.mqtt_tls = Webserver->hasArg("b3"); // SetOption102 - Enable MQTT TLS + Mqtt.mqtt_tls = Webserver->hasArg("b3"); // SetOption102 - Enable MQTT TLS #endif WebGetArg("mc", tmp, sizeof(tmp)); SettingsUpdateText(SET_MQTT_CLIENT, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp); diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index cd5f986d2..ea8223233 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -136,19 +136,19 @@ Ticker Script_ticker4; void Script_ticker1_end(void) { Script_ticker1.detach(); - Run_Scripter(">ti1", 4,0); + Run_Scripter(">ti1", 4, 0); } void Script_ticker2_end(void) { Script_ticker2.detach(); - Run_Scripter(">ti2", 4,0); + Run_Scripter(">ti2", 4, 0); } void Script_ticker3_end(void) { Script_ticker3.detach(); - Run_Scripter(">ti3", 4,0); + Run_Scripter(">ti3", 4, 0); } void Script_ticker4_end(void) { Script_ticker4.detach(); - Run_Scripter(">ti4", 4,0); + Run_Scripter(">ti4", 4, 0); } #endif @@ -169,7 +169,7 @@ FS *fsp; #ifdef LITTLEFS_SCRIPT_SIZE -void SaveFile(const char *name,const uint8_t *buf,uint32_t len) { +void SaveFile(const char *name, const uint8_t *buf, uint32_t len) { File file = fsp->open(name, "w"); if (!file) return; file.write(buf, len); @@ -179,7 +179,7 @@ void SaveFile(const char *name,const uint8_t *buf,uint32_t len) { uint8_t fs_mounted=0; -void LoadFile(const char *name,uint8_t *buf,uint32_t len) { +void LoadFile(const char *name, uint8_t *buf, uint32_t len) { if (!fs_mounted) { #ifdef ESP32 if (!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)) { @@ -214,7 +214,7 @@ FS *fsp; #else SDClass *fsp; #endif -#endif +#endif //USE_SCRIPT_FATFS #ifndef ESP32 // esp8266 @@ -404,7 +404,7 @@ struct SCRIPT_MEM { FILE_FLAGS file_flags[SFS_MAX]; uint8_t script_sd_found; char flink[2][14]; -#endif +#endif //USE_SCRIPT_FATFS #ifdef USE_SCRIPT_GLOBVARS UDP_FLAGS udp_flags; #endif @@ -423,8 +423,8 @@ char * IPAddressToString(const IPAddress& ip_address) { sprintf_P(ipbuffer, PSTR("%u.%u.%u.%u"), ip_address[0], ip_address[1], ip_address[2], ip_address[3]); return ipbuffer; } -#endif -#endif +#endif //USE_DEVICE_GROUPS +#endif //USE_SCRIPT_GLOBVARS int16_t last_findex; int16_t last_sindex; @@ -436,10 +436,10 @@ uint32_t script_lastmillis; #ifdef USE_BUTTON_EVENT int8_t script_button[MAX_KEYS]; -#endif +#endif //USE_BUTTON_EVENT -char *GetNumericResult(char *lp,uint8_t lastop,float *fp,JsonObject *jo); -char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo); +char *GetNumericArgument(char *lp,uint8_t lastop,float *fp,JsonObject *jo); +char *GetStringArgument(char *lp,uint8_t lastop,char *cp,JsonObject *jo); char *ForceStringVar(char *lp,char *dstr); void send_download(void); uint8_t reject(char *name); @@ -447,75 +447,80 @@ uint8_t reject(char *name); void ScriptEverySecond(void) { if (bitRead(Settings.rule_enabled, 0)) { - struct T_INDEX *vtp=glob_script_mem.type; - float delta=(millis()-script_lastmillis)/1000.0; - script_lastmillis=millis(); + struct T_INDEX *vtp = glob_script_mem.type; + float delta = (millis() - script_lastmillis) / 1000.0; + script_lastmillis = millis(); for (uint8_t count=0; count0) { // decrement - *fp-=delta; - if (*fp<0) *fp=0; + *fp -= delta; + if (*fp<0) *fp = 0; } } if (vtp[count].bits.is_autoinc) { // increments timers - float *fp=&glob_script_mem.fvars[vtp[count].index]; + float *fp = &glob_script_mem.fvars[vtp[count].index]; if (*fp>=0) { - *fp+=delta; + *fp += delta; } } } - Run_Scripter(">S",2,0); + Run_Scripter(">S", 2, 0); } } void RulesTeleperiod(void) { - if (bitRead(Settings.rule_enabled, 0) && mqtt_data[0]) Run_Scripter(">T",2, mqtt_data); + if (bitRead(Settings.rule_enabled, 0) && mqtt_data[0]) Run_Scripter(">T", 2, 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 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++; #define SCRIPT_SKIP_EOL while (*lp==SCRIPT_EOL) lp++; -float *Get_MFAddr(uint8_t index,uint16_t *len,uint16_t *ipos); +float *Get_MFAddr(uint8_t index, uint16_t *len, uint16_t *ipos); // allocates all variables and presets them int16_t Init_Scripter(void) { char *script; - script=glob_script_mem.script_ram; + script = glob_script_mem.script_ram; // scan lines for >DEF - uint16_t lines=0,nvars=0,svars=0,vars=0; - char *lp=script; + uint16_t lines = 0; + uint16_t nvars = 0; + uint16_t svars = 0; + uint16_t vars = 0; + char *lp = script; char vnames[MAXVARS*10]; - char *vnames_p=vnames; + char *vnames_p = vnames; char *vnp[MAXVARS]; - char **vnp_p=vnp; + char **vnp_p = vnp; char strings[MAXSVARS*SCRIPT_MAXSSIZE]; struct M_FILT mfilt[MAXFILT]; - char *strings_p=strings; + char *strings_p = strings; char *snp[MAXSVARS]; - char **snp_p=snp; - uint8_t numperm=0,numflt=0,count; + char **snp_p = snp; + uint8_t numperm = 0; + uint8_t numflt = 0; + uint8_t count; - glob_script_mem.max_ssize=SCRIPT_SVARSIZE; - glob_script_mem.scriptptr=0; + glob_script_mem.max_ssize = SCRIPT_SVARSIZE; + glob_script_mem.scriptptr = 0; if (!*script) return -999; float fvalues[MAXVARS]; struct T_INDEX vtypes[MAXVARS]; - char init=0; + char init = 0; while (1) { // check line // skip leading spaces @@ -527,84 +532,84 @@ char *script; if (init) { // init section if (*lp=='>' || !*lp) { - init=0; + init = 0; break; } - char *op=strchr(lp,'='); + char *op = strchr(lp, '='); if (op) { - vtypes[vars].bits.data=0; + vtypes[vars].bits.data = 0; // found variable definition if (*lp=='p' && *(lp+1)==':') { - lp+=2; + lp += 2; if (numpermMAXFILT) { return -6; } } else { - vtypes[vars].bits.is_filter=0; + vtypes[vars].bits.is_filter = 0; } - *vnp_p++=vnames_p; + *vnp_p ++= vnames_p; while (lpMAXNVARS) { return -1; @@ -616,27 +621,27 @@ char *script; while (*op==' ') op++; if (isdigit(*op)) { // lenght define follows - uint16_t flen=atoi(op); + uint16_t flen = atoi(op); if (flen>MAX_ARRAY_SIZE) { // limit array size - flen=MAX_ARRAY_SIZE; + flen = MAX_ARRAY_SIZE; } - mfilt[numflt-1].numvals&=OR_FILT_MASK; - mfilt[numflt-1].numvals|=flen&AND_FILT_MASK; + mfilt[numflt-1].numvals &= OR_FILT_MASK; + mfilt[numflt-1].numvals |= flen&AND_FILT_MASK; } } } else { // string vars op++; - *snp_p++=strings_p; + *snp_p ++= strings_p; while (*op!='\"') { if (*op==SCRIPT_EOL) break; - *strings_p++=*op++; + *strings_p++ = *op++; } - *strings_p++=0; - vtypes[vars].bits.is_string=1; - vtypes[vars].index=svars; + *strings_p++ = 0; + vtypes[vars].bits.is_string = 1; + vtypes[vars].index = svars; svars++; if (svars>MAXSVARS) { return -2; @@ -648,15 +653,15 @@ char *script; } } } else { - if (!strncmp(lp,">D",2)) { - lp+=2; + if (!strncmp(lp, ">D", 2)) { + lp += 2; SCRIPT_SKIP_SPACES if (isdigit(*lp)) { - uint8_t ssize=atoi(lp)+1; + uint8_t ssize = atoi(lp)+1; if (ssize<10 || ssize>SCRIPT_MAXSSIZE) ssize=SCRIPT_MAXSSIZE; - glob_script_mem.max_ssize=ssize; + glob_script_mem.max_ssize = ssize; } - init=1; + init = 1; } } // next line @@ -666,78 +671,78 @@ char *script; lp++; } - uint16_t fsize=0; + uint16_t fsize = 0; for (count=0; countnumvals=mfilt[count].numvals; - mp+=sizeof(struct M_FILT)+((mfilt[count].numvals&AND_FILT_MASK)-1)*sizeof(float); + uint8_t *mp = (uint8_t*)glob_script_mem.mfilt; + for (count = 0; countnumvals = mfilt[count].numvals; + mp += sizeof(struct M_FILT) + ((mfilt[count].numvals & AND_FILT_MASK) - 1) * sizeof(float); } - glob_script_mem.numvars=vars; - glob_script_mem.script_dprec=SCRIPT_FLOAT_PRECISION; - glob_script_mem.script_loglevel=LOG_LEVEL_INFO; + glob_script_mem.numvars = vars; + glob_script_mem.script_dprec = SCRIPT_FLOAT_PRECISION; + glob_script_mem.script_loglevel = LOG_LEVEL_INFO; #if SCRIPT_DEBUG>2 - struct T_INDEX *dvtp=glob_script_mem.type; - for (uint8_t count=0; count=0 // user sd card - fsp=&SD; + fsp = &SD; if (SD.begin(USE_SCRIPT_FATFS)) { #else // use flash file @@ -836,35 +841,35 @@ char *script; if (FFat.begin(true)) { #else if (fsp->begin()) { -#endif +#endif // ESP32 #endif // USE_SCRIPT_FATFS>=0 - glob_script_mem.script_sd_found=1; + glob_script_mem.script_sd_found = 1; } else { - glob_script_mem.script_sd_found=0; + glob_script_mem.script_sd_found = 0; } } - for (uint8_t cnt=0;cnt0 ClaimSerial(); SetSerialBaudrate(9600); -#endif +#endif //SCRIPT_DEBUG // store start of actual program here - glob_script_mem.scriptptr=lp-1; - glob_script_mem.scriptptr_bu=glob_script_mem.scriptptr; + glob_script_mem.scriptptr = lp - 1; + glob_script_mem.scriptptr_bu = glob_script_mem.scriptptr; #ifdef USE_SCRIPT_GLOBVARS if (glob_script_mem.udp_flags.udp_used) { Script_Init_UDP(); - glob_script=Run_Scripter(">G",-2,0); + glob_script = Run_Scripter(">G", -2, 0); } -#endif +#endif //USE_SCRIPT_GLOBVARS return 0; @@ -899,42 +904,42 @@ void Script_PollUdp(void) { if (glob_script_mem.udp_flags.udp_connected ) { while (Script_PortUdp.parsePacket()) { char packet_buffer[SCRIPT_UDP_BUFFER_SIZE]; - int32_t len = Script_PortUdp.read(packet_buffer, SCRIPT_UDP_BUFFER_SIZE -1); + int32_t len = Script_PortUdp.read(packet_buffer, SCRIPT_UDP_BUFFER_SIZE - 1); packet_buffer[len] = 0; script_udp_remote_ip = Script_PortUdp.remoteIP(); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("UDP: Packet %s - %d - %s"), packet_buffer, len, script_udp_remote_ip.toString().c_str()); char *lp=packet_buffer; - if (!strncmp(lp,"=>",2)) { - lp+=2; - char *cp=strchr(lp,'='); + if (!strncmp(lp,"=>", 2)) { + lp += 2; + char *cp=strchr(lp, '='); if (cp) { char vnam[32]; - for (uint32_t count=0; countG",2,0); + Run_Scripter(">G", 2, 0); } } } @@ -950,167 +955,169 @@ void script_udp_sendvar(char *vname,float *fp,char *sp) { if (!glob_script_mem.udp_flags.udp_used) return; if (!glob_script_mem.udp_flags.udp_connected) return; - char sbuf[SCRIPT_MAXSSIZE+4]; - strcpy(sbuf,"=>"); - strcat(sbuf,vname); - strcat(sbuf,"="); + char sbuf[SCRIPT_MAXSSIZE + 4]; + strcpy(sbuf, "=>"); + strcat(sbuf, vname); + strcat(sbuf, "="); if (fp) { char flstr[16]; - dtostrfd(*fp,8,flstr); - strcat(sbuf,flstr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("num var updated - %s"),sbuf); + dtostrfd(*fp, 8, flstr); + strcat(sbuf, flstr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("num var updated - %s"), sbuf); } else { - strcat(sbuf,sp); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("string var updated - %s"),sbuf); + strcat(sbuf, sp); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("string var updated - %s"), sbuf); } - Script_PortUdp.beginPacket(IPAddress(239,255,255,250), SCRIPT_UDP_PORT); + Script_PortUdp.beginPacket(IPAddress(239, 255, 255, 250), SCRIPT_UDP_PORT); // Udp.print(String("RET UC: ") + String(recv_Packet)); - Script_PortUdp.write((const uint8_t*)sbuf,strlen(sbuf)); + Script_PortUdp.write((const uint8_t*)sbuf, strlen(sbuf)); Script_PortUdp.endPacket(); } -#endif +#endif //USE_SCRIPT_GLOBVARS #ifdef USE_LIGHT #ifdef USE_WS2812 void ws2812_set_array(float *array ,uint32_t len, uint32_t offset) { Ws2812ForceSuspend(); - for (uint32_t cnt=0;cntSettings.light_pixels) break; - uint32_t col=array[cnt]; - Ws2812SetColor(index+1,col>>16,col>>8,col,0); + uint32_t col = array[cnt]; + Ws2812SetColor(index + 1, col>>16, col>>8, col, 0); } Ws2812ForceUpdate(); } -#endif -#endif +#endif //USE_WS2812 +#endif //USE_LIGHT -float median_array(float *array,uint16_t len) { +float median_array(float *array, uint16_t len) { uint8_t ind[len]; - uint8_t mind=0,index=0,flg; - float min=FLT_MAX; + uint8_t mind = 0; + uint8_t index = 0; + uint8_t flg; + float min = FLT_MAX; - for (uint8_t hcnt=0; hcntnumvals&AND_FILT_MASK; - if (ipos) *ipos=mflp->index; + *len = mflp->numvals & AND_FILT_MASK; + if (ipos) *ipos = mflp->index; return mflp->rbuff; } - mp+=sizeof(struct M_FILT)+((mflp->numvals&AND_FILT_MASK)-1)*sizeof(float); + mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float); } return 0; } -float Get_MFVal(uint8_t index,int16_t bind) { - uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; - for (uint8_t count=0; countnumvals&AND_FILT_MASK; + uint16_t maxind = mflp->numvals & AND_FILT_MASK; if (!bind) { return mflp->index; } if (bind<0) { return maxind; } - if (bind<1 || bind>maxind) bind=maxind; - return mflp->rbuff[bind-1]; + if (bind<1 || bind>maxind) bind = maxind; + return mflp->rbuff[bind - 1]; } - mp+=sizeof(struct M_FILT)+((mflp->numvals&AND_FILT_MASK)-1)*sizeof(float); + mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float); } return 0; } -void Set_MFVal(uint8_t index,uint16_t bind,float val) { - uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; - for (uint8_t count=0; countnumvals&AND_FILT_MASK; + uint16_t maxind = mflp->numvals & AND_FILT_MASK; if (!bind) { - mflp->index=val; + mflp->index = val; } else { - if (bind<1 || bind>maxind) bind=maxind; - mflp->rbuff[bind-1]=val; + if (bind<1 || bind>maxind) bind = maxind; + mflp->rbuff[bind-1] = val; } return; } - mp+=sizeof(struct M_FILT)+((mflp->numvals&AND_FILT_MASK)-1)*sizeof(float); + mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float); } } float Get_MFilter(uint8_t index) { - uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; - for (uint8_t count=0; countnumvals&OR_FILT_MASK) { + if (mflp->numvals & OR_FILT_MASK) { // moving average - return mflp->maccu/(mflp->numvals&AND_FILT_MASK); + return mflp->maccu / (mflp->numvals & AND_FILT_MASK); } else { // median, sort array indices - return median_array(mflp->rbuff,mflp->numvals); + return median_array(mflp->rbuff, mflp->numvals); } } - mp+=sizeof(struct M_FILT)+((mflp->numvals&AND_FILT_MASK)-1)*sizeof(float); + mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float); } return 0; } void Set_MFilter(uint8_t index, float invar) { - uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; - for (uint8_t count=0; countnumvals&OR_FILT_MASK) { + if (mflp->numvals & OR_FILT_MASK) { // moving average - mflp->maccu-=mflp->rbuff[mflp->index]; - mflp->maccu+=invar; - mflp->rbuff[mflp->index]=invar; + mflp->maccu -= mflp->rbuff[mflp->index]; + mflp->maccu += invar; + mflp->rbuff[mflp->index] = invar; mflp->index++; - if (mflp->index>=(mflp->numvals&AND_FILT_MASK)) mflp->index=0; + if (mflp->index>=(mflp->numvals&AND_FILT_MASK)) mflp->index = 0; } else { // median - mflp->rbuff[mflp->index]=invar; + mflp->rbuff[mflp->index] = invar; mflp->index++; - if (mflp->index>=mflp->numvals) mflp->index=0; + if (mflp->index>=mflp->numvals) mflp->index = 0; } break; } - mp+=sizeof(struct M_FILT)+((mflp->numvals&AND_FILT_MASK)-1)*sizeof(float); + mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float); } } @@ -1124,17 +1131,16 @@ int8_t index; float DoMedian5(uint8_t index, float in) { - if (index>=MEDIAN_FILTER_NUM) index=0; + if (index>=MEDIAN_FILTER_NUM) index = 0; - struct MEDIAN_FILTER* mf=&script_mf[index]; - mf->buffer[mf->index]=in; + struct MEDIAN_FILTER* mf = &script_mf[index]; + mf->buffer[mf->index] = in; mf->index++; - if (mf->index>=MEDIAN_SIZE) mf->index=0; - return median_array(mf->buffer,MEDIAN_SIZE); + if (mf->index>=MEDIAN_SIZE) mf->index = 0; + return median_array(mf->buffer, MEDIAN_SIZE); } #ifdef USE_LIGHT -//#ifdef USE_WS2812 uint32_t HSVToRGB(uint16_t hue, uint8_t saturation, uint8_t value) { float r = 0, g = 0, b = 0; struct HSV { @@ -1143,9 +1149,9 @@ struct HSV { float V; } hsv; -hsv.H=hue; -hsv.S=(float)saturation/100.0; -hsv.V=(float)value/100.0; +hsv.H = hue; +hsv.S = (float)saturation / 100.0; +hsv.V = (float)value / 100.0; if (hsv.S == 0) { r = hsv.V; @@ -1208,16 +1214,16 @@ if (hsv.S == 0) { } - uint8_t ir,ig,ib; - ir=r*255; - ig=g*255; - ib=b*255; + uint8_t ir, ig, ib; + ir = r * 255; + ig = g * 255; + ib = b * 255; - uint32_t rgb=(ir<<16)|(ig<<8)|ib; + uint32_t rgb = (ir<<16) | (ig<<8) | ib; return rgb; } -#endif -//#endif +#endif //USE_LIGHT + #ifdef USE_ANGLE_FUNC uint32_t pulse_time_hl; @@ -1249,8 +1255,8 @@ uint32_t MeasurePulseTime(int32_t in) { if (in >= 0) { // define pin; pt_pin = in; - pinMode(pt_pin&0x3f,INPUT_PULLUP); - attachInterrupt(pt_pin&0x3f, MP_Timer, CHANGE); + pinMode(pt_pin & 0x3f, INPUT_PULLUP); + attachInterrupt(pt_pin & 0x3f, MP_Timer, CHANGE); pulse_ltime_lh = millis(); pulse_ltime_hl = millis(); return 0; @@ -1269,26 +1275,26 @@ uint32_t MeasurePulseTime(int32_t in) { #ifdef USE_SCRIPT_GLOBVARS uint32_t match_vars(char *dvnam, float **fp, char **sp, uint32_t *ind) { - uint16_t olen=strlen(dvnam); - struct T_INDEX *vtp=glob_script_mem.type; - for (uint32_t count=0; count ff=nothing found, fe=constant number,fd = constant string else bit 7 => 80 = string, 0 = number // no flash strings here for performance reasons!!! -char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,JsonObject *jo) { - uint16_t count,len=0; - uint8_t nres=0; +char *isvar(char *lp, uint8_t *vtype, struct T_INDEX *tind, float *fp, char *sp, JsonObject *jo) { + uint16_t count,len = 0; + uint8_t nres = 0; char vname[32]; - float fvar=0; - tind->index=0; - tind->bits.data=0; + float fvar = 0; + tind->index = 0; + tind->bits.data = 0; if (isdigit(*lp) || (*lp=='-' && isdigit(*(lp+1))) || *lp=='.') { // isnumber if (fp) { if (*lp=='0' && *(lp+1)=='x') { - lp+=2; - *fp=strtol(lp,0,16); + lp += 2; + *fp = strtol(lp, 0, 16); } else { - *fp=CharToFloat(lp); + *fp = CharToFloat(lp); } } if (*lp=='-') lp++; @@ -1324,109 +1330,109 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso if (*lp==0 || *lp==SCRIPT_EOL) break; lp++; } - tind->bits.constant=1; - tind->bits.is_string=0; - *vtype=NUM_RES; + tind->bits.constant = 1; + tind->bits.is_string = 0; + *vtype = NUM_RES; return lp; } if (*lp=='"') { lp++; while (*lp!='"') { if (*lp==0 || *lp==SCRIPT_EOL) break; - uint8_t iob=*lp; + uint8_t iob = *lp; if (iob=='\\') { lp++; if (*lp=='t') { - iob='\t'; + iob = '\t'; } else if (*lp=='n') { - iob='\n'; + iob = '\n'; } else if (*lp=='r') { - iob='\r'; + iob = '\r'; } else if (*lp=='\\') { - iob='\\'; + iob = '\\'; } else { lp--; } - if (sp) *sp++=iob; + if (sp) *sp++ = iob; } else { - if (sp) *sp++=iob; + if (sp) *sp++ = iob; } lp++; } - if (sp) *sp=0; - *vtype=STR_RES; - tind->bits.constant=1; - tind->bits.is_string=1; - return lp+1; + if (sp) *sp = 0; + *vtype = STR_RES; + tind->bits.constant = 1; + tind->bits.is_string = 1; + return lp + 1; } if (*lp=='-') { // inverted var - nres=1; + nres = 1; lp++; } - const char *term="\n\r ])=+-/*%>index=VAR_NV; - glob_script_mem.var_not_found=1; + *vtype = VAR_NV; + tind->index = VAR_NV; + glob_script_mem.var_not_found = 1; return lp; } - struct T_INDEX *vtp=glob_script_mem.type; + struct T_INDEX *vtp = glob_script_mem.type; char dvnam[32]; - strcpy (dvnam,vname); - uint8_t olen=len; - last_findex=-1; - last_sindex=-1; - char *ja=strchr(dvnam,'['); + strcpy (dvnam, vname); + uint8_t olen = len; + last_findex = -1; + last_sindex = -1; + char *ja = strchr(dvnam, '['); if (ja) { - *ja=0; + *ja = 0; ja++; - olen=strlen(dvnam); + olen = strlen(dvnam); } - for (count=0; countindex=count; // overwrite with global var index + if (!strncmp(cp, dvnam, olen)) { + uint8_t index = vtp[count].index; + *tind = vtp[count]; + tind->index = count; // overwrite with global var index if (vtp[count].bits.is_string==0) { - *vtype=NTYPE|index; + *vtype = NTYPE | index; if (vtp[count].bits.is_filter) { if (ja) { - lp+=olen+1; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - last_findex=fvar; - fvar=Get_MFVal(index,fvar); - len=1; + lp += olen + 1; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + last_findex = fvar; + fvar = Get_MFVal(index, fvar); + len = 1; } else { - fvar=Get_MFilter(index); + fvar = Get_MFilter(index); } } else { - fvar=glob_script_mem.fvars[index]; + fvar = glob_script_mem.fvars[index]; } - if (nres) fvar=-fvar; - if (fp) *fp=fvar; + if (nres) fvar = -fvar; + if (fp) *fp = fvar; } else { - *vtype=STYPE|index; - if (sp) strlcpy(sp,glob_script_mem.glob_snp+(index*glob_script_mem.max_ssize),SCRIPT_MAXSSIZE); + *vtype = STYPE|index; + if (sp) strlcpy(sp, glob_script_mem.glob_snp + (index * glob_script_mem.max_ssize), SCRIPT_MAXSSIZE); } - return lp+len; + return lp + len; } } } @@ -1434,50 +1440,50 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso if (jo) { // look for json input char jvname[32]; - strcpy(jvname,vname); + strcpy(jvname, vname); const char* str_value; uint8_t aindex; String vn; - char *ja=strchr(jvname,'['); + char *ja=strchr(jvname, '['); if (ja) { // json array - *ja=0; + *ja = 0; ja++; // fetch array index float fvar; - GetNumericResult(ja,OPER_EQU,&fvar,0); - aindex=fvar; - if (aindex<1 || aindex>6) aindex=1; + GetNumericArgument(ja, OPER_EQU, &fvar, 0); + aindex = fvar; + if (aindex<1 || aindex>6) aindex = 1; aindex--; } if (jo->success()) { - char *subtype=strchr(jvname,'#'); + char *subtype = strchr(jvname, '#'); char *subtype2; if (subtype) { - *subtype=0; + *subtype = 0; subtype++; - subtype2=strchr(subtype,'#'); + subtype2 = strchr(subtype, '#'); if (subtype2) { - *subtype2=0; + *subtype2 = 0; *subtype2++; } } - vn=jvname; + vn = jvname; str_value = (*jo)[vn]; if ((*jo)[vn].success()) { if (subtype) { - JsonObject &jobj1=(*jo)[vn]; + JsonObject &jobj1 = (*jo)[vn]; if (jobj1.success()) { - vn=subtype; - jo=&jobj1; + vn = subtype; + jo = &jobj1; str_value = (*jo)[vn]; if ((*jo)[vn].success()) { // 2. stage if (subtype2) { - JsonObject &jobj2=(*jo)[vn]; + JsonObject &jobj2 = (*jo)[vn]; if ((*jo)[vn].success()) { - vn=subtype2; - jo=&jobj2; + vn = subtype2; + jo = &jobj2; str_value = (*jo)[vn]; if ((*jo)[vn].success()) { goto skip; @@ -1502,33 +1508,33 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso } if (str_value && *str_value) { if ((*jo).is(vn)) { - if (!strncmp(str_value,"ON",2)) { - if (fp) *fp=1; + if (!strncmp(str_value, "ON", 2)) { + if (fp) *fp = 1; goto nexit; - } else if (!strncmp(str_value,"OFF",3)) { - if (fp) *fp=0; + } else if (!strncmp(str_value, "OFF", 3)) { + if (fp) *fp = 0; goto nexit; } else { - *vtype=STR_RES; - tind->bits.constant=1; - tind->bits.is_string=1; - if (sp) strlcpy(sp,str_value,SCRIPT_MAXSSIZE); - return lp+len; + *vtype = STR_RES; + tind->bits.constant = 1; + tind->bits.is_string = 1; + if (sp) strlcpy(sp, str_value, SCRIPT_MAXSSIZE); + return lp + len; } } else { if (fp) { - if (!strncmp(vn.c_str(),"Epoch",5)) { - *fp=atoi(str_value)-(uint32_t)EPOCH_OFFSET; + if (!strncmp(vn.c_str(), "Epoch", 5)) { + *fp = atoi(str_value) - (uint32_t)EPOCH_OFFSET; } else { - *fp=CharToFloat((char*)str_value); + *fp = CharToFloat((char*)str_value); } } nexit: - *vtype=NUM_RES; - tind->bits.constant=1; - tind->bits.is_string=0; - return lp+len; + *vtype = NUM_RES; + tind->bits.constant = 1; + tind->bits.is_string = 0; + return lp + len; } } } @@ -1539,29 +1545,28 @@ chknext: switch (vname[0]) { case 'a': #ifdef USE_ANGLE_FUNC - if (!strncmp(vname,"acos(",5)) { - lp+=5; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - fvar=acosf(fvar); + if (!strncmp(vname, "acos(", 5)) { + lp=GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); + fvar = acosf(fvar); lp++; - len=0; + len = 0; goto exit; } #endif - if (!strncmp(vname,"asc(",4)) { + if (!strncmp(vname, "asc(", 4)) { char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp+4,OPER_EQU,str,0); - fvar=str[0]; + lp = GetStringArgument(lp + 4, OPER_EQU, str, 0); + fvar = str[0]; lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"adc(",4)) { - lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0); + if (!strncmp(vname, "adc(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); while (*lp==' ') lp++; - float fvar1=1; + float fvar1 = 1; if (*lp!=')') { - lp=GetNumericResult(lp,OPER_EQU,&fvar1,0); + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); if (fvar1<32 || fvar1>39) fvar1 = 32; } lp++; @@ -1569,146 +1574,144 @@ chknext: #ifdef ESP32 // ESP32 #ifdef USE_ADC - fvar=AdcRead(fvar1, fvar); + fvar = AdcRead(fvar1, fvar); #else - fvar=999.999; + fvar = 999.999; #endif // USE_ADC #else // ESP8266 #ifndef USE_ADC_VCC - fvar=AdcRead(fvar); + fvar = AdcRead(fvar); #else - fvar=(float)ESP.getVcc()/1000.0; + fvar = (float)ESP.getVcc() / 1000.0; #endif // USE_ADC_VCC #endif // ESP32 - len=0; + len = 0; goto exit; } break; case 'b': - if (!strncmp(vname,"boot",4)) { + if (!strncmp(vname, "boot", 4)) { if (rules_flag.system_boot) { - rules_flag.system_boot=0; - fvar=1; + rules_flag.system_boot = 0; + fvar = 1; } goto exit; } #ifdef USE_BUTTON_EVENT - if (!strncmp(vname,"bt[",3)) { + if (!strncmp(vname, "bt[", 3)) { // tasmota button state - GetNumericResult(vname+3,OPER_EQU,&fvar,0); - uint32_t index=fvar; - if (index<1 || index>MAX_KEYS) index=1; - fvar=script_button[index-1]; - script_button[index-1]|=0x80; + GetNumericArgument(vname+3, OPER_EQU, &fvar, 0); + uint32_t index = fvar; + if (index<1 || index>MAX_KEYS) index = 1; + fvar=script_button[index - 1]; + script_button[index - 1] |= 0x80; len++; goto exit; } -#endif +#endif //USE_BUTTON_EVENT break; case 'c': - if (!strncmp(vname,"chg[",4)) { + if (!strncmp(vname, "chg[", 4)) { // var changed struct T_INDEX ind; uint8_t vtype; - isvar(vname+4,&vtype,&ind,0,0,0); + isvar(vname + 4, &vtype, &ind, 0, 0, 0); if (!ind.bits.constant) { - uint8_t index=glob_script_mem.type[ind.index].index; - if (glob_script_mem.fvars[index]!=glob_script_mem.s_fvars[index]) { + uint8_t index = glob_script_mem.type[ind.index].index; + if (glob_script_mem.fvars[index] != glob_script_mem.s_fvars[index]) { // var has changed - glob_script_mem.s_fvars[index]=glob_script_mem.fvars[index]; - fvar=1; + glob_script_mem.s_fvars[index] = glob_script_mem.fvars[index]; + fvar = 1; len++; goto exit; } else { - fvar=0; + fvar = 0; len++; goto exit; } } } #ifdef ESP32 - if (!strncmp(vname,"core",4)) { - fvar=xPortGetCoreID(); + if (!strncmp(vname, "core", 4)) { + fvar = xPortGetCoreID(); goto exit; } #ifdef USE_SCRIPT_TASK - if (!strncmp(vname,"ct(",3)) { - lp+=3; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + if (!strncmp(vname, "ct(", 3)) { + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); while (*lp==' ') lp++; float fvar1; - lp=GetNumericResult(lp,OPER_EQU,&fvar1,0); + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); while (*lp==' ') lp++; float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); lp++; - fvar=scripter_create_task(fvar,fvar1,fvar2); - len=0; + fvar = scripter_create_task(fvar, fvar1, fvar2); + len = 0; goto exit; } -#endif -#endif +#endif //USE_SCRIPT_TASK +#endif //ESP32 break; case 'd': - if (!strncmp(vname,"day",3)) { - fvar=RtcTime.day_of_month; + if (!strncmp(vname, "day", 3)) { + fvar = RtcTime.day_of_month; goto exit; } break; case 'e': - if (!strncmp(vname,"epoch",5)) { - fvar=UtcTime()-(uint32_t)EPOCH_OFFSET; + if (!strncmp(vname, "epoch", 5)) { + fvar = UtcTime() - (uint32_t)EPOCH_OFFSET; goto exit; } - if (!strncmp(vname,"eres",4)) { - fvar=event_handeled; - tind->index=SCRIPT_EVENT_HANDLED; + if (!strncmp(vname, "eres", 4)) { + fvar = event_handeled; + tind->index = SCRIPT_EVENT_HANDLED; goto exit_settable; } #ifdef USE_ENERGY_SENSOR - if (!strncmp(vname,"enrg[",5)) { - lp+=5; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + if (!strncmp(vname, "enrg[", 5)) { + lp=GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); while (*lp==' ') lp++; switch ((uint32_t)fvar) { case 0: - fvar=Energy.total; + fvar = Energy.total; break; case 1: - fvar=Energy.voltage[0]; + fvar = Energy.voltage[0]; break; case 2: - fvar=Energy.voltage[1]; + fvar = Energy.voltage[1]; break; case 3: - fvar=Energy.voltage[2]; + fvar = Energy.voltage[2]; break; case 4: - fvar=Energy.current[0]; + fvar = Energy.current[0]; break; case 5: - fvar=Energy.current[1]; + fvar = Energy.current[1]; break; case 6: - fvar=Energy.current[2]; + fvar = Energy.current[2]; break; case 7: - fvar=Energy.active_power[0]; + fvar = Energy.active_power[0]; break; case 8: - fvar=Energy.active_power[1]; + fvar = Energy.active_power[1]; break; case 9: - fvar=Energy.active_power[2]; + fvar = Energy.active_power[2]; break; default: - fvar=99999; + fvar = 99999; break; } - len=0; + len = 0; lp++; goto exit; } @@ -1717,166 +1720,161 @@ chknext: case 'f': //#define DEBUG_FS #ifdef USE_SCRIPT_FATFS - if (!strncmp(vname,"fo(",3)) { - lp+=3; + if (!strncmp(vname, "fo(", 3)) { char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,0); + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); while (*lp==' ') lp++; - uint8_t mode=0; + uint8_t mode = 0; if ((*lp=='r') || (*lp=='w') || (*lp=='a')) { switch (*lp) { case 'r': - mode=0; + mode = 0; break; case 'w': - mode=1; + mode = 1; break; case 'a': - mode=2; + mode = 2; break; } lp++; } else { - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - mode=fvar; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + mode = fvar; } - fvar=-1; - for (uint8_t cnt=0;cntopen(str,FILE_READ); + glob_script_mem.files[cnt] = fsp->open(str, FILE_READ); if (glob_script_mem.files[cnt].isDirectory()) { glob_script_mem.files[cnt].rewindDirectory(); - glob_script_mem.file_flags[cnt].is_dir=1; + glob_script_mem.file_flags[cnt].is_dir = 1; } else { - glob_script_mem.file_flags[cnt].is_dir=0; + glob_script_mem.file_flags[cnt].is_dir = 0; } } else { if (mode==1) { - glob_script_mem.files[cnt]=fsp->open(str,FILE_WRITE); + glob_script_mem.files[cnt] = fsp->open(str,FILE_WRITE); #ifdef DEBUG_FS - AddLog_P2(LOG_LEVEL_INFO,PSTR("open file for write %d"),cnt); + AddLog_P2(LOG_LEVEL_INFO, PSTR("open file for write %d"), cnt); #endif } else { - glob_script_mem.files[cnt]=fsp->open(str,FILE_APPEND); + glob_script_mem.files[cnt] = fsp->open(str,FILE_APPEND); #ifdef DEBUG_FS - AddLog_P2(LOG_LEVEL_INFO,PSTR("open file for append %d"),cnt); + AddLog_P2(LOG_LEVEL_INFO, PSTR("open file for append %d"), cnt); #endif } } if (glob_script_mem.files[cnt]) { - fvar=cnt; - glob_script_mem.file_flags[cnt].is_open=1; + fvar = cnt; + glob_script_mem.file_flags[cnt].is_open = 1; } else { - AddLog_P(LOG_LEVEL_INFO,PSTR("file open failed")); + AddLog_P(LOG_LEVEL_INFO, PSTR("file open failed")); } break; } } lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"fc(",3)) { - lp+=3; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + if (!strncmp(vname, "fc(", 3)) { + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); if (fvar>=0) { - uint8_t ind=fvar; - if (ind>=SFS_MAX) ind=SFS_MAX-1; + uint8_t ind = fvar; + if (ind>=SFS_MAX) ind = SFS_MAX - 1; #ifdef DEBUG_FS - AddLog_P2(LOG_LEVEL_INFO,PSTR("closing file %d"),ind); + AddLog_P2(LOG_LEVEL_INFO, PSTR("closing file %d"), ind); #endif glob_script_mem.files[ind].close(); - glob_script_mem.file_flags[ind].is_open=0; + glob_script_mem.file_flags[ind].is_open = 0; } - fvar=0; + fvar = 0; lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"ff(",3)) { - lp+=3; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - uint8_t ind=fvar; - if (ind>=SFS_MAX) ind=SFS_MAX-1; + if (!strncmp(vname, "ff(", 3)) { + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); + uint8_t ind = fvar; + if (ind>=SFS_MAX) ind = SFS_MAX - 1; glob_script_mem.files[ind].flush(); - fvar=0; + fvar = 0; lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"fw(",3)) { - lp+=3; + if (!strncmp(vname, "fw(", 3)) { char str[SCRIPT_MAXSSIZE]; - lp=ForceStringVar(lp,str); + lp = ForceStringVar(lp + 3, str); while (*lp==' ') lp++; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - uint8_t ind=fvar; - if (ind>=SFS_MAX) ind=SFS_MAX-1; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + uint8_t ind = fvar; + if (ind>=SFS_MAX) ind = SFS_MAX - 1; if (glob_script_mem.file_flags[ind].is_open) { - fvar=glob_script_mem.files[ind].print(str); + fvar = glob_script_mem.files[ind].print(str); } else { - fvar=0; + fvar = 0; } lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"fr(",3)) { - lp+=3; + if (!strncmp(vname, "fr(", 3)) { struct T_INDEX ind; uint8_t vtype; - uint8_t sindex=0; - lp=isvar(lp,&vtype,&ind,0,0,0); + uint8_t sindex = 0; + lp = isvar(lp + 3, &vtype, &ind, 0, 0, 0); if (vtype!=VAR_NV) { // found variable as result if ((vtype&STYPE)==0) { // error - fvar=0; + fvar = 0; goto exit; } else { // string result - sindex=glob_script_mem.type[ind.index].index; + sindex = glob_script_mem.type[ind.index].index; } } else { // error - fvar=0; + fvar = 0; goto exit; } while (*lp==' ') lp++; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - uint8_t find=fvar; - if (find>=SFS_MAX) find=SFS_MAX-1; - uint8_t index=0; - char str[glob_script_mem.max_ssize+1]; - char *cp=str; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + uint8_t find = fvar; + if (find>=SFS_MAX) find = SFS_MAX - 1; + uint8_t index = 0; + char str[glob_script_mem.max_ssize + 1]; + char *cp = str; if (glob_script_mem.file_flags[find].is_open) { if (glob_script_mem.file_flags[find].is_dir) { while (true) { - File entry=glob_script_mem.files[find].openNextFile(); + File entry = glob_script_mem.files[find].openNextFile(); if (entry) { if (!reject((char*)entry.name())) { - char *ep=(char*)entry.name(); + char *ep = (char*)entry.name(); if (*ep=='/') ep++; char *lcp = strrchr(ep,'/'); if (lcp) { - ep=lcp+1; + ep = lcp + 1; } - strcpy(str,ep); + strcpy(str, ep); entry.close(); break; } } else { - *cp=0; + *cp = 0; break; } entry.close(); } - index=strlen(str); + index = strlen(str); } else { while (glob_script_mem.files[find].available()) { uint8_t buf[1]; @@ -1884,244 +1882,234 @@ chknext: if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { break; } else { - *cp++=buf[0]; + *cp++ = buf[0]; index++; - if (index>=glob_script_mem.max_ssize-1) break; + if (index>=glob_script_mem.max_ssize - 1) break; } } - *cp=0; + *cp = 0; } } else { - strcpy(str,"file error"); + strcpy(str, "file error"); } lp++; - strlcpy(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); - fvar=index; - len=0; + strlcpy(glob_script_mem.glob_snp + (sindex * glob_script_mem.max_ssize), str, glob_script_mem.max_ssize); + fvar = index; + len = 0; goto exit; } - if (!strncmp(vname,"fd(",3)) { - lp+=3; - char str[glob_script_mem.max_ssize+1]; - lp=GetStringResult(lp,OPER_EQU,str,0); + if (!strncmp(vname, "fd(", 3)) { + char str[glob_script_mem.max_ssize + 1]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); fsp->remove(str); lp++; - len=0; + len = 0; goto exit; } #if defined(ESP32) && defined(USE_WEBCAM) - if (!strncmp(vname,"fwp(",4)) { - lp+=4; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + if (!strncmp(vname, "fwp(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); while (*lp==' ') lp++; float fvar1; - lp=GetNumericResult(lp,OPER_EQU,&fvar1,0); - uint8_t ind=fvar1; - if (ind>=SFS_MAX) ind=SFS_MAX-1; + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); + uint8_t ind = fvar1; + if (ind>=SFS_MAX) ind = SFS_MAX - 1; if (glob_script_mem.file_flags[ind].is_open) { uint8_t *buff; - float maxps=WcGetPicstore(-1,0); - if (fvar<1 || fvar>maxps) fvar=1; - uint32_t len=WcGetPicstore(fvar-1, &buff); + float maxps = WcGetPicstore(-1, 0); + if (fvar<1 || fvar>maxps) fvar = 1; + uint32_t len = WcGetPicstore(fvar - 1, &buff); if (len) { //glob_script_mem.files[ind].seek(0,SeekEnd); - fvar=glob_script_mem.files[ind].write(buff,len); + fvar = glob_script_mem.files[ind].write(buff, len); } else { - fvar=0; + fvar = 0; } //AddLog_P2(LOG_LEVEL_INFO, PSTR("picture save: %d"), len); } else { - fvar=0; + fvar = 0; } lp++; - len=0; + len = 0; goto exit; } -#endif +#endif //ESP32 && USE_WEBCAM #ifdef USE_SCRIPT_FATFS_EXT - if (!strncmp(vname,"fe(",3)) { - lp+=3; - char str[glob_script_mem.max_ssize+1]; - lp=GetStringResult(lp,OPER_EQU,str,0); + if (!strncmp(vname, "fe(", 3)) { + char str[glob_script_mem.max_ssize + 1]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); // execute script - File ef=fsp->open(str,FILE_READ); + File ef = fsp->open(str, FILE_READ); if (ef) { - uint16_t fsiz=ef.size(); + uint16_t fsiz = ef.size(); if (fsiz<2048) { - char *script=(char*)calloc(fsiz+16,1); + char *script = (char*)calloc(fsiz + 16, 1); if (script) { ef.read((uint8_t*)script,fsiz); execute_script(script); free(script); - fvar=1; + fvar = 1; } } ef.close(); } lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"fmd(",4)) { - lp+=4; - char str[glob_script_mem.max_ssize+1]; - lp=GetStringResult(lp,OPER_EQU,str,0); - fvar=fsp->mkdir(str); + if (!strncmp(vname, "fmd(", 4)) { + char str[glob_script_mem.max_ssize + 1]; + lp = GetStringArgument(lp + 4, OPER_EQU, str, 0); + fvar = fsp->mkdir(str); lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"frd(",4)) { - lp+=4; - char str[glob_script_mem.max_ssize+1]; - lp=GetStringResult(lp,OPER_EQU,str,0); - fvar=fsp->rmdir(str); + if (!strncmp(vname, "frd(", 4)) { + char str[glob_script_mem.max_ssize + 1]; + lp = GetStringArgument(lp + 4, OPER_EQU, str, 0); + fvar = fsp->rmdir(str); lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"fx(",3)) { - lp+=3; - char str[glob_script_mem.max_ssize+1]; - lp=GetStringResult(lp,OPER_EQU,str,0); - if (fsp->exists(str)) fvar=1; - else fvar=0; + if (!strncmp(vname, "fx(", 3)) { + char str[glob_script_mem.max_ssize + 1]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + if (fsp->exists(str)) fvar = 1; + else fvar = 0; lp++; - len=0; + len = 0; goto exit; } #endif // USE_SCRIPT_FATFS_EXT - if (!strncmp(vname,"fl1(",4) || !strncmp(vname,"fl2(",4) ) { - uint8_t lknum=*(lp+2)&3; - lp+=4; - char str[glob_script_mem.max_ssize+1]; - lp=GetStringResult(lp,OPER_EQU,str,0); - if (lknum<1 || lknum>2) lknum=1; - strlcpy(glob_script_mem.flink[lknum-1],str,14); + if (!strncmp(vname, "fl1(", 4) || !strncmp(vname, "fl2(", 4) ) { + uint8_t lknum = *(lp+2)&3; + char str[glob_script_mem.max_ssize + 1]; + lp = GetStringArgument(lp + 4, OPER_EQU, str, 0); + if (lknum<1 || lknum>2) lknum = 1; + strlcpy(glob_script_mem.flink[lknum - 1], str, 14); lp++; - fvar=0; - len=0; + fvar = 0; + len = 0; goto exit; } - if (!strncmp(vname,"fsm",3)) { + if (!strncmp(vname, "fsm", 3)) { fvar=glob_script_mem.script_sd_found; //card_init(); goto exit; } #endif //USE_SCRIPT_FATFS - if (!strncmp(vname,"freq",4)) { + if (!strncmp(vname, "freq", 4)) { #ifdef ESP32 - fvar=getCpuFrequencyMhz(); + fvar = getCpuFrequencyMhz(); #else - fvar=ESP.getCpuFreqMHz(); + fvar = ESP.getCpuFreqMHz(); #endif goto exit; } break; case 'g': - if (!strncmp(vname,"gtmp",4)) { - fvar=global_temperature_celsius; + if (!strncmp(vname, "gtmp", 4)) { + fvar = global_temperature_celsius; goto exit; } - if (!strncmp(vname,"ghum",4)) { - fvar=global_humidity; + if (!strncmp(vname, "ghum", 4)) { + fvar = global_humidity; goto exit; } - if (!strncmp(vname,"gprs",4)) { - fvar=global_pressure_hpa; + if (!strncmp(vname, "gprs", 4)) { + fvar = global_pressure_hpa; goto exit; } - if (!strncmp(vname,"gtopic",6)) { - if (sp) strlcpy(sp,SettingsText(SET_MQTT_GRP_TOPIC),glob_script_mem.max_ssize); + if (!strncmp(vname, "gtopic", 6)) { + if (sp) strlcpy(sp, SettingsText(SET_MQTT_GRP_TOPIC), glob_script_mem.max_ssize); goto strexit; } #ifdef SCRIPT_GET_HTTPS_JP - if (!strncmp(vname,"gjp(",4)) { + if (!strncmp(vname, "gjp(", 4)) { char host[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp+4,OPER_EQU,host,0); + lp = GetStringArgument(lp + 4, OPER_EQU, host, 0); SCRIPT_SKIP_SPACES char path[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,path,0); - fvar=call2https(host,path); + lp = GetStringArgument(lp, OPER_EQU, path, 0); + fvar = call2https(host, path); lp++; - len=0; + len = 0; goto exit; } -#endif +#endif //SCRIPT_GET_HTTPS_JP break; case 'h': - if (!strncmp(vname,"hours",5)) { - fvar=RtcTime.hour; + if (!strncmp(vname, "hours", 5)) { + fvar = RtcTime.hour; goto exit; } - if (!strncmp(vname,"heap",4)) { - fvar=ESP_getFreeHeap(); + if (!strncmp(vname, "heap", 4)) { + fvar = ESP_getFreeHeap(); goto exit; } - if (!strncmp(vname,"hn(",3)) { - lp=GetNumericResult(lp+3,OPER_EQU,&fvar,0); - if (fvar<0 || fvar>255) fvar=0; + if (!strncmp(vname, "hn(", 3)) { + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); + if (fvar<0 || fvar>255) fvar = 0; lp++; - len=0; + len = 0; if (sp) { - sprintf(sp,"%02x",(uint8_t)fvar); + sprintf(sp, "%02x", (uint8_t)fvar); } goto strexit; } - if (!strncmp(vname,"hx(",3)) { - lp=GetNumericResult(lp+3,OPER_EQU,&fvar,0); + if (!strncmp(vname, "hx(", 3)) { + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); lp++; - len=0; + len = 0; if (sp) { - sprintf(sp,"%08x",(uint32_t)fvar); + sprintf(sp, "%08x", (uint32_t)fvar); } goto strexit; } - if (!strncmp(vname,"hd(",3)) { + if (!strncmp(vname, "hd(", 3)) { char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp+3,OPER_EQU,str,0); - fvar=strtol(str,NULL,16); + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + fvar = strtol(str, NULL, 16); lp++; - len=0; + len = 0; goto exit; } #ifdef USE_LIGHT -//#ifdef USE_WS2812 - if (!strncmp(vname,"hsvrgb(",7)) { - lp=GetNumericResult(lp+7,OPER_EQU,&fvar,0); - if (fvar<0 || fvar>360) fvar=0; + if (!strncmp(vname, "hsvrgb(", 7)) { + lp = GetNumericArgument(lp + 7, OPER_EQU, &fvar, 0); + if (fvar<0 || fvar>360) fvar = 0; SCRIPT_SKIP_SPACES // arg2 float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); - if (fvar2<0 || fvar2>100) fvar2=0; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + if (fvar2<0 || fvar2>100) fvar2 = 0; SCRIPT_SKIP_SPACES // arg3 float fvar3; - lp=GetNumericResult(lp,OPER_EQU,&fvar3,0); - if (fvar3<0 || fvar3>100) fvar3=0; - - fvar=HSVToRGB(fvar,fvar2,fvar3); + lp = GetNumericArgument(lp, OPER_EQU, &fvar3, 0); + if (fvar3<0 || fvar3>100) fvar3 = 0; + fvar = HSVToRGB(fvar, fvar2, fvar3); lp++; - len=0; + len = 0; goto exit; } -//#endif -#endif +#endif //USE_LIGHT break; #define MAX_SARRAY_NUM 32 case 'i': - if (!strncmp(vname,"int(",4)) { - lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0); - fvar=floor(fvar); + if (!strncmp(vname, "int(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + fvar = floor(fvar); lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"is(",3)) { - lp=GetNumericResult(lp+3,OPER_EQU,&fvar,0); + if (!strncmp(vname, "is(", 3)) { + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); SCRIPT_SKIP_SPACES if (*lp!='"') { break; @@ -2131,15 +2119,15 @@ chknext: if (glob_script_mem.si_num>0 && glob_script_mem.last_index_string) { free(glob_script_mem.last_index_string); } - char *sstart=lp; - uint8_t slen=0; - for (uint32_t cnt=0; cnt<256; cnt++) { + char *sstart = lp; + uint8_t slen = 0; + for (uint32_t cnt = 0; cnt<256; cnt++) { if (*lp=='\n' || *lp=='"' || *lp==0) { lp++; if (cnt>0 && !slen) { slen++; } - glob_script_mem.siro_num=slen; + glob_script_mem.siro_num = slen; break; } if (*lp=='|') { @@ -2151,31 +2139,31 @@ chknext: glob_script_mem.si_num = fvar; if (glob_script_mem.si_num>0) { if (glob_script_mem.si_num>MAX_SARRAY_NUM) { - glob_script_mem.si_num=MAX_SARRAY_NUM; + glob_script_mem.si_num = MAX_SARRAY_NUM; } - glob_script_mem.last_index_string=(char*)calloc(glob_script_mem.max_ssize*glob_script_mem.si_num,1); - for (uint32_t cnt=0; cntglob_script_mem.si_num) { - index=glob_script_mem.si_num; + index = glob_script_mem.si_num; } - strlcpy(str,glob_script_mem.last_index_string+(index*glob_script_mem.max_ssize),glob_script_mem.max_ssize); + strlcpy(str,glob_script_mem.last_index_string + (index * glob_script_mem.max_ssize), glob_script_mem.max_ssize); } } lp++; - if (sp) strlcpy(sp,str,glob_script_mem.max_ssize); - len=0; + if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); + len = 0; goto strexit; } break; case 'l': - if (!strncmp(vname,"lip",3)) { - if (sp) strlcpy(sp,(const char*)WiFi.localIP().toString().c_str(),glob_script_mem.max_ssize); + if (!strncmp(vname, "lip", 3)) { + if (sp) strlcpy(sp, (const char*)WiFi.localIP().toString().c_str(), glob_script_mem.max_ssize); goto strexit; } #ifdef USE_SCRIPT_GLOBVARS - if (!strncmp(vname,"luip",4)) { - if (sp) strlcpy(sp,IPAddressToString(last_udp_ip),glob_script_mem.max_ssize); + if (!strncmp(vname, "luip", 4)) { + if (sp) strlcpy(sp, IPAddressToString(last_udp_ip), glob_script_mem.max_ssize); goto strexit; } -#endif - if (!strncmp(vname,"loglvl",6)) { - fvar=glob_script_mem.script_loglevel; - tind->index=SCRIPT_LOGLEVEL; +#endif //USE_SCRIPT_GLOBVARS + if (!strncmp(vname, "loglvl", 6)) { + fvar = glob_script_mem.script_loglevel; + tind->index = SCRIPT_LOGLEVEL; exit_settable: - if (fp) *fp=fvar; - *vtype=NTYPE; - tind->bits.settable=1; - tind->bits.is_string=0; - return lp+len; + if (fp) *fp = fvar; + *vtype = NTYPE; + tind->bits.settable = 1; + tind->bits.is_string = 0; + return lp + len; } break; case 'm': - if (!strncmp(vname,"med(",4)) { + if (!strncmp(vname, "med(", 4)) { float fvar1; - lp=GetNumericResult(lp+4,OPER_EQU,&fvar1,0); + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar1, 0); SCRIPT_SKIP_SPACES // arg2 float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); - fvar=DoMedian5(fvar1,fvar2); + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + fvar = DoMedian5(fvar1, fvar2); lp++; - len=0; + len = 0; goto exit; } #ifdef USE_ANGLE_FUNC - if (!strncmp(vname,"mpt(",4)) { - lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0); - fvar=MeasurePulseTime(fvar); + if (!strncmp(vname, "mpt(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + fvar = MeasurePulseTime(fvar); lp++; - len=0; + len = 0; goto exit; } -#endif - if (!strncmp(vname,"micros",6)) { - fvar=micros(); +#endif //USE_ANGLE_FUNC + if (!strncmp(vname, "micros", 6)) { + fvar = micros(); goto exit; } - if (!strncmp(vname,"millis",6)) { - fvar=millis(); + if (!strncmp(vname, "millis", 6)) { + fvar = millis(); goto exit; } - if (!strncmp(vname,"mins",4)) { - fvar=RtcTime.minute; + if (!strncmp(vname, "mins", 4)) { + fvar = RtcTime.minute; goto exit; } - if (!strncmp(vname,"month",5)) { - fvar=RtcTime.month; + if (!strncmp(vname, "month", 5)) { + fvar = RtcTime.month; goto exit; } - if (!strncmp(vname,"mqttc",5)) { + if (!strncmp(vname, "mqttc", 5)) { if (rules_flag.mqtt_connected) { - rules_flag.mqtt_connected=0; - fvar=1; + rules_flag.mqtt_connected = 0; + fvar = 1; } goto exit; } - if (!strncmp(vname,"mqttd",5)) { + if (!strncmp(vname, "mqttd", 5)) { if (rules_flag.mqtt_disconnected) { - rules_flag.mqtt_disconnected=0; - fvar=1; + rules_flag.mqtt_disconnected = 0; + fvar = 1; } goto exit; } - if (!strncmp(vname,"mqtts",5)) { - fvar=!global_state.mqtt_down; + if (!strncmp(vname, "mqtts", 5)) { + fvar = !global_state.mqtt_down; goto exit; } - if (!strncmp(vname,"mp(",3)) { - lp+=3; + if (!strncmp(vname, "mp(", 3)) { float fvar1; - lp=GetNumericResult(lp,OPER_EQU,&fvar1,0); + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar1, 0); SCRIPT_SKIP_SPACES while (*lp!=')') { - char *opp=lp; + char *opp = lp; lp++; float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); SCRIPT_SKIP_SPACES - fvar=fvar1; + fvar = fvar1; if ((*opp=='<' && fvar1' && fvar1>fvar2) || - (*opp=='=' && fvar1==fvar2)) - { - if (*lp!='<' && *lp!='>' && *lp!='=' && *lp!=')' && *lp!=SCRIPT_EOL) { - float fvar3; - lp=GetNumericResult(lp,OPER_EQU,&fvar3,0); - SCRIPT_SKIP_SPACES - fvar=fvar3; - } else { - fvar=fvar2; - } - break; + (*opp=='=' && fvar1==fvar2)) { + if (*lp!='<' && *lp!='>' && *lp!='=' && *lp!=')' && *lp!=SCRIPT_EOL) { + float fvar3; + lp = GetNumericArgument(lp, OPER_EQU, &fvar3, 0); + SCRIPT_SKIP_SPACES + fvar=fvar3; + } else { + fvar = fvar2; + } + break; } while (*lp!='<' && *lp!='>' && *lp!='=' && *lp!=')' && *lp!=SCRIPT_EOL) lp++; } - len=0; + len = 0; goto exit; } #ifdef USE_MORITZ - if (!strncmp(vname,"mo(",3)) { + if (!strncmp(vname, "mo(", 3)) { float fvar1; - lp=GetNumericResult(lp+3,OPER_EQU,&fvar1,0); + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar1, 0); SCRIPT_SKIP_SPACES float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); SCRIPT_SKIP_SPACES char rbuff[64]; - fvar=mo_getvars(fvar1,fvar2,rbuff); + fvar = mo_getvars(fvar1, fvar2, rbuff); lp++; - if (sp) strlcpy(sp,rbuff,glob_script_mem.max_ssize); - len=0; + if (sp) strlcpy(sp, rbuff, glob_script_mem.max_ssize); + len = 0; goto strexit; } -#endif +#endif //USE_MORITZ break; case 'p': - if (!strncmp(vname,"pin[",4)) { + if (!strncmp(vname, "pin[", 4)) { // raw pin level - GetNumericResult(vname+4,OPER_EQU,&fvar,0); - fvar=digitalRead((uint8_t)fvar); + GetNumericArgument(vname + 4, OPER_EQU, &fvar, 0); + fvar = digitalRead((uint8_t)fvar); // skip ] bracket len++; goto exit; } - if (!strncmp(vname,"pn[",3)) { - GetNumericResult(vname+3,OPER_EQU,&fvar,0); - fvar=Pin(fvar); + if (!strncmp(vname, "pn[", 3)) { + GetNumericArgument(vname + 3, OPER_EQU, &fvar, 0); + fvar = Pin(fvar); // skip ] bracket len++; goto exit; } #if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH)) - if (!strncmp(vname,"pl(",3)) { + if (!strncmp(vname, "pl(", 3)) { char path[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp+3,OPER_EQU,path,0); + lp = GetStringArgument(lp + 3, OPER_EQU, path, 0); Play_mp3(path); len++; - len=0; + len = 0; goto exit; } #endif // USE_I2S_AUDIO - if (!strncmp(vname,"pd[",3)) { - GetNumericResult(vname+3,OPER_EQU,&fvar,0); - uint8_t gpiopin=fvar; + if (!strncmp(vname, "pd[", 3)) { + GetNumericArgument(vname + 3, OPER_EQU, &fvar, 0); + uint8_t gpiopin = fvar; /* for (uint8_t i=0;iMAX_COUNTERS) index=1; - fvar=RtcSettings.pulse_counter[index-1]; - len+=1; + if (!strncmp(vname, "pc[", 3)) { + GetNumericArgument(vname + 3, OPER_EQU, &fvar, 0); + uint8_t index = fvar; + if (index<1 || index>MAX_COUNTERS) index = 1; + fvar = RtcSettings.pulse_counter[index - 1]; + len += 1; goto exit; } break; case 'r': - if (!strncmp(vname,"ram",3)) { - fvar=glob_script_mem.script_mem_size+(glob_script_mem.script_size)+(PMEM_SIZE); + if (!strncmp(vname, "ram", 3)) { + fvar = glob_script_mem.script_mem_size + (glob_script_mem.script_size) + (PMEM_SIZE); goto exit; } - if (!strncmp(vname,"rnd(",4)) { + if (!strncmp(vname, "rnd(", 4)) { // tasmota switch state - GetNumericResult(vname+4,OPER_EQU,&fvar,0); + GetNumericArgument(vname + 4, OPER_EQU, &fvar, 0); if (fvar<0) { randomSeed(-fvar); - fvar=0; + fvar = 0; } else { - fvar=random(fvar); + fvar = random(fvar); } // skip ] bracket len++; @@ -2444,81 +2429,78 @@ chknext: } break; case 's': - if (!strncmp(vname,"secs",4)) { - fvar=RtcTime.second; + if (!strncmp(vname, "secs", 4)) { + fvar = RtcTime.second; goto exit; } - if (!strncmp(vname,"sw[",3)) { + if (!strncmp(vname, "sw[", 3)) { // tasmota switch state - GetNumericResult(vname+3,OPER_EQU,&fvar,0); - fvar=SwitchLastState((uint32_t)fvar); + GetNumericArgument(vname + 3, OPER_EQU, &fvar, 0); + fvar = SwitchLastState((uint32_t)fvar); // skip ] bracket len++; goto exit; } - if (!strncmp(vname,"stack",5)) { - fvar=GetStack(); + if (!strncmp(vname, "stack", 5)) { + fvar = GetStack(); goto exit; } - if (!strncmp(vname,"slen",4)) { - fvar=strlen(glob_script_mem.script_ram); + if (!strncmp(vname, "slen", 4)) { + fvar = strlen(glob_script_mem.script_ram); goto exit; } - if (!strncmp(vname,"sl(",3)) { - lp+=3; + if (!strncmp(vname, "sl(", 3)) { char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,0); + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); lp++; - len=0; - fvar=strlen(str); + len = 0; + fvar = strlen(str); goto exit; } - if (!strncmp(vname,"sb(",3)) { - lp+=3; + if (!strncmp(vname, "sb(", 3)) { char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,0); + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); SCRIPT_SKIP_SPACES float fvar1; - lp=GetNumericResult(lp,OPER_EQU,&fvar1,0); + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); SCRIPT_SKIP_SPACES float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); lp++; - len=0; + len = 0; if (fvar1<0) { - fvar1=strlen(str)+fvar1; + fvar1 = strlen(str) + fvar1; } - memcpy(sp,&str[(uint8_t)fvar1],(uint8_t)fvar2); + memcpy(sp, &str[(uint8_t)fvar1], (uint8_t)fvar2); sp[(uint8_t)fvar2] = '\0'; goto strexit; } - if (!strncmp(vname,"st(",3)) { - lp+=3; + if (!strncmp(vname, "st(", 3)) { char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,0); + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); while (*lp==' ') lp++; char token[2]; - token[0]=*lp++; - token[1]=0; + token[0] = *lp++; + token[1] = 0; while (*lp==' ') lp++; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); // skip ) bracket lp++; - len=0; + len = 0; if (sp) { // get stringtoken - char *st=strtok(str,token); + char *st = strtok(str, token); if (!st) { - *sp=0; + *sp = 0; } else { - for (uint8_t cnt=1; cnt<=fvar; cnt++) { + for (uint8_t cnt = 1; cnt<=fvar; cnt++) { if (cnt==fvar) { - strcpy(sp,st); + strcpy(sp, st); break; } - st=strtok(NULL,token); + st = strtok(NULL, token); if (!st) { - *sp=0; + *sp = 0; break; } } @@ -2526,249 +2508,237 @@ chknext: } goto strexit; } - if (!strncmp(vname,"s(",2)) { - lp+=2; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - char str[glob_script_mem.max_ssize+1]; - dtostrfd(fvar,glob_script_mem.script_dprec,str); - if (sp) strlcpy(sp,str,glob_script_mem.max_ssize); + if (!strncmp(vname, "s(", 2)) { + lp = GetNumericArgument(lp + 2, OPER_EQU, &fvar, 0); + char str[glob_script_mem.max_ssize + 1]; + dtostrfd(fvar, glob_script_mem.script_dprec, str); + if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); lp++; - len=0; + len = 0; goto strexit; } #if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH)) - if (!strncmp(vname,"say(",4)) { + if (!strncmp(vname, "say(", 4)) { char text[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp+4,OPER_EQU,text,0); + lp = GetStringArgument(lp + 4, OPER_EQU, text, 0); Say(text); len++; - len=0; + len = 0; goto exit; } #endif // USE_I2S_AUDIO #ifdef ESP32 - if (!strncmp(vname,"sf(",3)) { - lp+=2; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - if (fvar<80) fvar=80; - if (fvar>240) fvar=240; + if (!strncmp(vname, "sf(", 3)) { + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); + if (fvar<80) fvar = 80; + if (fvar>240) fvar = 240; setCpuFrequencyMhz(fvar); - fvar=getCpuFrequencyMhz(); + fvar = getCpuFrequencyMhz(); lp++; - len=0; + len = 0; goto exit; } -#endif +#endif //ESP32 #ifdef USE_TTGO_WATCH - if (!strncmp(vname,"slp(",4)) { - lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0); + if (!strncmp(vname, "slp(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); SCRIPT_SKIP_SPACES TTGO_Sleep(fvar); lp++; - len=0; + len = 0; goto exit; } -#endif +#endif //USE_TTGO_WATCH #if defined(USE_TIMERS) && defined(USE_SUNRISE) - if (!strncmp(vname,"sunrise",7)) { - fvar=SunMinutes(0); + if (!strncmp(vname, "sunrise", 7)) { + fvar = SunMinutes(0); goto exit; } - if (!strncmp(vname,"sunset",6)) { - fvar=SunMinutes(1); + if (!strncmp(vname, "sunset", 6)) { + fvar = SunMinutes(1); goto exit; } -#endif +#endif //USE_TIMERS #ifdef USE_SHUTTER - if (!strncmp(vname,"sht[",4)) { - GetNumericResult(vname+4,OPER_EQU,&fvar,0); - uint8_t index=fvar; + if (!strncmp(vname, "sht[", 4)) { + GetNumericArgument(vname + 4, OPER_EQU, &fvar, 0); + uint8_t index = fvar; if (index<=shutters_present) { - fvar=Settings.shutter_position[index-1]; + fvar = Settings.shutter_position[index - 1]; } else { - fvar=-1; + fvar = -1; } - len+=1; + len += 1; goto exit; } -#endif +#endif //USE_SHUTTER #ifdef USE_ANGLE_FUNC - if (!strncmp(vname,"sin(",4)) { - lp+=4; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - fvar=sinf(fvar); + if (!strncmp(vname, "sin(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + fvar = sinf(fvar); lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"sqrt(",5)) { - lp+=5; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - fvar=sqrtf(fvar); + if (!strncmp(vname, "sqrt(", 5)) { + lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); + fvar = sqrtf(fvar); lp++; - len=0; + len = 0; goto exit; } -#endif +#endif //USE_ANGLE_FUNC #if defined(USE_SML_M) && defined (USE_SML_SCRIPT_CMD) - if (!strncmp(vname,"sml[",4)) { - lp+=4; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + if (!strncmp(vname, "sml[", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); SCRIPT_SKIP_SPACES - fvar=SML_GetVal(fvar); + fvar = SML_GetVal(fvar); lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"sml(",4)) { - lp+=4; + if (!strncmp(vname, "sml(", 4)) { float fvar1; - lp=GetNumericResult(lp,OPER_EQU,&fvar1,0); + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar1, 0); SCRIPT_SKIP_SPACES float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); SCRIPT_SKIP_SPACES if (fvar2==0) { float fvar3; - lp=GetNumericResult(lp,OPER_EQU,&fvar3,0); - fvar=SML_SetBaud(fvar1,fvar3); + lp = GetNumericArgument(lp, OPER_EQU, &fvar3, 0); + fvar = SML_SetBaud(fvar1, fvar3); } else if (fvar2==1) { char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,0); - fvar=SML_Write(fvar1,str); + lp = GetStringArgument(lp, OPER_EQU, str, 0); + fvar = SML_Write(fvar1, str); } else if (fvar2==2) { char str[SCRIPT_MAXSSIZE]; - str[0]=0; - fvar=SML_Read(fvar1,str,SCRIPT_MAXSSIZE); - if (sp) strlcpy(sp,str,glob_script_mem.max_ssize); + str[0] = 0; + fvar = SML_Read(fvar1, str, SCRIPT_MAXSSIZE); + if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); lp++; - len=0; + len = 0; goto strexit; } else { #ifdef ED300L - fvar=SML_Status(fvar1); + fvar = SML_Status(fvar1); #else - fvar=0; -#endif + fvar = 0; +#endif //ED300L } lp++; - len=0; + len = 0; goto exit; } -#endif +#endif //USE_SML_M break; case 't': - if (!strncmp(vname,"time",4)) { - fvar=MinutesPastMidnight(); + if (!strncmp(vname, "time", 4)) { + fvar = MinutesPastMidnight(); goto exit; } - if (!strncmp(vname,"tper",4)) { - fvar=Settings.tele_period; - tind->index=SCRIPT_TELEPERIOD; + if (!strncmp(vname, "tper", 4)) { + fvar = Settings.tele_period; + tind->index = SCRIPT_TELEPERIOD; goto exit_settable; } - if (!strncmp(vname,"tinit",5)) { - if (rules_flag.time_init) { - rules_flag.time_init=0; - fvar=1; - } + if (!strncmp(vname, "tinit", 5)) { + fvar = rules_flag.time_init; goto exit; } - if (!strncmp(vname,"tset",4)) { - if (rules_flag.time_set) { - rules_flag.time_set=0; - fvar=1; - } + if (!strncmp(vname, "tset", 4)) { + fvar = rules_flag.time_set; goto exit; } - if (!strncmp(vname,"tstamp",6)) { - if (sp) strlcpy(sp,GetDateAndTime(DT_LOCAL).c_str(),glob_script_mem.max_ssize); + if (!strncmp(vname, "tstamp", 6)) { + if (sp) strlcpy(sp, GetDateAndTime(DT_LOCAL).c_str(), glob_script_mem.max_ssize); goto strexit; } - if (!strncmp(vname,"topic",5)) { - if (sp) strlcpy(sp,SettingsText(SET_MQTT_TOPIC),glob_script_mem.max_ssize); + if (!strncmp(vname, "topic", 5)) { + if (sp) strlcpy(sp, SettingsText(SET_MQTT_TOPIC), glob_script_mem.max_ssize); goto strexit; } #ifdef USE_SCRIPT_TIMER - if (!strncmp(vname,"ts1(",4)) { - lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0); - if (fvar<10) fvar=10; + if (!strncmp(vname, "ts1(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + if (fvar<10) fvar = 10; Script_ticker1.attach_ms(fvar, Script_ticker1_end); lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"ts2(",4)) { - lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0); - if (fvar<10) fvar=10; + if (!strncmp(vname, "ts2(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + if (fvar<10) fvar = 10; Script_ticker2.attach_ms(fvar, Script_ticker2_end); lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"ts3(",4)) { - lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0); - if (fvar<10) fvar=10; + if (!strncmp(vname, "ts3(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + if (fvar<10) fvar = 10; Script_ticker3.attach_ms(fvar, Script_ticker3_end); lp++; - len=0; + len = 0; goto exit; } - if (!strncmp(vname,"ts4(",4)) { - lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0); - if (fvar<10) fvar=10; + if (!strncmp(vname, "ts4(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + if (fvar<10) fvar = 10; Script_ticker4.attach_ms(fvar, Script_ticker4_end); lp++; - len=0; + len = 0; goto exit; } #endif // USE_SCRIPT_TIMER #ifdef USE_DISPLAY #ifdef USE_TOUCH_BUTTONS - if (!strncmp(vname,"tbut[",5)) { - GetNumericResult(vname+5,OPER_EQU,&fvar,0); - uint8_t index=fvar; - if (index<1 || index>MAXBUTTONS) index=1; + if (!strncmp(vname, "tbut[", 5)) { + GetNumericArgument(vname + 5, OPER_EQU, &fvar, 0); + uint8_t index = fvar; + if (index<1 || index>MAXBUTTONS) index = 1; index--; if (buttons[index]) { - fvar=buttons[index]->vpower.on_off; + fvar = buttons[index]->vpower.on_off; } else { - fvar=-1; + fvar = -1; } - len+=1; + len += 1; goto exit; } -#endif -#endif +#endif //USE_TOUCH_BUTTONS +#endif //USE_DISPLAY break; case 'u': - if (!strncmp(vname,"uptime",6)) { - fvar=MinutesUptime(); + if (!strncmp(vname, "uptime", 6)) { + fvar = MinutesUptime(); goto exit; } - if (!strncmp(vname,"upsecs",6)) { - fvar=uptime; + if (!strncmp(vname, "upsecs", 6)) { + fvar = uptime; goto exit; } - if (!strncmp(vname,"upd[",4)) { + if (!strncmp(vname, "upd[", 4)) { // var was updated struct T_INDEX ind; uint8_t vtype; - isvar(vname+4,&vtype,&ind,0,0,0); + isvar(vname + 4, &vtype, &ind, 0, 0, 0); if (!ind.bits.constant) { if (!ind.bits.changed) { - fvar=0; + fvar = 0; len++; goto exit; } else { - glob_script_mem.type[ind.index].bits.changed=0; - fvar=1; + glob_script_mem.type[ind.index].bits.changed = 0; + fvar = 1; len++; goto exit; } @@ -2779,112 +2749,111 @@ chknext: case 'w': #if defined(ESP32) && defined(USE_WEBCAM) - if (!strncmp(vname,"wc(",3)) { - lp+=3; + if (!strncmp(vname, "wc(", 3)) { float fvar1; - lp=GetNumericResult(lp,OPER_EQU,&fvar1,0); + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar1, 0); SCRIPT_SKIP_SPACES switch ((uint32)fvar1) { case 0: { float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); - fvar=WcSetup(fvar2); + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + fvar = WcSetup(fvar2); } break; case 1: { float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); - fvar=WcGetFrame(fvar2); + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + fvar = WcGetFrame(fvar2); } break; case 2: { float fvar2,fvar3; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); SCRIPT_SKIP_SPACES - lp=GetNumericResult(lp,OPER_EQU,&fvar3,0); - fvar=WcSetOptions(fvar2,fvar3); + lp = GetNumericArgument(lp, OPER_EQU, &fvar3, 0); + fvar = WcSetOptions(fvar2, fvar3); } break; case 3: - fvar=WcGetWidth(); + fvar = WcGetWidth(); break; case 4: - fvar=WcGetHeight(); + fvar = WcGetHeight(); break; case 5: { float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); - fvar=WcSetStreamserver(fvar2); + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + fvar = WcSetStreamserver(fvar2); } break; case 6: { float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); - fvar=WcSetMotionDetect(fvar2); + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + fvar = WcSetMotionDetect(fvar2); } break; #ifdef USE_FACE_DETECT case 7: { float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); - fvar=WcSetFaceDetect(fvar2); + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + fvar = WcSetFaceDetect(fvar2); } break; -#endif +#endif //USE_FACE_DETECT default: - fvar=0; + fvar = 0; } lp++; - len=0; + len = 0; goto exit; } #endif //ESP32, USE_WEBCAM #if defined(USE_TTGO_WATCH) && defined(USE_BMA423) - if (!strncmp(vname,"wdclk",5)) { - fvar=TTGO_doubleclick(); + if (!strncmp(vname, "wdclk", 5)) { + fvar = TTGO_doubleclick(); goto exit; } - if (!strncmp(vname,"wbut",4)) { - fvar=TTGO_button(); + if (!strncmp(vname, "wbut", 4)) { + fvar = TTGO_button(); goto exit; } #endif // USE_TTGO_WATCH #if defined(USE_TTGO_WATCH) && defined(USE_FT5206) - if (!strncmp(vname,"wtch(",5)) { - lp=GetNumericResult(lp+5,OPER_EQU,&fvar,0); - fvar=Touch_Status(fvar); + if (!strncmp(vname, "wtch(", 5)) { + lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); + fvar = Touch_Status(fvar); lp++; - len=0; + len = 0; goto exit; } #endif // USE_FT5206 - if (!strncmp(vname,"wday",4)) { - fvar=RtcTime.day_of_week; + if (!strncmp(vname, "wday", 4)) { + fvar = RtcTime.day_of_week; goto exit; } - if (!strncmp(vname,"wific",5)) { + if (!strncmp(vname, "wific", 5)) { if (rules_flag.wifi_connected) { - rules_flag.wifi_connected=0; - fvar=1; + rules_flag.wifi_connected = 0; + fvar = 1; } goto exit; } - if (!strncmp(vname,"wifid",5)) { + if (!strncmp(vname, "wifid", 5)) { if (rules_flag.wifi_disconnected) { - rules_flag.wifi_disconnected=0; - fvar=1; + rules_flag.wifi_disconnected = 0; + fvar = 1; } goto exit; } - if (!strncmp(vname,"wifis",5)) { - fvar=!global_state.wifi_down; + if (!strncmp(vname, "wifis", 5)) { + fvar = !global_state.wifi_down; goto exit; } break; case 'y': - if (!strncmp(vname,"year",4)) { - fvar=RtcTime.year; + if (!strncmp(vname, "year", 4)) { + fvar = RtcTime.year; goto exit; } break; @@ -2894,23 +2863,23 @@ chknext: // nothing valid found notfound: if (fp) *fp=0; - *vtype=VAR_NV; - tind->index=VAR_NV; - glob_script_mem.var_not_found=1; + *vtype = VAR_NV; + tind->index = VAR_NV; + glob_script_mem.var_not_found = 1; return lp; // return constant numbers exit: - if (fp) *fp=fvar; - *vtype=NUM_RES; - tind->bits.constant=1; - tind->bits.is_string=0; - return lp+len; + if (fp) *fp = fvar; + *vtype = NUM_RES; + tind->bits.constant = 1; + tind->bits.is_string = 0; + return lp + len; // return constant strings strexit: - *vtype=STYPE; - tind->bits.constant=1; - tind->bits.is_string=1; - return lp+len; + *vtype = STYPE; + tind->bits.constant = 1; + tind->bits.is_string = 1; + return lp + len; } @@ -2918,113 +2887,113 @@ strexit: char *getop(char *lp, uint8_t *operand) { switch (*lp) { case '=': - if (*(lp+1)=='=') { - *operand=OPER_EQUEQU; - return lp+2; + if (*(lp + 1)=='=') { + *operand = OPER_EQUEQU; + return lp + 2; } else { - *operand=OPER_EQU; - return lp+1; + *operand = OPER_EQU; + return lp + 1; } break; case '+': - if (*(lp+1)=='=') { - *operand=OPER_PLSEQU; - return lp+2; + if (*(lp + 1)=='=') { + *operand = OPER_PLSEQU; + return lp + 2; } else { - *operand=OPER_PLS; - return lp+1; + *operand = OPER_PLS; + return lp + 1; } break; case '-': - if (*(lp+1)=='=') { - *operand=OPER_MINEQU; - return lp+2; + if (*(lp + 1)=='=') { + *operand = OPER_MINEQU; + return lp + 2; } else { - *operand=OPER_MIN; - return lp+1; + *operand = OPER_MIN; + return lp + 1; } break; case '*': - if (*(lp+1)=='=') { - *operand=OPER_MULEQU; - return lp+2; + if (*(lp + 1)=='=') { + *operand = OPER_MULEQU; + return lp + 2; } else { - *operand=OPER_MUL; - return lp+1; + *operand = OPER_MUL; + return lp + 1; } break; case '/': - if (*(lp+1)=='=') { - *operand=OPER_DIVEQU; - return lp+2; + if (*(lp + 1)=='=') { + *operand = OPER_DIVEQU; + return lp + 2; } else { - *operand=OPER_DIV; - return lp+1; + *operand = OPER_DIV; + return lp + 1; } break; case '!': - if (*(lp+1)=='=') { - *operand=OPER_NOTEQU; - return lp+2; + if (*(lp + 1)=='=') { + *operand = OPER_NOTEQU; + return lp + 2; } break; case '>': - if (*(lp+1)=='=') { - *operand=OPER_GRTEQU; - return lp+2; + if (*(lp + 1)=='=') { + *operand = OPER_GRTEQU; + return lp + 2; } else { - *operand=OPER_GRT; - return lp+1; + *operand = OPER_GRT; + return lp + 1; } break; case '<': - if (*(lp+1)=='=') { - *operand=OPER_LOWEQU; - return lp+2; + if (*(lp + 1)=='=') { + *operand = OPER_LOWEQU; + return lp + 2; } else { - *operand=OPER_LOW; - return lp+1; + *operand = OPER_LOW; + return lp + 1; } break; case '%': - if (*(lp+1)=='=') { - *operand=OPER_PERCEQU; - return lp+2; + if (*(lp + 1)=='=') { + *operand = OPER_PERCEQU; + return lp + 2; } else { - *operand=OPER_PERC; - return lp+1; + *operand = OPER_PERC; + return lp + 1; } break; case '^': - if (*(lp+1)=='=') { - *operand=OPER_XOREQU; - return lp+2; + if (*(lp + 1)=='=') { + *operand = OPER_XOREQU; + return lp + 2; } else { - *operand=OPER_XOR; - return lp+1; + *operand = OPER_XOR; + return lp + 1; } break; case '&': - if (*(lp+1)=='=') { - *operand=OPER_ANDEQU; - return lp+2; + if (*(lp + 1)=='=') { + *operand = OPER_ANDEQU; + return lp + 2; } else { - *operand=OPER_AND; - return lp+1; + *operand = OPER_AND; + return lp + 1; } break; case '|': - if (*(lp+1)=='=') { - *operand=OPER_OREQU; - return lp+2; + if (*(lp + 1)=='=') { + *operand = OPER_OREQU; + return lp + 2; } else { - *operand=OPER_OR; - return lp+1; + *operand = OPER_OR; + return lp + 1; } break; } - *operand=0; + *operand = 0; return lp; } @@ -3043,31 +3012,31 @@ uint16_t GetStack(void) { register uint8_t *sp asm("a1"); return (sp - pxTaskGetStackStart(NULL)); } -#endif +#endif //ESP8266 -char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo) { - uint8_t operand=0; +char *GetStringArgument(char *lp, uint8_t lastop, char *cp, JsonObject *jo) { + uint8_t operand = 0; uint8_t vtype; char *slp; struct T_INDEX ind; char str[SCRIPT_MAXSSIZE],str1[SCRIPT_MAXSSIZE]; while (1) { - lp=isvar(lp,&vtype,&ind,0,str1,jo); - if (vtype!=STR_RES && !(vtype&STYPE)) { + lp=isvar(lp, &vtype, &ind, 0, str1, jo); + if (vtype!=STR_RES && !(vtype & STYPE)) { // numeric type - glob_script_mem.glob_error=1; + glob_script_mem.glob_error = 1; return lp; } switch (lastop) { case OPER_EQU: - strlcpy(str,str1,sizeof(str)); + strlcpy(str, str1, sizeof(str)); break; case OPER_PLS: - strncat(str,str1,sizeof(str)-strlen(str1)); + strncat(str, str1, sizeof(str) - strlen(str1)); break; } - slp=lp; - lp=getop(lp,&operand); + slp = lp; + lp = getop(lp, &operand); switch (operand) { case OPER_EQUEQU: case OPER_NOTEQU: @@ -3075,24 +3044,24 @@ char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo) { case OPER_LOWEQU: case OPER_GRT: case OPER_GRTEQU: - lp=slp; - strcpy(cp,str); + lp = slp; + strcpy(cp, str); return lp; break; default: break; } - lastop=operand; + lastop = operand; if (!operand) { - strcpy(cp,str); + strcpy(cp, str); return lp; } } return lp; } -char *GetNumericResult(char *lp,uint8_t lastop,float *fp,JsonObject *jo) { -uint8_t operand=0; +char *GetNumericArgument(char *lp, uint8_t lastop, float *fp, JsonObject *jo) { +uint8_t operand = 0; float fvar1,fvar; char *slp; uint8_t vtype; @@ -3101,50 +3070,50 @@ struct T_INDEX ind; // get 1. value if (*lp=='(') { lp++; - lp=GetNumericResult(lp,OPER_EQU,&fvar1,jo); + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, jo); lp++; //if (*lp==')') lp++; } else { - lp=isvar(lp,&vtype,&ind,&fvar1,0,jo); - if (vtype!=NUM_RES && vtype&STYPE) { + lp = isvar(lp, &vtype, &ind, &fvar1, 0, jo); + if ((vtype!=NUM_RES) && (vtype&STYPE)) { // string type - glob_script_mem.glob_error=1; + glob_script_mem.glob_error = 1; } } switch (lastop) { case OPER_EQU: - fvar=fvar1; + fvar = fvar1; break; case OPER_PLS: - fvar+=fvar1; + fvar += fvar1; break; case OPER_MIN: - fvar-=fvar1; + fvar -= fvar1; break; case OPER_MUL: - fvar*=fvar1; + fvar *= fvar1; break; case OPER_DIV: - fvar/=fvar1; + fvar /= fvar1; break; case OPER_PERC: - fvar=fmodf(fvar,fvar1); + fvar = fmodf(fvar, fvar1); break; case OPER_XOR: - fvar=(uint32_t)fvar^(uint32_t)fvar1; + fvar = (uint32_t)fvar ^ (uint32_t)fvar1; break; case OPER_AND: - fvar=(uint32_t)fvar&(uint32_t)fvar1; + fvar = (uint32_t)fvar & (uint32_t)fvar1; break; case OPER_OR: - fvar=(uint32_t)fvar|(uint32_t)fvar1; + fvar = (uint32_t)fvar | (uint32_t)fvar1; break; default: break; } - slp=lp; - lp=getop(lp,&operand); + slp = lp; + lp = getop(lp, &operand); switch (operand) { case OPER_EQUEQU: case OPER_NOTEQU: @@ -3152,102 +3121,115 @@ struct T_INDEX ind; case OPER_LOWEQU: case OPER_GRT: case OPER_GRTEQU: - lp=slp; - *fp=fvar; + lp = slp; + *fp = fvar; return lp; break; default: break; } - lastop=operand; + lastop = operand; if (!operand) { - *fp=fvar; + *fp = fvar; return lp; } } } -char *ForceStringVar(char *lp,char *dstr) { +char *ForceStringVar(char *lp, char *dstr) { float fvar; - char *slp=lp; - glob_script_mem.glob_error=0; - lp=GetStringResult(lp,OPER_EQU,dstr,0); + char *slp = lp; + glob_script_mem.glob_error = 0; + lp = GetStringArgument(lp, OPER_EQU, dstr, 0); if (glob_script_mem.glob_error) { // mismatch - lp=GetNumericResult(slp,OPER_EQU,&fvar,0); - dtostrfd(fvar,6,dstr); - glob_script_mem.glob_error=0; + lp = GetNumericArgument(slp, OPER_EQU, &fvar, 0); + dtostrfd(fvar, 6, dstr); + glob_script_mem.glob_error = 0; } return lp; } // replace vars in cmd %var% -void Replace_Cmd_Vars(char *srcbuf,uint32_t srcsize, char *dstbuf,uint32_t dstsize) { +void Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dstsize) { char *cp; uint16_t count; uint8_t vtype; - uint8_t dprec=glob_script_mem.script_dprec; + uint8_t dprec = glob_script_mem.script_dprec; float fvar; - cp=srcbuf; + cp = srcbuf; struct T_INDEX ind; char string[SCRIPT_MAXSSIZE]; - dstsize-=2; - for (count=0;count=sizeof(str)) len=len>=sizeof(str); - strlcpy(str,cp,len); + if (len>=sizeof(str)) len = sizeof(str); + strlcpy(str, cp, len); toSLog(str); } void toLogEOL(const char *s1,const char *str) { if (!str) return; - uint8_t index=0; - char *cp=log_data; - strcpy(cp,s1); - cp+=strlen(s1); + uint8_t index = 0; + char *cp = log_data; + strcpy(cp, s1); + cp += strlen(s1); while (*str) { if (*str==SCRIPT_EOL) break; - *cp++=*str++; + *cp++ = *str++; } - *cp=0; + *cp = 0; AddLog(LOG_LEVEL_INFO); } @@ -3297,70 +3279,70 @@ void toSLog(const char *str) { #endif } -char *Evaluate_expression(char *lp,uint8_t and_or, uint8_t *result,JsonObject *jo) { +char *Evaluate_expression(char *lp, uint8_t and_or, uint8_t *result,JsonObject *jo) { float fvar,*dfvar,fvar1; uint8_t numeric; struct T_INDEX ind; - uint8_t vtype=0,lastop; - uint8_t res=0; - char *llp=lp; + uint8_t vtype = 0,lastop; + uint8_t res = 0; + char *llp = lp; char *slp; SCRIPT_SKIP_SPACES if (*lp=='(') { - uint8_t res=0; - uint8_t xand_or=0; + uint8_t res = 0; + uint8_t xand_or = 0; lp++; loop: SCRIPT_SKIP_SPACES - lp=Evaluate_expression(lp,xand_or,&res,jo); + lp = Evaluate_expression(lp, xand_or, &res, jo); if (*lp==')') { lp++; goto exit0; } // check for next and or SCRIPT_SKIP_SPACES - if (!strncmp(lp,"or",2)) { - lp+=2; - xand_or=1; + if (!strncmp(lp, "or", 2)) { + lp += 2; + xand_or = 1; goto loop; - } else if (!strncmp(lp,"and",3)) { - lp+=3; - xand_or=2; + } else if (!strncmp(lp, "and", 3)) { + lp += 3; + xand_or = 2; goto loop; } exit0: if (!and_or) { - *result=res; + *result = res; } else if (and_or==1) { *result|=res; } else { - *result&=res; + *result &= res; } goto exit10; } - llp=lp; + llp = lp; // compare - dfvar=&fvar; - glob_script_mem.glob_error=0; - slp=lp; - numeric=1; - lp=GetNumericResult(lp,OPER_EQU,dfvar,0); + dfvar = &fvar; + glob_script_mem.glob_error = 0; + slp = lp; + numeric = 1; + lp = GetNumericArgument(lp, OPER_EQU, dfvar, 0); if (glob_script_mem.glob_error==1) { // was string, not number char cmpstr[SCRIPT_MAXSSIZE]; - lp=slp; - numeric=0; + lp = slp; + numeric = 0; // get the string - lp=isvar(lp,&vtype,&ind,0,cmpstr,0); - lp=getop(lp,&lastop); + lp = isvar(lp, &vtype, &ind, 0, cmpstr, 0); + lp = getop(lp, &lastop); // compare string char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,jo); + lp = GetStringArgument(lp, OPER_EQU, str, jo); if (lastop==OPER_EQUEQU || lastop==OPER_NOTEQU) { - res=strcmp(cmpstr,str); + res = strcmp(cmpstr, str); if (lastop==OPER_EQUEQU) res=!res; goto exit; } @@ -3368,26 +3350,26 @@ exit0: } else { // numeric // evaluate operand - lp=getop(lp,&lastop); - lp=GetNumericResult(lp,OPER_EQU,&fvar1,jo); + lp = getop(lp, &lastop); + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, jo); switch (lastop) { case OPER_EQUEQU: - res=(*dfvar==fvar1); + res = (*dfvar==fvar1); break; case OPER_NOTEQU: - res=(*dfvar!=fvar1); + res = (*dfvar!=fvar1); break; case OPER_LOW: - res=(*dfvarfvar1); + res = (*dfvar>fvar1); break; case OPER_GRTEQU: - res=(*dfvar>=fvar1); + res = (*dfvar>=fvar1); break; default: // error @@ -3396,11 +3378,11 @@ exit0: exit: if (!and_or) { - *result=res; + *result = res; } else if (and_or==1) { - *result|=res; + *result |= res; } else { - *result&=res; + *result &= res; } } @@ -3408,8 +3390,8 @@ exit: exit10: #if IFTHEN_DEBUG>0 char tbuff[128]; - sprintf(tbuff,"p1=%d,p2=%d,cmpres=%d,and_or=%d line: ",(int32_t)*dfvar,(int32_t)fvar1,*result,and_or); - toLogEOL(tbuff,llp); + sprintf(tbuff,"p1=%d,p2=%d,cmpres=%d,and_or=%d line: ", (int32_t)*dfvar, (int32_t)fvar1, *result, and_or); + toLogEOL(tbuff, llp); #endif return lp; } @@ -3420,28 +3402,28 @@ TimerHandle_t beep_th; void StopBeep( TimerHandle_t xTimer ); void StopBeep( TimerHandle_t xTimer ) { - ledcWriteTone(7,0); + ledcWriteTone(7, 0); xTimerStop(xTimer, 0); } void esp32_beep(int32_t freq ,uint32_t len) { if (freq<0) { - ledcSetup(7,500,10); - ledcAttachPin(-freq,7); - ledcWriteTone(7,0); + ledcSetup(7, 500, 10); + ledcAttachPin(-freq, 7); + ledcWriteTone(7, 0); if (!beep_th) { - beep_th = xTimerCreate("beep",100,pdFALSE,( void * ) 0,StopBeep); + beep_th = xTimerCreate("beep", 100, pdFALSE, ( void * ) 0, StopBeep); } } else { if (!beep_th) return; if (!freq) { - ledcWriteTone(7,0); + ledcWriteTone(7, 0); xTimerStop(beep_th, 10); return; } if (len < 10) return; if (xTimerIsTimerActive(beep_th)) return; - ledcWriteTone(7,freq); + ledcWriteTone(7, freq); uint32_t ticks = pdMS_TO_TICKS(len); xTimerChangePeriod( beep_th, ticks, 10); } @@ -3460,13 +3442,13 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { if (tasm_cmd_activ && tlen>0) return 0; - JsonObject *jo=0; + JsonObject *jo = 0; DynamicJsonBuffer jsonBuffer; // on heap - JsonObject &jobj=jsonBuffer.parseObject(js); + JsonObject &jobj = jsonBuffer.parseObject(js); if (js) { - jo=&jobj; + jo = &jobj; } else { - jo=0; + jo = 0; } return Run_script_sub(type, tlen, jo); @@ -3477,23 +3459,23 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonObject *jo) { char *lp_next; int16_t globaindex,saindex; struct T_INDEX ind; - uint8_t operand,lastop,numeric=1,if_state[IF_NEST],if_exe[IF_NEST],if_result[IF_NEST],and_or,ifstck=0; - if_state[ifstck]=0; - if_result[ifstck]=0; - if_exe[ifstck]=1; + uint8_t operand,lastop,numeric = 1,if_state[IF_NEST],if_exe[IF_NEST],if_result[IF_NEST],and_or,ifstck = 0; + if_state[ifstck] = 0; + if_result[ifstck] = 0; + if_exe[ifstck] = 1; char cmpstr[SCRIPT_MAXSSIZE]; - uint8_t check=0; + uint8_t check = 0; if (tlen<0) { - tlen=abs(tlen); - check=1; + tlen = abs(tlen); + check = 1; } float *dfvar,*cv_count,cv_max,cv_inc; char *cv_ptr; - float fvar=0,fvar1,sysvar,swvar; - uint8_t section=0,sysv_type=0,swflg=0; + float fvar = 0,fvar1,sysvar,swvar; + uint8_t section = 0,sysv_type = 0,swflg = 0; - char *lp=glob_script_mem.scriptptr; + char *lp = glob_script_mem.scriptptr; while (1) { // check line @@ -3514,71 +3496,71 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonObject *jo) { if (*lp=='#') { return 0; } - glob_script_mem.var_not_found=0; + glob_script_mem.var_not_found = 0; //#if SCRIPT_DEBUG>0 #ifdef IFTHEN_DEBUG char tbuff[128]; - sprintf(tbuff,"stack=%d,exe=%d,state=%d,cmpres=%d line: ",ifstck,if_exe[ifstck],if_state[ifstck],if_result[ifstck]); - toLogEOL(tbuff,lp); -#endif + sprintf(tbuff, "stack=%d,exe=%d,state=%d,cmpres=%d line: ", ifstck, if_exe[ifstck], if_state[ifstck], if_result[ifstck]); + toLogEOL(tbuff, lp); +#endif //IFTHEN_DEBUG //if (if_state[s_ifstck]==3 && if_result[s_ifstck]) goto next_line; //if (if_state[s_ifstck]==2 && !if_result[s_ifstck]) goto next_line; - if (!strncmp(lp,"if",2)) { - lp+=2; + if (!strncmp(lp, "if", 2)) { + lp += 2; if (ifstck=2) { - lp+=5; + if_state[ifstck] = 1; + if_result[ifstck] = 0; + if (ifstck==1) if_exe[ifstck] = 1; + else if_exe[ifstck] = if_exe[ifstck - 1]; + and_or = 0; + } else if (!strncmp(lp, "then", 4) && if_state[ifstck]==1) { + lp += 4; + if_state[ifstck] = 2; + if (if_exe[ifstck - 1]) if_exe[ifstck] = if_result[ifstck]; + } else if (!strncmp(lp, "else", 4) && if_state[ifstck]==2) { + lp += 4; + if_state[ifstck] = 3; + if (if_exe[ifstck - 1]) if_exe[ifstck] = !if_result[ifstck]; + } else if (!strncmp(lp, "endif", 5) && if_state[ifstck]>=2) { + lp += 5; if (ifstck>0) { - if_state[ifstck]=0; + if_state[ifstck] = 0; ifstck--; } goto next_line; - } else if (!strncmp(lp,"or",2) && if_state[ifstck]==1) { - lp+=2; - and_or=1; - } else if (!strncmp(lp,"and",3) && if_state[ifstck]==1) { - lp+=3; - and_or=2; + } else if (!strncmp(lp, "or", 2) && if_state[ifstck]==1) { + lp += 2; + and_or = 1; + } else if (!strncmp(lp, "and", 3) && if_state[ifstck]==1) { + lp += 3; + and_or = 2; } if (*lp=='{' && if_state[ifstck]==1) { - lp+=1; // then - if_state[ifstck]=2; - if (if_exe[ifstck-1]) if_exe[ifstck]=if_result[ifstck]; + lp += 1; // then + if_state[ifstck] = 2; + if (if_exe[ifstck - 1]) if_exe[ifstck]=if_result[ifstck]; } else if (*lp=='{' && if_state[ifstck]==3) { - lp+=1; // after else + lp += 1; // after else //if_state[ifstck]=3; } else if (*lp=='}' && if_state[ifstck]>=2) { lp++; // must check for else - char *slp=lp; - uint8_t iselse=0; - for (uint8_t count=0; count<8;count++) { + char *slp = lp; + uint8_t iselse = 0; + for (uint8_t count = 0; count<8;count++) { if (*lp=='}') { // must be endif break; } - if (!strncmp(lp,"else",4)) { + if (!strncmp(lp, "else", 4)) { // is before else, no endif - if_state[ifstck]=3; + if_state[ifstck] = 3; if (if_exe[ifstck-1]) if_exe[ifstck]=!if_result[ifstck]; - lp+=4; - iselse=1; + lp += 4; + iselse = 1; SCRIPT_SKIP_SPACES if (*lp=='{') lp++; break; @@ -3586,111 +3568,111 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonObject *jo) { lp++; } if (!iselse) { - lp=slp; + lp = slp; // endif if (ifstck>0) { - if_state[ifstck]=0; + if_state[ifstck] = 0; ifstck--; } goto next_line; } } - if (!strncmp(lp,"for",3)) { + if (!strncmp(lp, "for", 3)) { // start for next loop, fetch 3 params // simple implementation, zero loop count not supported - lp+=3; + lp += 3; SCRIPT_SKIP_SPACES - lp_next=0; - lp=isvar(lp,&vtype,&ind,0,0,0); + lp_next = 0; + lp = isvar(lp, &vtype, &ind, 0, 0, 0); if ((vtype!=VAR_NV) && (vtype&STYPE)==0) { // numeric var - uint8_t index=glob_script_mem.type[ind.index].index; - cv_count=&glob_script_mem.fvars[index]; + uint8_t index = glob_script_mem.type[ind.index].index; + cv_count = &glob_script_mem.fvars[index]; SCRIPT_SKIP_SPACES - lp=GetNumericResult(lp,OPER_EQU,cv_count,0); + lp = GetNumericArgument(lp, OPER_EQU, cv_count, 0); SCRIPT_SKIP_SPACES - lp=GetNumericResult(lp,OPER_EQU,&cv_max,0); + lp = GetNumericArgument(lp, OPER_EQU, &cv_max, 0); SCRIPT_SKIP_SPACES - lp=GetNumericResult(lp,OPER_EQU,&cv_inc,0); + lp = GetNumericArgument(lp, OPER_EQU, &cv_inc, 0); //SCRIPT_SKIP_EOL - cv_ptr=lp; + cv_ptr = lp; if (*cv_count<=cv_max && cv_inc>0) { // inc loop - floop=1; + floop = 1; } else { // dec loop - floop=2; + floop = 2; if (cv_inc>0) { - floop=1; + floop = 1; } } } else { // error - toLogEOL("for error",lp); + toLogEOL("for error", lp); } - } else if (!strncmp(lp,"next",4)) { - lp_next=lp; + } else if (!strncmp(lp, "next", 4)) { + lp_next = lp; if (floop>0) { // for next loop - *cv_count+=cv_inc; + *cv_count += cv_inc; if (floop==1) { if (*cv_count<=cv_max) { - lp=cv_ptr; + lp = cv_ptr; } else { - lp+=4; - floop=0; + lp += 4; + floop = 0; } } else { if (*cv_count>=cv_max) { - lp=cv_ptr; + lp = cv_ptr; } else { - lp+=4; - floop=0; + lp += 4; + floop = 0; } } } } - if (!strncmp(lp,"switch",6)) { - lp+=6; + if (!strncmp(lp, "switch", 6)) { + lp += 6; SCRIPT_SKIP_SPACES - char *slp=lp; - lp=GetNumericResult(lp,OPER_EQU,&swvar,0); + char *slp = lp; + lp = GetNumericArgument(lp, OPER_EQU, &swvar, 0); if (glob_script_mem.glob_error==1) { // was string, not number - lp=slp; + lp = slp; // get the string - lp=isvar(lp,&vtype,&ind,0,cmpstr,0); - swflg=0x81; + lp = isvar(lp, &vtype, &ind, 0, cmpstr, 0); + swflg = 0x81; } else { - swflg=1; + swflg = 1; } - } else if (!strncmp(lp,"case",4) && swflg>0) { - lp+=4; + } else if (!strncmp(lp, "case", 4) && swflg>0) { + lp += 4; SCRIPT_SKIP_SPACES float cvar; - if (!(swflg&0x80)) { - lp=GetNumericResult(lp,OPER_EQU,&cvar,0); + if (!(swflg & 0x80)) { + lp = GetNumericArgument(lp, OPER_EQU, &cvar, 0); if (swvar!=cvar) { - swflg=2; + swflg = 2; } else { - swflg=1; + swflg = 1; } } else { char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,0); - if (!strcmp(cmpstr,str)) { - swflg=0x81; + lp = GetStringArgument(lp, OPER_EQU, str, 0); + if (!strcmp(cmpstr, str)) { + swflg = 0x81; } else { - swflg=0x82; + swflg = 0x82; } } - } else if (!strncmp(lp,"ends",4) && swflg>0) { - lp+=4; - swflg=0; + } else if (!strncmp(lp, "ends", 4) && swflg>0) { + lp += 4; + swflg = 0; } - if ((swflg&3)==2) goto next_line; + if ((swflg & 3)==2) goto next_line; SCRIPT_SKIP_SPACES //SCRIPT_SKIP_EOL @@ -3702,34 +3684,34 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonObject *jo) { if (!if_exe[ifstck] && if_state[ifstck]!=1) goto next_line; #ifdef IFTHEN_DEBUG - sprintf(tbuff,"stack=%d,exe=%d,state=%d,cmpres=%d execute line: ",ifstck,if_exe[ifstck],if_state[ifstck],if_result[ifstck]); - toLogEOL(tbuff,lp); -#endif + sprintf(tbuff, "stack=%d,exe=%d,state=%d,cmpres=%d execute line: ", ifstck, if_exe[ifstck], if_state[ifstck], if_result[ifstck]); + toLogEOL(tbuff, lp); +#endif //IFTHEN_DEBUG - if (!strncmp(lp,"break",5)) { - lp+=5; + if (!strncmp(lp, "break", 5)) { + lp += 5; if (floop) { // should break loop if (lp_next) { - lp=lp_next; + lp = lp_next; } - floop=0; + floop = 0; } else { - section=0; + section = 0; } goto next_line; - } else if (!strncmp(lp,"dp",2) && isdigit(*(lp+2))) { - lp+=2; + } else if (!strncmp(lp, "dp", 2) && isdigit(*(lp + 2))) { + lp += 2; // number precision - glob_script_mem.script_dprec=atoi(lp); + glob_script_mem.script_dprec = atoi(lp); goto next_line; } #ifdef USE_DISPLAY - else if (!strncmp(lp,"dt",2)) { + else if (!strncmp(lp, "dt", 2)) { char dstbuf[256]; - lp+=2; + lp += 2; SCRIPT_SKIP_SPACES - Replace_Cmd_Vars(lp,1,dstbuf,sizeof(dstbuf)); + Replace_Cmd_Vars(lp, 1, dstbuf, sizeof(dstbuf)); char *savptr = XdrvMailbox.data; XdrvMailbox.data = dstbuf; XdrvMailbox.data_len = 0; @@ -3737,165 +3719,160 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonObject *jo) { XdrvMailbox.data = savptr; goto next_line; } -#endif - else if (!strncmp(lp,"delay(",6)) { - lp+=5; +#endif //USE_DISPLAY + else if (!strncmp(lp, "delay(", 6)) { // delay - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); delay(fvar); goto next_line; - } else if (!strncmp(lp,"spinm(",6)) { - lp+=6; + } else if (!strncmp(lp, "spinm(", 6)) { // set pin mode - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - int8_t pinnr=fvar; + lp = GetNumericArgument(lp + 6, OPER_EQU, &fvar, 0); + int8_t pinnr = fvar; SCRIPT_SKIP_SPACES - uint8_t mode=0; + uint8_t mode = 0; if ((*lp=='I') || (*lp=='O') || (*lp=='P')) { switch (*lp) { case 'I': - mode=0; + mode = 0; break; case 'O': - mode=1; + mode = 1; break; case 'P': - mode=2; + mode = 2; break; } lp++; } else { - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - mode=fvar; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + mode = fvar; } uint8_t pm=0; - if (mode==0) pm=INPUT; - if (mode==1) pm=OUTPUT; - if (mode==2) pm=INPUT_PULLUP; - pinMode(pinnr,pm); + if (mode==0) pm = INPUT; + if (mode==1) pm = OUTPUT; + if (mode==2) pm = INPUT_PULLUP; + pinMode(pinnr, pm); goto next_line; - } else if (!strncmp(lp,"spin(",5)) { - lp+=5; + } else if (!strncmp(lp, "spin(", 5)) { // set pin - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - int8_t pinnr=fvar; + lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); + int8_t pinnr = fvar; SCRIPT_SKIP_SPACES - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - int8_t mode=fvar; - digitalWrite(pinnr,mode&1); + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + int8_t mode = fvar; + digitalWrite(pinnr, mode & 1); goto next_line; - } else if (!strncmp(lp,"svars(",5)) { - lp+=5; + } else if (!strncmp(lp, "svars(", 5)) { + lp += 5; // save vars Scripter_save_pvars(); goto next_line; } #ifdef USE_LIGHT #ifdef USE_WS2812 - else if (!strncmp(lp,"ws2812(",7)) { - lp+=7; - lp=isvar(lp,&vtype,&ind,0,0,0); + else if (!strncmp(lp, "ws2812(", 7)) { + lp = isvar(lp + 7, &vtype, &ind, 0, 0, 0); if (vtype!=VAR_NV) { SCRIPT_SKIP_SPACES if (*lp!=')') { - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); } else { - fvar=0; + fvar = 0; } // found variable as result - uint8_t index=glob_script_mem.type[ind.index].index; + uint8_t index = glob_script_mem.type[ind.index].index; if ((vtype&STYPE)==0) { // numeric result if (glob_script_mem.type[ind.index].bits.is_filter) { - uint16_t len=0; - float *fa=Get_MFAddr(index,&len,0); + uint16_t len = 0; + float *fa = Get_MFAddr(index, &len, 0); //Serial.printf(">> 2 %d\n",(uint32_t)*fa); - if (fa && len) ws2812_set_array(fa,len,fvar); + if (fa && len) ws2812_set_array(fa, len, fvar); } } } goto next_line; } -#endif -#endif +#endif //USE_WS2812 +#endif //USE_LIGHT #ifdef ESP32 - else if (!strncmp(lp,"beep(",5)) { - lp+=5; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + else if (!strncmp(lp, "beep(", 5)) { + lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); SCRIPT_SKIP_SPACES float fvar1; - lp=GetNumericResult(lp,OPER_EQU,&fvar1,0); - esp32_beep(fvar,fvar1); + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); + esp32_beep(fvar, fvar1); lp++; goto next_line; } -#endif +#endif //ESP32 else if (!strncmp(lp,"=>",2) || !strncmp(lp,"->",2) || !strncmp(lp,"+>",2) || !strncmp(lp,"print",5)) { // execute cmd - uint8_t sflag=0,pflg=0,svmqtt,swll; + uint8_t sflag = 0,pflg = 0,svmqtt,swll; if (*lp=='p') { - pflg=1; - lp+=5; + pflg = 1; + lp += 5; } else { - if (*lp=='-') sflag=1; - if (*lp=='+') sflag=2; - lp+=2; + if (*lp=='-') sflag = 1; + if (*lp=='+') sflag = 2; + lp += 2; } - char *slp=lp; + char *slp = lp; SCRIPT_SKIP_SPACES #define SCRIPT_CMDMEM 512 - char *cmdmem=(char*)malloc(SCRIPT_CMDMEM); + char *cmdmem = (char*)malloc(SCRIPT_CMDMEM); if (cmdmem) { - char *cmd=cmdmem; + char *cmd = cmdmem; uint16_t count; - for (count=0; count",1,jo); - glob_script_mem.scriptptr=svd_sp; + char *svd_sp = glob_script_mem.scriptptr; + strcat(str, "\n#"); + glob_script_mem.scriptptr = str; + Run_script_sub(">", 1, jo); + glob_script_mem.scriptptr = svd_sp; } // check for variable result if (if_state[ifstck]==1) { // evaluate exxpression - lp=Evaluate_expression(lp,and_or,&if_result[ifstck],jo); + lp = Evaluate_expression(lp, and_or, &if_result[ifstck], jo); SCRIPT_SKIP_SPACES if (*lp=='{' && if_state[ifstck]==1) { - lp+=1; // then - if_state[ifstck]=2; - if (if_exe[ifstck-1]) if_exe[ifstck]=if_result[ifstck]; + lp += 1; // then + if_state[ifstck] = 2; + if (if_exe[ifstck - 1]) if_exe[ifstck] = if_result[ifstck]; } goto next_line; } else { - char *vnp=lp; - lp=isvar(lp,&vtype,&ind,&sysvar,0,0); + char *vnp = lp; + lp = isvar(lp, &vtype, &ind, &sysvar, 0, 0); if (vtype!=VAR_NV) { #ifdef USE_SCRIPT_GLOBVARS char varname[16]; - uint32_t vnl=(uint32_t)lp-(uint32)vnp; - strncpy(varname,vnp,vnl); - varname[vnl]=0; -#endif + uint32_t vnl = (uint32_t)lp - (uint32)vnp; + strncpy(varname, vnp, vnl); + varname[vnl] = 0; +#endif //USE_SCRIPT_GLOBVARS // found variable as result - globvindex=ind.index; // save destination var index here - globaindex=last_findex; - uint8_t index=glob_script_mem.type[ind.index].index; + globvindex = ind.index; // save destination var index here + globaindex = last_findex; + uint8_t index = glob_script_mem.type[ind.index].index; if ((vtype&STYPE)==0) { // numeric result if (ind.bits.settable || ind.bits.is_filter) { - dfvar=&sysvar; + dfvar = &sysvar; if (ind.bits.settable) { - sysv_type=ind.index; + sysv_type = ind.index; } else { - sysv_type=0; + sysv_type = 0; } } else { - dfvar=&glob_script_mem.fvars[index]; - sysv_type=0; + dfvar = &glob_script_mem.fvars[index]; + sysv_type = 0; } - numeric=1; - lp=getop(lp,&lastop); - char *slp=lp; - glob_script_mem.glob_error=0; - lp=GetNumericResult(lp,OPER_EQU,&fvar,jo); + numeric = 1; + lp = getop(lp, &lastop); + char *slp = lp; + glob_script_mem.glob_error = 0; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, jo); if (glob_script_mem.glob_error==1) { // mismatch was string, not number // get the string and convert to number - lp=isvar(slp,&vtype,&ind,0,cmpstr,jo); - fvar=CharToFloat(cmpstr); + lp = isvar(slp, &vtype, &ind, 0, cmpstr, jo); + fvar = CharToFloat(cmpstr); } switch (lastop) { case OPER_EQU: @@ -3984,105 +3961,105 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonObject *jo) { if (!jo) toLogEOL("var not found: ",lp); goto next_line; } - *dfvar=fvar; + *dfvar = fvar; break; case OPER_PLSEQU: - *dfvar+=fvar; + *dfvar += fvar; break; case OPER_MINEQU: - *dfvar-=fvar; + *dfvar -= fvar; break; case OPER_MULEQU: - *dfvar*=fvar; + *dfvar *= fvar; break; case OPER_DIVEQU: - *dfvar/=fvar; + *dfvar /= fvar; break; case OPER_PERCEQU: - *dfvar=fmodf(*dfvar,fvar); + *dfvar = fmodf(*dfvar, fvar); break; case OPER_ANDEQU: - *dfvar=(uint32_t)*dfvar&(uint32_t)fvar; + *dfvar = (uint32_t)*dfvar & (uint32_t)fvar; break; case OPER_OREQU: - *dfvar=(uint32_t)*dfvar|(uint32_t)fvar; + *dfvar = (uint32_t)*dfvar | (uint32_t)fvar; break; case OPER_XOREQU: - *dfvar=(uint32_t)*dfvar^(uint32_t)fvar; + *dfvar = (uint32_t)*dfvar ^ (uint32_t)fvar; break; default: // error break; } // var was changed - glob_script_mem.type[globvindex].bits.changed=1; + glob_script_mem.type[globvindex].bits.changed = 1; #ifdef USE_SCRIPT_GLOBVARS if (glob_script_mem.type[globvindex].bits.global) { - script_udp_sendvar(varname,dfvar,0); + script_udp_sendvar(varname, dfvar, 0); } -#endif +#endif //USE_SCRIPT_GLOBVARS if (glob_script_mem.type[globvindex].bits.is_filter) { if (globaindex>=0) { - Set_MFVal(glob_script_mem.type[globvindex].index,globaindex,*dfvar); + Set_MFVal(glob_script_mem.type[globvindex].index, globaindex, *dfvar); } else { - Set_MFilter(glob_script_mem.type[globvindex].index,*dfvar); + Set_MFilter(glob_script_mem.type[globvindex].index, *dfvar); } } if (sysv_type) { switch (sysv_type) { case SCRIPT_LOGLEVEL: - glob_script_mem.script_loglevel=*dfvar; + glob_script_mem.script_loglevel = *dfvar; break; case SCRIPT_TELEPERIOD: - if (*dfvar<10) *dfvar=10; - if (*dfvar>300) *dfvar=300; - Settings.tele_period=*dfvar; + if (*dfvar<10) *dfvar = 10; + if (*dfvar>300) *dfvar = 300; + Settings.tele_period = *dfvar; break; case SCRIPT_EVENT_HANDLED: - event_handeled=*dfvar; + event_handeled = *dfvar; break; } - sysv_type=0; + sysv_type = 0; } } else { // string result - numeric=0; - sindex=index; - saindex=last_sindex; + numeric = 0; + sindex = index; + saindex = last_sindex; // string result char str[SCRIPT_MAXSSIZE]; - lp=getop(lp,&lastop); - char *slp=lp; - glob_script_mem.glob_error=0; - lp=GetStringResult(lp,OPER_EQU,str,jo); + lp = getop(lp, &lastop); + char *slp = lp; + glob_script_mem.glob_error = 0; + lp = GetStringArgument(lp, OPER_EQU, str, jo); if (!jo && glob_script_mem.glob_error) { // mismatch - lp=GetNumericResult(slp,OPER_EQU,&fvar,0); - dtostrfd(fvar,6,str); - glob_script_mem.glob_error=0; + lp = GetNumericArgument(slp, OPER_EQU, &fvar, 0); + dtostrfd(fvar, 6, str); + glob_script_mem.glob_error = 0; } if (!glob_script_mem.var_not_found) { // var was changed - glob_script_mem.type[globvindex].bits.changed=1; + glob_script_mem.type[globvindex].bits.changed = 1; #ifdef USE_SCRIPT_GLOBVARS if (glob_script_mem.type[globvindex].bits.global) { - script_udp_sendvar(varname,0,str); + script_udp_sendvar(varname, 0, str); } -#endif +#endif //USE_SCRIPT_GLOBVARS if (saindex>=0) { if (lastop==OPER_EQU) { - strlcpy(glob_script_mem.last_index_string+(saindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); + strlcpy(glob_script_mem.last_index_string + (saindex * glob_script_mem.max_ssize), str, glob_script_mem.max_ssize); } else if (lastop==OPER_PLSEQU) { - strncat(glob_script_mem.last_index_string+(saindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); + strncat(glob_script_mem.last_index_string + (saindex * glob_script_mem.max_ssize), str, glob_script_mem.max_ssize); } - last_sindex=-1; + last_sindex = -1; } else { if (lastop==OPER_EQU) { - strlcpy(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); + strlcpy(glob_script_mem.glob_snp + (sindex * glob_script_mem.max_ssize), str, glob_script_mem.max_ssize); } else if (lastop==OPER_PLSEQU) { - strncat(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); + strncat(glob_script_mem.glob_snp + (sindex * glob_script_mem.max_ssize), str, glob_script_mem.max_ssize); } } } @@ -4091,7 +4068,7 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonObject *jo) { } SCRIPT_SKIP_SPACES if (*lp=='{' && if_state[ifstck]==3) { - lp+=1; // else + lp += 1; // else //if_state[ifstck]=3; } goto next_line; @@ -4102,67 +4079,67 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonObject *jo) { if (*lp=='>' && tlen==1) { // called from cmdline lp++; - section=1; - fromscriptcmd=1; + section = 1; + fromscriptcmd = 1; goto startline; } - if (!strncmp(lp,type,tlen)) { + if (!strncmp(lp, type, tlen)) { // found section - section=1; - glob_script_mem.section_ptr=lp; + section = 1; + glob_script_mem.section_ptr = lp; if (check) { return 99; } // check for subroutine - char *ctype=(char*)type; + char *ctype = (char*)type; if (*ctype=='#') { // check for parameter - ctype+=tlen; + ctype += tlen; if (*ctype=='(' && *(lp+tlen)=='(') { float fparam; - numeric=1; - glob_script_mem.glob_error=0; - GetNumericResult((char*)ctype,OPER_EQU,&fparam,0); + numeric = 1; + glob_script_mem.glob_error = 0; + GetNumericArgument((char*)ctype, OPER_EQU, &fparam, 0); if (glob_script_mem.glob_error==1) { // was string, not number - numeric=0; + numeric = 0; // get the string - GetStringResult((char*)ctype+1,OPER_EQU,cmpstr,0); + GetStringArgument((char*)ctype + 1, OPER_EQU, cmpstr, 0); } - lp+=tlen; + lp += tlen; if (*lp=='(') { // fetch destination lp++; - lp=isvar(lp,&vtype,&ind,0,0,0); + lp = isvar(lp, &vtype, &ind, 0, 0, 0); if (vtype!=VAR_NV) { // found variable as result - uint8_t index=glob_script_mem.type[ind.index].index; + uint8_t index = glob_script_mem.type[ind.index].index; if ((vtype&STYPE)==0) { // numeric result - dfvar=&glob_script_mem.fvars[index]; + dfvar = &glob_script_mem.fvars[index]; if (numeric) { - *dfvar=fparam; + *dfvar = fparam; } else { // mismatch - *dfvar=CharToFloat(cmpstr); + *dfvar = CharToFloat(cmpstr); } } else { // string result - sindex=index; + sindex = index; if (!numeric) { - strlcpy(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),cmpstr,glob_script_mem.max_ssize); + strlcpy(glob_script_mem.glob_snp + (sindex * glob_script_mem.max_ssize), cmpstr, glob_script_mem.max_ssize); } else { // mismatch - dtostrfd(fparam,6,glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize)); + dtostrfd(fparam, 6, glob_script_mem.glob_snp + (sindex * glob_script_mem.max_ssize)); } } } } } else { - lp+=tlen; + lp += tlen; if (*ctype=='(' || (*lp!=SCRIPT_EOL && *lp!='?')) { // revert - section=0; + section = 0; } } } @@ -4201,11 +4178,11 @@ void ScripterEvery100ms(void) { if (strlen(mqtt_data)) { mqtt_data[0] = '{'; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); - Run_Scripter(">T",2, mqtt_data); + Run_Scripter(">T", 2, mqtt_data); } } if (Settings.rule_enabled) { - if (fast_script==99) Run_Scripter(">F",2,0); + if (fast_script==99) Run_Scripter(">F", 2, 0); } } @@ -4213,48 +4190,48 @@ void ScripterEvery100ms(void) { // can hold 11 floats or floats + strings // should report overflow later void Scripter_save_pvars(void) { - int16_t mlen=0; - float *fp=(float*)glob_script_mem.script_pram; + int16_t mlen = 0; + float *fp = (float*)glob_script_mem.script_pram; mlen+=sizeof(float); - struct T_INDEX *vtp=glob_script_mem.type; - for (uint8_t count=0; countglob_script_mem.script_pram_size) { - vtp[count].bits.is_permanent=0; + vtp[count].bits.is_permanent = 0; return; } while (len--) { - *fp++=*fa++; + *fp++ = *fa++; } } else { - mlen+=sizeof(float); + mlen += sizeof(float); if (mlen>glob_script_mem.script_pram_size) { - vtp[count].bits.is_permanent=0; + vtp[count].bits.is_permanent = 0; return; } - *fp++=glob_script_mem.fvars[index]; + *fp++ = glob_script_mem.fvars[index]; } } } - char *cp=(char*)fp; - for (uint8_t count=0; countglob_script_mem.script_pram_size) { - vtp[count].bits.is_permanent=0; + vtp[count].bits.is_permanent = 0; return; } - strcpy(cp,sp); - cp+=slen+1; + strcpy(cp, sp); + cp += slen + 1; } } } @@ -4351,7 +4328,7 @@ const char HTTP_FORM_SCRIPT1b[] PROGMEM = "});" -#endif +#endif //SCRIPT_STRIP_COMMENTS ""; @@ -4415,38 +4392,38 @@ void script_upload_start(void) { HTTPUpload& upload = Webserver->upload(); if (upload.status == UPLOAD_FILE_START) { //AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload start")); - script_ex_ptr=(uint8_t*)glob_script_mem.script_ram; + script_ex_ptr = (uint8_t*)glob_script_mem.script_ram; //AddLog_P2(LOG_LEVEL_INFO, PSTR("HTP: upload file %s, %d"),upload.filename.c_str(),upload.totalSize); - if (strcmp(upload.filename.c_str(),"execute_script")) { - Web.upload_error=1; + if (strcmp(upload.filename.c_str(), "execute_script")) { + Web.upload_error = 1; WSSend(500, CT_PLAIN, F("500: wrong filename")); return; } if (upload.totalSize>=glob_script_mem.script_size) { - Web.upload_error=1; + Web.upload_error = 1; WSSend(500, CT_PLAIN, F("500: file to large")); return; } - uplsize=0; + uplsize = 0; sc_state = bitRead(Settings.rule_enabled, 0); - bitWrite(Settings.rule_enabled,0,0); + bitWrite(Settings.rule_enabled, 0, 0); } else if(upload.status == UPLOAD_FILE_WRITE) { //AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload write")); - uint32_t csiz=upload.currentSize; - uint32_t tsiz=glob_script_mem.script_size-1; + uint32_t csiz = upload.currentSize; + uint32_t tsiz = glob_script_mem.script_size - 1; if (uplsizeopen(path, FILE_READ); + File dir = fsp->open(path, FILE_READ); if (dir) { dir.rewindDirectory(); if (strlen(path)>1) { - snprintf_P(npath,sizeof(npath),PSTR("http://%s/upl?download=%s"),WiFi.localIP().toString().c_str(),path); - for (uint8_t cnt=strlen(npath)-1;cnt>0;cnt--) { + snprintf_P(npath, sizeof(npath), PSTR("http://%s/upl?download=%s"), WiFi.localIP().toString().c_str(),path); + for (uint8_t cnt = strlen(npath) - 1; cnt>0; cnt--) { if (npath[cnt]=='/') { - if (npath[cnt-1]=='=') npath[cnt+1]=0; - else npath[cnt]=0; + if (npath[cnt - 1]=='=') npath[cnt + 1] = 0; + else npath[cnt] = 0; break; } } - WSContentSend_P(HTTP_FORM_SDC_DIRd,npath,path,".."); + WSContentSend_P(HTTP_FORM_SDC_DIRd, npath,path, ".."); } char *ep; while (true) { - File entry=dir.openNextFile(); + File entry = dir.openNextFile(); if (!entry) { break; } // esp32 returns path here, shorten to filename - ep=(char*)entry.name(); + ep = (char*)entry.name(); if (*ep=='/') ep++; char *lcp = strrchr(ep,'/'); if (lcp) { - ep=lcp+1; + ep = lcp + 1; } //AddLog_P2(LOG_LEVEL_INFO, PSTR("entry: %s"),ep); - time_t tm=entry.getLastWrite(); + time_t tm = entry.getLastWrite(); char tstr[24]; strftime(tstr, 22, "%d-%m-%Y - %H:%M:%S ", localtime(&tm)); - char *pp=path; - if (!*(pp+1)) pp++; - char *cp=name; + char *pp = path; + if (!*(pp + 1)) pp++; + char *cp = name; // osx formatted disks contain a lot of stuff we dont want if (reject((char*)ep)) goto fclose; - for (uint8_t cnt=0;cnt1) { - strcat(path,"/"); + strcat(path, "/"); } - strcat(path,ep); - ListDir(path,depth+4); - path[plen]=0; + strcat(path, ep); + ListDir(path, depth + 4); + path[plen] = 0; } else { - snprintf_P(npath,sizeof(npath),HTTP_FORM_SDC_HREF,WiFi.localIP().toString().c_str(),pp,ep); - WSContentSend_P(HTTP_FORM_SDC_DIRb,npath,ep,name,tstr,entry.size()); + snprintf_P(npath, sizeof(npath), HTTP_FORM_SDC_HREF, WiFi.localIP().toString().c_str(), pp,ep); + WSContentSend_P(HTTP_FORM_SDC_DIRb, npath, ep, name, tstr, entry.size()); } fclose: entry.close(); @@ -4576,18 +4553,18 @@ void ListDir(char *path, uint8_t depth) { char path[48]; void Script_FileUploadConfiguration(void) { - uint8_t depth=0; + uint8_t depth = 0; - strcpy(path,"/"); + strcpy(path, "/"); if (!HttpCheckPriviledgedAccess()) { return; } if (Webserver->hasArg("download")) { String stmp = Webserver->arg("download"); - char *cp=(char*)stmp.c_str(); + char *cp = (char*)stmp.c_str(); if (DownloadFile(cp)) { // is directory - strcpy(path,cp); + strcpy(path, cp); } } @@ -4598,7 +4575,7 @@ void Script_FileUploadConfiguration(void) { #ifdef SDCARD_DIR WSContentSend_P(HTTP_FORM_SDC_DIRa); if (glob_script_mem.script_sd_found) { - ListDir(path,depth); + ListDir(path, depth); } WSContentSend_P(HTTP_FORM_SDC_DIRc); #endif @@ -4629,15 +4606,15 @@ void script_upload(void) { char npath[48]; #if defined(ESP32) && defined(USE_SCRIPT_FATFS) && USE_SCRIPT_FATFS==-1 //sprintf(npath,"/%s",upload.filename.c_str()); - sprintf(npath,"%s/%s",path,upload.filename.c_str()); + sprintf(npath, "%s/%s", path, upload.filename.c_str()); #else - sprintf(npath,"%s/%s",path,upload.filename.c_str()); + sprintf(npath, "%s/%s", path, upload.filename.c_str()); #endif fsp->remove(npath); - upload_file=fsp->open(npath,FILE_WRITE); - if (!upload_file) Web.upload_error=1; + upload_file = fsp->open(npath, FILE_WRITE); + if (!upload_file) Web.upload_error = 1; } else if(upload.status == UPLOAD_FILE_WRITE) { - if (upload_file) upload_file.write(upload.buf,upload.currentSize); + if (upload_file) upload_file.write(upload.buf, upload.currentSize); } else if(upload.status == UPLOAD_FILE_END) { if (upload_file) upload_file.close(); if (Web.upload_error) { @@ -4658,7 +4635,7 @@ uint8_t DownloadFile(char *file) { return 0; } - download_file=fsp->open(file,FILE_READ); + download_file = fsp->open(file, FILE_READ); if (!download_file) { AddLog_P(LOG_LEVEL_INFO,PSTR("could not open file")); return 0; @@ -4669,20 +4646,20 @@ uint8_t DownloadFile(char *file) { return 1; } - uint32_t flen=download_file.size(); + uint32_t flen = download_file.size(); download_Client = Webserver->client(); Webserver->setContentLength(flen); char attachment[100]; char *cp; - for (uint8_t cnt=strlen(file); cnt>=0; cnt--) { + for (uint8_t cnt = strlen(file); cnt>=0; cnt--) { if (file[cnt]=='/') { - cp=&file[cnt+1]; + cp = &file[cnt + 1]; break; } } - snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"),cp); + snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"), cp); Webserver->sendHeader(F("Content-Disposition"), attachment); WSSend(200, CT_STREAM, ""); @@ -4690,15 +4667,15 @@ uint8_t DownloadFile(char *file) { uint16_t bread; // transfer is about 150kb/s - uint8_t cnt=0; + uint8_t cnt = 0; while (download_file.available()) { - bread=download_file.read(buff,sizeof(buff)); - uint16_t bw=download_Client.write((const char*)buff,bread); + bread = download_file.read(buff, sizeof(buff)); + uint16_t bw = download_Client.write((const char*)buff, bread); if (!bw) break; cnt++; if (cnt>7) { - cnt=0; - if (glob_script_mem.script_loglevel&0x80) { + cnt = 0; + if (glob_script_mem.script_loglevel & 0x80) { // this indeed multitasks, but is slower 50 kB/s loop(); } @@ -4747,8 +4724,8 @@ void HandleScriptConfiguration(void) { #ifdef xSCRIPT_STRIP_COMMENTS - uint16_t ssize=glob_script_mem.script_size; - if (bitRead(Settings.rule_enabled, 1)) ssize*=2; + uint16_t ssize = glob_script_mem.script_size; + if (bitRead(Settings.rule_enabled, 1)) ssize *= 2; WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",ssize); #else WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",glob_script_mem.script_size); @@ -4763,10 +4740,10 @@ void HandleScriptConfiguration(void) { #ifdef USE_SCRIPT_FATFS if (glob_script_mem.script_sd_found) { WSContentSend_P(HTTP_FORM_SCRIPT1d); - if (glob_script_mem.flink[0][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,1,glob_script_mem.flink[0]); - if (glob_script_mem.flink[1][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,2,glob_script_mem.flink[1]); + if (glob_script_mem.flink[0][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c, 1, glob_script_mem.flink[0]); + if (glob_script_mem.flink[1][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c, 2, glob_script_mem.flink[1]); } -#endif +#endif //USE_SCRIPT_FATFS WSContentSend_P(HTTP_SCRIPT_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); @@ -4777,22 +4754,22 @@ void SaveScript(void) { #ifdef EEP_SCRIPT_SIZE if (glob_script_mem.flags&1) { - EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); + EEP_WRITE(0, EEP_SCRIPT_SIZE, glob_script_mem.script_ram); } #endif // EEP_SCRIPT_SIZE #ifdef USE_SCRIPT_FATFS - if (glob_script_mem.flags&1) { + if (glob_script_mem.flags & 1) { fsp->remove(FAT_SCRIPT_NAME); - File file=fsp->open(FAT_SCRIPT_NAME,FILE_WRITE); - file.write((const uint8_t*)glob_script_mem.script_ram,FAT_SCRIPT_SIZE); + File file = fsp->open(FAT_SCRIPT_NAME, FILE_WRITE); + file.write((const uint8_t*)glob_script_mem.script_ram, FAT_SCRIPT_SIZE); file.close(); } #endif // USE_SCRIPT_FATFS #ifdef LITTLEFS_SCRIPT_SIZE if (glob_script_mem.flags&1) { - SaveFile("/script.txt",(uint8_t*)glob_script_mem.script_ram,LITTLEFS_SCRIPT_SIZE); + SaveFile("/script.txt", (uint8_t*)glob_script_mem.script_ram, LITTLEFS_SCRIPT_SIZE); } #endif // LITTLEFS_SCRIPT_SIZE } @@ -4800,9 +4777,9 @@ void SaveScript(void) { void ScriptSaveSettings(void) { if (Webserver->hasArg("c1")) { - bitWrite(Settings.rule_enabled,0,1); + bitWrite(Settings.rule_enabled, 0, 1); } else { - bitWrite(Settings.rule_enabled,0,0); + bitWrite(Settings.rule_enabled, 0, 0); } @@ -4810,42 +4787,42 @@ void ScriptSaveSettings(void) { if (*str.c_str()) { - str.replace("\r\n","\n"); - str.replace("\r","\n"); + str.replace("\r\n", "\n"); + str.replace("\r", "\n"); #ifdef xSCRIPT_STRIP_COMMENTS if (bitRead(Settings.rule_enabled, 1)) { - char *sp=(char*)str.c_str(); - char *sp1=sp; - char *dp=sp; - uint8_t flg=0; + char *sp = (char*)str.c_str(); + char *sp1 = sp; + char *dp = sp; + uint8_t flg = 0; while (*sp) { while (*sp==' ') sp++; - sp1=sp; - sp=strchr(sp,'\n'); + sp1 = sp; + sp = strchr(sp,'\n'); if (!sp) { - flg=1; + flg = 1; } else { - *sp=0; + *sp = 0; } if (*sp1!=';') { - uint8_t slen=strlen(sp1); + uint8_t slen = strlen(sp1); if (slen) { - strcpy(dp,sp1); - dp+=slen; - *dp++='\n'; + strcpy(dp, sp1); + dp += slen; + *dp++ = '\n'; } } if (flg) { - *dp=0; + *dp = 0; break; } sp++; } } -#endif +#endif //xSCRIPT_STRIP_COMMENTS - strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size); + strlcpy(glob_script_mem.script_ram, str.c_str(), glob_script_mem.script_size); if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') { AddLog_P2(LOG_LEVEL_INFO, PSTR("script error: must start with >D")); @@ -4863,8 +4840,8 @@ void SaveScriptEnd(void) { if (glob_script_mem.script_mem) { Scripter_save_pvars(); free(glob_script_mem.script_mem); - glob_script_mem.script_mem=0; - glob_script_mem.script_mem_size=0; + glob_script_mem.script_mem = 0; + glob_script_mem.script_mem_size = 0; } #ifdef USE_SCRIPT_COMPRESSION @@ -4879,20 +4856,20 @@ void SaveScriptEnd(void) { #endif // USE_SCRIPT_COMPRESSION if (bitRead(Settings.rule_enabled, 0)) { - int16_t res=Init_Scripter(); + int16_t res = Init_Scripter(); if (res) { AddLog_P2(LOG_LEVEL_INFO, PSTR("script init error: %d"), res); return; } - Run_Scripter(">B\n",3,0); - Run_Scripter(">BS",3,0); + Run_Scripter(">B\n", 3, 0); + Run_Scripter(">BS", 3, 0); - fast_script=Run_Scripter(">F",-2,0); + fast_script = Run_Scripter(">F", -2, 0); } } -#endif +#endif // USE_WEBSERVER #if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) @@ -5026,22 +5003,22 @@ break; void Script_HueStatus(String *response, uint16_t hue_devs) { if (hue_script[hue_devs].type=='p') { - *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON2); - response->replace("{j1",hue_script[hue_devs].name); + *response += FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON2); + response->replace("{j1", hue_script[hue_devs].name); response->replace("{j2", GetHueDeviceId(hue_devs)); - uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; + uint8_t pwr = glob_script_mem.fvars[hue_script[hue_devs].index[0] - 1]; response->replace("{state}", (pwr ? "true" : "false")); return; } - *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON1); - uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; + *response += FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON1); + uint8_t pwr = glob_script_mem.fvars[hue_script[hue_devs].index[0] - 1]; response->replace("{state}", (pwr ? "true" : "false")); String light_status = ""; if (hue_script[hue_devs].index[1]>0) { // bri light_status += "\"bri\":"; - uint32_t bri=glob_script_mem.fvars[hue_script[hue_devs].index[1]-1]; + uint32_t bri = glob_script_mem.fvars[hue_script[hue_devs].index[1] - 1]; if (bri > 254) bri = 254; if (bri < 1) bri = 1; light_status += String(bri); @@ -5049,7 +5026,7 @@ void Script_HueStatus(String *response, uint16_t hue_devs) { } if (hue_script[hue_devs].index[2]>0) { // hue - uint32_t hue=glob_script_mem.fvars[hue_script[hue_devs].index[2]-1]; + uint32_t hue = glob_script_mem.fvars[hue_script[hue_devs].index[2] - 1]; //hue = changeUIntScale(hue, 0, 359, 0, 65535); light_status += "\"hue\":"; light_status += String(hue); @@ -5057,7 +5034,7 @@ void Script_HueStatus(String *response, uint16_t hue_devs) { } if (hue_script[hue_devs].index[3]>0) { // sat - uint32_t sat=glob_script_mem.fvars[hue_script[hue_devs].index[3]-1] ; + uint32_t sat = glob_script_mem.fvars[hue_script[hue_devs].index[3] - 1] ; if (sat > 254) sat = 254; if (sat < 1) sat = 1; light_status += "\"sat\":"; @@ -5066,7 +5043,7 @@ void Script_HueStatus(String *response, uint16_t hue_devs) { } if (hue_script[hue_devs].index[4]>0) { // ct - uint32_t ct=glob_script_mem.fvars[hue_script[hue_devs].index[4]-1]; + uint32_t ct = glob_script_mem.fvars[hue_script[hue_devs].index[4] - 1]; light_status += "\"ct\":"; light_status += String(ct); light_status += ","; @@ -5101,7 +5078,7 @@ void Script_HueStatus(String *response, uint16_t hue_devs) { } response->replace("{light_status}", light_status); - response->replace("{j1",hue_script[hue_devs].name); + response->replace("{j1", hue_script[hue_devs].name); response->replace("{j2", GetHueDeviceId(hue_devs)); } @@ -5109,14 +5086,14 @@ void Script_HueStatus(String *response, uint16_t hue_devs) { void Script_Check_Hue(String *response) { if (!bitRead(Settings.rule_enabled, 0)) return; - uint8_t hue_script_found=Run_Scripter(">H",-2,0); + uint8_t hue_script_found = Run_Scripter(">H", -2, 0); if (hue_script_found!=99) return; char tmp[256]; - uint8_t hue_devs=0; - uint8_t vindex=0; + uint8_t hue_devs = 0; + uint8_t vindex = 0; char *cp; - char *lp=glob_script_mem.section_ptr+2; + char *lp = glob_script_mem.section_ptr + 2; while (lp) { SCRIPT_SKIP_SPACES while (*lp==SCRIPT_EOL) { @@ -5127,69 +5104,69 @@ void Script_Check_Hue(String *response) { } if (*lp!=';') { // check this line - Replace_Cmd_Vars(lp,1,tmp,sizeof(tmp)); + Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); // check for hue defintions // NAME, TYPE , vars - cp=tmp; - cp=strchr(cp,','); + cp = tmp; + cp = strchr(cp,','); if (!cp) break; - *cp=0; + *cp = 0; // copy name - strlcpy(hue_script[hue_devs].name,tmp,HUE_DEV_NSIZE); + strlcpy(hue_script[hue_devs].name, tmp, HUE_DEV_NSIZE); cp++; while (*cp==' ') cp++; // get type - hue_script[hue_devs].type=*cp; + hue_script[hue_devs].type = *cp; - for (vindex=0;vindex0) *response+=",\""; - else *response+="\""; + if (hue_devs>0) *response += ",\""; + else *response += "\""; } - *response+=String(EncodeLightId(hue_devs+devices_present+1))+"\":"; - Script_HueStatus(response,hue_devs); + *response += String(EncodeLightId(hue_devs + devices_present + 1))+"\":"; + Script_HueStatus(response, hue_devs); //AddLog_P2(LOG_LEVEL_INFO, PSTR("Hue: %s - %d "),response->c_str(), hue_devs); } @@ -5252,13 +5229,13 @@ void Script_Handle_Hue(String *path) { bool resp = false; uint8_t device = DecodeLightId(atoi(path->c_str())); - uint8_t index = device-devices_present-1; + uint8_t index = device - devices_present - 1; if (Webserver->args()) { response = "["; StaticJsonBuffer<400> jsonBuffer; - JsonObject &hue_json = jsonBuffer.parseObject(Webserver->arg((Webserver->args())-1)); + JsonObject &hue_json = jsonBuffer.parseObject(Webserver->arg((Webserver->args()) - 1)); if (hue_json.containsKey("on")) { response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); @@ -5267,26 +5244,26 @@ void Script_Handle_Hue(String *path) { bool on = hue_json["on"]; if (on==false) { - glob_script_mem.fvars[hue_script[index].index[0]-1]=0; + glob_script_mem.fvars[hue_script[index].index[0] - 1] = 0; response.replace("{re", "false"); } else { - glob_script_mem.fvars[hue_script[index].index[0]-1]=1; + glob_script_mem.fvars[hue_script[index].index[0] - 1] = 1; response.replace("{re", "true"); } - glob_script_mem.type[hue_script[index].vindex[0]].bits.changed=1; + glob_script_mem.type[hue_script[index].vindex[0]].bits.changed = 1; resp = true; } if (hue_json.containsKey("bri")) { // Brightness is a scale from 1 (the minimum the light is capable of) to 254 (the maximum). Note: a brightness of 1 is not off. tmp = hue_json["bri"]; - bri=tmp; + bri = tmp; if (254 <= bri) { bri = 255; } if (resp) { response += ","; } response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); response.replace("{id", String(EncodeLightId(device))); response.replace("{cm", "bri"); response.replace("{re", String(tmp)); - glob_script_mem.fvars[hue_script[index].index[1]-1]=bri; - glob_script_mem.type[hue_script[index].vindex[1]].bits.changed=1; + glob_script_mem.fvars[hue_script[index].index[1] - 1] = bri; + glob_script_mem.type[hue_script[index].vindex[1]].bits.changed = 1; resp = true; } if (hue_json.containsKey("xy")) { // Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white). @@ -5303,10 +5280,10 @@ void Script_Handle_Hue(String *path) { response.replace("{id", String(device)); response.replace("{cm", "xy"); response.replace("{re", "[" + x_str + "," + y_str + "]"); - glob_script_mem.fvars[hue_script[index].index[2]-1]=hue; - glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1; - glob_script_mem.fvars[hue_script[index].index[3]-1]=sat; - glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1; + glob_script_mem.fvars[hue_script[index].index[2]-1] = hue; + glob_script_mem.type[hue_script[index].vindex[2]].bits.changed = 1; + glob_script_mem.fvars[hue_script[index].index[3]-1] = sat; + glob_script_mem.type[hue_script[index].vindex[3]].bits.changed = 1; resp = true; } @@ -5314,27 +5291,27 @@ void Script_Handle_Hue(String *path) { tmp = hue_json["hue"]; //hue = changeUIntScale(tmp, 0, 65535, 0, 359); //tmp = changeUIntScale(hue, 0, 359, 0, 65535); - hue=tmp; + hue = tmp; if (resp) { response += ","; } response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); response.replace("{id", String(EncodeLightId(device))); response.replace("{cm", "hue"); response.replace("{re", String(tmp)); - glob_script_mem.fvars[hue_script[index].index[2]-1]=hue; - glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1; + glob_script_mem.fvars[hue_script[index].index[2] - 1] = hue; + glob_script_mem.type[hue_script[index].vindex[2]].bits.changed = 1; resp = true; } if (hue_json.containsKey("sat")) { // Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white). tmp = hue_json["sat"]; - sat=tmp; + sat = tmp; if (254 <= sat) { sat = 255; } if (resp) { response += ","; } response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); response.replace("{id", String(EncodeLightId(device))); response.replace("{cm", "sat"); response.replace("{re", String(tmp)); - glob_script_mem.fvars[hue_script[index].index[3]-1]=sat; - glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1; + glob_script_mem.fvars[hue_script[index].index[3] - 1] = sat; + glob_script_mem.type[hue_script[index].vindex[3]].bits.changed = 1; resp = true; } if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm) @@ -5344,8 +5321,8 @@ void Script_Handle_Hue(String *path) { response.replace("{id", String(EncodeLightId(device))); response.replace("{cm", "ct"); response.replace("{re", String(ct)); - glob_script_mem.fvars[hue_script[index].index[4]-1]=ct; - glob_script_mem.type[hue_script[index].vindex[4]].bits.changed=1; + glob_script_mem.fvars[hue_script[index].index[4] - 1] = ct; + glob_script_mem.type[hue_script[index].vindex[4]].bits.changed = 1; resp = true; } response += "]"; @@ -5356,7 +5333,7 @@ void Script_Handle_Hue(String *path) { AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); WSSend(code, CT_JSON, response); if (resp) { - Run_Scripter(">E",2,0); + Run_Scripter(">E", 2, 0); } } #endif // hue interface @@ -5369,30 +5346,30 @@ bool Script_SubCmd(void) { if (tasm_cmd_activ) return false; char command[CMDSZ]; - strlcpy(command,XdrvMailbox.topic,CMDSZ); - uint32_t pl=XdrvMailbox.payload; + strlcpy(command, XdrvMailbox.topic, CMDSZ); + uint32_t pl = XdrvMailbox.payload; char pld[64]; - strlcpy(pld,XdrvMailbox.data,sizeof(pld)); + strlcpy(pld, XdrvMailbox.data, sizeof(pld)); char cmdbuff[128]; - char *cp=cmdbuff; - *cp++='#'; - strcpy(cp,XdrvMailbox.topic); - uint8_t tlen=strlen(XdrvMailbox.topic); - cp+=tlen; + char *cp = cmdbuff; + *cp++ = '#'; + strcpy(cp, XdrvMailbox.topic); + uint8_t tlen = strlen(XdrvMailbox.topic); + cp += tlen; if (XdrvMailbox.index > 0) { - *cp++=XdrvMailbox.index|0x30; + *cp++ = XdrvMailbox.index | 0x30; tlen++; } if ((XdrvMailbox.payload>0) || (XdrvMailbox.data_len>0)) { - *cp++='('; - strncpy(cp,XdrvMailbox.data,XdrvMailbox.data_len); - cp+=XdrvMailbox.data_len; - *cp++=')'; - *cp=0; + *cp++ = '('; + strncpy(cp, XdrvMailbox.data,XdrvMailbox.data_len); + cp += XdrvMailbox.data_len; + *cp++ = ')'; + *cp = 0; } //toLog(cmdbuff); - uint32_t res=Run_Scripter(cmdbuff,tlen+1,0); + uint32_t res = Run_Scripter(cmdbuff, tlen + 1, 0); //AddLog_P2(LOG_LEVEL_INFO,">>%d",res); if (res) return false; else { @@ -5404,14 +5381,14 @@ bool Script_SubCmd(void) { } return true; } -#endif +#endif //USE_SCRIPT_SUB_COMMAND void execute_script(char *script) { - char *svd_sp=glob_script_mem.scriptptr; - strcat(script,"\n#"); - glob_script_mem.scriptptr=script; - Run_Scripter(">",1,0); - glob_script_mem.scriptptr=svd_sp; + char *svd_sp = glob_script_mem.scriptptr; + strcat(script, "\n#"); + glob_script_mem.scriptptr = script; + Run_Scripter(">", 1, 0); + glob_script_mem.scriptptr = svd_sp; } #define D_CMND_SCRIPT "Script" #define D_CMND_SUBSCRIBE "Subscribe" @@ -5441,44 +5418,44 @@ bool ScriptCommand(void) { break; #ifdef xSCRIPT_STRIP_COMMENTS case 2: - bitWrite(Settings.rule_enabled, 1,0); + bitWrite(Settings.rule_enabled, 1, 0); break; case 3: - bitWrite(Settings.rule_enabled, 1,1); + bitWrite(Settings.rule_enabled, 1, 1); break; -#endif +#endif //xSCRIPT_STRIP_COMMENTS } } else { if ('>' == XdrvMailbox.data[0]) { // execute script - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"),command,XdrvMailbox.data); + snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"), command,XdrvMailbox.data); if (bitRead(Settings.rule_enabled, 0)) { - for (uint8_t count=0; count, [, ] String result = ScriptSubscribe(XdrvMailbox.data, XdrvMailbox.data_len); @@ -5486,7 +5463,7 @@ bool ScriptCommand(void) { } else if (CMND_UNSUBSCRIBE == command_code) { //MQTT Un-subscribe command. UnSubscribe String result = ScriptUnsubscribe(XdrvMailbox.data, XdrvMailbox.data_len); Response_P(S_JSON_COMMAND_SVALUE, command, result.c_str()); -#endif //SUPPORT_MQTT_EVENT +#endif //SUPPORT_MQTT_EVENT } return serviced; } @@ -5508,7 +5485,7 @@ void dateTime(uint16_t* date, uint16_t* time) { *time = xFAT_TIME(RtcTime.hour,RtcTime.minute,RtcTime.second); } -#endif +#endif //USE_SCRIPT_FATFS @@ -5519,7 +5496,7 @@ void dateTime(uint16_t* date, uint16_t* time) { #endif #ifndef MQTT_EVENT_JSIZE #define MQTT_EVENT_JSIZE 400 -#endif +#endif //SUPPORT_MQTT_EVENT /********************************************************************************************/ /* @@ -5565,21 +5542,21 @@ bool ScriptMqttData(void) if ((dot = key1.indexOf('.')) > 0) { key2 = key1.substring(dot+1); key1 = key1.substring(0, dot); - lkey=key2; + lkey = key2; if (!jsonData[key1][key2].success()) break; //Failed to get the key/value, ignore this message. value = (const char *)jsonData[key1][key2]; } else { if (!jsonData[key1].success()) break; value = (const char *)jsonData[key1]; - lkey=key1; + lkey = key1; } } value.trim(); char sbuffer[128]; - if (!strncmp(lkey.c_str(),"Epoch",5)) { - uint32_t ep=atoi(value.c_str())-(uint32_t)EPOCH_OFFSET; - snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=%d\n"), event_item.Event.c_str(),ep); + if (!strncmp(lkey.c_str(), "Epoch", 5)) { + uint32_t ep = atoi(value.c_str()) - (uint32_t)EPOCH_OFFSET; + snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=%d\n"), event_item.Event.c_str(), ep); } else { snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str()); } @@ -5611,7 +5588,7 @@ String ScriptSubscribe(const char *data, int data_len) MQTT_Subscription subscription_item; String events; if (data_len > 0) { - char parameters[data_len+1]; + char parameters[data_len + 1]; memcpy(parameters, data, data_len); parameters[data_len] = '\0'; String event_name, topic, key; @@ -5632,7 +5609,7 @@ String ScriptSubscribe(const char *data, int data_len) //event_name.toUpperCase(); if (event_name.length() > 0 && topic.length() > 0) { //Search all subscriptions - for (uint32_t index=0; index < subscriptions.size(); index++) { + for (uint32_t index = 0; index < subscriptions.size(); index++) { if (subscriptions.get(index).Event.equals(event_name)) { //If find exists one, remove it. String stopic = subscriptions.get(index).Topic + "/#"; @@ -5665,7 +5642,7 @@ String ScriptSubscribe(const char *data, int data_len) } } else { //If did not specify the event name, list all subscribed event - for (uint32_t index=0; index < subscriptions.size(); index++) { + for (uint32_t index = 0; index < subscriptions.size(); index++) { subscription_item = subscriptions.get(index); events.concat(subscription_item.Event + "," + subscription_item.Topic + (subscription_item.Key.length()>0 ? "," : "") @@ -5795,15 +5772,15 @@ void ScriptGetSDCard(void) { if (!HttpCheckPriviledgedAccess()) { return; } String stmp = Webserver->uri(); - char *cp=strstr_P(stmp.c_str(),PSTR("/sdc/")); + char *cp = strstr_P(stmp.c_str(), PSTR("/sdc/")); // if (cp) Serial.printf(">>>%s\n",cp); if (cp) { #ifdef ESP32 - cp+=4; + cp += 4; #else - cp+=5; + cp += 5; #endif - if (strstr_P(cp,PSTR("scrdmp.bmp"))) { + if (strstr_P(cp, PSTR("scrdmp.bmp"))) { SendFile(cp); return; } else { @@ -5821,34 +5798,34 @@ extern uint8_t *buffer; void SendFile(char *fname) { char buff[512]; const char *mime; - uint8_t sflg=0; - char *jpg=strstr(fname,".jpg"); + uint8_t sflg = 0; + char *jpg = strstr(fname,".jpg"); if (jpg) { - mime="image/jpeg"; + mime = "image/jpeg"; } #ifdef USE_DISPLAY_DUMP - char *sbmp=strstr_P(fname,PSTR("scrdmp.bmp")); + char *sbmp = strstr_P(fname, PSTR("scrdmp.bmp")); if (sbmp) { - mime="image/bmp"; - sflg=1; + mime = "image/bmp"; + sflg = 1; } #endif // USE_DISPLAY_DUMP - char *bmp=strstr(fname,".bmp"); + char *bmp = strstr(fname, ".bmp"); if (bmp) { - mime="image/bmp"; + mime = "image/bmp"; } - char *html=strstr(fname,".html"); + char *html = strstr(fname, ".html"); if (html) { - mime="text/html"; + mime = "text/html"; } - char *txt=strstr(fname,".txt"); + char *txt = strstr(fname, ".txt"); if (txt) { - mime="text/plain"; + mime = "text/plain"; } - WSContentSend_P(HTTP_SCRIPT_MIMES,fname,mime); + WSContentSend_P(HTTP_SCRIPT_MIMES, fname, mime); if (sflg) { #ifdef USE_DISPLAY_DUMP @@ -5856,8 +5833,8 @@ char buff[512]; #define fileHeaderSize 14 #define infoHeaderSize 40 if (buffer) { - uint8_t *bp=buffer; - uint8_t *lbuf=(uint8_t*)calloc(Settings.display_width+2,3); + uint8_t *bp = buffer; + uint8_t *lbuf = (uint8_t*)calloc(Settings.display_width + 2, 3); uint8_t *lbp; uint8_t fileHeader[fileHeaderSize]; createBitmapFileHeader(Settings.display_height , Settings.display_width , fileHeader); @@ -5865,37 +5842,37 @@ char buff[512]; uint8_t infoHeader[infoHeaderSize]; createBitmapInfoHeader(Settings.display_height, Settings.display_width, infoHeader ); Webserver->client().write((uint8_t *)infoHeader, infoHeaderSize); - for (uint32_t lins=0; lins>1; + bits = bits>>1; } bp++; } - Webserver->client().write((const char*)lbuf, Settings.display_width*3); + Webserver->client().write((const char*)lbuf, Settings.display_width * 3); } if (lbuf) free(lbuf); Webserver->client().stop(); } #endif // USE_DISPLAY_DUMP } else { - File file=fsp->open(fname,FILE_READ); + File file = fsp->open(fname,FILE_READ); uint32_t siz = file.size(); - uint32_t len=sizeof(buff); + uint32_t len = sizeof(buff); while (siz > 0) { - if (len>siz) len=siz; - file.read((uint8_t *)buff,len ); + if (len>siz) len = siz; + file.read((uint8_t *)buff, len); Webserver->client().write((const char*)buff, len); siz -= len; } @@ -5930,7 +5907,7 @@ void ScriptFullWebpage(void) { } WSContentBegin(200, CT_HTML); - const char *title="Full Screen"; + const char *title = "Full Screen"; WSContentSend_P(HTTP_SCRIPT_FULLPAGE1, SettingsText(SET_DEVICENAME), title, fullpage_refresh); WSContentSend_P(HTTP_SCRIPT_FULLPAGE2, fullpage_refresh); //WSContentSend_P(PSTR("
")); @@ -5954,34 +5931,34 @@ void Script_Check_HTML_Setvars(void) { if (Webserver->hasArg("sv")) { String stmp = Webserver->arg("sv"); - Serial.printf("fwp has arg dv %s\n",stmp.c_str()); + Serial.printf("fwp has arg dv %s\n", stmp.c_str()); char cmdbuf[64]; - memset(cmdbuf,0,sizeof(cmdbuf)); - char *cp=cmdbuf; - *cp++='>'; - strncpy(cp,stmp.c_str(),sizeof(cmdbuf)-1); - char *cp1=strchr(cp,'_'); + memset(cmdbuf, 0, sizeof(cmdbuf)); + char *cp = cmdbuf; + *cp++ = '>'; + strncpy(cp, stmp.c_str(), sizeof(cmdbuf) - 1); + char *cp1 = strchr(cp, '_'); if (!cp1) return; - *cp1=0; + *cp1 = 0; char vname[32]; - strncpy(vname,cp,sizeof(vname)); - *cp1='='; + strncpy(vname, cp, sizeof(vname)); + *cp1 = '='; cp1++; struct T_INDEX ind; uint8_t vtype; - isvar(vname,&vtype,&ind,0,0,0); + isvar(vname, &vtype, &ind, 0, 0, 0); if (vtype!=NUM_RES && vtype&STYPE) { // string type must insert quotes - uint8_t tlen=strlen(cp1); - memmove(cp1+1,cp1,tlen); - *cp1='\"'; - *(cp1+tlen+1)='\"'; + uint8_t tlen = strlen(cp1); + memmove(cp1 + 1, cp1, tlen); + *cp1 = '\"'; + *(cp1 + tlen +1 ) = '\"'; } //toLog(cmdbuf); execute_script(cmdbuf); - Run_Scripter(">E",2,0); + Run_Scripter(">E", 2, 0); } } @@ -6048,7 +6025,9 @@ const char SCRIPT_MSG_GTABLEd[] PROGMEM = const char SCRIPT_MSG_GTABLEb[] PROGMEM = "]);" - "var options={%s" CHART_EXTRA_OPTIONS "};" + "var options={%s" CHART_EXTRA_OPTIONS "};"; + +const char SCRIPT_MSG_GTABLEbx[] PROGMEM = "var chart=new google.visualization.%s(document.getElementById('chart%1d'));" "chart.draw(data,options);}" "google.charts.setOnLoadCallback(drawChart);"; @@ -6087,60 +6066,60 @@ const char SCRIPT_MSG_GTE1[] PROGMEM = "'%s'"; char *gc_get_arrays(char *lp, float **arrays, uint8_t *ranum, uint16_t *rentries, uint16_t *ipos) { struct T_INDEX ind; uint8_t vtype; -uint16 entries=0; -uint16_t cipos=0; +uint16 entries = 0; +uint16_t cipos = 0; - uint8_t anum=0; + uint8_t anum = 0; while (anum> 2 %d\n",len); if (fa && len>=entries) { if (!entries) { entries = len; } // add array to list - arrays[anum]=fa; + arrays[anum] = fa; anum++; } } else { // single numeric - arrays[anum]=&glob_script_mem.fvars[index]; + arrays[anum] = &glob_script_mem.fvars[index]; anum++; - entries=1; + entries = 1; } } else { - lp=lp1; + lp = lp1; break; } } } //Serial.printf(">> %d - %d - %d\n",anum,entries,(uint32_t)*arrays[0]); - *ranum=anum; - *rentries=entries; - *ipos=cipos; + *ranum = anum; + *rentries = entries; + *ipos = cipos; return lp; } char *gc_send_labels(char *lp,uint32_t anum) { WSContentSend_PD("["); - for (uint32_t cnt=0; cntw",-2,0); + web_script = Run_Scripter(">w", -2, 0); } else { - web_script=Run_Scripter(">W",-2,0); + web_script = Run_Scripter(">W", -2, 0); } if (web_script==99) { char tmp[256]; - uint8_t optflg=0; - uint8_t chartindex=1; - uint8_t google_libs=0; - char *lp=glob_script_mem.section_ptr+2; + uint8_t optflg = 0; + uint8_t chartindex = 1; + uint8_t google_libs = 0; + char *lp = glob_script_mem.section_ptr + 2; if (mc=='w') { while (*lp) { if (*lp=='\n') break; @@ -6194,175 +6173,175 @@ void ScriptWebShow(char mc) { } if (*lp!=';') { // send this line to web - Replace_Cmd_Vars(lp,1,tmp,sizeof(tmp)); - char *lin=tmp; + Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); + char *lin = tmp; if ((!mc && (*lin!='$')) || (mc=='w' && (*lin!='$'))) { // normal web section if (*lin=='@') { lin++; - optflg=1; + optflg = 1; } else { - optflg=0; + optflg = 0; } // check for input elements - if (!strncmp(lin,"sl(",3)) { + if (!strncmp(lin, "sl(", 3)) { // insert slider sl(min max var left mid right) - char *lp=lin; + char *lp = lin; float min; - lp=GetNumericResult(lp+3,OPER_EQU,&min,0); + lp = GetNumericArgument(lp + 3, OPER_EQU, &min, 0); SCRIPT_SKIP_SPACES // arg2 float max; - lp=GetNumericResult(lp,OPER_EQU,&max,0); + lp = GetNumericArgument(lp, OPER_EQU, &max, 0); SCRIPT_SKIP_SPACES float val; - char *slp=lp; - lp=GetNumericResult(lp,OPER_EQU,&val,0); + char *slp = lp; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); SCRIPT_SKIP_SPACES char vname[16]; - ScriptGetVarname(vname,slp,sizeof(vname)); + ScriptGetVarname(vname, slp, sizeof(vname)); char left[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,left,0); + lp = GetStringArgument(lp, OPER_EQU, left, 0); SCRIPT_SKIP_SPACES char mid[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,mid,0); + lp = GetStringArgument(lp, OPER_EQU, mid, 0); SCRIPT_SKIP_SPACES char right[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,right,0); + lp = GetStringArgument(lp, OPER_EQU, right, 0); SCRIPT_SKIP_SPACES - WSContentSend_PD(SCRIPT_MSG_SLIDER,left,mid,right,(uint32_t)min,(uint32_t)max,(uint32_t)val,vname); + WSContentSend_PD(SCRIPT_MSG_SLIDER, left,mid, right, (uint32_t)min, (uint32_t)max, (uint32_t)val, vname); - } else if (!strncmp(lin,"ck(",3)) { - char *lp=lin+3; - char *slp=lp; + } else if (!strncmp(lin, "ck(", 3)) { + char *lp = lin + 3; + char *slp = lp; float val; - lp=GetNumericResult(lp,OPER_EQU,&val,0); + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); SCRIPT_SKIP_SPACES char vname[16]; - ScriptGetVarname(vname,slp,sizeof(vname)); + ScriptGetVarname(vname, slp, sizeof(vname)); char label[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,label,0); + lp = GetStringArgument(lp, OPER_EQU, label, 0); const char *cp; uint8_t uval; if (val>0) { - cp="checked='checked'"; - uval=0; + cp = "checked='checked'"; + uval = 0; } else { - cp=""; - uval=1; + cp = ""; + uval = 1; } - WSContentSend_PD(SCRIPT_MSG_CHKBOX,label,(char*)cp,uval,vname); + WSContentSend_PD(SCRIPT_MSG_CHKBOX, label, (char*)cp, uval, vname); - } else if (!strncmp(lin,"bu(",3)) { - char *lp=lin+3; - uint8_t bcnt=0; - char *found=lin; + } else if (!strncmp(lin, "bu(", 3)) { + char *lp = lin + 3; + uint8_t bcnt = 0; + char *found = lin; while (bcnt<4) { - found=strstr(found,"bu("); + found = strstr(found, "bu("); if (!found) break; - found+=3; + found += 3; bcnt++; } - uint8_t proz=100/bcnt; - if (!optflg && bcnt>1) proz-=2; + uint8_t proz = 100 / bcnt; + if (!optflg && bcnt>1) proz -= 2; if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_START_TBL); else WSContentSend_PD(SCRIPT_MSG_BUT_START); - for (uint32_t cnt=0;cnt0) { - cp=ontxt; - uval=0; + cp = ontxt; + uval = 0; } else { - cp=offtxt; - uval=1; + cp = offtxt; + uval = 1; } if (bcnt>1 && cnt==bcnt-1) { - if (!optflg) proz+=2; + if (!optflg) proz += 2; } if (!optflg) { - WSContentSend_PD(SCRIPT_MSG_BUTTONa,proz,uval,vname,cp); + WSContentSend_PD(SCRIPT_MSG_BUTTONa, proz, uval, vname, cp); } else { - WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL,proz,uval,vname,cp); + WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL, proz, uval, vname, cp); } if (bcnt>1 && cnt%s"),lin); + WSContentSend_PD(PSTR("
%s
"), lin); } else { - WSContentSend_PD(PSTR("{s}%s{e}"),lin); + WSContentSend_PD(PSTR("{s}%s{e}"), lin); } } } @@ -6375,58 +6354,67 @@ void ScriptWebShow(char mc) { lin++; exgc: char *lp; - if (!strncmp(lin,"gc(",3)) { + if (!strncmp(lin, "gc(", 3)) { // get google table - lp=lin+3; + lp = lin + 3; SCRIPT_SKIP_SPACES const char *type; const char *func; char options[312]; - uint8_t nanum=MAX_GARRAY; - uint8_t y2f=0; + uint8_t nanum = MAX_GARRAY; + uint8_t y2f = 0; + uint8_t tonly = 0; char ctype; - ctype=*lp; + ctype = *lp; lp++; - if (!(google_libs&GLIBS_MAIN)) { - google_libs|=GLIBS_MAIN; + if (!(google_libs & GLIBS_MAIN)) { + google_libs |= GLIBS_MAIN; WSContentSend_PD(SCRIPT_MSG_GTABLE); } switch (ctype) { case 'l': - type=PSTR("LineChart"); + type = PSTR("LineChart"); break; case 'b': - type=PSTR("BarChart"); + type = PSTR("BarChart"); break; case 'p': - type=PSTR("PieChart"); + type = PSTR("PieChart"); break; case 'g': - type=PSTR("Gauge"); - if (!(google_libs&GLIBS_GAUGE)) { - google_libs|=GLIBS_GAUGE; + type = PSTR("Gauge"); + if (!(google_libs & GLIBS_GAUGE)) { + google_libs |= GLIBS_GAUGE; WSContentSend_PD(SCRIPT_MSG_GAUGE); } break; case 't': - type=PSTR("Table"); - if (!(google_libs&GLIBS_TABLE)) { - google_libs|=GLIBS_TABLE; + type = PSTR("Table"); + if (!(google_libs & GLIBS_TABLE)) { + google_libs |= GLIBS_TABLE; WSContentSend_PD(SCRIPT_MSG_TABLE); } break; case 'T': - type=PSTR("Timeline"); - if (!(google_libs&GLIBS_TIMELINE)) { - google_libs|=GLIBS_TIMELINE; + type = PSTR("Timeline"); + if (!(google_libs & GLIBS_TIMELINE)) { + google_libs |= GLIBS_TIMELINE; WSContentSend_PD(SCRIPT_MSG_TIMELINE); } break; case 'h': - type=PSTR("Histogram"); + type = PSTR("Histogram"); break; case 'c': - type=PSTR("ColumnChart"); + type = PSTR("ColumnChart"); + break; + case 'C': + type = PSTR("ComboChart"); + break; + case 'e': + WSContentSend_PD(SCRIPT_MSG_GTABLEbx, type, chartindex); + chartindex++; + goto nextwebline; break; default: // error @@ -6435,24 +6423,28 @@ exgc: } if (ctype=='l' && *lp=='f') { lp++; - func=PSTR(",curveType:'function'"); + func = PSTR(",curveType:'function'"); } else { - func=""; + func = ""; } if (*lp=='2') { lp++; - nanum=2; - y2f=1; + nanum = 2; + y2f = 1; + } + if (*lp=='t') { + lp++; + tonly = 1; } SCRIPT_SKIP_SPACES //Serial.printf("type %d\n",ctype); float *arrays[MAX_GARRAY]; - uint8_t anum=0; - uint16_t entries=0; - uint16_t ipos=0; - lp=gc_get_arrays(lp, &arrays[0], &anum, &entries, &ipos); + uint8_t anum = 0; + uint16_t entries = 0; + uint16_t ipos = 0; + lp = gc_get_arrays(lp, &arrays[0], &anum, &entries, &ipos); if (anum>nanum) { goto nextwebline; @@ -6461,98 +6453,120 @@ exgc: //Serial.printf("arrays %d\n",anum); //Serial.printf("entries %d\n",entries); if (ctype=='T') { - if (anum && !(entries&1)) { + if (anum && !(entries & 1)) { WSContentSend_PD(SCRIPT_MSG_GTABLEa); WSContentSend_PD(SCRIPT_MSG_GTABLEd); char label[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,label,0); + lp = GetStringArgument(lp, OPER_EQU, label, 0); SCRIPT_SKIP_SPACES - for (uint32_t ind=0; ind=entries) todflg=entries-1; + int16_t divflg = 1; + int16_t todflg = -1; + if (!strncmp(label, "cnt", 3)) { + char *cp = &label[3]; + //todflg=atoi(&label[3]); + todflg = strtol(cp, &cp, 10); + if (todflg>=entries) todflg = entries - 1; + if (*cp=='/') { + cp++; + divflg = strtol(cp, &cp, 10); + } } else { - uint16 segments=1; - for (uint32_t cnt=0; cnt=entries) aind=entries-1; - for (uint32_t cnt=0; cnt=entries) aind = entries - 1; + for (uint32_t cnt = 0; cnt < entries; cnt++) { WSContentSend_PD("['"); char lbl[16]; if (todflg>=0) { - sprintf(lbl,"%d",todflg); + sprintf(lbl, "%d", todflg / divflg); todflg++; - if (todflg>=entries) { - todflg=0; + if (todflg >= entries) { + todflg = 0; } } else { - GetTextIndexed(lbl, sizeof(lbl), aind/divflg, label); + if (todflg==-1) { + GetTextIndexed(lbl, sizeof(lbl), aind / divflg, label); + } else { + // day,hours,mins + GetTextIndexed(lbl, sizeof(lbl), aind / divflg, label + 4); + sprintf(lbl, "%s-%02d", lbl, aind % divflg); + } } WSContentSend_PD(lbl); WSContentSend_PD("',"); - for (uint32_t ind=0; ind=entries) { - aind=0; + aind = 0; } } - + // table complete + if (tonly) { + WSContentSend_PD("]);"); + goto nextwebline; + } // get header char header[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,header,0); + lp = GetStringArgument(lp, OPER_EQU, header, 0); SCRIPT_SKIP_SPACES switch (ctype) { case 't': - snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT2); + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT2); break; default: - snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT1,header); + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT1, header); break; } // check for 2 axis option @@ -6560,49 +6574,52 @@ exgc: // 2 y axes variant SCRIPT_SKIP_SPACES float max1; - lp=GetNumericResult(lp,OPER_EQU,&max1,0); + lp = GetNumericArgument(lp, OPER_EQU, &max1, 0); SCRIPT_SKIP_SPACES float max2; - lp=GetNumericResult(lp,OPER_EQU,&max2,0); + lp = GetNumericArgument(lp, OPER_EQU, &max2, 0); SCRIPT_SKIP_SPACES - snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT3,header,(uint32_t)max1,(uint32_t)max2,func); + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT3, header, (uint32_t)max1, (uint32_t)max2, func); } else { SCRIPT_SKIP_SPACES - if (*lp!=')') { - float max1; - lp=GetNumericResult(lp,OPER_EQU,&max1,0); - SCRIPT_SKIP_SPACES - float max2; - lp=GetNumericResult(lp,OPER_EQU,&max2,0); - SCRIPT_SKIP_SPACES - snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT6,header,(uint32_t)max1,(uint32_t)max2,func); + if (ctype!='g') { + if (*lp!=')') { + float max1; + lp = GetNumericArgument(lp, OPER_EQU, &max1, 0); + SCRIPT_SKIP_SPACES + float max2; + lp = GetNumericArgument(lp, OPER_EQU, &max2, 0); + SCRIPT_SKIP_SPACES + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT6, header, (uint32_t)max1, (uint32_t)max2, func); + } } } if (ctype=='g') { float yellowFrom; - lp=GetNumericResult(lp,OPER_EQU,&yellowFrom,0); + lp = GetNumericArgument(lp, OPER_EQU, &yellowFrom, 0); SCRIPT_SKIP_SPACES float redFrom; - lp=GetNumericResult(lp,OPER_EQU,&redFrom,0); + lp = GetNumericArgument(lp, OPER_EQU, &redFrom, 0); SCRIPT_SKIP_SPACES float maxValue; - lp=GetNumericResult(lp,OPER_EQU,&maxValue,0); + lp = GetNumericArgument(lp, OPER_EQU, &maxValue, 0); SCRIPT_SKIP_SPACES - float redTo=maxValue; - float yellowTo=redFrom; - snprintf_P(options,sizeof(options),SCRIPT_MSG_GAUGEOPT,(uint32_t)maxValue,(uint32_t)redFrom,(uint32_t)redTo, - (uint32_t)yellowFrom,(uint32_t)yellowTo); + float redTo = maxValue; + float yellowTo = redFrom; + snprintf_P(options, sizeof(options), SCRIPT_MSG_GAUGEOPT, (uint32_t)maxValue, (uint32_t)redFrom, (uint32_t)redTo, + (uint32_t)yellowFrom, (uint32_t)yellowTo); } } - WSContentSend_PD(SCRIPT_MSG_GTABLEb,options,type,chartindex); + WSContentSend_PD(SCRIPT_MSG_GTABLEb, options); + WSContentSend_PD(SCRIPT_MSG_GTABLEbx, type, chartindex); chartindex++; } else { - WSContentSend_PD(PSTR("%s"),lin); + WSContentSend_PD(PSTR("%s"), lin); } #else lin++; - WSContentSend_PD(PSTR("%s"),lin); + WSContentSend_PD(PSTR("%s"), lin); } else { // WSContentSend_PD(PSTR("%s"),lin); #endif //USE_GOOGLE_CHARTS @@ -6626,10 +6643,10 @@ nextwebline: #ifdef USE_SENDMAIL void script_send_email_body(void(*func)(char *)) { -uint8_t msect=Run_Scripter(">m",-2,0); +uint8_t msect = Run_Scripter(">m", -2, 0); if (msect==99) { char tmp[256]; - char *lp=glob_script_mem.section_ptr+2; + char *lp = glob_script_mem.section_ptr + 2; while (lp) { while (*lp==SCRIPT_EOL) { lp++; @@ -6639,7 +6656,7 @@ uint8_t msect=Run_Scripter(">m",-2,0); } if (*lp!=';') { // send this line to smtp - Replace_Cmd_Vars(lp,1,tmp,sizeof(tmp)); + Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); //client->println(tmp); func(tmp); } @@ -6656,14 +6673,14 @@ uint8_t msect=Run_Scripter(">m",-2,0); func((char*)"*"); } } -#endif +#endif //USE_SENDMAIL #ifdef USE_SCRIPT_JSON_EXPORT void ScriptJsonAppend(void) { - uint8_t web_script=Run_Scripter(">J",-2,0); + uint8_t web_script = Run_Scripter(">J", -2, 0); if (web_script==99) { char tmp[256]; - char *lp=glob_script_mem.section_ptr+2; + char *lp = glob_script_mem.section_ptr + 2; while (lp) { while (*lp==SCRIPT_EOL) { lp++; @@ -6673,8 +6690,8 @@ void ScriptJsonAppend(void) { } if (*lp!=';') { // send this line to mqtt - Replace_Cmd_Vars(lp,1,tmp,sizeof(tmp)); - ResponseAppend_P(PSTR("%s"),tmp); + Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); + ResponseAppend_P(PSTR("%s"), tmp); } if (*lp==SCRIPT_EOL) { lp++; @@ -6690,7 +6707,7 @@ void ScriptJsonAppend(void) { bool RulesProcessEvent(char *json_event) { - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,json_event); + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E", 2, json_event); return true; } @@ -6703,7 +6720,7 @@ bool RulesProcessEvent(char *json_event) { #ifndef STASK_PRIO #define STASK_PRIO 1 -#endif +#endif //ESP32 #if 1 @@ -6724,7 +6741,7 @@ void script_task1(void *arg) { //if (time<=esp32_tasks[0].task_timer) {vTaskDelay( pdMS_TO_TICKS( time ) ); } delay(esp32_tasks[0].task_timer); if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">t1",3,0); + Run_Scripter(">t1", 3, 0); } } } @@ -6740,7 +6757,7 @@ void script_task2(void *arg) { //if (time<=esp32_tasks[1].task_timer) {vTaskDelay( pdMS_TO_TICKS( time ) ); } delay(esp32_tasks[1].task_timer); if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">t2",3,0); + Run_Scripter(">t2", 3, 0); } } } @@ -6769,14 +6786,14 @@ TaskHandle_t task_t2; void script_task1(void *arg) { while (1) { delay(task_timer1); - Run_Scripter(">t1",3,0); + Run_Scripter(">t1", 3, 0); } } void script_task2(void *arg) { while (1) { delay(task_timer2); - Run_Scripter(">t2",3,0); + Run_Scripter(">t2", 3, 0); } } @@ -6805,12 +6822,12 @@ uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core) { #include "WiFiClientSecureLightBearSSL.h" #else #include -#endif +#endif //ESP8266 // get tesla powerwall info page json string uint32_t call2https(const char *host, const char *path) { if (global_state.wifi_down) return 1; - uint32_t status=0; + uint32_t status = 0; #ifdef ESP32 WiFiClientSecure *httpsClient; httpsClient = new WiFiClientSecure; @@ -6821,8 +6838,7 @@ uint32_t call2https(const char *host, const char *path) { httpsClient->setTimeout(1500); - int retry = 0; - String result; + uint32_t retry = 0; while ((!httpsClient->connect(host, 443)) && (retry < 5)) { delay(100); retry++; @@ -6842,6 +6858,7 @@ uint32_t call2https(const char *host, const char *path) { break; } } + String result; while (httpsClient->available()) { String line = httpsClient->readStringUntil('\n'); if (line!="") { @@ -6850,20 +6867,19 @@ uint32_t call2https(const char *host, const char *path) { } httpsClient->stop(); delete httpsClient; - Run_Scripter(">jp",3,(char*)result.c_str()); + Run_Scripter(">jp", 3, (char*)result.c_str()); return 0; } - #endif // SCRIPT_GET_HTTPS_JP -void cpy2lf(char *dst,uint32_t dstlen, char *src) { +void cpy2lf(char *dst, uint32_t dstlen, char *src) { for (uint32_t cnt=0; cnt0) glob_script_mem.script_ram[len_decompressed]=0; + if (len_decompressed>0) glob_script_mem.script_ram[len_decompressed] = 0; // indicates scripter use compression bitWrite(Settings.rule_once, 6, 1); //AddLog_P2(LOG_LEVEL_INFO, PSTR("decompressed script len %d"),len_decompressed); @@ -6908,29 +6924,29 @@ bool Xdrv10(uint8_t function) #endif // USE_SCRIPT_COMPRESSION #ifdef USE_BUTTON_EVENT - for (uint32_t cnt=0;cnt=0 AddLog_P(LOG_LEVEL_INFO,PSTR("FATFS mount OK!")); //fsp->dateTimeCallback(dateTime); - glob_script_mem.script_sd_found=1; + glob_script_mem.script_sd_found = 1; char *script; - script=(char*)calloc(FAT_SCRIPT_SIZE+4,1); + script = (char*)calloc(FAT_SCRIPT_SIZE + 4, 1); if (!script) break; - glob_script_mem.script_ram=script; - glob_script_mem.script_size=FAT_SCRIPT_SIZE; + glob_script_mem.script_ram = script; + glob_script_mem.script_size = FAT_SCRIPT_SIZE; if (fsp->exists(FAT_SCRIPT_NAME)) { - File file=fsp->open(FAT_SCRIPT_NAME,FILE_READ); - file.read((uint8_t*)script,FAT_SCRIPT_SIZE); + File file = fsp->open(FAT_SCRIPT_NAME, FILE_READ); + file.read((uint8_t*)script, FAT_SCRIPT_SIZE); file.close(); } - script[FAT_SCRIPT_SIZE-1]=0; + script[FAT_SCRIPT_SIZE - 1] = 0; // 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; + glob_script_mem.script_pram = (uint8_t*)Settings.rules[0]; + glob_script_mem.script_pram_size = MAX_SCRIPT_SIZE; - glob_script_mem.flags=1; + glob_script_mem.flags = 1; } else { AddLog_P(LOG_LEVEL_INFO,PSTR("FATFS mount failed!")); - glob_script_mem.script_sd_found=0; + glob_script_mem.script_sd_found = 0; } #endif // USE_SCRIPT_FATFS @@ -6997,46 +7013,46 @@ bool Xdrv10(uint8_t function) #else // lfs on esp8266 fsp = &LittleFS; -#endif +#endif //ESP32 char *script; - script=(char*)calloc(LITTLEFS_SCRIPT_SIZE+4,1); + script = (char*)calloc(LITTLEFS_SCRIPT_SIZE + 4, 1); if (!script) break; - LoadFile("/script.txt",(uint8_t*)script,LITTLEFS_SCRIPT_SIZE); + LoadFile("/script.txt", (uint8_t*)script, LITTLEFS_SCRIPT_SIZE); - glob_script_mem.script_ram=script; - glob_script_mem.script_size=LITTLEFS_SCRIPT_SIZE; - script[LITTLEFS_SCRIPT_SIZE-1]=0; + glob_script_mem.script_ram = script; + glob_script_mem.script_size = LITTLEFS_SCRIPT_SIZE; + script[LITTLEFS_SCRIPT_SIZE-1] = 0; // 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; - glob_script_mem.flags=1; + glob_script_mem.script_pram = (uint8_t*)Settings.rules[0]; + glob_script_mem.script_pram_size = MAX_SCRIPT_SIZE; + glob_script_mem.flags = 1; #endif // LITTLEFS_SCRIPT_SIZE // a valid script MUST start with >D if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') { // clr all - memset(glob_script_mem.script_ram,0,glob_script_mem.script_size); + memset(glob_script_mem.script_ram, 0 ,glob_script_mem.script_size); strcpy_P(glob_script_mem.script_ram, PSTR(">D\nscript error must start with >D")); bitWrite(Settings.rule_enabled, 0, 0); } // assure permanent memory is 4 byte aligned - { uint32_t ptr=(uint32_t)glob_script_mem.script_pram; - ptr&=0xfffffffc; - ptr+=4; - glob_script_mem.script_pram=(uint8_t*)ptr; - glob_script_mem.script_pram_size-=4; + { uint32_t ptr = (uint32_t)glob_script_mem.script_pram; + ptr &= 0xfffffffc; + ptr += 4; + glob_script_mem.script_pram = (uint8_t*)ptr; + glob_script_mem.script_pram_size -= 4; } if (bitRead(Settings.rule_enabled, 0)) Init_Scripter(); break; case FUNC_INIT: if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">B\n",3,0); - fast_script=Run_Scripter(">F",-2,0); + Run_Scripter(">B\n", 3, 0); + fast_script = Run_Scripter(">F", -2, 0); #if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) Script_Check_Hue(0); -#endif +#endif //USE_SCRIPT_HUE } break; case FUNC_EVERY_100_MSECOND: @@ -7050,18 +7066,18 @@ bool Xdrv10(uint8_t function) break; case FUNC_SET_POWER: #ifdef SCRIPT_POWER_SECTION - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">P",2,0); + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">P", 2, 0); #else if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">E",2,0); - result=event_handeled; + Run_Scripter(">E", 2, 0); + result = event_handeled; } -#endif +#endif //SCRIPT_POWER_SECTION break; case FUNC_RULES_PROCESS: if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">E",2,mqtt_data); - result=event_handeled; + Run_Scripter(">E", 2, mqtt_data); + result = event_handeled; } break; #ifdef USE_WEBSERVER @@ -7073,11 +7089,11 @@ bool Xdrv10(uint8_t function) if (bitRead(Settings.rule_enabled, 0)) { ScriptWebShow('$'); #ifdef SCRIPT_FULL_WEBPAGE - uint8_t web_script=Run_Scripter(">w",-2,0); + uint8_t web_script = Run_Scripter(">w", -2, 0); if (web_script==99) { char bname[48]; - cpy2lf(bname,sizeof(bname),glob_script_mem.section_ptr+3); - WSContentSend_PD(HTTP_WEB_FULL_DISPLAY,bname); + cpy2lf(bname, sizeof(bname), glob_script_mem.section_ptr + 3); + WSContentSend_PD(HTTP_WEB_FULL_DISPLAY, bname); Webserver->on("/sfd", ScriptFullWebpage); #ifdef USE_SCRIPT_FATFS Webserver->onNotFound(ScriptGetSDCard); @@ -7090,24 +7106,24 @@ bool Xdrv10(uint8_t function) case FUNC_WEB_ADD_HANDLER: Webserver->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); Webserver->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration); - Webserver->on("/exs", HTTP_POST,[]() { Webserver->sendHeader("Location","/exs");Webserver->send(303);},script_upload_start); - Webserver->on("/exs", HTTP_GET,ScriptExecuteUploadSuccess); + Webserver->on("/exs", HTTP_POST,[]() { Webserver->sendHeader("Location","/exs");Webserver->send(303);}, script_upload_start); + Webserver->on("/exs", HTTP_GET, ScriptExecuteUploadSuccess); #ifdef USE_SCRIPT_FATFS - Webserver->on("/u3", HTTP_POST,[]() { Webserver->sendHeader("Location","/u3");Webserver->send(303);},script_upload); - Webserver->on("/u3", HTTP_GET,ScriptFileUploadSuccess); - Webserver->on("/upl", HTTP_GET,Script_FileUploadConfiguration); -#endif + Webserver->on("/u3", HTTP_POST,[]() { Webserver->sendHeader("Location","/u3");Webserver->send(303);}, script_upload); + Webserver->on("/u3", HTTP_GET, ScriptFileUploadSuccess); + Webserver->on("/upl", HTTP_GET, Script_FileUploadConfiguration); +#endif //USE_SCRIPT_FATFS break; #endif // USE_WEBSERVER case FUNC_SAVE_BEFORE_RESTART: if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">R",2,0); + Run_Scripter(">R", 2, 0); Scripter_save_pvars(); } #ifdef USE_SCRIPT_GLOBVARS Script_Stop_UDP(); -#endif +#endif //USE_SCRIPT_GLOBVARS break; #ifdef SUPPORT_MQTT_EVENT case FUNC_MQTT_DATA: @@ -7136,18 +7152,18 @@ bool Xdrv10(uint8_t function) case FUNC_BUTTON_PRESSED: if (bitRead(Settings.rule_enabled, 0)) { if ((script_button[XdrvMailbox.index]&1)!=(XdrvMailbox.payload&1)) { - script_button[XdrvMailbox.index]=XdrvMailbox.payload; - Run_Scripter(">b",2,0); + script_button[XdrvMailbox.index] = XdrvMailbox.payload; + Run_Scripter(">b", 2, 0); } } break; -#endif +#endif //USE_BUTTON_EVENT #ifdef USE_SCRIPT_GLOBVARS case FUNC_LOOP: Script_PollUdp(); break; -#endif +#endif //USE_SCRIPT_GLOBVARS } return result; diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino index 3a87826f3..8a0c5d395 100644 --- a/tasmota/xdrv_13_display.ino +++ b/tasmota/xdrv_13_display.ino @@ -506,7 +506,7 @@ void DisplayText(void) } } break; -#endif +#endif // USE_SCRIPT_FATFS case 'h': // hor line to var = atoiv(cp, &temp); @@ -696,7 +696,7 @@ void DisplayText(void) Restore_graph(temp,bbuff); break; } -#endif +#endif // USE_SCRIPT_FATFS { int16_t num,gxp,gyp,gxs,gys,dec,icol; float ymin,ymax; var=atoiv(cp,&num); @@ -744,7 +744,7 @@ void DisplayText(void) AddValue(num,temp); } break; -#endif +#endif // USE_GRAPH #ifdef USE_AWATCH case 'w': @@ -752,7 +752,7 @@ void DisplayText(void) cp += var; DrawAClock(temp); break; -#endif +#endif // USE_AWATCH #ifdef USE_TOUCH_BUTTONS case 'b': @@ -834,12 +834,13 @@ void DisplayText(void) buttons[num]->vpower.is_pushbutton=0; } if (dflg) buttons[num]->xdrawButton(buttons[num]->vpower.on_off); + buttons[num]->vpower.disable=!dflg; } } } } break; -#endif +#endif // USE_TOUCH_BUTTONS default: // unknown escape Response_P(PSTR("Unknown Escape")); @@ -1530,8 +1531,8 @@ void CmndDisplayRows(void) bool jpg2rgb888(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale); char get_jpeg_size(unsigned char* data, unsigned int data_size, unsigned short *width, unsigned short *height); void rgb888_to_565(uint8_t *in, uint16_t *out, uint32_t len); -#endif -#endif +#endif // JPEG_PICTS +#endif // ESP32 #if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) extern FS *fsp; @@ -1626,7 +1627,7 @@ void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp) { #endif // ESP32 } } -#endif +#endif // USE_SCRIPT_FATFS #ifdef USE_AWATCH #define MINUTE_REDUCT 4 @@ -1663,7 +1664,7 @@ void DrawAClock(uint16_t rad) { temp=((float)RtcTime.minute*(pi/30.0)-(pi/2.0)); renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-MINUTE_REDUCT)*cosf(temp),disp_ypos+(frad-MINUTE_REDUCT)*sinf(temp), fg_color); } -#endif +#endif // USE_AWATCH #ifdef USE_GRAPH @@ -1938,7 +1939,7 @@ void Restore_graph(uint8_t num, char *path) { fp.close(); RedrawGraph(num,1); } -#endif +#endif // USE_SCRIPT_FATFS void RedrawGraph(uint8_t num, uint8_t flags) { uint16_t index=num%NUM_GRAPHS; @@ -2050,16 +2051,13 @@ void AddValue(uint8_t num,float fval) { #ifdef USE_FT5206 +#include // touch panel controller #undef FT5206_address #define FT5206_address 0x38 -#include FT5206_Class *touchp; TP_Point pLoc; - - -extern VButton *buttons[]; bool FT5206_found; bool Touch_Init(TwoWire &i2c) { @@ -2088,6 +2086,7 @@ uint32_t Touch_Status(uint32_t sel) { } } + #ifdef USE_TOUCH_BUTTONS void Touch_MQTT(uint8_t index, const char *cp) { ResponseTime_P(PSTR(",\"FT5206\":{\"%s%d\":\"%d\"}}"), cp, index+1, buttons[index]->vpower.on_off); @@ -2184,6 +2183,7 @@ uint8_t vbutt=0; pLoc.y = 0; } } + #endif // USE_TOUCH_BUTTONS #endif // USE_FT5206 diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino index 604c53835..c7e3093e2 100644 --- a/tasmota/xdrv_23_zigbee_1_headers.ino +++ b/tasmota/xdrv_23_zigbee_1_headers.ino @@ -37,6 +37,7 @@ public: }; void ZigbeeZCLSend_Raw(const ZigbeeZCLSendMessage &zcl); +bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_status_ok = false); // get the result as a string (const char*) and nullptr if there is no field or the string is empty const char * getCaseInsensitiveConstCharNull(const JsonObject &json, const char *needle) { diff --git a/tasmota/xdrv_23_zigbee_1z_libs.ino b/tasmota/xdrv_23_zigbee_1z_libs.ino index 0590cff81..1f9012152 100644 --- a/tasmota/xdrv_23_zigbee_1z_libs.ino +++ b/tasmota/xdrv_23_zigbee_1z_libs.ino @@ -101,11 +101,13 @@ public: SBuffer* bval; char* sval; } val; - Za_type type; // uint8_t in size, type of attribute, see above - bool key_is_str; // is the key a string? - bool key_is_pmem; // is the string in progmem, so we don't need to make a copy - bool val_str_raw; // if val is String, it is raw JSON and should not be escaped - uint8_t key_suffix; // append a suffix to key (default is 1, explicitly output if >1) + Za_type type; // uint8_t in size, type of attribute, see above + bool key_is_str; // is the key a string? + bool key_is_pmem; // is the string in progmem, so we don't need to make a copy + bool val_str_raw; // if val is String, it is raw JSON and should not be escaped + uint8_t key_suffix; // append a suffix to key (default is 1, explicitly output if >1) + uint8_t attr_type; // [opt] type of the attribute, default to Zunk (0xFF) + uint8_t attr_multiplier; // [opt] multiplier for attribute, defaults to 0x01 (no change) // Constructor with all defaults Z_attribute(): @@ -115,7 +117,9 @@ public: key_is_str(false), key_is_pmem(false), val_str_raw(false), - key_suffix(1) + key_suffix(1), + attr_type(0xFF), + attr_multiplier(1) {}; Z_attribute(const Z_attribute & rhs) { @@ -247,6 +251,7 @@ public: } inline bool isNum(void) const { return (type >= Za_type::Za_bool) && (type <= Za_type::Za_float); } + inline bool isNone(void) const { return (type == Za_type::Za_none);} // get num values float getFloat(void) const { switch (type) { @@ -483,6 +488,8 @@ protected: key_is_str = rhs.key_is_str; key_is_pmem = rhs.key_is_pmem; key_suffix = rhs.key_suffix; + attr_type = rhs.attr_type; + attr_multiplier = rhs.attr_multiplier; // copy value copyVal(rhs); // don't touch next pointer diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index 8ad36f861..b84db3e2e 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -36,6 +36,10 @@ public: char * manufacturerId; char * modelId; char * friendlyName; + // _defer_last_time : what was the last time an outgoing message is scheduled + // this is designed for flow control and avoid messages to be lost or unanswered + uint32_t defer_last_message_sent; + uint8_t endpoints[endpoints_max]; // static array to limit memory consumption, list of endpoints until 0x00 or end of array // Used for attribute reporting Z_attribute_list attr_list; @@ -78,6 +82,7 @@ public: manufacturerId(nullptr), modelId(nullptr), friendlyName(nullptr), + defer_last_message_sent(0), endpoints{ 0, 0, 0, 0, 0, 0, 0, 0 }, attr_list(), shortaddr(_shortaddr), @@ -145,21 +150,28 @@ public: * Structures for deferred callbacks \*********************************************************************************************/ -typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); +typedef void (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); // Category for Deferred actions, this allows to selectively remove active deferred or update them typedef enum Z_Def_Category { - Z_CAT_NONE = 0, // no category, it will happen anyways + Z_CAT_ALWAYS = 0, // no category, it will happen whatever new timers + // Below will clear any event in the same category for the same address (shortaddr / groupaddr) + Z_CLEAR_DEVICE = 0x01, Z_CAT_READ_ATTR, // Attribute reporting, either READ_ATTRIBUTE or REPORT_ATTRIBUTE, we coalesce all attributes reported if we can Z_CAT_VIRTUAL_OCCUPANCY, // Creation of a virtual attribute, typically after a time-out. Ex: Aqara presence sensor Z_CAT_REACHABILITY, // timer set to measure reachability of device, i.e. if we don't get an answer after 1s, it is marked as unreachable (for Alexa) - Z_CAT_READ_0006, // Read 0x0006 cluster - Z_CAT_READ_0008, // Read 0x0008 cluster - Z_CAT_READ_0102, // Read 0x0300 cluster - Z_CAT_READ_0300, // Read 0x0300 cluster + // Below will clear based on device + cluster pair. + Z_CLEAR_DEVICE_CLUSTER, + Z_CAT_READ_CLUSTER, + // Below will clear based on device + cluster + endpoint + Z_CLEAR_DEVICE_CLUSTER_ENDPOINT, + Z_CAT_EP_DESC, // read endpoint descriptor to gather clusters + Z_CAT_BIND, // send auto-binding to coordinator + Z_CAT_CONFIG_ATTR, // send a config attribute reporting request + Z_CAT_READ_ATTRIBUTE, // read a single attribute } Z_Def_Category; -const uint32_t Z_CAT_REACHABILITY_TIMEOUT = 1000; // 1000 ms or 1s +const uint32_t Z_CAT_REACHABILITY_TIMEOUT = 2000; // 1000 ms or 1s typedef struct Z_Deferred { // below are per device timers, used for example to query the new state of the device @@ -258,8 +270,9 @@ public: bool isHueBulbHidden(uint16_t shortaddr) const ; // Timers - void resetTimersForDevice(uint16_t shortaddr, uint16_t groupaddr, uint8_t category); + void resetTimersForDevice(uint16_t shortaddr, uint16_t groupaddr, uint8_t category, uint16_t cluster = 0xFFFF, uint8_t endpoint = 0xFF); void setTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func); + void queueTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func); void runTimer(void); // Append or clear attributes Json structure @@ -723,12 +736,17 @@ bool Z_Devices::isHueBulbHidden(uint16_t shortaddr) const { // Deferred actions // Parse for a specific category, of all deferred for a device if category == 0xFF -void Z_Devices::resetTimersForDevice(uint16_t shortaddr, uint16_t groupaddr, uint8_t category) { +// Only with specific cluster number or for all clusters if cluster == 0xFFFF +void Z_Devices::resetTimersForDevice(uint16_t shortaddr, uint16_t groupaddr, uint8_t category, uint16_t cluster, uint8_t endpoint) { // iterate the list of deferred, and remove any linked to the shortaddr for (auto & defer : _deferred) { if ((defer.shortaddr == shortaddr) && (defer.groupaddr == groupaddr)) { if ((0xFF == category) || (defer.category == category)) { - _deferred.remove(&defer); + if ((0xFFFF == cluster) || (defer.cluster == cluster)) { + if ((0xFF == endpoint) || (defer.endpoint == endpoint)) { + _deferred.remove(&defer); + } + } } } } @@ -737,8 +755,8 @@ void Z_Devices::resetTimersForDevice(uint16_t shortaddr, uint16_t groupaddr, uin // Set timer for a specific device void Z_Devices::setTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func) { // First we remove any existing timer for same device in same category, except for category=0x00 (they need to happen anyway) - if (category) { // if category == 0, we leave all previous - resetTimersForDevice(shortaddr, groupaddr, category); // remove any cluster + if (category >= Z_CLEAR_DEVICE) { // if category == 0, we leave all previous timers + resetTimersForDevice(shortaddr, groupaddr, category, category >= Z_CLEAR_DEVICE_CLUSTER ? cluster : 0xFFFF, category >= Z_CLEAR_DEVICE_CLUSTER_ENDPOINT ? endpoint : 0xFF); // remove any cluster } // Now create the new timer @@ -753,6 +771,21 @@ void Z_Devices::setTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_m func }; } +// Set timer after the already queued events +// I.e. the wait_ms is not counted from now, but from the last event queued, which is 'now' or in the future +void Z_Devices::queueTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func) { + Z_Device & device = getShortAddr(shortaddr); + uint32_t now_millis = millis(); + if (TimeReached(device.defer_last_message_sent)) { + device.defer_last_message_sent = now_millis; + } + // defer_last_message_sent equals now or a value in the future + device.defer_last_message_sent += wait_ms; + + // for queueing we don't clear the backlog, so we force category to Z_CAT_ALWAYS + setTimer(shortaddr, groupaddr, (device.defer_last_message_sent - now_millis), cluster, endpoint, Z_CAT_ALWAYS, value, func); +} + // Run timer at each tick // WARNING: don't set a new timer within a running timer, this causes memory corruption void Z_Devices::runTimer(void) { @@ -918,44 +951,43 @@ uint16_t Z_Devices::parseDeviceParam(const char * param, bool short_must_be_know // Display the tracked status for a light String Z_Devices::dumpLightState(uint16_t shortaddr) const { - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.createObject(); + Z_attribute_list attr_list; char hex[8]; const Z_Device & device = findShortAddr(shortaddr); - if (foundDevice(device)) { - const char * fname = getFriendlyName(shortaddr); + const char * fname = getFriendlyName(shortaddr); + bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); // should we replace shortaddr with friendlyname? + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); - bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); // should we replace shortaddr with friendlyname? - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); - - JsonObject& dev = use_fname ? json.createNestedObject((char*) fname) // casting (char*) forces a copy - : json.createNestedObject(hex); - if (use_fname) { - dev[F(D_JSON_ZIGBEE_DEVICE)] = hex; - } else if (fname) { - dev[F(D_JSON_ZIGBEE_NAME)] = (char*) fname; - } - - // expose the last known status of the bulb, for Hue integration - dev[F(D_JSON_ZIGBEE_LIGHT)] = getHueBulbtype(shortaddr); // sign extend, 0xFF changed as -1 - // dump all known values - dev[F("Reachable")] = device.getReachable(); // TODO TODO - if (device.validPower()) { dev[F("Power")] = device.getPower(); } - if (device.validDimmer()) { dev[F("Dimmer")] = device.dimmer; } - if (device.validColormode()) { dev[F("Colormode")] = device.colormode; } - if (device.validCT()) { dev[F("CT")] = device.ct; } - if (device.validSat()) { dev[F("Sat")] = device.sat; } - if (device.validHue()) { dev[F("Hue")] = device.hue; } - if (device.validX()) { dev[F("X")] = device.x; } - if (device.validY()) { dev[F("Y")] = device.y; } + attr_list.addAttribute(F(D_JSON_ZIGBEE_DEVICE)).setStr(hex); + if (fname) { + attr_list.addAttribute(F(D_JSON_ZIGBEE_NAME)).setStr(fname); } - String payload = ""; - payload.reserve(200); - json.printTo(payload); - return payload; + if (foundDevice(device)) { + // expose the last known status of the bulb, for Hue integration + attr_list.addAttribute(F(D_JSON_ZIGBEE_LIGHT)).setInt(getHueBulbtype(shortaddr)); // sign extend, 0xFF changed as -1 + // dump all known values + attr_list.addAttribute(F("Reachable")).setBool(device.getReachable()); + if (device.validPower()) { attr_list.addAttribute(F("Power")).setUInt(device.getPower()); } + if (device.validDimmer()) { attr_list.addAttribute(F("Dimmer")).setUInt(device.dimmer); } + if (device.validColormode()) { attr_list.addAttribute(F("Colormode")).setUInt(device.colormode); } + if (device.validCT()) { attr_list.addAttribute(F("CT")).setUInt(device.ct); } + if (device.validSat()) { attr_list.addAttribute(F("Sat")).setUInt(device.sat); } + if (device.validHue()) { attr_list.addAttribute(F("Hue")).setUInt(device.hue); } + if (device.validX()) { attr_list.addAttribute(F("X")).setUInt(device.x); } + if (device.validY()) { attr_list.addAttribute(F("Y")).setUInt(device.y); } + } + + Z_attribute_list attr_list_root; + Z_attribute * attr_root; + if (use_fname) { + attr_root = &attr_list_root.addAttribute(fname); + } else { + attr_root = &attr_list_root.addAttribute(hex); + } + attr_root->setStrRaw(attr_list.toString(true).c_str()); + return attr_list_root.toString(true); } // Dump the internal memory of Zigbee devices diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 1155a6f2e..f29c514d5 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -124,6 +124,16 @@ uint16_t CxToCluster(uint8_t cx) { } return 0xFFFF; } + +uint8_t ClusterToCx(uint16_t cluster) { + for (uint8_t i=0; icluster_short)); + uint16_t conv_attr_id = pgm_read_word(&converter->attribute); + + if ((conv_cluster == cluster) && (conv_attr_id == attr_id)) { + if (multiplier) { *multiplier = pgm_read_byte(&converter->multiplier); } + if (attr_type) { *attr_type = pgm_read_byte(&converter->type); } + return (const __FlashStringHelper*) (Z_strings + pgm_read_word(&converter->name_offset)); + } + } + return nullptr; +} + class ZCLFrame { public: @@ -1051,6 +1080,11 @@ void ZCLFrame::generateSyntheticAttributes(Z_attribute_list& attr_list) { uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; switch (ccccaaaa) { // 0xccccaaaa . c=cluster, a=attribute + case 0x00010020: // BatteryVoltage + if (attr_list.countAttribute(0x0001,0x0021) == 0) { // if it does not already contain BatteryPercentage + uint32_t mv = attr.getUInt()*100; + attr_list.addAttribute(0x0001, 0x0021).setUInt(toPercentageCR2032(mv) * 2); + } case 0x0000FF01: syntheticAqaraSensor(attr_list, attr); break; @@ -1095,35 +1129,30 @@ void ZCLFrame::generateCallBacks(Z_attribute_list& attr_list) { // Set timers to read back values. // If it's a device address, also set a timer for reachability test void sendHueUpdate(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint = 0) { - int32_t z_cat = -1; - uint32_t wait_ms = 0; + uint32_t wait_ms = 0xFFFF; switch (cluster) { case 0x0006: - z_cat = Z_CAT_READ_0006; wait_ms = 200; // wait 0.2 s break; case 0x0008: - z_cat = Z_CAT_READ_0008; wait_ms = 1050; // wait 1.0 s break; case 0x0102: - z_cat = Z_CAT_READ_0102; wait_ms = 10000; // wait 10.0 s break; case 0x0300: - z_cat = Z_CAT_READ_0300; wait_ms = 1050; // wait 1.0 s break; default: break; } - if (z_cat >= 0) { + if (0xFFFF != wait_ms) { if ((BAD_SHORTADDR != shortaddr) && (0 == endpoint)) { endpoint = zigbee_devices.findFirstEndpoint(shortaddr); } if ((BAD_SHORTADDR == shortaddr) || (endpoint)) { // send if group address or endpoint is known - zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, z_cat, 0 /* value */, &Z_ReadAttrCallback); + zigbee_devices.queueTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, Z_CAT_READ_CLUSTER, 0 /* value */, &Z_ReadAttrCallback); if (BAD_SHORTADDR != shortaddr) { // reachability test is not possible for group addresses, since we don't know the list of devices in the group zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, cluster, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable); } @@ -1170,16 +1199,27 @@ void ZCLFrame::parseReadAttributes(Z_attribute_list& attr_list) { // ZCL_CONFIGURE_REPORTING_RESPONSE void ZCLFrame::parseConfigAttributes(Z_attribute_list& attr_list) { - uint32_t i = 0; uint32_t len = _payload.len(); - uint8_t status = _payload.get8(i); - Z_attribute_list attr_config_response; - attr_config_response.addAttribute(F("Status")).setUInt(status); - attr_config_response.addAttribute(F("StatusMsg")).setStr(getZigbeeStatusMessage(status).c_str()); + Z_attribute_list attr_config_list; + for (uint32_t i=0; len >= i+4; i+=4) { + uint8_t status = _payload.get8(i); + uint16_t attr_id = _payload.get8(i+2); + + Z_attribute_list attr_config_response; + attr_config_response.addAttribute(F("Status")).setUInt(status); + attr_config_response.addAttribute(F("StatusMsg")).setStr(getZigbeeStatusMessage(status).c_str()); + + const __FlashStringHelper* attr_name = zigbeeFindAttributeById(_cluster_id, attr_id, nullptr, nullptr); + if (attr_name) { + attr_config_list.addAttribute(attr_name).setStrRaw(attr_config_response.toString(true).c_str()); + } else { + attr_config_list.addAttribute(_cluster_id, attr_id).setStrRaw(attr_config_response.toString(true).c_str()); + } + } Z_attribute &attr_1 = attr_list.addAttribute(F("ConfigResponse")); - attr_1.setStrRaw(attr_config_response.toString(true).c_str()); + attr_1.setStrRaw(attr_config_list.toString(true).c_str()); } // ZCL_READ_REPORTING_CONFIGURATION_RESPONSE @@ -1459,7 +1499,7 @@ void ZCLFrame::syntheticAqaraCubeOrButton(class Z_attribute_list &attr_list, cla // presentValue = x + 128 = 180º flip to side x on top // presentValue = x + 256 = push/slide cube while side x is on top // presentValue = x + 512 = double tap while side x is on top - } else if (modelId.startsWith(F("lumi.remote"))) { // only for Aqara button + } else if (modelId.startsWith(F("lumi.remote")) || modelId.startsWith(F("lumi.sensor_switch"))) { // only for Aqara buttons WXKG11LM & WXKG12LM int32_t val = attr.getInt(); const __FlashStringHelper *aqara_click = F("click"); const __FlashStringHelper *aqara_action = F("action"); @@ -1474,8 +1514,17 @@ void ZCLFrame::syntheticAqaraCubeOrButton(class Z_attribute_list &attr_list, cla case 2: attr_list.addAttribute(aqara_click).setStr(PSTR("double")); break; + case 16: + attr_list.addAttribute(aqara_action).setStr(PSTR("hold")); + break; + case 17: + attr_list.addAttribute(aqara_action).setStr(PSTR("release")); + break; + case 18: + attr_list.addAttribute(aqara_action).setStr(PSTR("shake")); + break; case 255: - attr_list.addAttribute(aqara_click).setStr(PSTR("release")); + attr_list.addAttribute(aqara_action).setStr(PSTR("release")); break; default: attr_list.addAttribute(aqara_click).setUInt(val); @@ -1534,11 +1583,10 @@ void ZCLFrame::syntheticAqaraVibration(class Z_attribute_list &attr_list, class } /// Publish a message for `"Occupancy":0` when the timer expired -int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { +void Z_OccupancyCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { Z_attribute_list attr_list; attr_list.addAttribute(F(OCCUPANCY)).setUInt(0); zigbee_devices.jsonPublishNow(shortaddr, attr_list); - return 0; // Fix GCC 10.1 warning } // ====================================================================== @@ -1616,4 +1664,78 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_ } } +// +// Given an attribute string, retrieve all attribute details. +// Input: the attribute has a key name, either: / or /% or "" +// Ex: "0008/0000", "0008/0000%20", "Dimmer" +// Use: +// Z_attribute attr; +// attr.setKeyName("0008/0000%20") +// if (Z_parseAttributeKey(attr)) { +// // ok +// } +// +// Output: +// The `attr` attribute has the correct cluster, attr_id, attr_type, attr_multiplier +// Note: the attribute value is unchanged and unparsed +// +// Note: if the type is specified in the key, the multiplier is not applied, no conversion happens +bool Z_parseAttributeKey(class Z_attribute & attr) { + // check if the name has the format "XXXX/YYYY" where XXXX is the cluster, YYYY the attribute id + // alternative "XXXX/YYYY%ZZ" where ZZ is the type (for unregistered attributes) + if (attr.key_is_str) { + const char * key = attr.key.key; + char * delimiter = strchr(key, '/'); + char * delimiter2 = strchr(key, '%'); + if (delimiter) { + uint16_t attr_id = 0xFFFF; + uint16_t cluster_id = 0xFFFF; + uint8_t type_id = Zunk; + + cluster_id = strtoul(key, &delimiter, 16); + if (!delimiter2) { + attr_id = strtoul(delimiter+1, nullptr, 16); + } else { + attr_id = strtoul(delimiter+1, &delimiter2, 16); + type_id = strtoul(delimiter2+1, nullptr, 16); + } + attr.setKeyId(cluster_id, attr_id); + attr.attr_type = type_id; + } + } + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("cluster_id = 0x%04X, attr_id = 0x%04X"), cluster_id, attr_id); + + // do we already know the type, i.e. attribute and cluster are also known + if (Zunk == attr.attr_type) { + // scan attributes to find by name, and retrieve type + for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + const Z_AttributeConverter *converter = &Z_PostProcess[i]; + bool match = false; + uint16_t local_attr_id = pgm_read_word(&converter->attribute); + uint16_t local_cluster_id = CxToCluster(pgm_read_byte(&converter->cluster_short)); + uint8_t local_type_id = pgm_read_byte(&converter->type); + int8_t local_multiplier = pgm_read_byte(&converter->multiplier); + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Try cluster = 0x%04X, attr = 0x%04X, type_id = 0x%02X"), local_cluster_id, local_attr_id, local_type_id); + + if (!attr.key_is_str) { + if ((attr.key.id.cluster == local_cluster_id) && (attr.key.id.attr_id == local_attr_id)) { + attr.attr_type = local_type_id; + break; + } + } else if (pgm_read_word(&converter->name_offset)) { + const char * key = attr.key.key; + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Comparing '%s' with '%s'"), attr_name, converter->name); + if (0 == strcasecmp_P(key, Z_strings + pgm_read_word(&converter->name_offset))) { + // match + attr.setKeyId(local_cluster_id, local_attr_id); + attr.attr_type = local_type_id; + attr.attr_multiplier = local_multiplier; + break; + } + } + } + } + return (Zunk != attr.attr_type) ? true : false; +} + #endif // USE_ZIGBEE diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index a32f637c4..947e2ffe0 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -148,7 +148,7 @@ const uint8_t CLUSTER_0009[] = { ZLE(0x0000) }; // AlarmCount const uint8_t CLUSTER_0300[] = { ZLE(0x0000), ZLE(0x0001), ZLE(0x0003), ZLE(0x0004), ZLE(0x0007), ZLE(0x0008) }; // Hue, Sat, X, Y, CT, ColorMode // This callback is registered after a cluster specific command and sends a read command for the same cluster -int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { +void Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { size_t attrs_len = 0; const uint8_t* attrs = nullptr; @@ -188,16 +188,14 @@ int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t clus attrs, attrs_len })); } - return 0; // Fix GCC 10.1 warning } // This callback is registered after a an attribute read command was made to a light, and fires if we don't get any response after 1000 ms -int32_t Z_Unreachable(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { +void Z_Unreachable(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { if (BAD_SHORTADDR != shortaddr) { zigbee_devices.setReachable(shortaddr, false); // mark device as reachable } - return 0; // Fix GCC 10.1 warning } // returns true if char is 'x', 'y' or 'z' @@ -349,6 +347,10 @@ void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster, if ((0 != xyz.z) && (0xFF != xyz.z)) { attr_list.addAttribute(command_name, PSTR("Zone")).setUInt(xyz.z); } + // for now convert alamrs 1 and 2 to Occupancy + // TODO we may only do this conversion to ZoneType == 0x000D 'Motion Sensor' + // Occupancy is 0406/0000 of type Zmap8 + attr_list.addAttribute(0x0406, 0x0000).setUInt((xyz.x) & 0x01 ? 1 : 0); break; case 0x00040000: case 0x00040001: diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index d800eaf71..c761cabb6 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -533,7 +533,11 @@ int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { #endif for (uint32_t i = 0; i < activeEpCount; i++) { - zigbee_devices.addEndpoint(nwkAddr, activeEpList[i]); + uint8_t ep = activeEpList[i]; + zigbee_devices.addEndpoint(nwkAddr, ep); + if ((i < 4) && (ep < 0x10)) { + zigbee_devices.queueTimer(nwkAddr, 0 /* groupaddr */, 1500, ep /* fake cluster as ep */, ep, Z_CAT_EP_DESC, 0 /* value */, &Z_SendSimpleDescReq); + } } Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" @@ -546,7 +550,132 @@ int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { ResponseAppend_P(PSTR("]}}")); MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - Z_SendAFInfoRequest(nwkAddr); // probe for ModelId and ManufId + Z_SendDeviceInfoRequest(nwkAddr); // probe for ModelId and ManufId + + return -1; +} + +// list of clusters that need bindings +const uint8_t Z_bindings[] PROGMEM = { + Cx0001, Cx0006, Cx0008, Cx0300, + Cx0400, Cx0402, Cx0403, Cx0405, Cx0406, + Cx0500, +}; + +int32_t Z_ClusterToCxBinding(uint16_t cluster) { + uint8_t cx = ClusterToCx(cluster); + for (uint32_t i=0; i= 0) { + bitSet(cluster_map, found_cx); + bitSet(cluster_in_map, found_cx); + } + } + // scan out clusters + for (uint32_t i=0; i= 0) { + bitSet(cluster_map, found_cx); + } + } + + // if IAS device, request the device type + if (bitRead(cluster_map, Z_ClusterToCxBinding(0x0500))) { + // send a read command to cluster 0x0500, attribute 0x0001 (ZoneType) - to read the type of sensor + zigbee_devices.queueTimer(shortaddr, 0 /* groupaddr */, 2000, 0x0500, endpoint, Z_CAT_READ_ATTRIBUTE, 0x0001, &Z_SendSingleAttributeRead); + } + + // enqueue bind requests + for (uint32_t i=0; i 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(numInIndex + i*2)); + } + ResponseAppend_P(PSTR("],\"OutClusters\":[")); + for (uint32_t i = 0; i < numOutCluster; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(numOutIndex + i*2)); + } + ResponseAppend_P(PSTR("]}}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + } return -1; } @@ -831,7 +960,7 @@ int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) { //uint64_t srcaddr = buf.get16(idx); // unused uint8_t srcep = buf.get8(idx + 8); - uint8_t cluster = buf.get16(idx + 9); + uint16_t cluster = buf.get16(idx + 9); uint8_t addrmode = buf.get8(idx + 11); uint16_t group = 0x0000; uint64_t dstaddr = 0; @@ -960,9 +1089,31 @@ void Z_SendActiveEpReq(uint16_t shortaddr) { } // -// Send AF Info Request +// Probe the clusters_out on the first endpoint // -void Z_SendAFInfoRequest(uint16_t shortaddr) { +// Send ZDO_SIMPLE_DESC_REQ to get full list of supported Clusters for a specific endpoint +void Z_SendSimpleDescReq(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { +#ifdef USE_ZIGBEE_ZNP + uint8_t SimpleDescReq[] = { Z_SREQ | Z_ZDO, ZDO_SIMPLE_DESC_REQ, // 2504 + Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr), + endpoint }; + ZigbeeZNPSend(SimpleDescReq, sizeof(SimpleDescReq)); +#endif +#ifdef USE_ZIGBEE_EZSP + uint8_t SimpleDescReq[] = { Z_B0(shortaddr), Z_B1(shortaddr), endpoint }; + EZ_SendZDO(shortaddr, ZDO_SIMPLE_DESC_REQ, SimpleDescReq, sizeof(SimpleDescReq)); +#endif +} + + +// +// Send AF Info Request +// Queue requests for the device +// 1. Request for 'ModelId' and 'Manufacturer': 0000/0005, 0000/0006 +// 2. Auto-bind to coordinator: +// Iterate among +// +void Z_SendDeviceInfoRequest(uint16_t shortaddr) { uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr); if (0x00 == endpoint) { endpoint = 0x01; } // if we don't know the endpoint, try 0x01 uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr); @@ -983,6 +1134,170 @@ void Z_SendAFInfoRequest(uint16_t shortaddr) { })); } +// +// Send sing attribute read request in Timer +// +void Z_SendSingleAttributeRead(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr); + uint8_t InfoReq[2] = { Z_B0(value), Z_B1(value) }; // list of single attribute + + ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ + shortaddr, + 0x0000, /* group */ + cluster /*cluster*/, + endpoint, + ZCL_READ_ATTRIBUTES, + 0x0000, /* manuf */ + false /* not cluster specific */, + true /* response */, + transacid, /* zcl transaction id */ + InfoReq, sizeof(InfoReq) + })); +} + +// +// Auto-bind some clusters to the coordinator's endpoint 0x01 +// +void Z_AutoBind(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + uint64_t srcLongAddr = zigbee_devices.getDeviceLongAddr(shortaddr); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "auto-bind `ZbBind {\"Device\":\"0x%04X\",\"Endpoint\":%d,\"Cluster\":\"0x%04X\"}`"), + shortaddr, endpoint, cluster); +#ifdef USE_ZIGBEE_ZNP + SBuffer buf(34); + buf.add8(Z_SREQ | Z_ZDO); + buf.add8(ZDO_BIND_REQ); + buf.add16(shortaddr); + buf.add64(srcLongAddr); + buf.add8(endpoint); + buf.add16(cluster); + buf.add8(Z_Addr_IEEEAddress); // DstAddrMode - 0x03 = ADDRESS_64_BIT + buf.add64(localIEEEAddr); + buf.add8(0x01); // toEndpoint + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); +#endif // USE_ZIGBEE_ZNP + +#ifdef USE_ZIGBEE_EZSP + SBuffer buf(24); + + // ZDO message payload (see Zigbee spec 2.4.3.2.2) + buf.add64(srcLongAddr); + buf.add8(endpoint); + buf.add16(cluster); + buf.add8(Z_Addr_IEEEAddress); // DstAddrMode - 0x03 = ADDRESS_64_BIT + buf.add64(localIEEEAddr); + buf.add8(0x01); // toEndpoint + + EZ_SendZDO(shortaddr, ZDO_BIND_REQ, buf.buf(), buf.len()); +#endif // USE_ZIGBEE_EZSP +} + +// +// Auto-bind some clusters to the coordinator's endpoint 0x01 +// + +// the structure below indicates which attributes need to be configured for attribute reporting +typedef struct Z_autoAttributeReporting_t { + uint16_t cluster; + uint16_t attr_id; + uint16_t min_interval; // minimum interval in seconds (consecutive reports won't happen before this value) + uint16_t max_interval; // maximum interval in seconds (attribut will always be reported after this interval) + float report_change; // for non discrete attributes, the value change that triggers a report +} Z_autoAttributeReporting_t; + +// Note the attribute must be registered in the converter list, used to retrieve the type of the attribute +const Z_autoAttributeReporting_t Z_autoAttributeReporting[] PROGMEM = { + { 0x0001, 0x0020, 15*60, 15*60, 0.1 }, // BatteryVoltage + { 0x0001, 0x0021, 15*60, 15*60, 1 }, // BatteryPercentage + { 0x0006, 0x0000, 1, 60*60, 0 }, // Power + { 0x0008, 0x0000, 1, 60*60, 5 }, // Dimmer + { 0x0300, 0x0000, 1, 60*60, 5 }, // Hue + { 0x0300, 0x0001, 1, 60*60, 5 }, // Sat + { 0x0300, 0x0003, 1, 60*60, 100 }, // X + { 0x0300, 0x0004, 1, 60*60, 100 }, // Y + { 0x0300, 0x0007, 1, 60*60, 5 }, // CT + { 0x0300, 0x0008, 1, 60*60, 0 }, // ColorMode + { 0x0400, 0x0000, 10, 60*60, 5 }, // Illuminance (5 lux) + { 0x0402, 0x0000, 30, 60*60, 0.2 }, // Temperature (0.2 °C) + { 0x0403, 0x0000, 30, 60*60, 1 }, // Pressure (1 hPa) + { 0x0405, 0x0000, 30, 60*60, 1.0 }, // Humidity (1 %) + { 0x0406, 0x0000, 10, 60*60, 0 }, // Occupancy + { 0x0500, 0x0002, 1, 60*60, 0 }, // ZoneStatus +}; + +// +// Called by Device Auto-config +// Configures default values for the most common Attribute Rerporting configurations +// +// Note: must be of type `Z_DeviceTimer` +void Z_AutoConfigReportingForCluster(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + // Buffer, max 12 bytes per attribute + SBuffer buf(12*6); + + + Response_P(PSTR("ZbSend {\"Device\":\"0x%04X\",\"Config\":{"), shortaddr); + + boolean comma = false; + for (uint32_t i=0; i 0) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "auto-bind `%s`"), mqtt_data); + ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ + shortaddr, + 0x0000, /* group */ + cluster /*cluster*/, + endpoint, + ZCL_CONFIGURE_REPORTING, + 0x0000, /* manuf */ + false /* not cluster specific */, + false /* no response */, + zigbee_devices.getNextSeqNumber(shortaddr), /* zcl transaction id */ + buf.buf(), buf.len() + })); + } +} // // Handle trustCenterJoinHandler @@ -1189,6 +1504,8 @@ int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) { return Z_ReceiveActiveEp(res, zdo_buf); case ZDO_IEEE_addr_rsp: return Z_ReceiveIEEEAddr(res, zdo_buf); + case ZDO_Simple_Desc_rsp: + return Z_ReceiveSimpleDesc(res, zdo_buf); case ZDO_Bind_rsp: return Z_BindRsp(res, zdo_buf); case ZDO_Unbind_rsp: @@ -1279,9 +1596,8 @@ int32_t EZ_Recv_Default(int32_t res, const class SBuffer &buf) { \*********************************************************************************************/ // Publish the received values once they have been coalesced -int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { +void Z_PublishAttributes(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { zigbee_devices.jsonPublishFlush(shortaddr); - return 1; } /*********************************************************************************************\ @@ -1363,6 +1679,7 @@ const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { { Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND }, &ZNP_ReceivePermitJoinStatus }, // 45CB { { Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP }, &ZNP_ReceiveNodeDesc }, // 4582 { { Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP }, &Z_ReceiveActiveEp }, // 4585 + { { Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP}, &Z_ReceiveSimpleDesc}, // 4584 { { Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP }, &Z_ReceiveIEEEAddr }, // 4581 { { Z_AREQ | Z_ZDO, ZDO_BIND_RSP }, &Z_BindRsp }, // 45A1 { { Z_AREQ | Z_ZDO, ZDO_UNBIND_RSP }, &Z_UnbindRsp }, // 45A2 @@ -1413,11 +1730,11 @@ void Z_Query_Bulb(uint16_t shortaddr, uint32_t &wait_ms) { uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr); if (endpoint) { // send only if we know the endpoint - zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0006, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); + zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0006, endpoint, Z_CAT_READ_CLUSTER, 0 /* value */, &Z_ReadAttrCallback); wait_ms += inter_message_ms; - zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0008, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); + zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0008, endpoint, Z_CAT_READ_CLUSTER, 0 /* value */, &Z_ReadAttrCallback); wait_ms += inter_message_ms; - zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0300, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); + zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0300, endpoint, Z_CAT_READ_CLUSTER, 0 /* value */, &Z_ReadAttrCallback); wait_ms += inter_message_ms; zigbee_devices.setTimer(shortaddr, 0, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, 0, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable); wait_ms += 1000; // wait 1 second between devices @@ -1451,20 +1768,21 @@ int32_t Z_State_Ready(uint8_t value) { // // Mostly used for routers/end-devices // json: holds the attributes in JSON format -void Z_AutoResponder(uint16_t srcaddr, uint16_t cluster, uint8_t endpoint, const uint16_t *attr_list, size_t attr_len) { - DynamicJsonBuffer jsonBuffer; - JsonObject& json_out = jsonBuffer.createObject(); +void Z_AutoResponder(uint16_t srcaddr, uint16_t cluster, uint8_t endpoint, const uint16_t *attr_list_ids, size_t attr_len) { + Z_attribute_list attr_list; for (uint32_t i=0; i 0xFEFF) ? uxy[i] : 0xFEFF; } - if (0x0000 == attr) { json_out[F("Hue")] = changeUIntScale(hue, 0, 360, 0, 254); } - if (0x0001 == attr) { json_out[F("Sat")] = changeUIntScale(sat, 0, 255, 0, 254); } - if (0x0003 == attr) { json_out[F("X")] = uxy[0]; } - if (0x0004 == attr) { json_out[F("Y")] = uxy[1]; } - if (0x0007 == attr) { json_out[F("CT")] = LightGetColorTemp(); } + if (0x0000 == attr_id) { attr.setUInt(changeUIntScale(hue, 0, 360, 0, 254)); } + if (0x0001 == attr_id) { attr.setUInt(changeUIntScale(sat, 0, 255, 0, 254)); } + if (0x0003 == attr_id) { attr.setUInt(uxy[0]); } + if (0x0004 == attr_id) { attr.setUInt(uxy[1]); } + if (0x0007 == attr_id) { attr.setUInt(LightGetColorTemp()); } } break; #endif case 0x000A0000: // Time - json_out[F("Time")] = (Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? Rtc.utc_time - 946684800 : Rtc.utc_time; + attr.setUInt((Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? Rtc.utc_time - 946684800 : Rtc.utc_time); break; case 0x000AFF00: // TimeEpoch - Tasmota specific - json_out[F("TimeEpoch")] = Rtc.utc_time; + attr.setUInt(Rtc.utc_time); break; case 0x000A0001: // TimeStatus - json_out[F("TimeStatus")] = (Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? 0x02 : 0x00; // if time is beyond 2010 then we are synchronized + attr.setUInt((Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? 0x02 : 0x00); // if time is beyond 2010 then we are synchronized break; case 0x000A0002: // TimeZone - json_out[F("TimeZone")] = Settings.toffset[0] * 60; + attr.setUInt(Settings.toffset[0] * 60); break; case 0x000A0007: // LocalTime // TODO take DST - json_out[F("LocalTime")] = Settings.toffset[0] * 60 + ((Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? Rtc.utc_time - 946684800 : Rtc.utc_time); + attr.setUInt(Settings.toffset[0] * 60 + ((Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? Rtc.utc_time - 946684800 : Rtc.utc_time)); break; } + if (!attr.isNone()) { + Z_parseAttributeKey(attr); + attr_list.addAttribute(cluster, attr_id) = attr; + } } - if (json_out.size() > 0) { + SBuffer buf(200); + for (const auto & attr : attr_list) { + if (!ZbAppendWriteBuf(buf, attr, true)) { // true = need status indicator in Read Attribute Responses + return; // error + } + } + + if (buf.len() > 0) { // we have a non-empty output // log first - String msg(""); - msg.reserve(100); - json_out.printTo(msg); AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: Auto-responder: ZbSend {\"Device\":\"0x%04X\"" ",\"Cluster\":\"0x%04X\"" ",\"Endpoint\":%d" ",\"Response\":%s}" ), srcaddr, cluster, endpoint, - msg.c_str()); + attr_list.toString().c_str()); // send - const JsonVariant &json_out_v = json_out; - ZbSendReportWrite(json_out_v, srcaddr, 0 /* group */,cluster, endpoint, 0 /* manuf */, ZCL_READ_ATTRIBUTES_RESPONSE); + // all good, send the packet + uint8_t seq = zigbee_devices.getNextSeqNumber(srcaddr); + ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ + srcaddr, + 0x0000, + cluster /*cluster*/, + endpoint, + ZCL_READ_ATTRIBUTES_RESPONSE, + 0x0000, /* manuf */ + false /* not cluster specific */, + false /* no response */, + seq, /* zcl transaction id */ + buf.getBuffer(), buf.len() + })); } } diff --git a/tasmota/xdrv_23_zigbee_9_serial.ino b/tasmota/xdrv_23_zigbee_9_serial.ino index fd69ee16a..c14c7f248 100644 --- a/tasmota/xdrv_23_zigbee_9_serial.ino +++ b/tasmota/xdrv_23_zigbee_9_serial.ino @@ -595,7 +595,9 @@ int32_t ZigbeeProcessInputEZSP(class SBuffer &buf) { case EZSP_getNetworkParameters: // 2800 case EZSP_sendUnicast: // 3400 case EZSP_sendBroadcast: // 3600 + case EZSP_sendMulticast: // 3800 case EZSP_messageSentHandler: // 3F00 + case EZSP_incomingMessageHandler: // 4500 case EZSP_setConfigurationValue: // 5300 case EZSP_setPolicy: // 5500 case 0x0059: // 5900 - supposedly removed by still happening diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index fff151af6..5ca3b555e 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -212,6 +212,34 @@ void ZbApplyMultiplier(double &val_d, int8_t multiplier) { } } +// +// Send Attribute Write, apply mutlipliers before +// +bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_status_ok) { + double val_d = attr.getFloat(); + const char * val_str = attr.getStr(); + + if (attr.key_is_str) { return false; } + if (attr.isNum() && (1 != attr.attr_multiplier)) { + ZbApplyMultiplier(val_d, attr.attr_multiplier); + } + + // push the value in the buffer + buf.add16(attr.key.id.attr_id); // prepend with attribute identifier + if (prepend_status_ok) { + buf.add8(Z_SUCCESS); // status OK = 0x00 + } + buf.add8(attr.attr_type); // prepend with attribute type + int32_t res = encodeSingleAttribute(buf, val_d, val_str, attr.attr_type); + if (res < 0) { + // remove the attribute type we just added + // buf.setLen(buf.len() - (operation == ZCL_READ_ATTRIBUTES_RESPONSE ? 4 : 3)); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Unsupported attribute type %04X/%04X '0x%02X'"), attr.key.id.cluster, attr.key.id.attr_id, attr.attr_type); + return false; + } + return true; +} + // Parse "Report", "Write", "Response" or "Condig" attribute // Operation is one of: ZCL_REPORT_ATTRIBUTES (0x0A), ZCL_WRITE_ATTRIBUTES (0x02) or ZCL_READ_ATTRIBUTES_RESPONSE (0x01) void ZbSendReportWrite(const JsonObject &val_pubwrite, uint16_t device, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint16_t manuf, uint8_t operation) { @@ -226,99 +254,42 @@ void ZbSendReportWrite(const JsonObject &val_pubwrite, uint16_t device, uint16_t const char *key = it->key; const JsonVariant &value = it->value; - uint16_t attr_id = 0xFFFF; - uint16_t cluster_id = 0xFFFF; - uint8_t type_id = Znodata; - int8_t multiplier = 1; // multiplier to adjust the key value - double val_d = 0; // I try to avoid `double` but this type capture both float and (u)int32_t without prevision loss - const char* val_str = ""; // variant as string - - // check if the name has the format "XXXX/YYYY" where XXXX is the cluster, YYYY the attribute id - // alternative "XXXX/YYYY%ZZ" where ZZ is the type (for unregistered attributes) - char * delimiter = strchr(key, '/'); - char * delimiter2 = strchr(key, '%'); - if (delimiter) { - cluster_id = strtoul(key, &delimiter, 16); - if (!delimiter2) { - attr_id = strtoul(delimiter+1, nullptr, 16); - } else { - attr_id = strtoul(delimiter+1, &delimiter2, 16); - type_id = strtoul(delimiter2+1, nullptr, 16); - } - } - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("cluster_id = 0x%04X, attr_id = 0x%04X"), cluster_id, attr_id); - - // do we already know the type, i.e. attribute and cluster are also known - if (Znodata == type_id) { - // scan attributes to find by name, and retrieve type - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { - const Z_AttributeConverter *converter = &Z_PostProcess[i]; - bool match = false; - uint16_t local_attr_id = pgm_read_word(&converter->attribute); - uint16_t local_cluster_id = CxToCluster(pgm_read_byte(&converter->cluster_short)); - uint8_t local_type_id = pgm_read_byte(&converter->type); - int8_t local_multiplier = pgm_read_byte(&converter->multiplier); - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Try cluster = 0x%04X, attr = 0x%04X, type_id = 0x%02X"), local_cluster_id, local_attr_id, local_type_id); - - if (delimiter) { - if ((cluster_id == local_cluster_id) && (attr_id == local_attr_id)) { - type_id = local_type_id; - break; - } - } else if (pgm_read_word(&converter->name_offset)) { - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Comparing '%s' with '%s'"), attr_name, converter->name); - if (0 == strcasecmp_P(key, Z_strings + pgm_read_word(&converter->name_offset))) { - // match - cluster_id = local_cluster_id; - attr_id = local_attr_id; - type_id = local_type_id; - multiplier = local_multiplier; - break; - } - } - } - } - - // Buffer ready, do some sanity checks - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("cluster_id = 0x%04X, attr_id = 0x%04X, type_id = 0x%02X"), cluster_id, attr_id, type_id); - if ((0xFFFF == attr_id) || (0xFFFF == cluster_id)) { - Response_P(PSTR("{\"%s\":\"%s'%s'\"}"), XdrvMailbox.command, PSTR("Unknown attribute "), key); - return; - } - if (Znodata == type_id) { - Response_P(PSTR("{\"%s\":\"%s'%s'\"}"), XdrvMailbox.command, PSTR("Unknown attribute type for attribute "), key); - return; - } - - if (0xFFFF == cluster) { - cluster = cluster_id; // set the cluster for this packet - } else if (cluster != cluster_id) { - ResponseCmndChar_P(PSTR("No more than one cluster id per command")); - return; - } - - // //////////////////////////////////////////////////////////////////////////////// - // Split encoding depending on message - if (operation != ZCL_CONFIGURE_REPORTING) { - // apply multiplier if needed - val_d = value.as(); - val_str = value.as(); - ZbApplyMultiplier(val_d, multiplier); - - // push the value in the buffer - buf.add16(attr_id); // prepend with attribute identifier - if (operation == ZCL_READ_ATTRIBUTES_RESPONSE) { - buf.add8(Z_SUCCESS); // status OK = 0x00 - } - buf.add8(type_id); // prepend with attribute type - int32_t res = encodeSingleAttribute(buf, val_d, val_str, type_id); - if (res < 0) { - // remove the attribute type we just added - // buf.setLen(buf.len() - (operation == ZCL_READ_ATTRIBUTES_RESPONSE ? 4 : 3)); - Response_P(PSTR("{\"%s\":\"%s'%s' 0x%02X\"}"), XdrvMailbox.command, PSTR("Unsupported attribute type "), key, type_id); + Z_attribute attr; + attr.setKeyName(key); + if (Z_parseAttributeKey(attr)) { + // Buffer ready, do some sanity checks + if (0xFFFF == cluster) { + cluster = attr.key.id.cluster; // set the cluster for this packet + } else if (cluster != attr.key.id.cluster) { + ResponseCmndChar_P(PSTR("No more than one cluster id per command")); return; } + } else { + if (attr.key_is_str) { + Response_P(PSTR("{\"%s\":\"%s'%s'\"}"), XdrvMailbox.command, PSTR("Unknown attribute "), key); + return; + } + if (Zunk == attr.attr_type) { + Response_P(PSTR("{\"%s\":\"%s'%s'\"}"), XdrvMailbox.command, PSTR("Unknown attribute type for attribute "), key); + return; + } + } + + if (value.is()) { + attr.setStr(value.as()); + } else if (value.is()) { + attr.setFloat(value.as()); + } + + double val_d = 0; // I try to avoid `double` but this type capture both float and (u)int32_t without prevision loss + const char* val_str = ""; // variant as string + //////////////////////////////////////////////////////////////////////////////// + // Split encoding depending on message + if (operation != ZCL_CONFIGURE_REPORTING) { + if (!ZbAppendWriteBuf(buf, attr, operation == ZCL_READ_ATTRIBUTES_RESPONSE)) { + return; // error + } } else { // //////////////////////////////////////////////////////////////////////////////// // ZCL_CONFIGURE_REPORTING @@ -350,7 +321,7 @@ void ZbSendReportWrite(const JsonObject &val_pubwrite, uint16_t device, uint16_t if (nullptr != &val_attr_rc) { val_d = val_attr_rc.as(); val_str = val_attr_rc.as(); - ZbApplyMultiplier(val_d, multiplier); + ZbApplyMultiplier(val_d, attr.attr_multiplier); } // read TimeoutPeriod @@ -358,22 +329,22 @@ void ZbSendReportWrite(const JsonObject &val_pubwrite, uint16_t device, uint16_t const JsonVariant &val_attr_timeout = GetCaseInsensitive(attr_config, PSTR("TimeoutPeriod")); if (nullptr != &val_attr_timeout) { attr_timeout = strToUInt(val_attr_timeout); } - bool attr_discrete = Z_isDiscreteDataType(type_id); + bool attr_discrete = Z_isDiscreteDataType(attr.attr_type); // all fields are gathered, output the butes into the buffer, ZCL 2.5.7.1 // common bytes buf.add8(attr_direction ? 0x01 : 0x00); - buf.add16(attr_id); + buf.add16(attr.key.id.attr_id); if (attr_direction) { buf.add16(attr_timeout); } else { - buf.add8(type_id); + buf.add8(attr.attr_type); buf.add16(attr_min_interval); buf.add16(attr_max_interval); if (!attr_discrete) { - int32_t res = encodeSingleAttribute(buf, val_d, val_str, type_id); + int32_t res = encodeSingleAttribute(buf, val_d, val_str, attr.attr_type); if (res < 0) { - Response_P(PSTR("{\"%s\":\"%s'%s' 0x%02X\"}"), XdrvMailbox.command, PSTR("Unsupported attribute type "), key, type_id); + Response_P(PSTR("{\"%s\":\"%s'%s' 0x%02X\"}"), XdrvMailbox.command, PSTR("Unsupported attribute type "), key, attr.attr_type); return; } } @@ -556,6 +527,7 @@ void ZbSendRead(const JsonVariant &val_attr, uint16_t device, uint16_t groupaddr uint16_t val = strToUInt(val_attr); if (val_attr.is()) { + // value is an array [] const JsonArray& attr_arr = val_attr.as(); attrs_len = attr_arr.size() * attr_item_len; attrs = (uint8_t*) calloc(attrs_len, 1); @@ -569,6 +541,7 @@ void ZbSendRead(const JsonVariant &val_attr, uint16_t device, uint16_t groupaddr i += attr_item_len - 2 - attr_item_offset; // normally 0 } } else if (val_attr.is()) { + // value is an object {} const JsonObject& attr_obj = val_attr.as(); attrs_len = attr_obj.size() * attr_item_len; attrs = (uint8_t*) calloc(attrs_len, 1); @@ -619,10 +592,13 @@ void ZbSendRead(const JsonVariant &val_attr, uint16_t device, uint16_t groupaddr attrs_len = actual_attr_len; } else { - attrs_len = attr_item_len; - attrs = (uint8_t*) calloc(attrs_len, 1); - attrs[0 + attr_item_offset] = val & 0xFF; // little endian - attrs[1 + attr_item_offset] = val >> 8; + // value is a literal + if (0xFFFF != cluster) { + attrs_len = attr_item_len; + attrs = (uint8_t*) calloc(attrs_len, 1); + attrs[0 + attr_item_offset] = val & 0xFF; // little endian + attrs[1 + attr_item_offset] = val >> 8; + } } if (attrs_len > 0) { @@ -1307,6 +1283,13 @@ void CmndZbConfig(void) { const JsonVariant &val_txradio = GetCaseInsensitive(json, PSTR("TxRadio")); if (nullptr != &val_txradio) { zb_txradio_dbm = strToUInt(val_txradio); } + // if network key is zero, we generate a truly random key with a hardware generator from ESP + if ((0 == zb_precfgkey_l) && (0 == zb_precfgkey_h)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "generating random Zigbee network key")); + zb_precfgkey_l = (uint64_t)HwRandom() << 32 | HwRandom(); + zb_precfgkey_h = (uint64_t)HwRandom() << 32 | HwRandom(); + } + // Check if a parameter was changed after all if ( (zb_channel != Settings.zb_channel) || (zb_pan_id != Settings.zb_pan_id) || diff --git a/tasmota/xdrv_24_buzzer.ino b/tasmota/xdrv_24_buzzer.ino index 82ebfc439..60f158d6f 100644 --- a/tasmota/xdrv_24_buzzer.ino +++ b/tasmota/xdrv_24_buzzer.ino @@ -90,7 +90,7 @@ void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32 Buzzer.count = count * 2; // Start buzzer // We can use PWM mode for buzzer output if enabled. - if (Settings.flag4.buzzer_freq_mode) { // SetOption110 - Enable frequency output mode for buzzer + if (Settings.flag4.buzzer_freq_mode) { // SetOption111 - Enable frequency output mode for buzzer Buzzer.freq_mode = 1; } else { diff --git a/tasmota/xdrv_42_i2s_audio.ino b/tasmota/xdrv_42_i2s_audio.ino index 77492992b..5a31d832b 100644 --- a/tasmota/xdrv_42_i2s_audio.ino +++ b/tasmota/xdrv_42_i2s_audio.ino @@ -52,7 +52,7 @@ AudioFileSourceFS *file; AudioOutputI2S *out; AudioFileSourceID3 *id3; AudioGeneratorMP3 *decoder = NULL; - +void *mp3ram = NULL; #ifdef USE_WEBRADIO AudioFileSourceICYStream *ifile = NULL; @@ -210,6 +210,12 @@ void I2S_Init(void) { is2_volume=10; out->SetGain(((float)is2_volume/100.0)*4.0); out->stop(); + mp3ram = nullptr; + +#ifdef ESP32 + if (psramFound()) { + mp3ram = heap_caps_malloc(preallocateCodecSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + } #ifdef USE_WEBRADIO if (psramFound()) { @@ -223,6 +229,7 @@ void I2S_Init(void) { //Serial.printf_P(PSTR("FATAL ERROR: Unable to preallocate %d bytes for app\n"), preallocateBufferSize+preallocateCodecSize); } #endif // USE_WEBRADIO +#endif // ESP32 } #ifdef ESP32 @@ -285,7 +292,7 @@ void Webradio(const char *url) { retryms = millis() + 2000; } - xTaskCreatePinnedToCore(mp3_task2, "MP3", 8192, NULL, 3, &mp3_task_h, 1); + xTaskCreatePinnedToCore(mp3_task2, "MP3-2", 8192, NULL, 3, &mp3_task_h, 1); } void mp3_task2(void *arg){ @@ -366,7 +373,12 @@ void Play_mp3(const char *path) { file = new AudioFileSourceFS(*fsp,path); id3 = new AudioFileSourceID3(file); - mp3 = new AudioGeneratorMP3(); + + if (mp3ram) { + mp3 = new AudioGeneratorMP3(mp3ram, preallocateCodecSize); + } else { + mp3 = new AudioGeneratorMP3(); + } mp3->begin(id3, out); if (I2S_Task) { diff --git a/tasmota/xdrv_43_mlx90640.ino b/tasmota/xdrv_43_mlx90640.ino new file mode 100644 index 000000000..88832acc6 --- /dev/null +++ b/tasmota/xdrv_43_mlx90640.ino @@ -0,0 +1,626 @@ +/* + xdrv_43_mlx90640.ino - MLX90640 support for Tasmota + + Copyright (C) 2020 Christian Baars and Theo Arends + + 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 . + + + -------------------------------------------------------------------------------------------- + Version yyyymmdd Action Description + -------------------------------------------------------------------------------------------- + 0.9.0.0 20200827 started - based on https://github.com/melexis/mlx90640-library +*/ + +#ifdef USE_I2C +#ifdef USE_MLX90640 + +#define MLX90640_ADDRESS 0x33 +#define MLX90640_POI_NUM 6 //some parts of the JS are hardcoded for 6!! + +/*********************************************************************************************\ +* MLX90640 +\*********************************************************************************************/ + +#define XDRV_43 43 +#define XI2C_53 53 // See I2CDEVICES.md +#include + +const char MLX90640type[] PROGMEM = "MLX90640"; + +#ifdef USE_WEBSERVER +#define WEB_HANDLE_MLX90640 "mlx" +const char HTTP_BTN_MENU_MLX90640[] PROGMEM = "

"; +#endif // USE_WEBSERVER + +struct { + uint32_t type:1; + uint32_t ready:1; + uint32_t dumpedEE:1; + uint32_t extractedParams:1; + paramsMLX90640 *params; + float Ta; + uint16_t Frame[834]; + float To[768]; + uint8_t pois[2*MLX90640_POI_NUM] = {2,1, 30,1, 10,12, 22,12, 2,23, 30,23}; // {x1,y1,x2,y2,...,x6,y6} +} MLX90640; + +/*********************************************************************************************\ + * commands +\*********************************************************************************************/ + +#define D_CMND_MLX90640 "MLX" + +const char S_JSON_MLX90640_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MLX90640 "%s\":%d}"; +const char S_JSON_MLX90640_COMMAND[] PROGMEM = "{\"" D_CMND_MLX90640 "%s\"}"; +const char kMLX90640_Commands[] PROGMEM = "POI"; + +enum MLX90640_Commands { // commands useable in console or rules + CMND_MLX90640_POI // MLXPOIn xxyy - set POI number n to x,y + }; + +/************************************************************************\ + * Web GUI +\************************************************************************/ +#ifdef USE_WEBSERVER + +#ifdef USE_UNISHOX_COMPRESSION +const size_t HTTP_MLX90640_1_SNS_SIZE = 389; +const char HTTP_MLX90640_1_SNS_COMPRESSED[] PROGMEM = "\x3D\x3C\x1F\xF4\x65\x2A\x2B\x32\x18\xCF\x87\xDD\x33\x65\x1D\x86\xBB\x33\xB0\x41" + "\xA4\x7D\x9F\x81\xE7\x7A\x90\xDB\x18\x7C\x3B\xA6\x76\x10\xB6\x75\x1B\x0E\x43\xA8" + "\x8C\x8E\x43\xA8\x8D\x87\x28\xEA\x23\x23\x94\x77\x8F\x87\xE1\x02\x0D\x13\xAC\xD8" + "\x72\x1D\xE3\xD6\x77\x48\xC8\xE5\x1D\x64\x6C\x39\x47\x78\xEC\x3B\xA4\x64\x72\x1D" + "\x64\x6C\x39\x0E\xF1\xDB\x23\x61\xCA\x3C\x10\x20\xE3\x3A\x36\xC7\x9A\x3E\x2E\x63" + "\xE8\xB4\x6D\x8F\x33\xC1\x9D\xFD\x07\x7C\x67\x7E\x3A\x83\xA3\x61\xD4\x3D\xF1\x0F" + "\x06\x77\xF4\x3C\x43\x0D\x87\x50\xCC\xD3\xE1\xEF\x1E\xF9\xE0\xCE\xFE\xBE\x56\x7C" + "\x3D\xE3\xDF\x3C\x18\x17\xC1\xD6\xE7\x21\xE7\x44\x37\x05\xF9\x90\xCC\xF1\xDD\x04" + "\x2C\x65\x33\x3A\x3B\xC8\xF6\x82\x0E\x87\xF6\x1D\x23\xE0\x21\x66\x87\x41\xE7\x44" + "\x3B\x05\xF0\x9B\xC3\xC4\x18\x5A\xFA\x8B\xEC\x3A\x3B\xA7\x78\xF0\x67\x7F\x46\xC4" + "\x7C\x4C\xCE\x8E\x81\x85\xAF\xA8\x8D\x87\x5F\xD8\x74\x74\x09\x98\xA3\xC6\x98\x3B" + "\xA6\xC3\xF0\xE5\xD3\x3B\xC7\xB4\x8D\x87\xC3\x97\x11\xE0\xF7\x17\xDD\x0B\xFF\x23" + "\xDA\x6C\x3C\xD1\x0D\xBA\x14\x74\x30\x16\x67\xCE\xE8\xDB\x18\x77\x4D\x87\x51\xC6" + "\x75\x5D\x33\xA9\x9D\x57\x0E\x88\xEF\x1D\xE3\xA8\x8C\x81\x32\xF9\xDD\x04\x5D\x04" + "\x8C\x91\xD6\xBE\xC3\xA3\xA5\x60\xC3\xBC\x75\x1C\x67\x55\x63\x3A\x99\xD5\x56\x74" + "\x47\x78\xEF\x1E\xE3\xC1\xEE"; +#define HTTP_MLX90640_1_SNS Decompress(HTTP_MLX90640_1_SNS_COMPRESSED,HTTP_MLX90640_1_SNS_SIZE).c_str() +#else +const char HTTP_MLX90640_1_SNS[] PROGMEM = + "" +; +#endif //USE_UNISHOX_COMPRESSION +#ifdef USE_UNISHOX_COMPRESSION +const size_t HTTP_MLX90640_4b_SNS_SIZE = 418; +const char HTTP_MLX90640_4b_SNS_COMPRESSED[] PROGMEM = "\x3D\x07\x60\x86\x4B\x38\x2C\xB1\x0F\x87\xDF\x9D\x0B\x18\x77\x4E\xF1\xE0\xFB\x3F" + "\x0F\x40\xEF\x8C\xEF\xCB\x44\x3E\x1F\x63\x42\x36\x1F\x68\x7F\x44\xA1\x47\xC3\xEC" + "\xE5\xE3\x3E\xCE\xE1\x0A\x7A\x3C\x2A\x2B\x8F\x87\xD9\xCA\xC6\x7D\x9F\x87\xA1\xD8" + "\x40\x83\x83\x9F\x87\xA0\x9A\x66\x7E\x1E\x87\x60\x9A\x66\x7E\x1E\x9E\x61\x30\xE9" + "\x68\x87\xC3\xEC\x66\x69\x04\x7D\xAC\xE0\xC5\x5F\x0F\x33\xE1\xF6\x37\x3C\x77\x4E" + "\xF1\xF6\x7E\x1E\x98\x32\xB7\x39\x19\xD8\x42\xD9\xF0\xFB\x38\xCF\xB3\xF0\x88\x61" + "\x61\x69\xD6\x72\x1E\x87\x61\x02\x0D\x40\x4B\xB8\x72\x10\x20\xDC\x39\x44\x0A\x77" + "\x0E\x51\x02\x0D\xC3\x96\x40\xA7\x70\xE5\x90\x20\xDC\x39\x84\x0A\x77\x0E\x61\x02" + "\x0D\xC3\x9A\x40\xA7\x70\xE6\x90\x20\xDC\x39\xC4\x08\xB7\x0E\xC0\x41\xE1\x2A\x01" + "\xFC\x3D\x04\xD3\x30\x41\xE2\x0C\xE4\x3E\xC8\x10\xF8\x5B\x13\x4C\xCF\xC2\x18\x58" + "\x5A\x75\x9C\x67\x99\xDC\x3D\x0B\xC3\x2F\x96\x88\x7C\x3E\xEC\xE4\x3E\xCF\xC3\xD0" + "\xEC\x2F\x0C\xBE\x3F\x26\x3B\x32\xF2\x0D\x1D\xDF\x3E\xF6\x7C\xEF\x02\x2E\x1E\x08" + "\x39\x11\xCA\x20\x44\xC8\x8E\xC1\xD8\x21\x91\xF8"; +#define HTTP_MLX90640_4b_SNS Decompress(HTTP_MLX90640_4b_SNS_COMPRESSED,HTTP_MLX90640_4b_SNS_SIZE).c_str() +#else +const char HTTP_MLX90640_4b_SNS[] PROGMEM = + "" + "" + "
" + "" + "
" + "
POI-0: °C (sensor)
" + "
" + "" + ; +#endif //USE_UNISHOX_COMPRESSION +void MLX90640UpdateGUI(void){ + WSContentStart_P("mlx"); + WSContentSendStyle(); + WSContentSend_P(HTTP_MLX90640_1_SNS); + WSContentSend_P(HTTP_MLX90640_2a_SNS); + WSContentSend_P(HTTP_MLX90640_2b_SNS); + WSContentSend_P(HTTP_MLX90640_3a_SNS); + WSContentSend_P(HTTP_MLX90640_3b_SNS); + WSContentSend_P(HTTP_MLX90640_4a_SNS); + WSContentSend_P(HTTP_MLX90640_4b_SNS); + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); +} + +void MLX90640HandleWebGuiResponse(void){ + char tmp[(MLX90640_POI_NUM*2)+4]; + WebGetArg("ul", tmp, sizeof(tmp)); // update line + if (strlen(tmp)) { + uint8_t _line = atoi(tmp); + // AddLog_P2(LOG_LEVEL_DEBUG, "MLX90640: send line %u", _line); + float _buf[65]; + if(_line==0){_buf[0]=1000+MLX90640.Ta;} //ambient temperature modulation hack + else{_buf[0]=(float)_line;} + memcpy((char*)&_buf[1],(char*)&MLX90640.To[_line*64],64*4); + Webserver->send(200,PSTR("application/octet-stream"),(const char*)&_buf,65*4); + return; + } + WebGetArg("up", tmp, sizeof(tmp)); // update POI to browser + if (strlen(tmp)==1) { + Webserver->send(200,PSTR("application/octet-stream"),(const char*)&MLX90640.pois,MLX90640_POI_NUM*2); + return; + } + else if (strlen(tmp)>2) { // receive updated POI from browser + uint32_t _poi = atoi(tmp); + uint32_t _poiNum = (_poi-(_poi%10000))/10000; + MLX90640.pois[_poiNum*2] = (_poi%10000)/100; + MLX90640.pois[(_poiNum*2)+1] = _poi%100; + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RAW: %u, POI-%u: x: %u, y: %u"),_poi,_poiNum,MLX90640.pois[_poiNum],MLX90640.pois[_poiNum+1]); + for(int i = 0;i(MLX90640_POI_NUM-1)&&XdrvMailbox.index<1) return false; + _idx = (XdrvMailbox.index-1)*2; + if (XdrvMailbox.data_len > 0) { + uint32_t _coord = TextToInt(XdrvMailbox.data); + MLX90640.pois[_idx] = (_coord%10000)/100; + if(MLX90640.pois[_idx]>31) MLX90640.pois[_idx]=31; + MLX90640.pois[_idx+1] = _coord%100; + if(MLX90640.pois[_idx+1]>23) MLX90640.pois[_idx+1]=23; + } + AddLog_P2(LOG_LEVEL_INFO, PSTR("POI-%u = x:%u,y:%u"),XdrvMailbox.index,MLX90640.pois[_idx],MLX90640.pois[_idx+1]); + Response_P(S_JSON_MLX90640_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + default: + // else for Unknown command + serviced = false; + break; + } + } else { + return false; + } + return serviced; +} + +/************************************************************************\ + * Init +\************************************************************************/ +void MLX90640init() +{ + if (MLX90640.type || !I2cSetDevice(MLX90640_ADDRESS)) { return; } + + Wire.setClock(400000); + int status = -1; + if(!MLX90640.dumpedEE){ + status = MLX90640_DumpEE(MLX90640_ADDRESS, MLX90640.Frame); + if (status != 0){ + AddLog_P2(LOG_LEVEL_INFO, PSTR("Failed to load system parameters")); + } + else { + AddLog_P2(LOG_LEVEL_INFO, PSTR("MLX90640: started")); + MLX90640.type = true; + } + MLX90640.params = new paramsMLX90640; + } +} + +/************************************************************************\ + * Run loop +\************************************************************************/ +void MLX90640every100msec(){ + static uint32_t _job = 0; + int status; + uint32_t _time; + + if(!MLX90640.extractedParams){ + static uint32_t _chunk = 0; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: will read chunk: %u"), _chunk); + _time = millis(); + status = MLX90640_ExtractParameters(MLX90640.Frame, MLX90640.params, _chunk); + if (status == 0){ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: parameter received after: %u msec, status: %u"), TimePassedSince(_time), status); + } + if (_chunk == 5) MLX90640.extractedParams = true; + _chunk++; + return; + } + + switch(_job){ + case 0: + if(MLX90640_SynchFrame(MLX90640_ADDRESS)!=0){ + _job=-1; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: frame not ready")); + break; + } + // _time = millis(); + status = MLX90640_GetFrameData(MLX90640_ADDRESS, MLX90640.Frame); + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: got frame 0 in %u msecs, status: %i"), TimePassedSince(_time), status); + break; + case 1: + MLX90640.Ta = MLX90640_GetTa(MLX90640.Frame, MLX90640.params); + break; + case 2: + // _time = millis(); + MLX90640_CalculateTo(MLX90640.Frame, MLX90640.params, 0.95f, MLX90640.Ta - 8, MLX90640.To, 0); + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: calculated temperatures in %u msecs"), TimePassedSince(_time)); + break; + case 5: + if(MLX90640_SynchFrame(MLX90640_ADDRESS)!=0){ + _job=4; + break; + } + // _time = millis(); + status = MLX90640_GetFrameData(MLX90640_ADDRESS, MLX90640.Frame); + // // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: got frame 1 in %u msecs, status: %i"), TimePassedSince(_time), status); + break; + case 7: + // _time = millis(); + MLX90640_CalculateTo(MLX90640.Frame, MLX90640.params, 0.95f, MLX90640.Ta - 8, MLX90640.To, 1); + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: calculated temperatures in %u msecs"), TimePassedSince(_time)); + break; + default: + break; + } + _job++; + if(_job>10) _job=0; +} + + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +void MLX90640Show(uint8_t json) +{ + char amb_tstr[FLOATSZ]; + dtostrfd(MLX90640.Ta, Settings.flag2.temperature_resolution, amb_tstr); + if (json) { + ResponseAppend_P(PSTR(",\"MLX90640\":{\"" D_JSON_TEMPERATURE "\":[%s"), amb_tstr); + for(int i = 0;ion("/mlx", MLX90640HandleWebGui); + break; +#endif // USE_WEBSERVER + case FUNC_COMMAND: + result = MLX90640Cmd(); + break; + } + } + return result; +} + +#endif // USE_MLX90640_SENSOR +#endif // USE_I2C diff --git a/tasmota/xsns_09_bmp.ino b/tasmota/xsns_09_bmp.ino index 9e3ee59b4..8e1bd074a 100644 --- a/tasmota/xsns_09_bmp.ino +++ b/tasmota/xsns_09_bmp.ino @@ -613,15 +613,17 @@ void BmpShow(bool json) void BMP_EnterSleep(void) { - for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { - switch (bmp_sensors[bmp_idx].bmp_type) { - case BMP180_CHIPID: - case BMP280_CHIPID: - case BME280_CHIPID: - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP_REGISTER_RESET, BMP_CMND_RESET); - break; - default: - break; + if (DeepSleepEnabled()) { + for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + switch (bmp_sensors[bmp_idx].bmp_type) { + case BMP180_CHIPID: + case BMP280_CHIPID: + case BME280_CHIPID: + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP_REGISTER_RESET, BMP_CMND_RESET); + break; + default: + break; + } } } } diff --git a/tools/decode-status.py b/tools/decode-status.py index 26f7fe900..cd32a5402 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -227,7 +227,7 @@ a_features = [[ "USE_VEML7700","USE_MCP9808","USE_BL0940","USE_TELEGRAM", "USE_HP303B","USE_TCP_BRIDGE","USE_TELEINFO","USE_LMT01", "USE_PROMETHEUS","USE_IEM3000","USE_DYP","USE_I2S_AUDIO", - "","","","", + "USE_MLX90640","","","", "","USE_TTGO_WATCH","USE_ETHERNET","USE_WEBCAM" ],[ "","","","",