diff --git a/sonoff/i18n.h b/sonoff/i18n.h
index b1bec3289..2347cba22 100644
--- a/sonoff/i18n.h
+++ b/sonoff/i18n.h
@@ -548,7 +548,7 @@ const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m}
const char HTTP_SNS_ANALOG[] PROGMEM = "%s{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} =
, {m} = | , {e} = |
const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = | , {e} = |
-#if defined(USE_MHZ19) || defined(USE_SENSEAIR)
+#if defined(USE_MHZ19) || defined(USE_SENSEAIR) || defined(USE_AZ7798)
const char HTTP_SNS_CO2[] PROGMEM = "%s{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = | , {e} = |
#endif // USE_WEBSERVER
diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h
index 6a2265f1a..222c62b58 100644
--- a/sonoff/language/bg-BG.h
+++ b/sonoff/language/bg-BG.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF датчик"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h
index 461de3a4d..45f55af6a 100644
--- a/sonoff/language/cs-CZ.h
+++ b/sonoff/language/cs-CZ.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h
index 293de0830..23d8de9ed 100644
--- a/sonoff/language/de-DE.h
+++ b/sonoff/language/de-DE.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h
index 2148baf42..a8b48ed35 100644
--- a/sonoff/language/el-GR.h
+++ b/sonoff/language/el-GR.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h
index 70825c5e3..2ea9c249a 100644
--- a/sonoff/language/en-GB.h
+++ b/sonoff/language/en-GB.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h
index 011c7a248..435f230ad 100644
--- a/sonoff/language/es-AR.h
+++ b/sonoff/language/es-AR.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h
index 642b4686d..0638b408a 100644
--- a/sonoff/language/fr-FR.h
+++ b/sonoff/language/fr-FR.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h
index 7dc8585db..cd1b0e92e 100644
--- a/sonoff/language/he-HE.h
+++ b/sonoff/language/he-HE.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h
index 707bb24ec..244d55776 100644
--- a/sonoff/language/hu-HU.h
+++ b/sonoff/language/hu-HU.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h
index d2e277a8c..a6d0d693c 100644
--- a/sonoff/language/it-IT.h
+++ b/sonoff/language/it-IT.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h
index 3383228ed..b3bf10989 100644
--- a/sonoff/language/nl-NL.h
+++ b/sonoff/language/nl-NL.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h
index 0019c8d53..d80826751 100644
--- a/sonoff/language/pl-PL.h
+++ b/sonoff/language/pl-PL.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h
index e8e536606..7add978f0 100644
--- a/sonoff/language/pt-BR.h
+++ b/sonoff/language/pt-BR.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h
index 58a39fff0..9869762b8 100644
--- a/sonoff/language/pt-PT.h
+++ b/sonoff/language/pt-PT.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h
index 85813373a..d0a3f6933 100644
--- a/sonoff/language/ru-RU.h
+++ b/sonoff/language/ru-RU.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "А"
diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h
index a01fa1b3e..f46372426 100644
--- a/sonoff/language/sk-SK.h
+++ b/sonoff/language/sk-SK.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Senzor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h
index 4ae68e78c..f36162a4b 100644
--- a/sonoff/language/sv-SE.h
+++ b/sonoff/language/sv-SE.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h
index 43acbaa77..06d82b9cb 100755
--- a/sonoff/language/tr-TR.h
+++ b/sonoff/language/tr-TR.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h
index a924a6cf4..509c90753 100644
--- a/sonoff/language/uk-UK.h
+++ b/sonoff/language/uk-UK.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "А"
diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h
index dfd5662e0..05bedca81 100644
--- a/sonoff/language/zh-CN.h
+++ b/sonoff/language/zh-CN.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "安"
diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h
index abc3df93d..2780181aa 100644
--- a/sonoff/language/zh-TW.h
+++ b/sonoff/language/zh-TW.h
@@ -538,6 +538,8 @@
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
+#define D_SENSOR_AZ_RX "AZ Rx"
+#define D_SENSOR_AZ_TX "AZ Tx"
// Units
#define D_UNIT_AMPERE "安"
diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h
index cbc7a7790..aa92cba85 100644
--- a/sonoff/my_user_config.h
+++ b/sonoff/my_user_config.h
@@ -367,6 +367,7 @@
#define TUYA_DIMMER_ID 0 // Default dimmer Id
#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code)
#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer
+//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code)
// Power monitoring sensors -----------------------
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)
diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h
index f8798e454..8eddeea5b 100644
--- a/sonoff/sonoff_post.h
+++ b/sonoff/sonoff_post.h
@@ -135,6 +135,7 @@ void KNX_CB_Action(message_t const &msg, void *arg);
#define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
// #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code)
#define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code)
+//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger
#endif // USE_SENSORS
/*********************************************************************************************\
@@ -193,6 +194,7 @@ void KNX_CB_Action(message_t const &msg, void *arg);
#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
#undef DEBUG_THEO // Disable debug code
#undef USE_DEBUG_DRIVER // Disable debug code
+#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
#endif // USE_CLASSIC
/*********************************************************************************************\
@@ -313,6 +315,7 @@ void KNX_CB_Action(message_t const &msg, void *arg);
#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
#undef DEBUG_THEO // Disable debug code
#undef USE_DEBUG_DRIVER // Disable debug code
+#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
#endif // USE_BASIC
/*********************************************************************************************\
@@ -375,6 +378,7 @@ void KNX_CB_Action(message_t const &msg, void *arg);
#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
#undef DEBUG_THEO // Disable debug code
#undef USE_DEBUG_DRIVER // Disable debug code
+#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
#endif // BE_MINIMAL
/*********************************************************************************************\
diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h
index 91eec21c7..48af9cf4b 100644
--- a/sonoff/sonoff_template.h
+++ b/sonoff/sonoff_template.h
@@ -141,6 +141,8 @@ enum UserSelectablePins {
GPIO_SSPI_CS, // Software SPI Chip Select
GPIO_SSPI_DC, // Software SPI Data or Command
GPIO_RF_SENSOR, // Rf receiver with sensor decoding
+ GPIO_AZ_TXD, // AZ-Instrument 7798 Serial interface
+ GPIO_AZ_RXD, // AZ-Instrument 7798 Serial interface
GPIO_SENSOR_END };
// Programmer selectable GPIO functionality offset by user selectable GPIOs
@@ -201,7 +203,8 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|"
D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET "|"
D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC "|"
- D_SENSOR_RF_SENSOR;
+ D_SENSOR_RF_SENSOR "|"
+ D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX;
/********************************************************************************************/
@@ -454,6 +457,10 @@ const uint8_t kGpioNiceList[] PROGMEM = {
GPIO_MGC3130_XFER,
GPIO_MGC3130_RESET
#endif
+#ifdef USE_AZ7798
+ GPIO_AZ_TXD, // AZ-Instrument 7798 CO2 datalogger Serial interface
+ GPIO_AZ_RXD // AZ-Instrument 7798 CO2 datalogger Serial interface
+#endif
};
const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino
index 652116b2f..75ddaf327 100644
--- a/sonoff/support_features.ino
+++ b/sonoff/support_features.ino
@@ -370,7 +370,9 @@ void GetFeatures(void)
#ifdef USE_ALECTO_V2
feature_sns2 |= 0x00020000;
#endif
-// feature_sns2 |= 0x00040000;
+#ifdef USE_AZ7798
+ feature_sns2 |= 0x00040000;
+#endif
// feature_sns2 |= 0x00080000;
// feature_sns2 |= 0x00100000;
// feature_sns2 |= 0x00200000;
diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino
new file mode 100644
index 000000000..6491be885
--- /dev/null
+++ b/sonoff/xsns_38_az7798.ino
@@ -0,0 +1,304 @@
+/*
+ xsns_38_az7798.ino - AZ_Instrument 7798 CO2/temperature/humidity meter support for Sonoff-Tasmota
+
+ Copyright (C) 2018 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_AZ7798
+
+#define XSNS_38 38
+
+/*********************************************************************************************\
+ * CO2, temperature and humidity meter and data logger
+ * Known by different names (brief survey 2018-12-16):
+ * - AZ-Instrument 7798 (http://www.az-instrument.com.tw)
+ * - co2meter.com AZ-0004
+ * - Extech CO200
+ * - BES CO7788 (https://www.aliexpress.com)
+ * - AZ CO87 (https://www.aliexpress.com)
+ * - no doubt there are more ...
+ *
+ * Hardware Serial will be selected if GPIO1 = [AZ Tx] and GPIO3 = [AZ Rx]
+ *
+ * Inside the meter, the serial comms wire with the red stripe goes to GPIO1.
+ * The other one therefore to GPIO3.
+ * WeMos D1 Mini is powered from the incoming 5V.
+ *
+ * This implementation was derived from xsns_15_mhz19.ino from
+ * Sonoff-Tasmota-6.3.0 by Arthur de Beun.
+ *
+ * The serial comms protocol is not publicly documented, that I could find.
+ * The info below was obtained by reverse-engineering.
+ * Port settings: 9600 8N1
+ * The suppied USB interface has a CP20x USB-serial bridge.
+ * The 3-way, 2.5mm jack has tip=RxD, middle=TxD and base=0V
+ * The TxD output swing is 3V3.
+ *
+ * There is never a space before the 0x0d, but the other spaces are there.
+ *
+ * serial number / ID
+ * request: I 0x0d
+ * response: i 12345678 7798V3.4 0x0d
+ *
+ * log info
+ * request: M 0x0d
+ * response: m 45 1 C 1af4 0cf4 0x0d
+ *
+ * 45 = number of records, but there are only 15 lines of 3 values each)
+ * 1 = sample rate in seconds
+ * C = celcius, F
+ * 1af4 0cf4 = seconds since 2000-01-01 00:00:00
+ *
+ * start time 2014-04-30 19:35:16
+ * end time 2014-04-30 19:35:30
+ *
+ * download log data
+ * request: D 0x0d
+ * response: m 45 1 C 1af4 0cf4 0x0d
+ * d 174 955 698 0x0d
+ * 174 = temp in [C * 10]
+ * 955 = CO2 [ppm]
+ * 698 = RH in [% * 10]
+ * d 174 990 694 0x0d
+ * ...
+ * d 173 929 654 0x0d
+ *
+ * 15 lines in total, 1 second apart
+ *
+ * Sync datalogger time with PC
+ * request: C 452295746 0x0d
+ * response: > 0x0d
+ *
+ * 452295746 = seconds since 2000-01-01 00:00:00
+ *
+ * Identifier:
+ * request: J -------- 1 0x0d
+ *
+ * the characters (dashes) in the above become the first part of the response to the I command (12345678 above)
+ *
+ * Set sample rate
+ * request: S 10 0x0d
+ * response: m 12 10 C 1af5 7be1 0x0d
+ *
+ * Other characters that seem to give a response:
+ * A responds with >
+ * so is similar to the response to C, so other characters may be required
+ * A is the beep alarm perhaps?
+ * parameters would be CO2 level and on/off, as per front panel P1.3 setting?
+ *
+ * L responds with >
+ * L perhaps sets the limits for the good and normal levels (P1.1 and P1.2)?
+ *
+ * Q responds with >
+ * Q is reset maybe (P4.1)?
+ *
+ * : responds with : T19.9C:C2167ppm:H57.4%
+ * This one gives the current readings.
+ **********************************************************************************************
+
+/*********************************************************************************************/
+
+#include
+
+#ifndef CO2_LOW
+#define CO2_LOW 800 // Below this CO2 value show green light
+#endif
+#ifndef CO2_HIGH
+#define CO2_HIGH 1200 // Above this CO2 value show red light
+#endif
+
+#define AZ_READ_TIMEOUT 400 // Must be way less than 1000 but enough to read 9 bytes at 9600 bps
+
+TasmotaSerial *AzSerial;
+
+const char ktype[] = "AZ7798";
+uint8_t az_type = 1;
+uint16_t az_co2 = 0;
+double az_temperature = 0;
+double az_humidity = 0;
+uint8_t az_received = 0;
+uint8_t az_state = 0;
+
+/*********************************************************************************************/
+
+void AzEverySecond(void)
+{
+ az_state++;
+ if (5 == az_state) { // every 5 seconds
+ az_state = 0;
+
+ AzSerial->flush(); // sync reception
+ AzSerial->write(":\r", 2);
+ az_received = 0;
+
+ uint8_t az_response[32];
+ unsigned long start = millis();
+ uint8_t counter = 0;
+ uint8_t i, j;
+ uint8_t response_substr[16];
+
+ do {
+ if (AzSerial->available() > 0) {
+ az_response[counter] = AzSerial->read();
+ if(az_response[counter] == 0x0d) { az_received = 1; }
+ counter++;
+ } else {
+ delay(5);
+ }
+ } while(((millis() - start) < AZ_READ_TIMEOUT) && (counter < sizeof(az_response)) && !az_received);
+
+ AddLogSerial(LOG_LEVEL_DEBUG_MORE, az_response, counter);
+
+ if (!az_received) {
+ AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 comms timeout"));
+ return;
+ }
+
+ i = 0;
+ while((az_response[i] != 'T') && (i < counter)) {i++;} // find the start of response
+ if(az_response[i] != 'T') {
+ AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find start of response"));
+ return;
+ }
+ i++; // advance to start of temperature value
+ j = 0;
+ // find the end of temperature
+ while((az_response[i] != 'C') && (az_response[i] != 'F') && (i < counter)) {
+ response_substr[j++] = az_response[i++];
+ }
+ if((az_response[i] != 'C') && (az_response[i] != 'F')){
+ AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of temperature"));
+ return;
+ }
+ response_substr[j] = 0; // add null terminator
+ az_temperature = CharToDouble((char*)response_substr); // units (C or F) depends on meter setting
+ if(az_response[i] == 'C') { // meter transmits in degC
+ az_temperature = ConvertTemp((float)az_temperature); // convert to degF, depending on settings
+ } else { // meter transmits in degF
+ az_temperature = ConvertTemp((az_temperature - 32) / 1.8); // convert to degC and then C or F depending on setting
+ }
+ i++; // advance to first delimiter
+ if(az_response[i] != ':') {
+ AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error first delimiter"));
+ return;
+ }
+ i++; // advance to start of CO2
+ if(az_response[i] != 'C') {
+ AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of CO2"));
+ return;
+ }
+ i++; // advance to start of CO2 value
+ j = 0;
+ // find the end of CO2
+ while((az_response[i] != 'p') && (i < counter)) {
+ response_substr[j++] = az_response[i++];
+ }
+ if(az_response[i] != 'p') {
+ AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of CO2"));
+ return;
+ }
+ response_substr[j] = 0; // add null terminator
+ az_co2 = atoi((char*)response_substr);
+ LightSetSignal(CO2_LOW, CO2_HIGH, az_co2);
+ i += 3; // advance to second delimiter
+ if(az_response[i] != ':') {
+ AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error second delimiter"));
+ return;
+ }
+ i++; // advance to start of humidity
+ if(az_response[i] != 'H') {
+ AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of humidity"));
+ return;
+ }
+ i++; // advance to start of humidity value
+ j = 0;
+ // find the end of humidity
+ while((az_response[i] != '%') && (i < counter)) {
+ response_substr[j++] = az_response[i++];
+ }
+ if(az_response[i] != '%') {
+ AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of humidity"));
+ return;
+ }
+ response_substr[j] = 0; // add null terminator
+ az_humidity = CharToDouble((char*)response_substr);
+ }
+}
+
+/*********************************************************************************************/
+
+void AzInit(void)
+{
+ az_type = 0;
+ if ((pin[GPIO_AZ_RXD] < 99) && (pin[GPIO_AZ_TXD] < 99)) {
+ AzSerial = new TasmotaSerial(pin[GPIO_AZ_RXD], pin[GPIO_AZ_TXD], 1);
+ if (AzSerial->begin(9600)) {
+ if (AzSerial->hardwareSerial()) { ClaimSerial(); }
+ az_type = 1;
+ }
+ }
+}
+
+void AzShow(boolean json)
+{
+ char temperature[10], humidity[10];
+ dtostrfd(az_temperature, Settings.flag2.temperature_resolution, temperature);
+ dtostrfd(az_humidity, Settings.flag2.humidity_resolution, humidity);
+
+ if (json) {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), mqtt_data, ktype, az_co2, temperature, humidity);
+#ifdef USE_DOMOTICZ
+ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, az_co2);
+#endif // USE_DOMOTICZ
+#ifdef USE_WEBSERVER
+ } else {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CO2, mqtt_data, ktype, az_co2);
+ snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, ktype, temperature, TempUnit());
+ snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, ktype, humidity);
+#endif // USE_WEBSERVER
+ }
+}
+
+/*********************************************************************************************\
+ * Interface
+\*********************************************************************************************/
+
+boolean Xsns38(byte function)
+{
+ boolean result = false;
+
+ if(az_type){
+ switch (function) {
+ case FUNC_INIT:
+ AzInit();
+ break;
+ case FUNC_EVERY_SECOND:
+ AzEverySecond();
+ break;
+ case FUNC_JSON_APPEND:
+ AzShow(1);
+ break;
+#ifdef USE_WEBSERVER
+ case FUNC_WEB_APPEND:
+ AzShow(0);
+ break;
+#endif // USE_WEBSERVER
+ }
+ }
+ return result;
+}
+
+#endif // USE_AZ7798
diff --git a/tools/decode-status.py b/tools/decode-status.py
index fa108bc02..ce8be9131 100644
--- a/tools/decode-status.py
+++ b/tools/decode-status.py
@@ -135,7 +135,7 @@ a_features = [[
"USE_MCP230xx_OUTPUT","USE_MCP230xx_DISPLAYOUTPUT","USE_HLW8012","USE_CSE7766",
"USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711",
"USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","USE_RF_SENSOR",
- "USE_THEO_V2","USE_ALECTO_V2","","",
+ "USE_THEO_V2","USE_ALECTO_V2","USE_AZ7798","",
"","","","",
"","","","",
"","","",""]]