analogsensors, outputs PWM, DAC, digital

This commit is contained in:
MichaelDvP
2022-02-16 18:35:25 +01:00
parent 7f5e0f7244
commit 073493cba2
11 changed files with 433 additions and 123 deletions

View File

@@ -59,7 +59,8 @@ import {
DeviceValue, DeviceValue,
DeviceValueUOM, DeviceValueUOM,
DeviceValueUOM_s, DeviceValueUOM_s,
AnalogTypes, AnalogType,
AnalogTypeNames,
Sensor, Sensor,
Analog Analog
} from './types'; } from './types';
@@ -715,7 +716,7 @@ const DashboardData: FC = () => {
))} ))}
</ValidatedTextField> </ValidatedTextField>
</Grid> </Grid>
{analog.t === 3 && ( {analog.t >= AnalogType.COUNTER && analog.t <= AnalogType.RATE && (
<> <>
<Grid item> <Grid item>
<ValidatedTextField name="u" label="UoM" value={analog.u} select onChange={updateValue(setAnalog)}> <ValidatedTextField name="u" label="UoM" value={analog.u} select onChange={updateValue(setAnalog)}>
@@ -726,7 +727,7 @@ const DashboardData: FC = () => {
))} ))}
</ValidatedTextField> </ValidatedTextField>
</Grid> </Grid>
<Grid item></Grid> {analog.t === AnalogType.ADC && (
<Grid item> <Grid item>
<ValidatedTextField <ValidatedTextField
name="o" name="o"
@@ -738,10 +739,25 @@ const DashboardData: FC = () => {
onChange={updateValue(setAnalog)} onChange={updateValue(setAnalog)}
inputProps={{ min: '0', max: '3300', step: '1' }} inputProps={{ min: '0', max: '3300', step: '1' }}
InputProps={{ InputProps={{
endAdornment: <InputAdornment position="end">mV</InputAdornment> startAdornment: <InputAdornment position="start">mV</InputAdornment>
}} }}
/> />
</Grid> </Grid>
)}
{analog.t === AnalogType.COUNTER && (
<Grid item>
<ValidatedTextField
name="o"
label="Start Value"
value={numberValue(analog.o)}
sx={{ width: '20ch' }}
type="number"
variant="outlined"
onChange={updateValue(setAnalog)}
inputProps={{ min: '0', step: '1' }}
/>
</Grid>
)}
<Grid item> <Grid item>
<ValidatedTextField <ValidatedTextField
name="f" name="f"
@@ -756,6 +772,73 @@ const DashboardData: FC = () => {
</Grid> </Grid>
</> </>
)} )}
{analog.t === AnalogType.DIGITAL_OUT && (analog.i === 25 || analog.i === 26) && (
<>
<Grid item>
<ValidatedTextField
name="o"
label="DAC Value"
value={numberValue(analog.o)}
sx={{ width: '20ch' }}
type="number"
variant="outlined"
onChange={updateValue(setAnalog)}
inputProps={{ min: '0', max: '255', step: '1' }}
/>
</Grid>
</>
)}
{analog.t === AnalogType.DIGITAL_OUT && analog.i !== 25 && analog.i !== 26 && (
<>
<Grid item>
<ValidatedTextField
name="o"
label="Value"
value={numberValue(analog.o)}
sx={{ width: '20ch' }}
type="number"
variant="outlined"
onChange={updateValue(setAnalog)}
inputProps={{ min: '0', max: '1', step: '1' }}
/>
</Grid>
</>
)}
{analog.t >= AnalogType.PWM_0 && (
<>
<Grid item>
<ValidatedTextField
name="f"
label="Frequency"
value={numberValue(analog.f)}
sx={{ width: '20ch' }}
type="number"
variant="outlined"
onChange={updateValue(setAnalog)}
inputProps={{ min: '1', max: '5000', step: '1' }}
InputProps={{
startAdornment: <InputAdornment position="start">Hz</InputAdornment>
}}
/>
</Grid>
<Grid item>
<ValidatedTextField
name="o"
label="Dutycycle"
value={numberValue(analog.o)}
sx={{ width: '20ch' }}
type="number"
variant="outlined"
onChange={updateValue(setAnalog)}
inputProps={{ min: '0', max: '100', step: '0.1' }}
InputProps={{
startAdornment: <InputAdornment position="start">%</InputAdornment>
}}
/>
</Grid>
</>
)}
</Grid> </Grid>
<Box color="warning.main" mt={2}> <Box color="warning.main" mt={2}>
<Typography variant="body2">Warning: be careful when assigning a GPIO!</Typography> <Typography variant="body2">Warning: be careful when assigning a GPIO!</Typography>

View File

