add counter 0..2 for short pulses, high frequency, #2758

This commit is contained in:
MichaelDvP
2025-11-26 18:14:58 +01:00
parent 9edcf47073
commit 2bcd548747
7 changed files with 120 additions and 40 deletions

View File

@@ -33,6 +33,8 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/).
- pumpmode enum for HT3 boilers, add commands for manual defrost, chimneysweeper [#2727](https://github.com/emsesp/EMS-ESP32/issues/2727) - pumpmode enum for HT3 boilers, add commands for manual defrost, chimneysweeper [#2727](https://github.com/emsesp/EMS-ESP32/issues/2727)
- pid settings [#2735](https://github.com/emsesp/EMS-ESP32/issues/2735) - pid settings [#2735](https://github.com/emsesp/EMS-ESP32/issues/2735)
- refresh MQTT button added to MQTT Settings page - refresh MQTT button added to MQTT Settings page
- heating assistance, rounding custum settings [#2763](https://github.com/emsesp/EMS-ESP32/discussions/2763)
- add counter 0..2 for short pulses, high frequency [#2758](https://github.com/emsesp/EMS-ESP32/issues/2758)
## Fixed ## Fixed

View File

@@ -586,6 +586,7 @@ const Sensors = () => {
creating={creating} creating={creating}
selectedItem={selectedAnalogSensor} selectedItem={selectedAnalogSensor}
analogGPIOList={sensorData.available_gpios} analogGPIOList={sensorData.available_gpios}
disabledTypeList={sensorData.exclude_types}
validator={analogSensorItemValidation(sensorData.as, selectedAnalogSensor)} validator={analogSensorItemValidation(sensorData.as, selectedAnalogSensor)}
/> />
)} )}

View File

@@ -35,6 +35,7 @@ interface DashboardSensorsAnalogDialogProps {
creating: boolean; creating: boolean;
selectedItem: AnalogSensor; selectedItem: AnalogSensor;
analogGPIOList: number[]; analogGPIOList: number[];
disabledTypeList: number[];
validator: Schema; validator: Schema;
} }
@@ -45,6 +46,7 @@ const SensorsAnalogDialog = ({
creating, creating,
selectedItem, selectedItem,
analogGPIOList, analogGPIOList,
disabledTypeList,
validator validator
}: DashboardSensorsAnalogDialogProps) => { }: DashboardSensorsAnalogDialogProps) => {
const { LL } = useI18nContext(); const { LL } = useI18nContext();
@@ -66,7 +68,16 @@ const SensorsAnalogDialog = ({
// Memoize helper functions to check sensor type conditions // Memoize helper functions to check sensor type conditions
const isCounterOrRate = useMemo( const isCounterOrRate = useMemo(
() => editItem.t >= AnalogType.COUNTER && editItem.t <= AnalogType.RATE, () =>
editItem.t === AnalogType.COUNTER ||
editItem.t === AnalogType.RATE ||
(editItem.t >= AnalogType.CNT_0 && editItem.t <= AnalogType.CNT_2),
[editItem.t]
);
const isCounter = useMemo(
() =>
editItem.t === AnalogType.COUNTER ||
(editItem.t >= AnalogType.CNT_0 && editItem.t <= AnalogType.CNT_2),
[editItem.t] [editItem.t]
); );
const isFreqType = useMemo( const isFreqType = useMemo(
@@ -80,13 +91,13 @@ const SensorsAnalogDialog = ({
editItem.t === AnalogType.PWM_2, editItem.t === AnalogType.PWM_2,
[editItem.t] [editItem.t]
); );
const isDigitalOutGPIO = useMemo( const isDACOutGPIO = useMemo(
() => () =>
editItem.t === AnalogType.DIGITAL_OUT && editItem.t === AnalogType.DIGITAL_OUT &&
(editItem.g === 25 || editItem.g === 26), (editItem.g === 25 || editItem.g === 26),
[editItem.t, editItem.g] [editItem.t, editItem.g]
); );
const isDigitalOutNonGPIO = useMemo( const isDigitalOutGPIO = useMemo(
() => () =>
editItem.t === AnalogType.DIGITAL_OUT && editItem.t === AnalogType.DIGITAL_OUT &&
editItem.g !== 25 && editItem.g !== 25 &&
@@ -98,7 +109,11 @@ const SensorsAnalogDialog = ({
const analogTypeMenuItems = useMemo( const analogTypeMenuItems = useMemo(
() => () =>
AnalogTypeNames.map((val, i) => ( AnalogTypeNames.map((val, i) => (
<MenuItem key={val} value={i + 1}> <MenuItem
key={val}
value={i + 1}
disabled={disabledTypeList.includes(i + 1)}
>
{val} {val}
</MenuItem> </MenuItem>
)), )),
@@ -264,7 +279,7 @@ const SensorsAnalogDialog = ({
/> />
</Grid> </Grid>
)} )}
{editItem.t === AnalogType.COUNTER && ( {isCounter && (
<Grid> <Grid>
<ValidatedTextField <ValidatedTextField
name="o" name="o"
@@ -309,7 +324,7 @@ const SensorsAnalogDialog = ({
/> />
</Grid> </Grid>
)} )}
{isDigitalOutGPIO && ( {isDACOutGPIO && (
<Grid> <Grid>
<ValidatedTextField <ValidatedTextField
name="o" name="o"
@@ -325,7 +340,7 @@ const SensorsAnalogDialog = ({
/> />
</Grid> </Grid>
)} )}
{isDigitalOutNonGPIO && ( {isDigitalOutGPIO && (
<> <>
<Grid> <Grid>
<ValidatedTextField <ValidatedTextField

View File

@@ -112,6 +112,7 @@ export interface SensorData {
as: AnalogSensor[]; as: AnalogSensor[];
analog_enabled: boolean; analog_enabled: boolean;
available_gpios: number[]; available_gpios: number[];
exclude_types: number[];
platform: string; platform: string;
} }
@@ -245,7 +246,10 @@ export enum AnalogType {
PULSE = 12, PULSE = 12,
FREQ_0 = 13, FREQ_0 = 13,
FREQ_1 = 14, FREQ_1 = 14,
FREQ_2 = 15 FREQ_2 = 15,
CNT_0 = 16,
CNT_1 = 17,
CNT_2 = 18
} }
export const AnalogTypeNames = [ export const AnalogTypeNames = [
@@ -263,7 +267,10 @@ export const AnalogTypeNames = [
'Pulse', // 12 'Pulse', // 12
'Freq 0', // 13 'Freq 0', // 13
'Freq 1', // 14 'Freq 1', // 14
'Freq 2' // 15 'Freq 2', // 15
'Counter 0', // 16
'Counter 1', // 17
'Counter2' // 18
] as const; ] as const;
export const BOARD_PROFILES = { export const BOARD_PROFILES = {

View File

@@ -21,7 +21,8 @@
namespace emsesp { namespace emsesp {
uuid::log::Logger AnalogSensor::logger_{F_(analogsensor), uuid::log::Facility::DAEMON}; uuid::log::Logger AnalogSensor::logger_{F_(analogsensor), uuid::log::Facility::DAEMON};
std::vector<uint8_t> AnalogSensor::exclude_types_;
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
@@ -30,20 +31,26 @@ unsigned long AnalogSensor::edgecnt[] = {0, 0, 0};
void IRAM_ATTR AnalogSensor::freqIrq0() { void IRAM_ATTR AnalogSensor::freqIrq0() {
portENTER_CRITICAL_ISR(&mux); portENTER_CRITICAL_ISR(&mux);
edgecnt[0]++; if (micros() - edge[0] > 10) { // limit to 100kHz
edge[0] = micros(); edgecnt[0]++;
edge[0] = micros();
}
portEXIT_CRITICAL_ISR(&mux); portEXIT_CRITICAL_ISR(&mux);
} }
void IRAM_ATTR AnalogSensor::freqIrq1() { void IRAM_ATTR AnalogSensor::freqIrq1() {
portENTER_CRITICAL_ISR(&mux); portENTER_CRITICAL_ISR(&mux);
edgecnt[1]++; if (micros() - edge[1] > 10) { // limit to 100kHz
edge[1] = micros(); edgecnt[1]++;
edge[1] = micros();
}
portEXIT_CRITICAL_ISR(&mux); portEXIT_CRITICAL_ISR(&mux);
} }
void IRAM_ATTR AnalogSensor::freqIrq2() { void IRAM_ATTR AnalogSensor::freqIrq2() {
portENTER_CRITICAL_ISR(&mux); portENTER_CRITICAL_ISR(&mux);
edgecnt[2]++; if (micros() - edge[2] > 10) { // limit to 100kHz
edge[2] = micros(); edgecnt[2]++;
edge[2] = micros();
}
portEXIT_CRITICAL_ISR(&mux); portEXIT_CRITICAL_ISR(&mux);
} }
#endif #endif
@@ -97,6 +104,7 @@ void AnalogSensor::start(const bool factory_settings) {
// load settings from the customization file, sorts them and initializes the GPIOs // load settings from the customization file, sorts them and initializes the GPIOs
void AnalogSensor::reload(bool get_nvs) { void AnalogSensor::reload(bool get_nvs) {
exclude_types_.clear();
EMSESP::webSettingsService.read([&](WebSettings & settings) { analog_enabled_ = settings.analog_enabled; }); EMSESP::webSettingsService.read([&](WebSettings & settings) { analog_enabled_ = settings.analog_enabled; });
#if defined(EMSESP_STANDALONE) #if defined(EMSESP_STANDALONE)
@@ -126,8 +134,8 @@ void AnalogSensor::reload(bool get_nvs) {
&& (sensor_.type() != sensor.type || sensor_.offset() != sensor.offset || sensor_.factor() != sensor.factor)) { && (sensor_.type() != sensor.type || sensor_.offset() != sensor.offset || sensor_.factor() != sensor.factor)) {
sensor_.set_value(sensor.offset); sensor_.set_value(sensor.offset);
} }
if (sensor.type == AnalogType::COUNTER && sensor_.offset() != sensor.offset if ((sensor.type == AnalogType::COUNTER || (sensor.type >= AnalogType::CNT_0 && sensor.type <= AnalogType::CNT_2))
&& sensor.offset != EMSESP::nvs_.getDouble(sensor.name.c_str(), 0)) { && sensor_.offset() != sensor.offset && sensor.offset != EMSESP::nvs_.getDouble(sensor.name.c_str(), 0)) {
EMSESP::nvs_.putDouble(sensor.name.c_str(), sensor.offset); EMSESP::nvs_.putDouble(sensor.name.c_str(), sensor.offset);
sensor_.set_value(sensor.offset); sensor_.set_value(sensor.offset);
} }
@@ -160,7 +168,8 @@ void AnalogSensor::reload(bool get_nvs) {
sensors_.emplace_back(sensor.gpio, sensor.name, sensor.offset, sensor.factor, sensor.uom, type, sensor.is_system); sensors_.emplace_back(sensor.gpio, sensor.name, sensor.offset, sensor.factor, sensor.uom, type, sensor.is_system);
sensors_.back().ha_registered = false; // this will trigger recreate of the HA config sensors_.back().ha_registered = false; // this will trigger recreate of the HA config
if (sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT) { if (sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT
|| (sensor.type >= AnalogType::CNT_0 && sensor.type <= AnalogType::CNT_2)) {
sensors_.back().set_value(sensor.offset); sensors_.back().set_value(sensor.offset);
} else { } else {
sensors_.back().set_value(0); // reset value only for new sensors sensors_.back().set_value(0); // reset value only for new sensors
@@ -169,16 +178,16 @@ void AnalogSensor::reload(bool get_nvs) {
// add the command to set the value of the sensor // add the command to set the value of the sensor
if (sensor.type == AnalogType::COUNTER || (sensor.type >= AnalogType::DIGITAL_OUT && sensor.type <= AnalogType::PWM_2) if (sensor.type == AnalogType::COUNTER || (sensor.type >= AnalogType::DIGITAL_OUT && sensor.type <= AnalogType::PWM_2)
|| sensor.type == AnalogType::RGB || sensor.type == AnalogType::PULSE) { || sensor.type == AnalogType::RGB || sensor.type == AnalogType::PULSE || (sensor.type >= AnalogType::CNT_0 && sensor.type <= AnalogType::CNT_2)) {
Command::add( Command::add(
EMSdevice::DeviceType::ANALOGSENSOR, EMSdevice::DeviceType::ANALOGSENSOR,
sensor.name.c_str(), sensor.name.c_str(),
[&](const char * value, const int8_t id) { return command_setvalue(value, sensor.gpio); }, [&](const char * value, const int8_t id) { return command_setvalue(value, sensor.gpio); },
sensor.type == AnalogType::COUNTER ? FL_(counter) sensor.type == AnalogType::COUNTER || (sensor.type >= AnalogType::CNT_0 && sensor.type <= AnalogType::CNT_2) ? FL_(counter)
: sensor.type == AnalogType::DIGITAL_OUT ? FL_(digital_out) : sensor.type == AnalogType::DIGITAL_OUT ? FL_(digital_out)
: sensor.type == AnalogType::RGB ? FL_(RGB) : sensor.type == AnalogType::RGB ? FL_(RGB)
: sensor.type == AnalogType::PULSE ? FL_(pulse) : sensor.type == AnalogType::PULSE ? FL_(pulse)
: FL_(pwm), : FL_(pwm),
CommandFlag::ADMIN_ONLY); CommandFlag::ADMIN_ONLY);
} }
} }
@@ -191,9 +200,20 @@ void AnalogSensor::reload(bool get_nvs) {
// activate each sensor // activate each sensor
for (auto & sensor : sensors_) { for (auto & sensor : sensors_) {
sensor.ha_registered = false; // force HA configs to be re-created sensor.ha_registered = false; // force HA configs to be re-created
if ((sensor.type() >= AnalogType::FREQ_0 && sensor.type() <= AnalogType::FREQ_2)) {
exclude_types_.push_back(sensor.type());
exclude_types_.push_back(sensor.type() + 3);
}
if ((sensor.type() >= AnalogType::CNT_0 && sensor.type() <= AnalogType::CNT_2)) {
exclude_types_.push_back(sensor.type());
exclude_types_.push_back(sensor.type() - 3);
}
if ((sensor.type() >= AnalogType::PWM_0 && sensor.type() <= AnalogType::PWM_2)) {
exclude_types_.push_back(sensor.type());
}
if (sensor.type() == AnalogType::COUNTER || sensor.type() == AnalogType::DIGITAL_IN || sensor.type() == AnalogType::RATE if (sensor.type() == AnalogType::COUNTER || sensor.type() == AnalogType::DIGITAL_IN || sensor.type() == AnalogType::RATE
|| sensor.type() == AnalogType::TIMER) { || sensor.type() == AnalogType::TIMER || (sensor.type() >= AnalogType::FREQ_0 && sensor.type() <= AnalogType::CNT_2)) {
// pullup is mapped to DAC, so set to 3.3V // pullup is mapped to DAC, so set to 3.3V
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
if (sensor.gpio() == 25 || sensor.gpio() == 26) { if (sensor.gpio() == 25 || sensor.gpio() == 26) {
@@ -204,6 +224,7 @@ void AnalogSensor::reload(bool get_nvs) {
dacWrite(sensor.gpio(), 255); dacWrite(sensor.gpio(), 255);
} }
#endif #endif
pinMode(sensor.gpio(), INPUT_PULLUP);
} }
if (sensor.type() == AnalogType::ADC) { if (sensor.type() == AnalogType::ADC) {
LOG_DEBUG("ADC Sensor on GPIO %02d", sensor.gpio()); LOG_DEBUG("ADC Sensor on GPIO %02d", sensor.gpio());
@@ -216,7 +237,6 @@ void AnalogSensor::reload(bool get_nvs) {
sensor.set_uom(DeviceValueUOM::DEGREES); sensor.set_uom(DeviceValueUOM::DEGREES);
} else if (sensor.type() == AnalogType::COUNTER) { } else if (sensor.type() == AnalogType::COUNTER) {
LOG_DEBUG("I/O Counter on GPIO %02d", sensor.gpio()); LOG_DEBUG("I/O Counter on GPIO %02d", sensor.gpio());
pinMode(sensor.gpio(), INPUT_PULLUP);
sensor.polltime_ = 0; sensor.polltime_ = 0;
sensor.poll_ = digitalRead(sensor.gpio()); sensor.poll_ = digitalRead(sensor.gpio());
if (double_t val = EMSESP::nvs_.getDouble(sensor.name().c_str(), 0)) { if (double_t val = EMSESP::nvs_.getDouble(sensor.name().c_str(), 0)) {
@@ -225,7 +245,6 @@ void AnalogSensor::reload(bool get_nvs) {
publish_sensor(sensor); publish_sensor(sensor);
} else if (sensor.type() == AnalogType::TIMER || sensor.type() == AnalogType::RATE) { } else if (sensor.type() == AnalogType::TIMER || sensor.type() == AnalogType::RATE) {
LOG_DEBUG("Timer/Rate on GPIO %02d", sensor.gpio()); LOG_DEBUG("Timer/Rate on GPIO %02d", sensor.gpio());
pinMode(sensor.gpio(), INPUT_PULLUP);
sensor.polltime_ = uuid::get_uptime(); sensor.polltime_ = uuid::get_uptime();
sensor.last_polltime_ = uuid::get_uptime(); sensor.last_polltime_ = uuid::get_uptime();
sensor.poll_ = digitalRead(sensor.gpio()); sensor.poll_ = digitalRead(sensor.gpio());
@@ -234,25 +253,33 @@ void AnalogSensor::reload(bool get_nvs) {
publish_sensor(sensor); publish_sensor(sensor);
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
} else if (sensor.type() >= AnalogType::FREQ_0 && sensor.type() <= AnalogType::FREQ_2) { } else if (sensor.type() >= AnalogType::FREQ_0 && sensor.type() <= AnalogType::FREQ_2) {
LOG_DEBUG("Frequency on GPIO %02d", sensor.gpio()); auto index = sensor.type() - AnalogType::FREQ_0;
pinMode(sensor.gpio(), INPUT_PULLUP); LOG_DEBUG("Frequency %d on GPIO %02d", index, sensor.gpio());
sensor.set_offset(0); sensor.set_offset(0);
sensor.set_value(0); sensor.set_value(0);
publish_sensor(sensor); publish_sensor(sensor);
auto index = sensor.type() - AnalogType::FREQ_0;
attachInterrupt(sensor.gpio(), index == 0 ? freqIrq0 : index == 1 ? freqIrq1 : freqIrq2, FALLING); attachInterrupt(sensor.gpio(), index == 0 ? freqIrq0 : index == 1 ? freqIrq1 : freqIrq2, FALLING);
lastedge[index] = edge[index] = micros(); lastedge[index] = edge[index] = micros();
edgecnt[index] = 0; edgecnt[index] = 0;
} else if (sensor.type() >= AnalogType::CNT_0 && sensor.type() <= AnalogType::CNT_2) {
auto index = sensor.type() - AnalogType::CNT_0;
LOG_DEBUG("Counter %d on GPIO %02d", index, sensor.gpio());
if (double_t val = EMSESP::nvs_.getDouble(sensor.name().c_str(), 0)) {
sensor.set_value(val);
}
publish_sensor(sensor);
attachInterrupt(sensor.gpio(), index == 0 ? freqIrq0 : index == 1 ? freqIrq1 : freqIrq2, FALLING);
edgecnt[index] = 0;
#endif #endif
} else if (sensor.type() == AnalogType::DIGITAL_IN) { } else if (sensor.type() == AnalogType::DIGITAL_IN) {
LOG_DEBUG("Digital Read on GPIO %02d", sensor.gpio()); LOG_DEBUG("Digital Read on GPIO %02d", sensor.gpio());
pinMode(sensor.gpio(), INPUT_PULLUP);
sensor.set_value(digitalRead(sensor.gpio())); // initial value sensor.set_value(digitalRead(sensor.gpio())); // initial value
sensor.set_uom(0); // no uom, just for safe measures sensor.set_uom(0); // no uom, just for safe measures
sensor.polltime_ = 0; sensor.polltime_ = 0;
sensor.poll_ = digitalRead(sensor.gpio()); sensor.poll_ = digitalRead(sensor.gpio());
publish_sensor(sensor); publish_sensor(sensor);
} else if (sensor.type() == AnalogType::RGB) { } else if (sensor.type() == AnalogType::RGB) {
sensor.set_uom(0); // no uom
LOG_DEBUG("RGB on GPIO %02d", sensor.gpio()); LOG_DEBUG("RGB on GPIO %02d", sensor.gpio());
uint32_t v = sensor.value(); uint32_t v = sensor.value();
uint8_t r = v / 10000; uint8_t r = v / 10000;
@@ -295,7 +322,10 @@ void AnalogSensor::reload(bool get_nvs) {
} else { } else {
sensor.set_offset(EMSESP::nvs_.getChar(sensor.name().c_str())); sensor.set_offset(EMSESP::nvs_.getChar(sensor.name().c_str()));
} }
} else if (sensor.uom() > 1) {
sensor.set_uom(2);
} }
sensor.set_offset(sensor.offset() > 0 ? 1 : 0);
digitalWrite(sensor.gpio(), (sensor.offset() == 0) ^ (sensor.factor() > 0)); digitalWrite(sensor.gpio(), (sensor.offset() == 0) ^ (sensor.factor() > 0));
sensor.set_value(sensor.offset()); sensor.set_value(sensor.offset());
} }
@@ -393,6 +423,18 @@ void AnalogSensor::measure() {
changed_ = true; changed_ = true;
publish_sensor(sensor); publish_sensor(sensor);
} }
} else if (sensor.type() >= AnalogType::CNT_0 && sensor.type() <= AnalogType::CNT_2) {
auto index = sensor.type() - AnalogType::CNT_0;
auto oldval = sensor.value();
portENTER_CRITICAL_ISR(&mux);
auto c = edgecnt[index];
edgecnt[index] = 0;
portEXIT_CRITICAL_ISR(&mux);
sensor.set_value(oldval + sensor.factor() * c);
if (sensor.value() != oldval) {
changed_ = true;
publish_sensor(sensor);
}
#endif #endif
} }
} }
@@ -453,7 +495,7 @@ void AnalogSensor::measure() {
// store counters to NVS, called every hour, on restart and update // store counters to NVS, called every hour, on restart and update
void AnalogSensor::store_counters() { void AnalogSensor::store_counters() {
for (auto & sensor : sensors_) { for (auto & sensor : sensors_) {
if (sensor.type() == AnalogType::COUNTER) { if (sensor.type() == AnalogType::COUNTER || (sensor.type() >= AnalogType::CNT_0 && sensor.type() <= AnalogType::CNT_2)) {
if (sensor.value() != EMSESP::nvs_.getDouble(sensor.name().c_str())) { if (sensor.value() != EMSESP::nvs_.getDouble(sensor.name().c_str())) {
EMSESP::nvs_.putDouble(sensor.name().c_str(), sensor.value()); EMSESP::nvs_.putDouble(sensor.name().c_str(), sensor.value());
} }
@@ -746,7 +788,7 @@ void AnalogSensor::publish_values(const bool force) {
config["max"] = 999999; config["max"] = 999999;
config["mode"] = "box"; // auto, slider or box config["mode"] = "box"; // auto, slider or box
config["step"] = 1; config["step"] = 1;
} else if (sensor.type() == AnalogType::COUNTER) { } else if (sensor.type() == AnalogType::COUNTER || (sensor.type() >= AnalogType::CNT_0 && sensor.type() <= AnalogType::CNT_2)) {
snprintf(topic, sizeof(topic), "sensor/%s/%s_%02d/config", Mqtt::basename().c_str(), F_(analogsensor), sensor.gpio()); snprintf(topic, sizeof(topic), "sensor/%s/%s_%02d/config", Mqtt::basename().c_str(), F_(analogsensor), sensor.gpio());
snprintf(command_topic, sizeof(command_topic), "%s/%s/%s", Mqtt::base().c_str(), F_(analogsensor), sensor.name().c_str()); snprintf(command_topic, sizeof(command_topic), "%s/%s/%s", Mqtt::base().c_str(), F_(analogsensor), sensor.name().c_str());
config["cmd_t"] = command_topic; config["cmd_t"] = command_topic;
@@ -833,10 +875,10 @@ void AnalogSensor::get_value_json(JsonObject output, const Sensor & sensor) {
output["value"] = sensor.value(); output["value"] = sensor.value();
output["readable"] = true; output["readable"] = true;
output["writeable"] = sensor.type() == AnalogType::COUNTER || sensor.type() == AnalogType::RGB || sensor.type() == AnalogType::PULSE output["writeable"] = sensor.type() == AnalogType::COUNTER || sensor.type() == AnalogType::RGB || sensor.type() == AnalogType::PULSE
|| (sensor.type() >= AnalogType::DIGITAL_OUT && sensor.type() <= AnalogType::PWM_2); || (sensor.type() >= AnalogType::DIGITAL_OUT && sensor.type() <= AnalogType::PWM_2)|| (sensor.type() >= AnalogType::CNT_0 && sensor.type() <= AnalogType::CNT_2);
output["visible"] = true; output["visible"] = true;
output["is_system"] = sensor.is_system(); output["is_system"] = sensor.is_system();
if (sensor.type() == AnalogType::COUNTER) { if (sensor.type() == AnalogType::COUNTER|| (sensor.type() >= AnalogType::CNT_0 && sensor.type() <= AnalogType::CNT_2)) {
output["min"] = 0; output["min"] = 0;
output["max"] = 4000000; output["max"] = 4000000;
output["start_value"] = sensor.offset(); output["start_value"] = sensor.offset();
@@ -899,7 +941,7 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) {
for (auto & sensor : sensors_) { for (auto & sensor : sensors_) {
if (sensor.gpio() == gpio) { if (sensor.gpio() == gpio) {
double oldoffset = sensor.offset(); double oldoffset = sensor.offset();
if (sensor.type() == AnalogType::COUNTER) { if (sensor.type() == AnalogType::COUNTER || (sensor.type() >= AnalogType::CNT_0 && sensor.type() <= AnalogType::CNT_2)) {
if (val < 0 || value[0] == '+') { // sign corrects values if (val < 0 || value[0] == '+') { // sign corrects values
// sensor.set_offset(sensor.value() + val); // sensor.set_offset(sensor.value() + val);
sensor.set_value(sensor.value() + val); sensor.set_value(sensor.value() + val);

View File

@@ -132,7 +132,10 @@ class AnalogSensor {
PULSE = 12, PULSE = 12,
FREQ_0 = 13, FREQ_0 = 13,
FREQ_1 = 14, FREQ_1 = 14,
FREQ_2 = 15 FREQ_2 = 15,
CNT_0 = 16,
CNT_1 = 17,
CNT_2 = 18
}; };
void start(const bool factory_settings = false); void start(const bool factory_settings = false);
@@ -174,6 +177,9 @@ class AnalogSensor {
bool update(uint8_t gpio, std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted, bool is_system); bool update(uint8_t gpio, std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted, bool is_system);
bool get_value_info(JsonObject output, const char * cmd, const int8_t id = -1); bool get_value_info(JsonObject output, const char * cmd, const int8_t id = -1);
void store_counters(); void store_counters();
static std::vector<uint8_t> exclude_types() {
return exclude_types_;
}
private: private:
static constexpr double Beta = 4260; static constexpr double Beta = 4260;
@@ -185,7 +191,6 @@ class AnalogSensor {
static constexpr uint32_t MEASURE_ANALOG_INTERVAL = 500; static constexpr uint32_t MEASURE_ANALOG_INTERVAL = 500;
static uuid::log::Logger logger_; static uuid::log::Logger logger_;
void remove_ha_topic(const int8_t type, const uint8_t id) const; void remove_ha_topic(const int8_t type, const uint8_t id) const;
bool command_setvalue(const char * value, const int8_t gpio); bool command_setvalue(const char * value, const int8_t gpio);
void measure(); void measure();
@@ -193,6 +198,7 @@ class AnalogSensor {
void get_value_json(JsonObject output, const Sensor & sensor); void get_value_json(JsonObject output, const Sensor & sensor);
std::vector<Sensor> sensors_; // our list of sensors std::vector<Sensor> sensors_; // our list of sensors
static std::vector<uint8_t> exclude_types_;
bool analog_enabled_; bool analog_enabled_;
bool changed_ = true; // this will force a publish of all sensors when initialising bool changed_ = true; // this will force a publish of all sensors when initialising

View File

@@ -158,6 +158,12 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) {
available_gpios.add(gpio); available_gpios.add(gpio);
} }
// disable types that can only be used once
JsonArray exclude_types = root["exclude_types"].to<JsonArray>();
for (uint8_t type : EMSESP::analogsensor_.exclude_types()) {
exclude_types.add(type);
}
response->setLength(); response->setLength();
request->send(response); request->send(response);
} }
@@ -462,7 +468,8 @@ void WebDataService::dashboard_data(AsyncWebServerRequest * request) {
} }
if (sensor.type() == AnalogSensor::AnalogType::COUNTER if (sensor.type() == AnalogSensor::AnalogType::COUNTER
|| (sensor.type() >= AnalogSensor::AnalogType::DIGITAL_OUT && sensor.type() <= AnalogSensor::AnalogType::PWM_2) || (sensor.type() >= AnalogSensor::AnalogType::DIGITAL_OUT && sensor.type() <= AnalogSensor::AnalogType::PWM_2)
|| sensor.type() == AnalogSensor::AnalogType::RGB || sensor.type() == AnalogSensor::AnalogType::PULSE) { || sensor.type() == AnalogSensor::AnalogType::RGB || sensor.type() == AnalogSensor::AnalogType::PULSE
|| (sensor.type() >= AnalogSensor::AnalogType::CNT_0 && sensor.type() <= AnalogSensor::AnalogType::CNT_2)) {
dv["c"] = sensor.name(); dv["c"] = sensor.name();
} }
} }