diff --git a/tasmota/xdrv_98_product_test.ino b/tasmota/xdrv_98_product_test.ino
deleted file mode 100644
index 39bdec35e..000000000
--- a/tasmota/xdrv_98_product_test.ino
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- xdrv_98_product_test.ino - Product test for Sonoff-Tasmota
-
- Copyright (C) 2021 Theo Arends and Adrian Scillato
-
- 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 .
-*/
-
-//#define PRODUCT_TEST // Enable this to include Tuya product test protocol
-#define PRODUCT_TEST_DEBUG // Enable to compile status messages as shown below
-
-#define PRODUCT_TEST_SSID "FACILITY_SSID" // <-- CHANGE THIS TO YOURS
-
-#define PRODUCT_VOLTAGE "220.0" // Volt
-#define PRODUCT_CURRENT "392.0" // milliAmpere
-#define PRODUCT_POWER "87.0" // Watt
-#define PRODUCT_CALIBRATE_CYCLE 20 // Seconds - Need at least 8 seconds
-
-#define PRODUCT_SCAN_INTERVAL 8 // Seconds
-#define PRODUCT_SCAN_RETRY 4 // Scan retry count
-
-#define PRODUCT_TEST_VERSION "3.2"
-
-/*********************************************************************************************\
-This code is supported starting with Tasmota version 9.2.0.
-The product test will run at power on when both SSids are empty.
-The test can be restarted by power cycling off then on.
-
-*** Flash firmware
-Write binary firmware.bin
- esptool.py --port COM4 write_flash -fs 1MB -fm dout 0x0 firmware.bin
-
-*** Typical succesful product test with succesful wifi scan
-Initial Power ON
- 00:00:00 CFG: Use defaults
- 00:00:00 TST: Product test v3.0
- 00:00:00 TST: 1/6 Product test started using ssid tuya_mdev_test1
- 00:00:00 SRC: Restart
- 00:00:00 Project sonoff Sonoff Version 6.4.1.19(basic)-2_4_2
- 00:00:00 CFG: Saved to flash at FA, Count 2, Bytes 3584
- 00:00:00 WIF: WifiManager active for 3 minutes
- 00:00:00 WIF: Wifimanager set AccessPoint
- 00:00:00 HTP: Web server active on sonoff-2927 with IP address 192.168.4.1
- 00:00:01 CFG: Saved to flash at F9, Count 3, Bytes 3584
- 00:00:04 TST: Scanned SSId1 indebuurt1
- 00:00:04 TST: Scanned SSId2 indebuurt2
- 00:00:04 TST: Scanned SSId3 indebuurt3
- 00:00:04 TST: Scanned SSId4 tuya_mdev_test1
- 00:00:04 TST: 2/6 Wifi found
- 00:00:13 APP: Boot Count 1
-Button pressed
- 00:00:15 TST: 3/6 Button pressed first time - Toggle relay and led once
- 00:00:15 APP: Button1 immediate
- 00:00:15 SRC: Button
- 00:00:15 RSL: stat/sonoff/RESULT = {"POWER":"ON"}
- 00:00:15 RSL: stat/sonoff/POWER = ON
-Button pressed again
- 00:00:20 TST: 4/6 Button pressed second time - Toggle relay and led three times
- 00:00:21 RSL: stat/sonoff/RESULT = {"POWER":"OFF"}
- 00:00:21 RSL: stat/sonoff/POWER = OFF
- 00:00:22 RSL: stat/sonoff/RESULT = {"POWER":"ON"}
- 00:00:22 RSL: stat/sonoff/POWER = ON
- 00:00:23 RSL: stat/sonoff/RESULT = {"POWER":"OFF"}
- 00:00:23 RSL: stat/sonoff/POWER = OFF
- 00:00:24 TST: 5/6 Button test finished - Start calibration
- 00:00:27 CFG: Saved to flash at FB, Count 4, Bytes 3584
- 00:00:27 TST: 6/6 Product test finished - Save to power off
-Device can and should be powered off now as it is in an unknown state
-
-*** Restore Product test prerequisite
- Power off device
-\*********************************************************************************************/
-
-#ifdef PRODUCT_TEST
-/*********************************************************************************************\
- * Product test procedure support
- *
- * - Initiate test if power on and no user SSIDs configured
- * - Init test environment (Led OFF, flash save off)
- * - Wait for wifi scan to find PRODUCT_TEST_SSID then start flashing led every 250 mSec
- * - Wait for user press button then turn relay and led ON
- * - Wait for user press button again then toggle relay and led 3 times and increment bootcount
- * - If energy monitoring is detected calibrate Voltage, Current and Power
- * - Wait for power down
-\*********************************************************************************************/
-
-/*********************************************************************************************\
- * Examples to test a particular device:
- *
- * Set in user_config_override.h the following:
- *
- * #undef MODULE
- * #define MODULE SONOFF_BASIC // [Module] Select default model (the list is kModuleNiceList() in file tasmota_template.h)
- * #undef FALLBACK_MODULE
- * #define FALLBACK_MODULE SONOFF_BASIC // to Select the default model as FALLBACK when the user does a RESET 1
- *
- * or
- *
- * #define USER_TEMPLATE "{\"NAME\":\"Shelly 2.5\",\"GPIO\":[320,0,32,0,224,193,0,0,640,192,608,225,3456,4736],\"FLAG\":0,\"BASE\":18}" // [Template] Set JSON template
- *
- * For ESP32 examples check user_config.h
- *
-\*********************************************************************************************/
-
-
-#define XDRV_98 98
-
-enum ProductTestStates { PROD_TEST_IDLE, PROD_TEST_START, PROD_TEST_WIFI, PROD_TEST_BUTTON, PROD_TEST_CALIBRATE, PROD_TEST_DONE };
-
-struct PRODUCTTEST {
- uint8_t state = PROD_TEST_IDLE; // No product test
- uint8_t blink = 3; // Toggle relay three times
- uint8_t button_step = 0; // Either initial power toggle or end of test
- uint8_t last_button = 0; // Store initial power toggle last button state
- uint8_t scan_interval = 2; // Seconds after power on
- uint8_t scan_retry = PRODUCT_SCAN_RETRY +1;
- uint8_t calibrate_state = PRODUCT_CALIBRATE_CYCLE; // Calibrate cycle max seconds
- uint8_t calibrate_timer = 0; // 100mS timer
-
- uint16_t save_data_counter;
- uint8_t ledstate;
- uint8_t button_single;
- uint8_t global_state;
-} prodtest;
-
-bool ProductTestTrigger(void)
-{
-// AddLog(LOG_LEVEL_INFO, PSTR("TST: resetInfo %d, sta_ssid1 (%s), sta_ssid2 (%s), save_flag %d"), resetInfo.reason, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), Settings.save_flag);
-
- if (((resetInfo.reason == REASON_DEFAULT_RST) || (resetInfo.reason == REASON_EXT_SYS_RST)) && // Power on
- !strlen(SettingsText(SET_STASSID1)) && // No configured SSID1
- !strlen(SettingsText(SET_STASSID2)) // No configured SSID2
- ) {
- return true;
- }
-
- return false;
-}
-
-bool ProductTestSsidFound(void)
-{
- bool result = false;
-
- if (prodtest.scan_interval) {
- prodtest.scan_interval--;
- if (!prodtest.scan_interval) {
- prodtest.scan_retry--;
- if (prodtest.scan_retry) {
- prodtest.scan_interval = PRODUCT_SCAN_INTERVAL;
- int n = WiFi.scanNetworks();
- if (n > 0) {
- for (int i = 0; i < n; i++) {
-#ifdef PRODUCT_TEST_DEBUG
- AddLog(LOG_LEVEL_DEBUG, PSTR("TST: Scanned SSId%d %s"), i +1, WiFi.SSID(i).c_str());
-#endif
- if (!strcasecmp_P(WiFi.SSID(i).c_str(), PSTR(PRODUCT_TEST_SSID))) { result = true; }
- }
- }
- } else {
- if (Wifi.config_type) {
- TasmotaGlobal.blinks = 255; // Re-enable wifi config blinks
- }
- Settings.ledstate = prodtest.ledstate;
- Settings.flag.global_state = prodtest.global_state;
- TasmotaGlobal.save_data_counter = prodtest.save_data_counter;
-#ifdef PRODUCT_TEST_DEBUG
- AddLog(LOG_LEVEL_INFO, PSTR("TST: 6/6 Product test failed"));
-#endif
- prodtest.state = PROD_TEST_IDLE;
- }
- }
- }
- return result;
-}
-
-void ProductTestLedOff(void)
-{
- TasmotaGlobal.blinks = 0; // No blinks
- SetLedLink(0);
- SetLedPower(0);
-}
-
-void ProductTestInit(void)
-{
- if (ProductTestTrigger()) {
-#ifdef PRODUCT_TEST_DEBUG
- TasmotaGlobal.seriallog_level = 3; // Enable more serial logging
- AddLog(LOG_LEVEL_INFO, PSTR("TST: Product test v" PRODUCT_TEST_VERSION));
-#endif
- // Prepare for product test procedure
- prodtest.save_data_counter = TasmotaGlobal.save_data_counter;
- TasmotaGlobal.save_data_counter = 32000; // Stop auto saving data - Updating Settings
- prodtest.global_state = Settings.flag.global_state;
- Settings.flag.global_state = 1; // Disable global state (wifi and mqtt) led blinks as it interferes with the test protocol
- prodtest.ledstate = Settings.ledstate;
- Settings.ledstate = 0; // Disable led power state as it interferes with the test protocol
-
- ProductTestLedOff(); // Signal start of test
-#ifdef PRODUCT_TEST_DEBUG
- AddLog(LOG_LEVEL_INFO, PSTR("TST: 1/6 Product test started using ssid " PRODUCT_TEST_SSID));
-#endif // PRODUCT_TEST_DEBUG
- prodtest.state = PROD_TEST_START;
- } else {
- prodtest.state = PROD_TEST_IDLE;
- }
-}
-
-bool ProductTestButton(void)
-{
- bool result = false; // Ignore
-
- if (prodtest.state > PROD_TEST_IDLE) {
- result = true; // Disable button processing
-
- if (PROD_TEST_WIFI == prodtest.state) {
- if ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == prodtest.last_button)) { // Button pressed
- if (0 == prodtest.button_step) {
-#ifdef PRODUCT_TEST_DEBUG
- AddLog(LOG_LEVEL_INFO, PSTR("TST: 3/6 Button pressed first time - Toggle relay and led once"));
-#endif
- ProductTestLedOff(); // Signal button pressed and activate relay
- Settings.ledstate = 1; // Enable led power state
- prodtest.button_step++;
- result = false; // Process normal button press which will turn relay and led on
- } else {
-#ifdef PRODUCT_TEST_DEBUG
- AddLog(LOG_LEVEL_INFO, PSTR("TST: 4/6 Button pressed second time - Toggle relay and led three times"));
-#endif
- prodtest.state = PROD_TEST_BUTTON;
- result = true; // Disable further button processing
- }
- }
- prodtest.last_button = XdrvMailbox.payload;
- }
- }
-
- return result;
-}
-
-void ProductTestEverySecond(void)
-{
- if (PROD_TEST_IDLE == prodtest.state) {
- return;
- }
- else if (PROD_TEST_START == prodtest.state) {
- TasmotaGlobal.blinks = 0; // Disable blinks initiated by WifiManager
- if (ProductTestSsidFound()) {
-#ifdef PRODUCT_TEST_DEBUG
- AddLog(LOG_LEVEL_INFO, PSTR("TST: 2/6 Wifi found"));
-#endif
- TasmotaGlobal.sleep = 0; // Disable sleep
- TasmotaGlobal.restart_flag = 0; // No restart and enable blinks
- TasmotaGlobal.ota_state_flag = 0; // No OTA and enable blinks
-
- prodtest.button_single = Settings.flag.button_single;
- Settings.flag.button_single = 1; // Allow only single press
-
- TasmotaGlobal.blinks = 255; // Signal wifi connection with blinks
- prodtest.state = PROD_TEST_WIFI;
- }
- }
- else if (PROD_TEST_BUTTON == prodtest.state) {
- if (prodtest.blink) {
- prodtest.blink--;
- ExecuteCommandPower(1, POWER_TOGGLE, SRC_IGNORE); // Toggle relay and led
- } else {
- if (TasmotaGlobal.energy_driver != ENERGY_NONE) {
- prodtest.state = PROD_TEST_CALIBRATE;
- } else {
-#ifdef PRODUCT_TEST_DEBUG
- AddLog(LOG_LEVEL_INFO, PSTR("TST: 5/6 Button test finished"));
-#endif
- prodtest.state = PROD_TEST_DONE;
- }
- }
- }
- else if (PROD_TEST_CALIBRATE == prodtest.state) {
- if (prodtest.calibrate_state) {
- prodtest.calibrate_state--;
- if (PRODUCT_CALIBRATE_CYCLE -1 == prodtest.calibrate_state) {
-#ifdef PRODUCT_TEST_DEBUG
- AddLog(LOG_LEVEL_INFO, PSTR("TST: 5/6 Start calibration"));
-#endif
- ExecuteCommandPower(1, POWER_ON, SRC_IGNORE); // On relay and led - start energy measurment
- }
- else if ((prodtest.calibrate_state < PRODUCT_CALIBRATE_CYCLE -4) && (prodtest.calibrate_state > 1)) {
- // Allow a few seconds before starting calibration
- uint8_t all_done = 0;
- if (HLW_PREF_PULSE == Settings.energy_power_calibration) {
- char set_value[] = PRODUCT_POWER;
- XdrvMailbox.data = set_value;
- XdrvMailbox.data_len = sizeof(set_value);
- Energy.command_code = CMND_POWERSET;
- HlwCommand(); // Get calibrated setting
- } else {
- all_done++;
- }
- if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) {
- char set_value[] = PRODUCT_VOLTAGE;
- XdrvMailbox.data = set_value;
- XdrvMailbox.data_len = sizeof(set_value);
- Energy.command_code = CMND_VOLTAGESET;
- HlwCommand(); // Get calibrated setting
- } else {
- all_done++;
- }
- if (HLW_IREF_PULSE == Settings.energy_current_calibration) {
- char set_value[] = PRODUCT_CURRENT;
- XdrvMailbox.data = set_value;
- XdrvMailbox.data_len = sizeof(set_value);
- Energy.command_code = CMND_CURRENTSET;
- HlwCommand(); // Get calibrated setting
- } else {
- all_done++;
- }
- if (3 == all_done) {
- prodtest.calibrate_state = 2;
- }
- }
- else if (1 == prodtest.calibrate_state) {
- ExecuteCommandPower(1, POWER_OFF, SRC_IGNORE); // Off relay and led - stop energy measurment
- }
- else if (0 == prodtest.calibrate_state) {
- // Save calibration data
- uint32_t power_calibration = Settings.energy_power_calibration;
- uint32_t voltage_calibration = Settings.energy_voltage_calibration;
- uint32_t current_calibration = Settings.energy_current_calibration;
- SettingsDefaultSet1(); // Reset any Settings change
- SettingsDefaultSet2(); // Init default settings
- // Store calibration data
- Settings.energy_power_calibration = power_calibration;
- Settings.energy_voltage_calibration = voltage_calibration;
- Settings.energy_current_calibration = current_calibration;
- SettingsSave(2);
- TasmotaGlobal.save_data_counter = 32000; // Stop auto saving data - Updating Settings
- }
- } else {
- prodtest.state = PROD_TEST_DONE;
- SetLedLink(1); // Wifi led on - Succesful calibration
- }
- }
- else if (PROD_TEST_DONE == prodtest.state) {
-#ifdef PRODUCT_TEST_DEBUG
- AddLog(LOG_LEVEL_INFO, PSTR("TST: 6/6 Product test finished - Save to power off"));
-#endif
-
- while (1) {
- OsWatchLoop(); // Feed OsWatch timer to prevent restart
- delay(50); // Satisfy SDK
- }
- }
-}
-
-void ProductTestEvery100mSecond(void)
-{
- if (PROD_TEST_CALIBRATE == prodtest.state) {
- // Blink wifi led 2 flashes every 3 seconds - Calibrating
- prodtest.calibrate_timer++;
- if (1 == prodtest.calibrate_timer) {
- SetLedLink(0); // Wifi led off
- }
- else if (12 == prodtest.calibrate_timer) {
- SetLedLink(1); // Wifi led on
- }
- else if (16 == prodtest.calibrate_timer) {
- prodtest.calibrate_timer = 0;
- }
- }
-}
-
-/*********************************************************************************************\
- * Interface
-\*********************************************************************************************/
-
-bool Xdrv98(uint8_t function)
-{
- bool result = false;
-
- switch (function) {
- case FUNC_EVERY_100_MSECOND:
- ProductTestEvery100mSecond();
- break;
- case FUNC_EVERY_SECOND:
- ProductTestEverySecond();
- break;
- case FUNC_BUTTON_PRESSED:
- result = ProductTestButton();
- break;
- case FUNC_PRE_INIT:
- ProductTestInit();
- break;
- }
- return result;
-}
-
-#endif // PRODUCT_TEST
diff --git a/tasmota/xsns_31_ccs811_v2_test.ino b/tasmota/xsns_31_ccs811_v2_test.ino
deleted file mode 100644
index 8fec2aaba..000000000
--- a/tasmota/xsns_31_ccs811_v2_test.ino
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- xsns_31_ccs811_v2.ino - CCS811 gas and air quality sensor support for Tasmota
-
- Copyright (C) 2021 Gerhard Mutz 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 .
-*/
-
-#ifdef USE_I2C
-#ifdef USE_CCS811_V2_TEST
-/*********************************************************************************************\
- * CCS811 - Gas (TVOC - Total Volatile Organic Compounds) and Air Quality (CO2)
- *
- * Source: Adafruit
- *
- * This driver supports one to two devices at a time at
- * addressses 0x5A or/and 0x5B
- * - for I2C address 0x5A, connect ADDR to GND
- * - for I2C address 0x5B, connect ADDR to VCC
- * NOTE:
- * - Wake must be connected to GND (no sleep mode supported!)
- * - depending on the breakout bouard, SDA & SCL may require
- * pull-ups to VCC, e.g. 4k7R
- *
-\*********************************************************************************************/
-
-#define XSNS_31 31
-#define XI2C_24 24 // See I2CDEVICES.md
-
-#define EVERYNSECONDS 5
-#define RESETCOUNT 6
-
-#include "Adafruit_CCS811.h"
-
-uint8_t CCS811_addresses[] = { CCS811_ADDRESS, (CCS811_ADDRESS + 1) };
-#define MAXDEVICECOUNT (sizeof( CCS811_addresses) / sizeof(uint8_t))
-
-typedef struct {
- uint8_t address;
- uint8_t device_found;
- uint8_t device_index;
- uint8_t device_ready;
- Adafruit_CCS811 ccsinstance;
- uint16_t eCO2;
- uint16_t TVOC;
- uint8_t refresh_count;
- uint8_t reset_count;
-} CCS811DATA;
-
-uint8_t CCS811_devices_found = 0;
-CCS811DATA ccsd[ MAXDEVICECOUNT];
-CCS811DATA * pccsd;
-uint32_t i;
-
-
-#define D_CMND_CCS811 "CCS811"
-
-const char S_JSON_CCS811_COMMAND_XVALUE[] PROGMEM = "{\"" D_CMND_CCS811 "%s\":0x%02x}";
-const char S_JSON_CCS811_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_CCS811 "%s\":%u}";
-const char S_JSON_CCS811_COMMAND_HWVERSION[] PROGMEM = "{\"" D_CMND_CCS811 "%s\":\"%x\"}";
-const char S_JSON_CCS811_COMMAND_FWAPPVERSION[] PROGMEM = "{\"" D_CMND_CCS811 "%s\":\"%x.%x.%x\"}";
-
-const char S_JSON_CCS811_COMMAND[] PROGMEM = "{\"" D_CMND_CCS811 "%s\"}";
-const char kCCS811_Commands[] PROGMEM = "HW|FWApp|Baseline";
-
-enum CCS811_Commands { // commands useable in console or rules
- CMND_CCS811_HW,
- CMND_CCS811_FWAPP,
- CMND_CCS811_BASELINE
-};
-
-/********************************************************************************************/
-
-void CCS811Detect(void)
-{
- if (!CCS811_devices_found) {
- memset( ccsd, 0, sizeof( ccsd));
- }
- int active_index = 1;
- for (i = 0, pccsd = ccsd; i < MAXDEVICECOUNT; i++, pccsd++) {
- pccsd->address = CCS811_addresses[ i];
- if (I2cActive( pccsd->address)) { continue; }
- if (!pccsd->ccsinstance.begin(pccsd->address)) {
- pccsd->device_found = 1;
- CCS811_devices_found += 1;
- I2cSetActiveFound( pccsd->address, "CCS811");
- pccsd->device_index = active_index;
- active_index++;
- }
- }
-}
-
-void CCS811Update(void) // Perform every n second
-{
- for (i = 0, pccsd = ccsd; i < MAXDEVICECOUNT; i++, pccsd++) {
-
- if (!pccsd->device_found)
- continue;
-
- pccsd->refresh_count++;
- if (pccsd->refresh_count >= EVERYNSECONDS) {
- pccsd->refresh_count = 0;
- pccsd->device_ready = 0;
- if (pccsd->ccsinstance.available()) {
- if (!pccsd->ccsinstance.readData()){
- pccsd->TVOC = pccsd->ccsinstance.getTVOC();
- pccsd->eCO2 = pccsd->ccsinstance.geteCO2();
- pccsd->device_ready = 1;
- if ((TasmotaGlobal.global_update) &&
- (TasmotaGlobal.humidity > 0) &&
- (!isnan(TasmotaGlobal.temperature_celsius))) {
- pccsd->ccsinstance.setEnvironmentalData((uint8_t)TasmotaGlobal.humidity,
- TasmotaGlobal.temperature_celsius);
- }
- pccsd->reset_count = 0;
- }
- } else {
- // failed, count up
- pccsd->reset_count++;
- if (pccsd->reset_count > RESETCOUNT) {
- // after 30 seconds, restart
- pccsd->ccsinstance.begin( pccsd->address);
- pccsd->reset_count = 0;
- }
- }
- }
- }
-}
-
-
-// no methods available in Adafruit library to read version data or
-// read/set the baseline value, so we need to emulate the private methods
-
-void CCS811ReadMailboxValue( uint8_t address, uint8_t mailbox, byte * pbuf, uint8_t buflen)
-{
- Wire.beginTransmission(address);
- Wire.write(mailbox);
- Wire.endTransmission();
- Wire.requestFrom(address, buflen);
- for (uint8_t i = 0; i < buflen; i++) {
- *(pbuf + i) = Wire.read();
-#ifdef CCS811_DEBUG
- AddLog(LOG_LEVEL_DEBUG, PSTR( D_LOG_DEBUG D_CMND_CCS811 " reading byte %u: 0%02x / %u"), i, *(pbuf + i), *(pbuf + i));
-#endif
- }
-}
-
-void CCS811WriteMailboxValue(uint8_t address, uint8_t mailbox, byte * pbuf, uint8_t buflen)
-{
-#ifdef CCS811_DEBUG
- for (uint8_t i = 0; i < buflen; i++) {
- AddLog(LOG_LEVEL_DEBUG, PSTR( D_LOG_DEBUG D_CMND_CCS811 " writing byte %u: 0%02x / %u"), i, *(pbuf + i), *(pbuf + i));
- }
-#endif
- Wire.beginTransmission(address);
- Wire.write((uint8_t)mailbox);
- Wire.write(pbuf, buflen);
- Wire.endTransmission();
-}
-
-/*********************************************************************************************\
- * Command Sensor31
-\*********************************************************************************************/
-
-bool CCS811CommandSensor()
-{
-
- char command[CMDSZ];
- bool serviced = true;
- uint8_t prefix_len = strlen(D_CMND_CCS811);
-
- if ((!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_CCS811), prefix_len)) &&
- (XdrvMailbox.index <= CCS811_devices_found)) { // check prefix and device index
-
- int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + prefix_len, kCCS811_Commands);
-
- // select device data matching the index
- CCS811DATA * pccsd_command;
- for (i = 0, pccsd = ccsd; i < MAXDEVICECOUNT; i++, pccsd++) {
- if (pccsd->device_index == XdrvMailbox.index) {
- pccsd_command = pccsd;
-#ifdef CCS811_DEBUG
- AddLog(LOG_LEVEL_DEBUG, PSTR( D_LOG_DEBUG D_CMND_CCS811 " I2C Address: 0%02x"), pccsd_command->address);
-#endif
- break;
- }
- }
- if (!pccsd_command) {
- return false;
- }
-
- switch (command_code) {
-
- case CMND_CCS811_HW:
- {
- byte CCS811_hw_version;
- CCS811ReadMailboxValue( pccsd_command->address,
- CCS811_HW_VERSION,
- &CCS811_hw_version,
- sizeof(CCS811_hw_version));
- Response_P(S_JSON_CCS811_COMMAND_HWVERSION, command, CCS811_hw_version);
- }
- break;
-
- case CMND_CCS811_FWAPP:
- {
- byte CCS811_fw_app_version[2];
- CCS811ReadMailboxValue( pccsd_command->address,
- CCS811_FW_APP_VERSION,
- CCS811_fw_app_version,
- (sizeof(CCS811_fw_app_version) / sizeof(byte)));
- Response_P(S_JSON_CCS811_COMMAND_FWAPPVERSION,
- command,
- (CCS811_fw_app_version[0] >> 4), // major
- (CCS811_fw_app_version[0] & 0xF), // minor
- CCS811_fw_app_version[1]); // build
- }
- break;
-
- case CMND_CCS811_BASELINE:
- {
- byte CCS811_baseline[2];
- if (XdrvMailbox.data_len > 0) {
- CCS811_baseline[0] = (XdrvMailbox.payload & 0xFF00) >> 8;
- CCS811_baseline[1] = XdrvMailbox.payload & 0xFF;
- CCS811WriteMailboxValue( pccsd_command->address,
- CCS811_BASELINE,
- CCS811_baseline,
- (sizeof(CCS811_baseline) / sizeof(byte)));
- } else {
- CCS811ReadMailboxValue( pccsd_command->address,
- CCS811_BASELINE,
- CCS811_baseline,
- (sizeof(CCS811_baseline) / sizeof(byte)));
- }
- Response_P(S_JSON_CCS811_COMMAND_NVALUE,
- command,
- ((CCS811_baseline[0] << 8) + CCS811_baseline[1]));
- }
- break;
-
- default:
- // else for Unknown command
- serviced = false;
- break;
- }
- }
-
- return serviced;
-}
-
-
-const char HTTP_SNS_CCS811[] PROGMEM =
- "{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" // {s} =
, {m} = | , {e} = |
- "{s}%s " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}";
-
-const char * devicenamelist[] PROGMEM = { "CCS811", "CCS811_1", "CCS811_2" };
-
-void CCS811Show(bool json)
-{
- uint8_t ready_count = 0;
- for (i = 0, pccsd = ccsd; i < MAXDEVICECOUNT; i++, pccsd++) {
- if ((pccsd->device_found) && (pccsd->device_ready)) {
- ready_count += 1;
- }
- }
- if (!ready_count) {
- return;
- }
-
- // in upcoming loops use either one device name
- // with no index or or two names with index
- const char ** pdevicename;
- const char ** pdevicename_first = devicenamelist;
- if (ready_count > 1) {
- pdevicename_first++;
- }
-
- if (json) {
- for (i = 0, pccsd = ccsd, pdevicename = pdevicename_first; i < MAXDEVICECOUNT; i++, pccsd++) {
- if (pccsd->device_ready) {
- ResponseAppend_P( PSTR(",\"%s\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"),
- *pdevicename,
- pccsd->eCO2,
- pccsd->TVOC);
- pdevicename++;
- }
- }
-#ifdef USE_DOMOTICZ
- if (0 == TasmotaGlobal.tele_period) {
- if (pccsd->device_ready) {
- pccsd = ccsd;
- DomoticzSensor(DZ_AIRQUALITY, pccsd->eCO2);
- }
- }
-#endif // USE_DOMOTICZ
-#ifdef USE_WEBSERVER
- } else {
- for (i = 0, pccsd = ccsd, pdevicename = pdevicename_first; i < MAXDEVICECOUNT; i++, pccsd++) {
- if (pccsd->device_ready) {
- WSContentSend_PD( HTTP_SNS_CCS811,
- *pdevicename, pccsd->eCO2,
- *pdevicename, pccsd->TVOC);
- pdevicename++;
- }
- }
-#endif
- }
-}
-
-/*********************************************************************************************\
- * Interface
-\*********************************************************************************************/
-
-bool Xsns31(uint8_t function)
-{
- if (!I2cEnabled(XI2C_24)) { return false; }
-
- bool result = false;
-
- if (FUNC_INIT == function) {
- CCS811Detect();
- }
- else if (CCS811_devices_found) {
- switch (function) {
- case FUNC_EVERY_SECOND:
- CCS811Update();
- break;
- case FUNC_COMMAND:
- result = CCS811CommandSensor();
- break;
- case FUNC_JSON_APPEND:
- CCS811Show(1);
- break;
-#ifdef USE_WEBSERVER
- case FUNC_WEB_SENSOR:
- CCS811Show(0);
- break;
-#endif // USE_WEBSERVER
- }
- }
- return result;
-}
-
-#endif // USE_CCS811_V2
-#endif // USE_I2C
\ No newline at end of file