/*
* EMS-ESP - https://github.com/emsesp/EMS-ESP
* Copyright 2020-2024 emsesp.org - proddy, MichaelDvP
*
* 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 .
*/
#ifndef EMSESP_ANALOGSENSOR_H
#define EMSESP_ANALOGSENSOR_H
#include "helpers.h"
#include "mqtt.h"
#include "console.h"
#include
namespace emsesp {
// names, same order as AnalogType, see list_sensortype in local_common.h
// MAKE_ENUM_FIXED(AnalogTypeName, "disabled", "dig_in", "counter", "adc", "timer", "rate", "dig_out", "pwm0", "pwm1", "pwm2")
class AnalogSensor {
public:
class Sensor {
public:
Sensor(const uint8_t gpio, const std::string & name, const double offset, const double factor, const uint8_t uom, const int8_t type);
~Sensor() = default;
void set_offset(const double offset) {
offset_ = offset;
}
std::string name() const {
return name_;
}
void set_name(const std::string & name) {
name_ = name;
}
uint8_t gpio() const {
return gpio_;
}
double value() const {
return value_;
}
void set_value(const double value) {
value_ = value;
}
double factor() const {
return factor_;
}
void set_factor(const double factor) {
factor_ = factor;
}
double offset() const {
return offset_;
}
void set_uom(const uint8_t uom) {
uom_ = uom;
}
uint8_t uom() const {
return uom_;
}
int8_t type() const {
return type_;
}
void set_type(const int8_t type) {
type_ = type;
}
bool ha_registered = false;
uint16_t analog_ = 0; // ADC - average value
uint32_t sum_ = 0; // ADC - rolling sum
uint16_t last_reading_ = 0; // IO COUNTER & ADC - last reading
uint16_t count_ = 0; // counter raw counts
uint32_t polltime_ = 0; // digital IO & COUNTER debounce time
int poll_ = 0;
uint32_t last_polltime_ = 0; // for timer
private:
uint8_t gpio_;
std::string name_;
double offset_;
double factor_;
uint8_t uom_;
double value_; // double because of the factor is a double
int8_t type_; // one of the AnalogType enum
};
AnalogSensor() = default;
~AnalogSensor() = default;
enum AnalogType : int8_t {
NOTUSED = 0, // 0 = disabled
DIGITAL_IN = 1,
COUNTER = 2,
ADC = 3,
TIMER = 4,
RATE = 5,
DIGITAL_OUT = 6,
PWM_0 = 7,
PWM_1 = 8,
PWM_2 = 9,
NTC = 10,
RGB = 11,
PULSE = 12,
FREQ_0 = 13,
FREQ_1 = 14,
FREQ_2 = 15
};
void start(const bool factory_settings = false);
void loop();
void publish_sensor(const Sensor & sensor) const;
void publish_values(const bool force);
void reload(bool get_nvs = false);
bool updated_values();
// return back reference to the sensor list, used by other classes
std::vector sensors() const {
return sensors_;
}
uint32_t reads() const {
return sensorreads_;
}
uint32_t fails() const {
return sensorfails_;
}
bool analog_enabled() const {
return (analog_enabled_);
}
bool have_sensors() const {
return (!sensors_.empty());
}
size_t count_entities(bool include_disabled = true) const {
if (!include_disabled) {
// count number of items in sensors_ where type is not set to disabled
return std::count_if(sensors_.begin(), sensors_.end(), [](const Sensor & sensor) { return sensor.type() != AnalogSensor::AnalogType::NOTUSED; });
}
return sensors_.size();
}
bool update(uint8_t gpio, std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted = false);
bool get_value_info(JsonObject output, const char * cmd, const int8_t id = -1);
void store_counters();
private:
static constexpr double Beta = 4260;
static constexpr double T0 = 273.15;
static constexpr double T25 = 298.15;
static constexpr double R0 = 100000;
static constexpr double Rt = 60000;
static constexpr uint8_t MAX_SENSORS = 20;
static constexpr uint32_t MEASURE_ANALOG_INTERVAL = 500;
static uuid::log::Logger logger_;
void remove_ha_topic(const int8_t type, const uint8_t id) const;
bool command_setvalue(const char * value, const int8_t gpio);
void measure();
void addSensorJson(JsonObject output, const Sensor & sensor);
void get_value_json(JsonObject output, const Sensor & sensor);
std::vector sensors_; // our list of sensors
bool analog_enabled_;
bool changed_ = true; // this will force a publish of all sensors when initialising
uint32_t sensorfails_ = 0;
uint32_t sensorreads_ = 0;
#ifndef EMSESP_STANDALONE
static void IRAM_ATTR freqIrq0();
static void IRAM_ATTR freqIrq1();
static void IRAM_ATTR freqIrq2();
static unsigned long edge[3];
static unsigned long edgecnt[3];
unsigned long lastedge[3] = {0, 0, 0};
#endif
};
} // namespace emsesp
#endif