mirror of https://github.com/arendst/Tasmota.git
EZOpH & EZOORP support
This commits adds support for EZOpH and EZOORP to Tasmota
This commit is contained in:
parent
df5538f554
commit
d8b8636a44
|
@ -186,6 +186,10 @@
|
|||
| USE_DISPLAY_ILI9488 | - | - | - | - | - | - | - |
|
||||
| USE_DISPLAY_SSD1351 | - | - | - | - | - | - | - |
|
||||
| USE_DISPLAY_RA8876 | - | - | - | - | - | - | - |
|
||||
| | | | | | | | |
|
||||
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
|
||||
| USE_EZOPH | - | - | - | - | - | - | - |
|
||||
| USE_EZOORP | - | - | - | - | - | - | - |
|
||||
|
||||
## Additional Features and Sensors on ESP32
|
||||
|
||||
|
|
|
@ -77,3 +77,5 @@ Index | Define | Driver | Device | Address(es) | Description
|
|||
52 | USE_HP303B | xsns_73 | HP303B | 0x76 - 0x77 | Pressure and temperature sensor
|
||||
53 | USE_MLX90640 | xdrv_84 | MLX90640 | 0x33 | IR array temperature sensor
|
||||
54 | USE_VL53L1X | xsns_77 | VL53L1X | 0x29 | Time-of-flight (ToF) distance sensor
|
||||
55 | USE_EZO,USE_EZO_PH | xsns_78 | EZOPH | 0x61 - 0x70 | pH Sensor
|
||||
55 | USE_EZO,USE_EZO_ORP | xsns_79 | EZOORP | 0x61 - 0x70 | ORP Sensor
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
platformio run -e tasmota --target upload --upload-port /dev/ttyS4
|
Binary file not shown.
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
ezo.ino - EZO modules base class
|
||||
|
||||
Copyright (C) 2020 Christopher Tremblay
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef USE_I2C
|
||||
#if defined(USE_EZOPH) || defined(USE_EZOORP)
|
||||
|
||||
#define D_EZO_DELAY 300 // Minimum delay for any instruction
|
||||
#define D_EZO_MAX_BUF 40 // Maximum response
|
||||
|
||||
|
||||
|
||||
// This baseclass provides common functionality for all EZO devices
|
||||
struct EZOStruct {
|
||||
void MeasureRequest(void)
|
||||
{
|
||||
const uint8_t EZOMeasureCmd[2] = {'R', 0};
|
||||
|
||||
if (valid) {
|
||||
valid--;
|
||||
}
|
||||
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(EZOMeasureCmd, sizeof(EZOMeasureCmd));
|
||||
Wire.endTransmission();
|
||||
|
||||
lastRead = millis();
|
||||
}
|
||||
|
||||
void ProcessMeasurement(char *const data, const uint32_t len, const uint32_t latency)
|
||||
{
|
||||
// Wait for the data to arrive first
|
||||
const int32_t dur = lastRead + latency - millis();
|
||||
|
||||
// Wait for the last readout to complete (only when commands are issued)
|
||||
if (dur > 0) {
|
||||
delay(dur);
|
||||
}
|
||||
|
||||
Wire.requestFrom(addr, len);
|
||||
const char code = Wire.read();
|
||||
|
||||
if (code == 1) {
|
||||
for (uint32_t i = 0; (Wire.available() > 0) && (i < len); i++) {
|
||||
data[i] = Wire.read();
|
||||
}
|
||||
|
||||
valid = SENSOR_MAX_MISS;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleCommand(uint32_t index) const
|
||||
{
|
||||
char *at = XdrvMailbox.data;
|
||||
uint32_t len = XdrvMailbox.data_len;
|
||||
|
||||
// Figure out if we're trying to address a specific device
|
||||
// PS: This should ideally be done through the Tasmota mailbox
|
||||
if (at[0] == '-') {
|
||||
uint32_t idx = atoi(&at[1]);
|
||||
at = strchr(at, ' ');
|
||||
|
||||
if (!at++) {
|
||||
return;
|
||||
}
|
||||
|
||||
len -= (at - XdrvMailbox.data);
|
||||
|
||||
if (idx != index) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Transmit our command verbatim
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(at, len);
|
||||
if (Wire.endTransmission() != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Attempt to read the results
|
||||
char data[D_EZO_MAX_BUF];
|
||||
for (uint32_t code = 254; code == 254; code = Wire.read()) {
|
||||
delay(D_EZO_DELAY);
|
||||
Wire.requestFrom(addr, sizeof(data));
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; Wire.available() > 0; i++) {
|
||||
data[i] = Wire.read();
|
||||
}
|
||||
|
||||
ResponseCmndChar((char *)data);
|
||||
}
|
||||
|
||||
public:
|
||||
uint8_t valid = 0;
|
||||
uint8_t addr;
|
||||
|
||||
private:
|
||||
uint32_t lastRead = -2000;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // USE_EZO*
|
||||
#endif // USE_I2C
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
ezoManager.ino - EZO device manager
|
||||
|
||||
Copyright (C) 2020 Christopher Tremblay
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef USE_I2C
|
||||
#if defined(USE_EZOPH) || defined(USE_EZOORP)
|
||||
|
||||
#define XI2C_55 55 // See I2CDEVICES.md
|
||||
|
||||
#define EZO_ADDR_0 0x61 // First EZO address
|
||||
#define EZO_ADDR_n 16 // Number of ports for use with EZO devices
|
||||
|
||||
|
||||
// List of known EZO devices and their default address
|
||||
enum EZOType {
|
||||
EZO_DO = 0x61, // D.O.
|
||||
EZO_ORP = 0x62, // ORP
|
||||
EZO_PH = 0x63, // pH
|
||||
EZO_EC = 0x64, // EC
|
||||
|
||||
EZO_RTD = 0x66, // RTD
|
||||
EZO_PMP = 0x67, // PMP
|
||||
EZO_FLO = 0x68, // FLO
|
||||
EZO_CO2 = 0x69, // CO2
|
||||
EZO_PRS = 0x6A, // PRS
|
||||
|
||||
EZO_O2 = 0x6C, // O2
|
||||
|
||||
|
||||
EZO_HUM = 0x6F, // HUM
|
||||
EZO_RGB = 0x70, // RGB
|
||||
};
|
||||
|
||||
const char EZO_EMPTY[] PROGMEM = "";
|
||||
//const char EZO_DO_NAME[] PROGMEM = "DO";
|
||||
#ifdef USE_EZOORP
|
||||
const char EZO_ORP_NAME[] PROGMEM = "ORP";
|
||||
#endif
|
||||
#ifdef USE_EZOPH
|
||||
const char EZO_PH_NAME[] PROGMEM = "pH";
|
||||
#endif
|
||||
//const char EZO_EC_NAME[] PROGMEM = "EC";
|
||||
//const char EZO_RTD_NAME[] PROGMEM = "RTD";
|
||||
//const char EZO_PMP_NAME[] PROGMEM = "PMP";
|
||||
//const char EZO_FLO_NAME[] PROGMEM = "FLO";
|
||||
//const char EZO_CO2_NAME[] PROGMEM = "CO2";
|
||||
//const char EZO_PRS_NAME[] PROGMEM = "PRS";
|
||||
//const char EZO_O2_NAME[] PROGMEM = "O2";
|
||||
//const char EZO_HUM_NAME[] PROGMEM = "HUM";
|
||||
//const char EZO_RGB_NAME[] PROGMEM = "RGB";
|
||||
|
||||
const char *const EZOSupport[EZO_ADDR_n] PROGMEM = {
|
||||
EZO_EMPTY,
|
||||
|
||||
#ifdef USE_EZOORP
|
||||
EZO_ORP_NAME,
|
||||
#else
|
||||
EZO_EMPTY,
|
||||
#endif
|
||||
|
||||
#ifdef USE_EZOPH
|
||||
EZO_PH_NAME,
|
||||
#else
|
||||
EZO_EMPTY,
|
||||
#endif
|
||||
|
||||
EZO_EMPTY,
|
||||
EZO_EMPTY,
|
||||
EZO_EMPTY,
|
||||
EZO_EMPTY,
|
||||
EZO_EMPTY,
|
||||
EZO_EMPTY,
|
||||
EZO_EMPTY,
|
||||
EZO_EMPTY,
|
||||
EZO_EMPTY,
|
||||
EZO_EMPTY,
|
||||
EZO_EMPTY,
|
||||
EZO_EMPTY,
|
||||
EZO_EMPTY,
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct EZOManager {
|
||||
// Returns the count of devices of the specified type or -1 if the driver isn't ready yet
|
||||
// list must be a client-allocated array of atleast 16 elements
|
||||
int getDevice(const EZOType type, uint32_t *list)
|
||||
{
|
||||
// EZO devices take 2s to boot
|
||||
if (uptime >= next) {
|
||||
if (stage == 0) {
|
||||
DetectRequest();
|
||||
next = uptime + 1;
|
||||
} else if (stage == 1) {
|
||||
ProcessDetection();
|
||||
}
|
||||
|
||||
stage++;
|
||||
}
|
||||
|
||||
if (stage >= 2) {
|
||||
int count = 0;
|
||||
|
||||
for (uint32_t i = 0; i < EZO_ADDR_n; i++) {
|
||||
if ((alive & (1 << i)) && (((devices[i >> 3] >> ((i & 7) << 2)) & 0xF) == (type - EZO_ADDR_0))) {
|
||||
list[count++] = i + EZO_ADDR_0;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private:
|
||||
void DetectRequest(void)
|
||||
{
|
||||
const uint8_t EZOInfoCmd[2] = {'i', 0};
|
||||
alive = 0;
|
||||
|
||||
// Scan the address range
|
||||
uint16_t shift = 1;
|
||||
for (uint8_t i = EZO_ADDR_0; shift; i++) {
|
||||
if (!I2cActive(i)) {
|
||||
// Request the device to identify itself
|
||||
Wire.beginTransmission(i);
|
||||
Wire.write(EZOInfoCmd, sizeof(EZOInfoCmd));
|
||||
|
||||
int c = Wire.endTransmission();
|
||||
|
||||
if (c == 0) {
|
||||
alive |= shift;
|
||||
}
|
||||
}
|
||||
shift <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessDetection(void)
|
||||
{
|
||||
uint32_t mask = alive;
|
||||
|
||||
devices[0] = devices[1] = 0;
|
||||
|
||||
// Check every address that we sent a request to
|
||||
for (uint8_t addr = 0; addr < EZO_ADDR_n; addr++) {
|
||||
if (mask & 1) {
|
||||
char data[D_EZO_MAX_BUF];
|
||||
Wire.requestFrom(addr + EZO_ADDR_0, sizeof(data));
|
||||
char code = Wire.read();
|
||||
|
||||
if (code == 1) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; Wire.available() > 0; i++) {
|
||||
char c = Wire.read();
|
||||
|
||||
// Helps us strcmp
|
||||
data[i] = (c == ',') ? 0 : c;
|
||||
}
|
||||
|
||||
// Technically the response starts with "?I," but we'll skip testing it to save space
|
||||
if (i >= 3) {
|
||||
for (uint32_t j = 0; j < EZO_ADDR_n; j++) {
|
||||
if (strcasecmp_P(&data[3], EZOSupport[j]) == 0) {
|
||||
data[0] = 'E';
|
||||
data[1] = 'Z';
|
||||
data[2] = 'O';
|
||||
I2cSetActiveFound(addr, data);
|
||||
devices[addr >> 3] |= j << ((addr & 7) * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t next = 2;
|
||||
uint8_t stage = 0;
|
||||
|
||||
// Following 2 members are harcoded to allow a maximum of 16 entries
|
||||
uint16_t alive;
|
||||
uint32_t devices[2];
|
||||
} EZOManager;
|
||||
|
||||
|
||||
|
||||
// The main driver is the same for all devices.
|
||||
// What changes is the implementation of the class itself
|
||||
template <class T, EZOType type> bool XsnsEZO(uint8_t function)
|
||||
{
|
||||
if (!I2cEnabled(XI2C_55)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialization: Gather the list of devices for this class
|
||||
if ((T::count < 0) && (function == FUNC_EVERY_SECOND)) {
|
||||
uint32_t addr[EZO_ADDR_n];
|
||||
T::count = EZOManager.getDevice(type, &addr[0]);
|
||||
|
||||
if (T::count > 0) {
|
||||
T::list = new T[T::count];
|
||||
|
||||
for (uint32_t i = 0; i < T::count; i++) {
|
||||
T::list[i].addr = addr[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process the function on each of them
|
||||
T *cur = &T::list[0];
|
||||
for (int32_t i = 0; i < T::count; i++) {
|
||||
switch (function) {
|
||||
case FUNC_COMMAND_SENSOR:
|
||||
cur->ProcessMeasurement();
|
||||
cur->HandleCommand(i);
|
||||
break;
|
||||
|
||||
case FUNC_EVERY_SECOND:
|
||||
if (uptime & 1) {
|
||||
cur->ProcessMeasurement();
|
||||
cur->MeasureRequest();
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNC_JSON_APPEND:
|
||||
cur->Show(1, i);
|
||||
break;
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_SENSOR:
|
||||
cur->Show(0, i);
|
||||
break;
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
cur++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // USE_EZO*
|
||||
#endif // USE_I2C
|
|
@ -111,7 +111,9 @@
|
|||
#define D_JSON_NOISE "Noise"
|
||||
#define D_JSON_NONE "None"
|
||||
#define D_JSON_OR "or"
|
||||
#define D_JSON_ORP "ORP"
|
||||
#define D_JSON_PERIOD "Period"
|
||||
#define D_JSON_PH "pH"
|
||||
#define D_JSON_PHASE_ANGLE "PhaseAngle"
|
||||
#define D_JSON_POWERFACTOR "Factor"
|
||||
#define D_JSON_POWERUSAGE "Power"
|
||||
|
@ -768,6 +770,8 @@ const char HTTP_SNS_VOLTAGE[] PROGMEM = "{s}" D_VOLTAGE "{
|
|||
const char HTTP_SNS_CURRENT[] PROGMEM = "{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}";
|
||||
const char HTTP_SNS_POWER[] PROGMEM = "{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}";
|
||||
const char HTTP_SNS_ENERGY_TOTAL[] PROGMEM = "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
|
||||
const char HTTP_SNS_PH[] PROGMEM = "{s}%s " D_PH "{m}%s " "{e}";
|
||||
const char HTTP_SNS_ORP[] PROGMEM = "{s}%s " D_ORP "{m}%s " D_UNIT_MILLIVOLT "{e}";
|
||||
|
||||
const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU;
|
||||
const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION;
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
#define D_OK "Ok"
|
||||
#define D_ON "On"
|
||||
#define D_ONLINE "Online"
|
||||
#define D_ORP "ORP"
|
||||
#define D_PASSWORD "Password"
|
||||
#define D_PORT "Port"
|
||||
#define D_POWER_FACTOR "Power Factor"
|
||||
|
@ -136,6 +137,7 @@
|
|||
#define D_POWERUSAGE_ACTIVE "Active Power"
|
||||
#define D_POWERUSAGE_APPARENT "Apparent Power"
|
||||
#define D_POWERUSAGE_REACTIVE "Reactive Power"
|
||||
#define D_PH "pH"
|
||||
#define D_PRESSURE "Pressure"
|
||||
#define D_PRESSUREATSEALEVEL "SeaPressure"
|
||||
#define D_PROGRAM_FLASH_SIZE "Program Flash Size"
|
||||
|
@ -749,6 +751,7 @@
|
|||
#define D_UNIT_MILLIMETER "mm"
|
||||
#define D_UNIT_MILLIMETER_MERCURY "mmHg"
|
||||
#define D_UNIT_MILLISECOND "ms"
|
||||
#define D_UNIT_MILLIVOLT "mV"
|
||||
#define D_UNIT_MINUTE "Min"
|
||||
#define D_UNIT_PARTS_PER_BILLION "ppb"
|
||||
#define D_UNIT_PARTS_PER_DECILITER "ppd"
|
||||
|
|
|
@ -796,6 +796,9 @@
|
|||
//#define USE_WEBCAM // Add support for webcam
|
||||
|
||||
#endif
|
||||
// Shared EZO code required for any EZO device (+1k0 code)
|
||||
// #define USE_EZOPH // Add support for EZO's pH sensor (+0k6 code)
|
||||
// #define USE_EZOORP // Add support for EZO's ORP sensor (+0k6 code)
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Debug features
|
||||
|
|
|
@ -613,9 +613,9 @@ void GetFeatures(void)
|
|||
#if defined(USE_ENERGY_SENSOR) && defined(USE_WE517)
|
||||
feature6 |= 0x08000000; // xnrg_17_ornowe517.ino
|
||||
#endif
|
||||
|
||||
// feature6 |= 0x10000000;
|
||||
|
||||
#if defined(USE_I2C) && defined(USE_EZOPH)
|
||||
feature6 |= 0x10000000; // xsns_78_ezoph.ino
|
||||
#endif
|
||||
#if defined(ESP32) && defined(USE_TTGO_WATCH)
|
||||
feature6 |= 0x20000000; // xdrv_83_esp32watch.ino
|
||||
#endif
|
||||
|
@ -630,7 +630,9 @@ void GetFeatures(void)
|
|||
|
||||
feature7 = 0x00000000;
|
||||
|
||||
// feature7 |= 0x00000001;
|
||||
#if defined(USE_I2C) && defined(USE_EZOORP)
|
||||
feature7 |= 0x00000001; // xsns_79_ezoorp.ino
|
||||
#endif
|
||||
// feature7 |= 0x00000002;
|
||||
// feature7 |= 0x00000004;
|
||||
// feature7 |= 0x00000008;
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
xsns_78_ezoph.ino - EZO pH I2C pH sensor support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Christopher Tremblay
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_EZOPH
|
||||
|
||||
#define XSNS_78 78
|
||||
|
||||
#define EZO_PH_READ_LATENCY 900
|
||||
|
||||
struct EZOpH : public EZOStruct {
|
||||
void ProcessMeasurement(void)
|
||||
{
|
||||
char data[D_EZO_MAX_BUF];
|
||||
|
||||
EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_PH_READ_LATENCY);
|
||||
pH = CharToFloat(data);
|
||||
}
|
||||
|
||||
void Show(bool json, uint32_t index)
|
||||
{
|
||||
if (valid) {
|
||||
char str[6];
|
||||
dtostrfd(pH, 2, str);
|
||||
|
||||
char name[10];
|
||||
snprintf_P(name, sizeof(name), PSTR("%s%c%X"), EZOpH::name, IndexSeparator(), index + 1);
|
||||
|
||||
if (count == 1) {
|
||||
name[sizeof("EZOpH") - 1] = 0;
|
||||
}
|
||||
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_PH "\":%s}" ), name, str);
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
else {
|
||||
WSContentSend_PD(HTTP_SNS_PH, name, str);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t count;
|
||||
static EZOpH *list;
|
||||
static const char name[];
|
||||
|
||||
private:
|
||||
float pH = NAN;
|
||||
};
|
||||
|
||||
int8_t EZOpH::count = -1;
|
||||
EZOpH *EZOpH::list = NULL;
|
||||
const char EZOpH::name[] PROGMEM = "EZOpH";
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
#define Xsns78 XsnsEZO<EZOpH, EZO_PH>
|
||||
|
||||
#endif // USE_EZOPH
|
||||
#endif // USE_I2C
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
xsns_79_ezoorp.ino - EZO ORP I2C ORP sensor support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Christopher Tremblay
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_EZOORP
|
||||
|
||||
#define XSNS_79 79
|
||||
|
||||
#define EZO_ORP_READ_LATENCY 900
|
||||
|
||||
struct EZOORP : public EZOStruct {
|
||||
void ProcessMeasurement(void)
|
||||
{
|
||||
char data[D_EZO_MAX_BUF];
|
||||
|
||||
EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_ORP_READ_LATENCY);
|
||||
ORP = CharToFloat(data);
|
||||
}
|
||||
|
||||
void Show(bool json, uint32_t index)
|
||||
{
|
||||
if (valid) {
|
||||
char str[6];
|
||||
dtostrfd(ORP, 2, str);
|
||||
|
||||
char name[10];
|
||||
snprintf_P(name, sizeof(name), PSTR("%s%c%X"), EZOORP::name, IndexSeparator(), index + 1);
|
||||
|
||||
if (count == 1) {
|
||||
name[sizeof("EZOORP") - 1] = 0;
|
||||
}
|
||||
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ORP "\":%s}" ), name, str);
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
else {
|
||||
WSContentSend_PD(HTTP_SNS_ORP, name, str);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t count;
|
||||
static EZOORP *list;
|
||||
static const char name[];
|
||||
|
||||
private:
|
||||
float ORP = NAN;
|
||||
};
|
||||
|
||||
int8_t EZOORP::count = -1;
|
||||
EZOORP *EZOORP::list = NULL;
|
||||
const char EZOORP::name[] PROGMEM = "EZOORP";
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
#define Xsns79 XsnsEZO<EZOORP, EZO_ORP>
|
||||
|
||||
#endif // USE_EZOORP
|
||||
#endif // USE_I2C
|
Loading…
Reference in New Issue