@@ -176,7 +176,9 @@ export enum DeviceValueUOM {
DBM, DBM,
FAHRENHEIT, FAHRENHEIT,
MV, MV,
SQM SQM,
M3,
L
} }
export const DeviceValueUOM_s = [ export const DeviceValueUOM_s = [
@@ -199,10 +201,36 @@ export const DeviceValueUOM_s = [
'°F', '°F',
'mV', 'mV',
'sqm', 'sqm',
"o'clock" "m3",
"l"
];
export enum AnalogType {
NOTUSED = 0,
DIGITAL_IN,
COUNTER,
ADC,
TIMER,
RATE,
DIGITAL_OUT,
PWM_0,
PWM_1,
PWM_2
}
export const AnalogTypeNames = [
'(disabled)',
'Digital in',
'Counter',
'ADC',
'Timer',
'Rate',
'Digital out',
'PWM 0',
'PWM 1',
'PWM 2'
]; ];
export const AnalogTypes = ['(disabled)', 'Digital in', 'Counter', 'ADC'];
type BoardProfiles = { type BoardProfiles = {
[name: string]: string; [name: string]: string;

View File

@@ -27,7 +27,7 @@ void AnalogSensor::start() {
reload(); // fetch the list of sensors from our customization service reload(); // fetch the list of sensors from our customization service
if (analog_enabled_) { if (analog_enabled_) {
analogSetAttenuation(ADC_2_5db); // for all channels analogSetAttenuation(ADC_2_5db); // for all channels 1.5V
} }
LOG_INFO(F("Starting Analog sensor service")); LOG_INFO(F("Starting Analog sensor service"));
@@ -40,10 +40,15 @@ void AnalogSensor::start() {
F_(info_cmd)); F_(info_cmd));
Command::add( Command::add(
EMSdevice::DeviceType::ANALOGSENSOR, EMSdevice::DeviceType::ANALOGSENSOR,
F_(counter), F_(setvalue),
[&](const char * value, const int8_t id) { return command_counter(value, id); }, [&](const char * value, const int8_t id) { return command_setvalue(value, id); },
F("set counter value"), F("set io value"),
CommandFlag::ADMIN_ONLY); CommandFlag::ADMIN_ONLY);
Command::add(
EMSdevice::DeviceType::ANALOGSENSOR,
F_(commands),
[&](const char * value, const int8_t id, JsonObject & output) { return command_commands(value, id, output); },
F_(commands_cmd));
} }
// load settings from the customization file, sorts them and initializes the GPIOs // load settings from the customization file, sorts them and initializes the GPIOs
@@ -58,11 +63,47 @@ void AnalogSensor::reload() {
// and store them locally and then activate them // and store them locally and then activate them
EMSESP::webCustomizationService.read([&](WebCustomization & settings) { EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
auto sensors = settings.analogCustomizations; auto sensors = settings.analogCustomizations;
sensors_.clear(); // start with an empty list auto it = sensors_.begin();
if (sensors.size() != 0) { for (auto & sensor_ : sensors_) {
// update existing sensors
bool found = false;
for (auto & sensor : sensors) { //search customlist
if (sensor_.id() == sensor.id) {
// for output sensors set value to new start-value
if ((sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT)
&& (sensor_.type() != sensor.type || sensor_.offset() != sensor.offset || sensor_.factor() != sensor.factor)) {
sensor_.set_value(sensor.offset);
}
sensor_.set_name(sensor.name);
sensor_.set_type(sensor.type);
sensor_.set_offset(sensor.offset);
sensor_.set_factor(sensor.factor);
sensor_.set_uom(sensor.uom);
sensor_.ha_registered = false;
found = true;
}
}
if (!found) {
sensors_.erase(it);
}
it++;
}
// add new sensors from list
for (auto & sensor : sensors) { for (auto & sensor : sensors) {
bool found = false;
for (auto & sensor_ : sensors_) {
if (sensor_.id() == sensor.id) {
found = true;
}
}
if (!found) {
sensors_.emplace_back(sensor.id, sensor.name, sensor.offset, sensor.factor, sensor.uom, sensor.type); sensors_.emplace_back(sensor.id, sensor.name, sensor.offset, sensor.factor, sensor.uom, sensor.type);
sensors_.back().ha_registered = false; // this will trigger recrate of the HA config sensors_.back().ha_registered = false; // this will trigger recrate of the HA config
if (sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT) {
sensors_.back().set_value(sensor.offset);
} else {
sensors_.back().set_value(0); // reset value only for new sensors
}
} }
} }
return true; return true;
@@ -82,11 +123,21 @@ void AnalogSensor::reload() {
} else if (sensor.type() == AnalogType::COUNTER) { } else if (sensor.type() == AnalogType::COUNTER) {
LOG_DEBUG(F("Adding analog I/O Counter sensor on GPIO%d"), sensor.id()); LOG_DEBUG(F("Adding analog I/O Counter sensor on GPIO%d"), sensor.id());
pinMode(sensor.id(), INPUT_PULLUP); pinMode(sensor.id(), INPUT_PULLUP);
sensor.set_value(0); // reset count if (sensor.id() == 25 || sensor.id() == 26) {
sensor.set_uom(0); // no uom, just for safe measures dacWrite(sensor.id(), 255);
}
sensor.polltime_ = 0; sensor.polltime_ = 0;
sensor.poll_ = digitalRead(sensor.id()); sensor.poll_ = digitalRead(sensor.id());
publish_sensor(sensor); publish_sensor(sensor);
} else if (sensor.type() == AnalogType::TIMER || sensor.type() == AnalogType::RATE) {
LOG_DEBUG(F("Adding analog Timer/Rate sensor on GPIO%d"), sensor.id());
pinMode(sensor.id(), INPUT_PULLUP);
sensor.polltime_ = uuid::get_uptime();
sensor.last_polltime_ = uuid::get_uptime();
sensor.poll_ = digitalRead(sensor.id());
sensor.set_offset(0);
sensor.set_value(0);
publish_sensor(sensor);
} else if (sensor.type() == AnalogType::DIGITAL_IN) { } else if (sensor.type() == AnalogType::DIGITAL_IN) {
LOG_DEBUG(F("Adding analog Read sensor on GPIO%d"), sensor.id()); LOG_DEBUG(F("Adding analog Read sensor on GPIO%d"), sensor.id());
pinMode(sensor.id(), INPUT_PULLUP); pinMode(sensor.id(), INPUT_PULLUP);
@@ -95,18 +146,49 @@ void AnalogSensor::reload() {
sensor.polltime_ = 0; sensor.polltime_ = 0;
sensor.poll_ = digitalRead(sensor.id()); sensor.poll_ = digitalRead(sensor.id());
publish_sensor(sensor); publish_sensor(sensor);
} else if (sensor.type() == AnalogType::DIGITAL_OUT) {
LOG_DEBUG(F("Adding analog Write sensor on GPIO%d"), sensor.id());
pinMode(sensor.id(), OUTPUT);
if (sensor.id() == 25 || sensor.id() == 26) {
if (sensor.offset() > 255) {
sensor.set_offset(255);
} else if (sensor.offset() < 0) {
sensor.set_offset(0);
}
dacWrite(sensor.id(), sensor.offset());
sensor.set_value(sensor.offset());
} else {
digitalWrite(sensor.id(), sensor.offset() > 0 ? 1 : 0);
sensor.set_value(digitalRead(sensor.id()));
}
sensor.set_uom(0); // no uom, just for safe measures
publish_sensor(sensor);
} else if (sensor.type() >= AnalogType::PWM_0) {
LOG_DEBUG(F("Adding PWM output sensor on GPIO%d"), sensor.id());
uint channel = sensor.type() - AnalogType::PWM_0;
ledcSetup(channel, sensor.factor(), 13);
ledcAttachPin(sensor.id(), channel);
if (sensor.offset() > 100) {
sensor.set_offset(100);
} else if (sensor.offset() < 0) {
sensor.set_offset(0);
}
ledcWrite(channel, (uint32_t)(sensor.offset() * 8191 / 100));
sensor.set_value(sensor.offset());
sensor.set_uom(DeviceValueUOM::PERCENT);
publish_sensor(sensor);
} }
} }
} }
// measure and moving average adc // measure input sensors and moving average adc
void AnalogSensor::measure() { void AnalogSensor::measure() {
static uint32_t measure_last_ = 0; static uint32_t measure_last_ = 0;
// measure interval 500ms for analog sensors // measure interval 500ms for adc sensors
if (!measure_last_ || (uuid::get_uptime() - measure_last_) >= MEASURE_ANALOG_INTERVAL) { if (!measure_last_ || (uuid::get_uptime() - measure_last_) >= MEASURE_ANALOG_INTERVAL) {
measure_last_ = uuid::get_uptime(); measure_last_ = uuid::get_uptime();
// go through the list of ADC sensors // go through the list of adc sensors
for (auto & sensor : sensors_) { for (auto & sensor : sensors_) {
if (sensor.type() == AnalogType::ADC) { if (sensor.type() == AnalogType::ADC) {
uint16_t a = analogReadMilliVolts(sensor.id()); // e.g. ADC1_CHANNEL_0_GPIO_NUM uint16_t a = analogReadMilliVolts(sensor.id()); // e.g. ADC1_CHANNEL_0_GPIO_NUM
@@ -128,26 +210,31 @@ void AnalogSensor::measure() {
} }
} }
} }
// poll digital io every time // poll digital io every time with debounce
// go through the list of digital sensors // go through the list of digital sensors
for (auto & sensor : sensors_) { for (auto & sensor : sensors_) {
if (sensor.type() == AnalogType::DIGITAL_IN || sensor.type() == AnalogType::COUNTER) { if (sensor.type() == AnalogType::DIGITAL_IN || sensor.type() == AnalogType::COUNTER || sensor.type() == AnalogType::TIMER
|| sensor.type() == AnalogType::RATE) {
auto old_value = sensor.value(); // remember current value before reading auto old_value = sensor.value(); // remember current value before reading
auto current_reading = digitalRead(sensor.id()); auto current_reading = digitalRead(sensor.id());
if (sensor.poll_ != current_reading) { // check for pinchange if (sensor.poll_ != current_reading) { // check for pinchange
sensor.polltime_ = uuid::get_uptime(); sensor.polltime_ = uuid::get_uptime(); // remember time of pinchange
sensor.poll_ = current_reading; sensor.poll_ = current_reading;
} }
if (uuid::get_uptime() - sensor.polltime_ >= 15) { // debounce // debounce and check for real pinchange
if (uuid::get_uptime() - sensor.polltime_ >= 15 && sensor.poll_ != sensor.last_reading_) {
sensor.last_reading_ = sensor.poll_;
if (sensor.type() == AnalogType::DIGITAL_IN) { if (sensor.type() == AnalogType::DIGITAL_IN) {
sensor.set_value(sensor.poll_); sensor.set_value(sensor.poll_);
} else if (sensor.type() == AnalogType::COUNTER) { } else if (!sensor.poll_) { // falling edge
// capture reading and compare with the last one to see if there is high/low change if (sensor.type() == AnalogType::COUNTER) {
if (sensor.poll_ != sensor.last_reading_) { sensor.set_value(old_value + sensor.factor());
sensor.last_reading_ = sensor.poll_; } else if (sensor.type() == AnalogType::RATE) { // dafault uom: Hz (1/sec) with factor 1
if (!sensor.poll_) { sensor.set_value(sensor.factor() * 1000 / (sensor.polltime_ - sensor.last_polltime_));
sensor.set_value(old_value + 1); } else if (sensor.type() == AnalogType::TIMER) { // default seconds with factor 1
sensor.set_value(sensor.factor() * (sensor.polltime_ - sensor.last_polltime_) / 1000);
} }
sensor.last_polltime_ = sensor.polltime_;
} }
} }
// see if there is a change and increment # reads // see if there is a change and increment # reads
@@ -158,7 +245,6 @@ void AnalogSensor::measure() {
} }
} }
} }
}
} }
void AnalogSensor::loop() { void AnalogSensor::loop() {
@@ -170,7 +256,7 @@ void AnalogSensor::loop() {
} }
// update analog information name and offset // update analog information name and offset
bool AnalogSensor::update(uint8_t id, const std::string & name, uint16_t offset, float factor, uint8_t uom, int8_t type) { bool AnalogSensor::update(uint8_t id, const std::string & name, float offset, float factor, uint8_t uom, int8_t type) {
boolean found_sensor = false; // see if we can find the sensor in our customization list boolean found_sensor = false; // see if we can find the sensor in our customization list
EMSESP::webCustomizationService.update( EMSESP::webCustomizationService.update(
@@ -240,7 +326,11 @@ bool AnalogSensor::updated_values() {
void AnalogSensor::publish_sensor(const Sensor & sensor) { void AnalogSensor::publish_sensor(const Sensor & sensor) {
if (Mqtt::publish_single()) { if (Mqtt::publish_single()) {
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
if (Mqtt::publish_single2cmd()) {
snprintf(topic, sizeof(topic), "%s/%s", read_flash_string(F_(analogsensor)).c_str(), sensor.name().c_str()); snprintf(topic, sizeof(topic), "%s/%s", read_flash_string(F_(analogsensor)).c_str(), sensor.name().c_str());
} else {
snprintf(topic, sizeof(topic), "%s%s/%s", read_flash_string(F_(analogsensor)).c_str(), "_data", sensor.name().c_str());
}
char payload[10]; char payload[10];
Mqtt::publish(topic, Helpers::render_value(payload, sensor.value(), 2)); // always publish as floats Mqtt::publish(topic, Helpers::render_value(payload, sensor.value(), 2)); // always publish as floats
} }
@@ -285,12 +375,16 @@ void AnalogSensor::publish_values(const bool force) {
dataSensor["name"] = sensor.name(); dataSensor["name"] = sensor.name();
switch (sensor.type()) { switch (sensor.type()) {
case AnalogType::COUNTER: case AnalogType::COUNTER:
dataSensor["value"] = (uint16_t)sensor.value(); // convert to integer case AnalogType::TIMER:
break; case AnalogType::RATE:
case AnalogType::ADC: case AnalogType::ADC:
case AnalogType::PWM_0:
case AnalogType::PWM_1:
case AnalogType::PWM_2:
dataSensor["value"] = (float)sensor.value(); // float dataSensor["value"] = (float)sensor.value(); // float
break; break;
case AnalogType::DIGITAL_IN: case AnalogType::DIGITAL_IN:
case AnalogType::DIGITAL_OUT:
default: default:
dataSensor["value"] = (uint8_t)sensor.value(); // convert to char for 1 or 0 dataSensor["value"] = (uint8_t)sensor.value(); // convert to char for 1 or 0
break; break;
@@ -373,6 +467,15 @@ bool AnalogSensor::command_info(const char * value, const int8_t id, JsonObject
dataSensor["uom"] = EMSdevice::uom_to_string(sensor.uom()); dataSensor["uom"] = EMSdevice::uom_to_string(sensor.uom());
dataSensor["offset"] = sensor.offset(); dataSensor["offset"] = sensor.offset();
dataSensor["factor"] = sensor.factor(); dataSensor["factor"] = sensor.factor();
} else if (sensor.type() == AnalogType::COUNTER) {
dataSensor["uom"] = EMSdevice::uom_to_string(sensor.uom());
dataSensor["start_value"] = sensor.offset();
dataSensor["factor"] = sensor.factor();
} else if (sensor.type() == AnalogType::TIMER || sensor.type() == AnalogType::RATE) {
dataSensor["factor"] = sensor.factor();
} else if (sensor.type() >= AnalogType::PWM_0) {
dataSensor["uom"] = EMSdevice::uom_to_string(sensor.uom());
dataSensor["frequency"] = sensor.factor();
} }
dataSensor["value"] = sensor.value(); dataSensor["value"] = sensor.value();
} else { } else {
@@ -384,7 +487,7 @@ bool AnalogSensor::command_info(const char * value, const int8_t id, JsonObject
} }
// this creates the sensor, initializing everything // this creates the sensor, initializing everything
AnalogSensor::Sensor::Sensor(const uint8_t id, const std::string & name, const uint16_t offset, const float factor, const uint8_t uom, const int8_t type) AnalogSensor::Sensor::Sensor(const uint8_t id, const std::string & name, const float offset, const float factor, const uint8_t uom, const int8_t type)
: id_(id) : id_(id)
, name_(name) , name_(name)
, offset_(offset) , offset_(offset)
@@ -405,28 +508,70 @@ std::string AnalogSensor::Sensor::name() const {
} }
// set the counter value, id is gpio-no // set the counter value, id is gpio-no
bool AnalogSensor::command_counter(const char * value, const int8_t id) { bool AnalogSensor::command_setvalue(const char * value, const int8_t id) {
int val; float val;
if (!Helpers::value2number(value, val)) { if (!Helpers::value2float(value, val)) {
return false; return false;
} }
for (auto & sensor : sensors_) { for (auto & sensor : sensors_) {
if (sensor.type() == AnalogType::COUNTER && sensor.id() == id) { if (sensor.id() == id) {
if (val < 0) { // negative values corrects if (sensor.type() == AnalogType::COUNTER) {
if (val < 0 || value[0] == '+') { // sign corrects values
sensor.set_offset(sensor.value() + val);
sensor.set_value(sensor.value() + val); sensor.set_value(sensor.value() + val);
} else { // positive values are set } else { // positive values are set
sensor.set_offset(val);
sensor.set_value(val); sensor.set_value(val);
} }
publish_sensor(sensor);
return true; return true;
} else if (sensor.type() == AnalogType::ADC) {
sensor.set_offset(val);
return true;
} else if (sensor.type() == AnalogType::DIGITAL_OUT) {
uint8_t v = val;
if ((sensor.id() == 25 || sensor.id() == 26) && v <= 255) {
sensor.set_offset(v);
sensor.set_value(v);
pinMode(sensor.id(), OUTPUT);
dacWrite(sensor.id(), sensor.offset());
publish_sensor(sensor);
return true;
} else if (v == 0 || v == 1) {
sensor.set_offset(v);
sensor.set_value(v);
pinMode(sensor.id(), OUTPUT);
digitalWrite(sensor.id(), sensor.offset() > 0 ? 1 : 0);
publish_sensor(sensor);
return true;
}
} else if (sensor.type() >= AnalogType::PWM_0) {
uint8_t channel = sensor.type() - AnalogType::PWM_0;
if (val > 100) {
val = 100;
} else if (val < 0) {
val = 0;
}
sensor.set_offset(val);
sensor.set_value(val);
ledcWrite(channel, (uint32_t)(val * 8191 / 100));
publish_sensor(sensor);
return true;
}
} }
} }
return false; return false;
} }
// list commands
bool AnalogSensor::command_commands(const char * value, const int8_t id, JsonObject & output) {
return Command::list(EMSdevice::DeviceType::ANALOGSENSOR, output);
}
// hard coded tests // hard coded tests
#ifdef EMSESP_DEBUG #ifdef EMSESP_DEBUG
void AnalogSensor::test() { void AnalogSensor::test() {
// Sensor(const uint8_t id, const std::string & name, const uint16_t offset, const float factor, const uint8_t uom, const int8_t type); // Sensor(const uint8_t id, const std::string & name, const float offset, const float factor, const uint8_t uom, const int8_t type);
sensors_.emplace_back(36, "test12", 0, 0.1, 17, AnalogType::ADC); sensors_.emplace_back(36, "test12", 0, 0.1, 17, AnalogType::ADC);
sensors_.back().set_value(12.4); sensors_.back().set_value(12.4);

View File

@@ -36,10 +36,10 @@ class AnalogSensor {
public: public:
class Sensor { class Sensor {
public: public:
Sensor(const uint8_t id, const std::string & name, const uint16_t offset, const float factor, const uint8_t uom, const int8_t type); Sensor(const uint8_t id, const std::string & name, const float offset, const float factor, const uint8_t uom, const int8_t type);
~Sensor() = default; ~Sensor() = default;
void set_offset(const uint16_t offset) { void set_offset(const float offset) {
offset_ = offset; offset_ = offset;
} }
@@ -68,7 +68,7 @@ class AnalogSensor {
factor_ = factor; factor_ = factor;
} }
uint16_t offset() const { float offset() const {
return offset_; return offset_;
} }
@@ -93,13 +93,15 @@ class AnalogSensor {
uint16_t analog_ = 0; // ADC - average value uint16_t analog_ = 0; // ADC - average value
uint32_t sum_ = 0; // ADC - rolling sum uint32_t sum_ = 0; // ADC - rolling sum
uint16_t last_reading_ = 0; // IO COUNTER & ADC - last reading 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 uint32_t polltime_ = 0; // digital IO & COUNTER debounce time
int poll_ = 0; int poll_ = 0;
uint32_t last_polltime_ = 0; // for timer
private: private:
uint8_t id_; uint8_t id_;
std::string name_; std::string name_;
uint16_t offset_; float offset_;
float factor_; float factor_;
uint8_t uom_; uint8_t uom_;
float value_; // float because of the factor is a float float value_; // float because of the factor is a float
@@ -112,9 +114,15 @@ class AnalogSensor {
enum AnalogType : int8_t { enum AnalogType : int8_t {
MARK_DELETED = -1, // mark for deletion MARK_DELETED = -1, // mark for deletion
NOTUSED, // 0 - disabled NOTUSED, // 0 - disabled
DIGITAL_IN, // 1 DIGITAL_IN,
COUNTER, // 2 COUNTER,
ADC // 3 ADC,
TIMER,
RATE,
DIGITAL_OUT,
PWM_0,
PWM_1,
PWM_2
}; };
void start(); void start();
@@ -149,7 +157,7 @@ class AnalogSensor {
return sensors_.size(); return sensors_.size();
} }
bool update(uint8_t id, const std::string & name, uint16_t offset, float factor, uint8_t uom, int8_t type); bool update(uint8_t id, const std::string & name, float offset, float factor, uint8_t uom, int8_t type);
bool get_value_info(JsonObject & output, const char * cmd, const int8_t id); bool get_value_info(JsonObject & output, const char * cmd, const int8_t id);
#ifdef EMSESP_DEBUG #ifdef EMSESP_DEBUG
@@ -163,9 +171,10 @@ class AnalogSensor {
static uuid::log::Logger logger_; static uuid::log::Logger logger_;
void remove_ha_topic(const uint8_t id); void remove_ha_topic(const uint8_t id);
bool command_counter(const char * value, const int8_t id); bool command_setvalue(const char * value, const int8_t id);
void measure(); void measure();
bool command_info(const char * value, const int8_t id, JsonObject & output); bool command_info(const char * value, const int8_t id, JsonObject & output);
bool command_commands(const char * value, const int8_t id, JsonObject & output);
std::vector<Sensor> sensors_; // our list of sensors std::vector<Sensor> sensors_; // our list of sensors

View File

@@ -66,7 +66,9 @@ class DeviceValue {
DBM, // 15 DBM, // 15
FAHRENHEIT, // 16 FAHRENHEIT, // 16
MV, // 17 MV, // 17
SQM // 18 SQM, // 18 squaremeter
M3, // 19 cubic meter
L // 20
}; };
// TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp // TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp

View File

@@ -526,6 +526,10 @@ bool Helpers::value2float(const char * v, float & value) {
value = atof((char *)v); value = atof((char *)v);
return true; return true;
} }
if (v[0] == '+' && (v[1] == '.' || (v[1] >= '0' && v[1] <= '9'))) {
value = atof((char *)(v + 1));
return true;
}
return false; return false;
} }

View File

@@ -70,7 +70,7 @@ MAKE_PSTR_WORD(pin)
MAKE_PSTR_WORD(publish) MAKE_PSTR_WORD(publish)
MAKE_PSTR_WORD(timeout) MAKE_PSTR_WORD(timeout)
MAKE_PSTR_WORD(board_profile) MAKE_PSTR_WORD(board_profile)
MAKE_PSTR_WORD(counter) MAKE_PSTR_WORD(setvalue)
// for commands // for commands
MAKE_PSTR_WORD(call) MAKE_PSTR_WORD(call)
@@ -121,7 +121,7 @@ MAKE_STR(productid_fmt, "%s EMS ProductID")
MAKE_PSTR_LIST(enum_syslog_level, F_(off), F("emerg"), F("alert"), F("crit"), F_(error), F("warn"), F("notice"), F_(info), F_(debug), F("trace"), F("all")) MAKE_PSTR_LIST(enum_syslog_level, F_(off), F("emerg"), F("alert"), F("crit"), F_(error), F("warn"), F("notice"), F_(info), F_(debug), F("trace"), F("all"))
MAKE_PSTR_LIST(enum_watch, F_(off), F_(on), F_(raw), F_(unknown)) MAKE_PSTR_LIST(enum_watch, F_(off), F_(on), F_(raw), F_(unknown))
MAKE_PSTR_LIST(enum_sensortype, F("none"), F("digital in"), F("counter"), F("adc")) MAKE_PSTR_LIST(enum_sensortype, F("none"), F("digital in"), F("counter"), F("adc"), F("timer"), F("rate"), F("digital out"), F("pwm 0"), F("pwm 1"), F("pwm 2"))
// strings // strings
MAKE_PSTR(EMSESP, "EMS-ESP") MAKE_PSTR(EMSESP, "EMS-ESP")
@@ -196,6 +196,8 @@ MAKE_PSTR(dbm, "dBm")
MAKE_PSTR(fahrenheit, "°F") MAKE_PSTR(fahrenheit, "°F")
MAKE_PSTR(mv, "mV") MAKE_PSTR(mv, "mV")
MAKE_PSTR(sqm, "sqm") MAKE_PSTR(sqm, "sqm")
MAKE_PSTR(m3, "m3")
MAKE_PSTR(l, "l")
// MAKE_PSTR(times, "mal") // MAKE_PSTR(times, "mal")
// MAKE_PSTR(oclock, "Uhr") // MAKE_PSTR(oclock, "Uhr")
@@ -585,6 +587,9 @@ MAKE_PSTR_LIST(mode, F("mode"), F("modus"))
MAKE_PSTR_LIST(modetype, F("modetype"), F("modus Typ")) MAKE_PSTR_LIST(modetype, F("modetype"), F("modus Typ"))
MAKE_PSTR_LIST(fastheatup, F("fastheatup"), F("fast heatup")) MAKE_PSTR_LIST(fastheatup, F("fastheatup"), F("fast heatup"))
MAKE_PSTR_LIST(daytemp, F("daytemp"), F("Tagestemperatur")) MAKE_PSTR_LIST(daytemp, F("daytemp"), F("Tagestemperatur"))
MAKE_PSTR_LIST(daylowtemp, F("daytemp2"), F("Tagestemperatur T2"))
MAKE_PSTR_LIST(daymidtemp, F("daytemp3"), F("Tagestemperatur T3"))
MAKE_PSTR_LIST(dayhightemp, F("daytemp4"), F("Tagestemperatur T4"))
MAKE_PSTR_LIST(heattemp, F("heattemp"), F("Heizen Temperatur")) MAKE_PSTR_LIST(heattemp, F("heattemp"), F("Heizen Temperatur"))
MAKE_PSTR_LIST(nighttemp, F("nighttemp"), F("Nachttemperatur")) MAKE_PSTR_LIST(nighttemp, F("nighttemp"), F("Nachttemperatur"))
MAKE_PSTR_LIST(ecotemp, F("ecotemp"), F("eco Temperatur")) MAKE_PSTR_LIST(ecotemp, F("ecotemp"), F("eco Temperatur"))
@@ -597,7 +602,8 @@ MAKE_PSTR_LIST(offsettemp, F("offsettemp"), F("Temperaturanhebung"))
MAKE_PSTR_LIST(minflowtemp, F("minflowtemp"), F("min Flusstemperatur")) MAKE_PSTR_LIST(minflowtemp, F("minflowtemp"), F("min Flusstemperatur"))
MAKE_PSTR_LIST(maxflowtemp, F("maxflowtemp"), F("max Flusstemperatur")) MAKE_PSTR_LIST(maxflowtemp, F("maxflowtemp"), F("max Flusstemperatur"))
MAKE_PSTR_LIST(roominfluence, F("roominfluence"), F("Raumeinfluss")) MAKE_PSTR_LIST(roominfluence, F("roominfluence"), F("Raumeinfluss"))
MAKE_PSTR_LIST(curroominfl, F("curroominfl"), F("current room influence")) MAKE_PSTR_LIST(roominfl_factor, F("roominflfactor"), F("Raumeinfluss Factor"))
MAKE_PSTR_LIST(curroominfl, F("curroominfl"), F("aktueller Raumeinfluss"))
MAKE_PSTR_LIST(nofrosttemp, F("nofrosttemp"), F("Frostschutztemperatur")) MAKE_PSTR_LIST(nofrosttemp, F("nofrosttemp"), F("Frostschutztemperatur"))
MAKE_PSTR_LIST(targetflowtemp, F("targetflowtemp"), F("berechnete Flusstemperatur")) MAKE_PSTR_LIST(targetflowtemp, F("targetflowtemp"), F("berechnete Flusstemperatur"))
MAKE_PSTR_LIST(heatingtype, F("heatingtype"), F("Heizungstyp")) MAKE_PSTR_LIST(heatingtype, F("heatingtype"), F("Heizungstyp"))

View File

@@ -70,7 +70,7 @@ MAKE_PSTR_WORD(pin)
MAKE_PSTR_WORD(publish) MAKE_PSTR_WORD(publish)
MAKE_PSTR_WORD(timeout) MAKE_PSTR_WORD(timeout)
MAKE_PSTR_WORD(board_profile) MAKE_PSTR_WORD(board_profile)
MAKE_PSTR_WORD(counter) MAKE_PSTR_WORD(setvalue)
// for commands // for commands
MAKE_PSTR_WORD(call) MAKE_PSTR_WORD(call)
@@ -121,7 +121,7 @@ MAKE_STR(productid_fmt, "%s EMS ProductID")
MAKE_PSTR_LIST(enum_syslog_level, F_(off), F("emerg"), F("alert"), F("crit"), F_(error), F("warn"), F("notice"), F_(info), F_(debug), F("trace"), F("all")) MAKE_PSTR_LIST(enum_syslog_level, F_(off), F("emerg"), F("alert"), F("crit"), F_(error), F("warn"), F("notice"), F_(info), F_(debug), F("trace"), F("all"))
MAKE_PSTR_LIST(enum_watch, F_(off), F_(on), F_(raw), F_(unknown)) MAKE_PSTR_LIST(enum_watch, F_(off), F_(on), F_(raw), F_(unknown))
MAKE_PSTR_LIST(enum_sensortype, F("none"), F("digital in"), F("counter"), F("adc")) MAKE_PSTR_LIST(enum_sensortype, F("none"), F("digital in"), F("counter"), F("adc"), F("timer"), F("rate"), F("digital out"), F("pwm 0"), F("pwm 1"), F("pwm 2"))
// strings // strings
MAKE_PSTR(EMSESP, "EMS-ESP") MAKE_PSTR(EMSESP, "EMS-ESP")
@@ -196,6 +196,8 @@ MAKE_PSTR(dbm, "dBm")
MAKE_PSTR(fahrenheit, "°F") MAKE_PSTR(fahrenheit, "°F")
MAKE_PSTR(mv, "mV") MAKE_PSTR(mv, "mV")
MAKE_PSTR(sqm, "sqm") MAKE_PSTR(sqm, "sqm")
MAKE_PSTR(m3, "m3")
MAKE_PSTR(l, "l")
// MAKE_PSTR(times, "times") // MAKE_PSTR(times, "times")
// MAKE_PSTR(oclock, "o'clock") // MAKE_PSTR(oclock, "o'clock")

View File

@@ -73,18 +73,18 @@ bool System::command_pin(const char * value, const int8_t id) {
} else if (Helpers::value2bool(value, v)) { } else if (Helpers::value2bool(value, v)) {
pinMode(id, OUTPUT); pinMode(id, OUTPUT);
digitalWrite(id, v); digitalWrite(id, v);
LOG_INFO(F("GPIO %d set to %s"), id, v ? "HIGH" : "LOW"); // LOG_INFO(F("GPIO %d set to %s"), id, v ? "HIGH" : "LOW");
return true; return true;
} else if (Helpers::value2string(value, v1)) { } else if (Helpers::value2string(value, v1)) {
if (v1 == "input" || v1 == "in" || v1 == "-1") { if (v1 == "input" || v1 == "in" || v1 == "-1") {
pinMode(id, INPUT); pinMode(id, INPUT);
v = digitalRead(id); v = digitalRead(id);
LOG_INFO(F("GPIO %d set input, state %s"), id, v ? "HIGH" : "LOW"); // LOG_INFO(F("GPIO %d set input, state %s"), id, v ? "HIGH" : "LOW");
return true; return true;
} }
} }
LOG_INFO(F("GPIO %d: invalid value"), id); // LOG_INFO(F("GPIO %d: invalid value"), id);
#endif #endif
return false; return false;
@@ -162,13 +162,19 @@ bool System::command_publish(const char * value, const int8_t id) {
bool System::command_syslog_level(const char * value, const int8_t id) { bool System::command_syslog_level(const char * value, const int8_t id) {
uint8_t s = 0xff; uint8_t s = 0xff;
if (Helpers::value2enum(value, s, FL_(enum_syslog_level))) { if (Helpers::value2enum(value, s, FL_(enum_syslog_level))) {
bool changed = false;
EMSESP::webSettingsService.update( EMSESP::webSettingsService.update(
[&](WebSettings & settings) { [&](WebSettings & settings) {
if (settings.syslog_level != (int8_t)s - 1) {
settings.syslog_level = (int8_t)s - 1; settings.syslog_level = (int8_t)s - 1;
changed = true;
}
return StateUpdateResult::CHANGED; return StateUpdateResult::CHANGED;
}, },
"local"); "local");
if (changed) {
EMSESP::system_.syslog_init(); EMSESP::system_.syslog_init();
}
return true; return true;
} }
return false; return false;
@@ -177,28 +183,34 @@ bool System::command_syslog_level(const char * value, const int8_t id) {
// watch // watch
bool System::command_watch(const char * value, const int8_t id) { bool System::command_watch(const char * value, const int8_t id) {
uint8_t w = 0xff; uint8_t w = 0xff;
uint16_t i = Helpers::hextoint(value);
if (Helpers::value2enum(value, w, FL_(enum_watch))) { if (Helpers::value2enum(value, w, FL_(enum_watch))) {
if (w == 0 || EMSESP::watch() == EMSESP::Watch::WATCH_OFF) { if (w == 0 || EMSESP::watch() == EMSESP::Watch::WATCH_OFF) {
EMSESP::watch_id(0); EMSESP::watch_id(0);
} }
if (Mqtt::publish_single() && w != EMSESP::watch()) {
if (Mqtt::publish_single2cmd()) {
Mqtt::publish(F("system/watch"),
EMSESP::system_.enum_format() == ENUM_FORMAT_INDEX ? Helpers::itoa(w) : read_flash_string(FL_(enum_watch)[w]).c_str());
} else {
Mqtt::publish(F("system_data/watch"),
EMSESP::system_.enum_format() == ENUM_FORMAT_INDEX ? Helpers::itoa(w) : read_flash_string(FL_(enum_watch)[w]).c_str());
}
}
EMSESP::watch(w); EMSESP::watch(w);
if (Mqtt::publish_single()) {
Mqtt::publish(F("system/watch"), read_flash_string(FL_(enum_watch)[w]).c_str());
}
return true; return true;
} else if (i) {
if (Mqtt::publish_single() && i != EMSESP::watch_id()) {
if (Mqtt::publish_single2cmd()) {
Mqtt::publish(F("system/watch"), Helpers::hextoa(i));
} else {
Mqtt::publish(F("system_data/watch"), Helpers::hextoa(i));
}
} }
uint16_t i = Helpers::hextoint(value);
if (i) {
EMSESP::watch_id(i); EMSESP::watch_id(i);
if (EMSESP::watch() == EMSESP::Watch::WATCH_OFF) { if (EMSESP::watch() == EMSESP::Watch::WATCH_OFF) {
EMSESP::watch(EMSESP::Watch::WATCH_ON); EMSESP::watch(EMSESP::Watch::WATCH_ON);
} }
if (Mqtt::publish_single()) {
char s[10];
snprintf(s, sizeof(s), "0x%04X", i);
Mqtt::publish(F("system/watch"), s);
// Mqtt::publish(F("system/watch"), read_flash_string(FL_(enum_watch)[EMSESP::watch()]).c_str());
}
return true; return true;
} }
return false; return false;
@@ -273,13 +285,25 @@ void System::syslog_init() {
} }
if (Mqtt::publish_single()) { if (Mqtt::publish_single()) {
if (Mqtt::publish_single2cmd()) {
Mqtt::publish(F("system/syslog"), syslog_enabled_ ? read_flash_string(FL_(enum_syslog_level)[syslog_level_ + 1]).c_str() : "off"); Mqtt::publish(F("system/syslog"), syslog_enabled_ ? read_flash_string(FL_(enum_syslog_level)[syslog_level_ + 1]).c_str() : "off");
if (EMSESP::watch_id() == 0 || EMSESP::watch() == 0) { if (EMSESP::watch_id() == 0 || EMSESP::watch() == 0) {
Mqtt::publish(F("system/watch"), read_flash_string(FL_(enum_watch)[EMSESP::watch()]).c_str()); Mqtt::publish(F("system/watch"),
EMSESP::system_.enum_format() == ENUM_FORMAT_INDEX ? Helpers::itoa(EMSESP::watch())
: read_flash_string(FL_(enum_watch)[EMSESP::watch()]).c_str());
} else { } else {
char s[10]; Mqtt::publish(F("system/watch"), Helpers::hextoa(EMSESP::watch_id()));
snprintf(s, sizeof(s), "0x%04X", EMSESP::watch_id()); }
Mqtt::publish(F("system/watch"), s);
} else {
Mqtt::publish(F("system_data/syslog"), syslog_enabled_ ? read_flash_string(FL_(enum_syslog_level)[syslog_level_ + 1]).c_str() : "off");
if (EMSESP::watch_id() == 0 || EMSESP::watch() == 0) {
Mqtt::publish(F("system_data/watch"),
EMSESP::system_.enum_format() == ENUM_FORMAT_INDEX ? Helpers::itoa(EMSESP::watch())
: read_flash_string(FL_(enum_watch)[EMSESP::watch()]).c_str());
} else {
Mqtt::publish(F("system_data/watch"), Helpers::hextoa(EMSESP::watch_id()));
}
} }
} }
#endif #endif
@@ -524,7 +548,7 @@ bool System::heartbeat_json(JsonObject & output) {
output["txfails"] = EMSESP::txservice_.telegram_read_fail_count() + EMSESP::txservice_.telegram_write_fail_count(); output["txfails"] = EMSESP::txservice_.telegram_read_fail_count() + EMSESP::txservice_.telegram_write_fail_count();
if (Mqtt::enabled()) { if (Mqtt::enabled()) {
output["mqttfails"] = Mqtt::publish_fails(); output["mqttcount"] = Mqtt::publish_count();
output["mqttfails"] = Mqtt::publish_fails(); output["mqttfails"] = Mqtt::publish_fails();
} }
output["apicalls"] = WebAPIService::api_count(); // + WebAPIService::api_fails(); output["apicalls"] = WebAPIService::api_count(); // + WebAPIService::api_fails();
@@ -636,16 +660,12 @@ void System::system_check() {
// commands - takes static function pointers // commands - takes static function pointers
void System::commands_init() { void System::commands_init() {
Command::add(EMSdevice::DeviceType::SYSTEM, // Command::add(EMSdevice::DeviceType::SYSTEM, F_(pin), System::command_pin, F("set a GPIO on/off"), CommandFlag::ADMIN_ONLY);
F_(pin),
System::command_pin,
F("set a GPIO on/off"),
CommandFlag::MQTT_SUB_FLAG_NOSUB | CommandFlag::ADMIN_ONLY); // dont create a MQTT topic for this
Command::add(EMSdevice::DeviceType::SYSTEM, F_(send), System::command_send, F("send a telegram"), CommandFlag::ADMIN_ONLY); Command::add(EMSdevice::DeviceType::SYSTEM, F_(send), System::command_send, F("send a telegram"), CommandFlag::ADMIN_ONLY);
Command::add(EMSdevice::DeviceType::SYSTEM, F_(fetch), System::command_fetch, F("refresh all EMS values"), CommandFlag::ADMIN_ONLY); Command::add(EMSdevice::DeviceType::SYSTEM, F_(fetch), System::command_fetch, F("refresh all EMS values"), CommandFlag::ADMIN_ONLY);
Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, F("restart EMS-ESP"), CommandFlag::ADMIN_ONLY); Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, F("restart EMS-ESP"), CommandFlag::ADMIN_ONLY);
Command::add(EMSdevice::DeviceType::SYSTEM, F_(watch), System::command_watch, F("watch incoming telegrams")); Command::add(EMSdevice::DeviceType::SYSTEM, F_(watch), System::command_watch, F("watch incoming telegrams"));
// register syslog command in syslog init
// Command::add(EMSdevice::DeviceType::SYSTEM, F_(syslog), System::command_syslog_level, F("set syslog level"), CommandFlag::ADMIN_ONLY); // Command::add(EMSdevice::DeviceType::SYSTEM, F_(syslog), System::command_syslog_level, F("set syslog level"), CommandFlag::ADMIN_ONLY);
if (Mqtt::enabled()) { if (Mqtt::enabled()) {
@@ -822,7 +842,7 @@ void System::show_system(uuid::console::Shell & shell) {
// show Ethernet if connected // show Ethernet if connected
if (ethernet_connected_) { if (ethernet_connected_) {
shell.println(); shell.println();
shell.printfln(F(" Wired Network: connected")); shell.printfln(F(" Ethernet Network: connected"));
shell.printfln(F(" MAC address: %s"), ETH.macAddress().c_str()); shell.printfln(F(" MAC address: %s"), ETH.macAddress().c_str());
shell.printfln(F(" Hostname: %s"), ETH.getHostname()); shell.printfln(F(" Hostname: %s"), ETH.getHostname());
shell.printfln(F(" IPv4 address: %s/%s"), uuid::printable_to_string(ETH.localIP()).c_str(), uuid::printable_to_string(ETH.subnetMask()).c_str()); shell.printfln(F(" IPv4 address: %s/%s"), uuid::printable_to_string(ETH.localIP()).c_str(), uuid::printable_to_string(ETH.subnetMask()).c_str());
@@ -1021,6 +1041,13 @@ bool System::command_customizations(const char * value, const int8_t id, JsonObj
sensorJson["offset"] = sensor.offset; sensorJson["offset"] = sensor.offset;
sensorJson["factor"] = sensor.factor; sensorJson["factor"] = sensor.factor;
sensorJson["uom"] = EMSdevice::uom_to_string(sensor.uom); sensorJson["uom"] = EMSdevice::uom_to_string(sensor.uom);
} else if (sensor.type == AnalogSensor::AnalogType::COUNTER || sensor.type == AnalogSensor::AnalogType::TIMER
|| sensor.type == AnalogSensor::AnalogType::RATE) {
sensorJson["factor"] = sensor.factor;
sensorJson["uom"] = EMSdevice::uom_to_string(sensor.uom);
} else if (sensor.type >= AnalogSensor::AnalogType::PWM_0) {
sensorJson["frequency"] = sensor.factor;
sensorJson["factor"] = sensor.factor;
} }
} }
@@ -1156,7 +1183,11 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
if ((emsdevice) && (emsdevice->device_type() == device_class.first)) { if ((emsdevice) && (emsdevice->device_type() == device_class.first)) {
JsonObject obj = devices.createNestedObject(); JsonObject obj = devices.createNestedObject();
obj["type"] = emsdevice->device_type_name(); obj["type"] = emsdevice->device_type_name();
obj["name"] = emsdevice->to_string(); // obj["name"] = emsdevice->to_string();
obj["name"] = emsdevice->name();
obj["device id"] = Helpers::hextoa(emsdevice->device_id());
obj["product id"] = emsdevice->product_id();
obj["version"] = emsdevice->version();
obj["entities"] = emsdevice->count_entities(); obj["entities"] = emsdevice->count_entities();
char result[200]; char result[200];
(void)emsdevice->show_telegram_handlers(result, EMSdevice::Handlers::RECEIVED); (void)emsdevice->show_telegram_handlers(result, EMSdevice::Handlers::RECEIVED);

View File

@@ -44,7 +44,7 @@ class AnalogCustomization {
public: public:
uint8_t id; uint8_t id;
std::string name; std::string name;
uint16_t offset; float offset;
float factor; float factor;
uint8_t uom; // 0 is none uint8_t uom; // 0 is none
int8_t type; // -1 is for deletion int8_t type; // -1 is for deletion

View File

@@ -275,7 +275,7 @@ void WebDataService::write_analog(AsyncWebServerRequest * request, JsonVariant &
uint8_t id = analog["id"]; // this is the unique key uint8_t id = analog["id"]; // this is the unique key
std::string name = analog["name"]; std::string name = analog["name"];
float factor = analog["factor"]; float factor = analog["factor"];
int16_t offset = analog["offset"]; float offset = analog["offset"];
uint8_t uom = analog["uom"]; uint8_t uom = analog["uom"];
int8_t type = analog["type"]; int8_t type = analog["type"];
ok = EMSESP::analogsensor_.update(id, name, offset, factor, uom, type); ok = EMSESP::analogsensor_.update(id, name, offset, factor, uom, type);