diff --git a/interface/src/project/DashboardData.tsx b/interface/src/project/DashboardData.tsx
index 36614e0f0..19047073c 100644
--- a/interface/src/project/DashboardData.tsx
+++ b/interface/src/project/DashboardData.tsx
@@ -59,7 +59,8 @@ import {
DeviceValue,
DeviceValueUOM,
DeviceValueUOM_s,
- AnalogTypes,
+ AnalogType,
+ AnalogTypeNames,
Sensor,
Analog
} from './types';
@@ -715,7 +716,7 @@ const DashboardData: FC = () => {
))}
- {analog.t === 3 && (
+ {analog.t >= AnalogType.COUNTER && analog.t <= AnalogType.RATE && (
<>
@@ -726,22 +727,37 @@ const DashboardData: FC = () => {
))}
-
-
- mV
- }}
- />
-
+ {analog.t === AnalogType.ADC && (
+
+ mV
+ }}
+ />
+
+ )}
+ {analog.t === AnalogType.COUNTER && (
+
+
+
+ )}
{
>
)}
+ {analog.t === AnalogType.DIGITAL_OUT && (analog.i === 25 || analog.i === 26) && (
+ <>
+
+
+
+ >
+ )}
+ {analog.t === AnalogType.DIGITAL_OUT && analog.i !== 25 && analog.i !== 26 && (
+ <>
+
+
+
+ >
+ )}
+ {analog.t >= AnalogType.PWM_0 && (
+ <>
+
+ Hz
+ }}
+ />
+
+
+ %
+ }}
+
+ />
+
+ >
+ )}
Warning: be careful when assigning a GPIO!
diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts
index 1c0871691..b5f3a9497 100644
--- a/interface/src/project/types.ts
+++ b/interface/src/project/types.ts
@@ -176,7 +176,9 @@ export enum DeviceValueUOM {
DBM,
FAHRENHEIT,
MV,
- SQM
+ SQM,
+ M3,
+ L
}
export const DeviceValueUOM_s = [
@@ -199,10 +201,36 @@ export const DeviceValueUOM_s = [
'°F',
'mV',
'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 = {
[name: string]: string;
diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp
index 734b9e441..5ea7dffac 100644
--- a/src/analogsensor.cpp
+++ b/src/analogsensor.cpp
@@ -27,7 +27,7 @@ void AnalogSensor::start() {
reload(); // fetch the list of sensors from our customization service
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"));
@@ -40,10 +40,15 @@ void AnalogSensor::start() {
F_(info_cmd));
Command::add(
EMSdevice::DeviceType::ANALOGSENSOR,
- F_(counter),
- [&](const char * value, const int8_t id) { return command_counter(value, id); },
- F("set counter value"),
+ F_(setvalue),
+ [&](const char * value, const int8_t id) { return command_setvalue(value, id); },
+ F("set io value"),
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
@@ -58,11 +63,47 @@ void AnalogSensor::reload() {
// and store them locally and then activate them
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
auto sensors = settings.analogCustomizations;
- sensors_.clear(); // start with an empty list
- if (sensors.size() != 0) {
- for (auto & sensor : sensors) {
+ auto it = sensors_.begin();
+ 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) {
+ 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_.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;
@@ -82,11 +123,21 @@ void AnalogSensor::reload() {
} else if (sensor.type() == AnalogType::COUNTER) {
LOG_DEBUG(F("Adding analog I/O Counter sensor on GPIO%d"), sensor.id());
pinMode(sensor.id(), INPUT_PULLUP);
- sensor.set_value(0); // reset count
- sensor.set_uom(0); // no uom, just for safe measures
+ if (sensor.id() == 25 || sensor.id() == 26) {
+ dacWrite(sensor.id(), 255);
+ }
sensor.polltime_ = 0;
sensor.poll_ = digitalRead(sensor.id());
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) {
LOG_DEBUG(F("Adding analog Read sensor on GPIO%d"), sensor.id());
pinMode(sensor.id(), INPUT_PULLUP);
@@ -95,18 +146,49 @@ void AnalogSensor::reload() {
sensor.polltime_ = 0;
sensor.poll_ = digitalRead(sensor.id());
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() {
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) {
measure_last_ = uuid::get_uptime();
- // go through the list of ADC sensors
+ // go through the list of adc sensors
for (auto & sensor : sensors_) {
if (sensor.type() == AnalogType::ADC) {
uint16_t a = analogReadMilliVolts(sensor.id()); // e.g. ADC1_CHANNEL_0_GPIO_NUM
@@ -128,34 +210,38 @@ void AnalogSensor::measure() {
}
}
}
- // poll digital io every time
+ // poll digital io every time with debounce
// go through the list of digital 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 current_reading = digitalRead(sensor.id());
- if (sensor.poll_ != current_reading) { // check for pinchange
- sensor.polltime_ = uuid::get_uptime();
+ if (sensor.poll_ != current_reading) { // check for pinchange
+ sensor.polltime_ = uuid::get_uptime(); // remember time of pinchange
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) {
sensor.set_value(sensor.poll_);
- } else if (sensor.type() == AnalogType::COUNTER) {
- // capture reading and compare with the last one to see if there is high/low change
- if (sensor.poll_ != sensor.last_reading_) {
- sensor.last_reading_ = sensor.poll_;
- if (!sensor.poll_) {
- sensor.set_value(old_value + 1);
- }
+ } else if (!sensor.poll_) { // falling edge
+ if (sensor.type() == AnalogType::COUNTER) {
+ sensor.set_value(old_value + sensor.factor());
+ } else if (sensor.type() == AnalogType::RATE) { // dafault uom: Hz (1/sec) with factor 1
+ sensor.set_value(sensor.factor() * 1000 / (sensor.polltime_ - sensor.last_polltime_));
+ } 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
- if (old_value != sensor.value()) {
- sensorreads_++;
- changed_ = true;
- publish_sensor(sensor);
- }
+ }
+ // see if there is a change and increment # reads
+ if (old_value != sensor.value()) {
+ sensorreads_++;
+ changed_ = true;
+ publish_sensor(sensor);
}
}
}
@@ -170,7 +256,7 @@ void AnalogSensor::loop() {
}
// 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
EMSESP::webCustomizationService.update(
@@ -240,7 +326,11 @@ bool AnalogSensor::updated_values() {
void AnalogSensor::publish_sensor(const Sensor & sensor) {
if (Mqtt::publish_single()) {
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
- snprintf(topic, sizeof(topic), "%s/%s", read_flash_string(F_(analogsensor)).c_str(), sensor.name().c_str());
+ if (Mqtt::publish_single2cmd()) {
+ 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];
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();
switch (sensor.type()) {
case AnalogType::COUNTER:
- dataSensor["value"] = (uint16_t)sensor.value(); // convert to integer
- break;
+ case AnalogType::TIMER:
+ case AnalogType::RATE:
case AnalogType::ADC:
+ case AnalogType::PWM_0:
+ case AnalogType::PWM_1:
+ case AnalogType::PWM_2:
dataSensor["value"] = (float)sensor.value(); // float
break;
case AnalogType::DIGITAL_IN:
+ case AnalogType::DIGITAL_OUT:
default:
dataSensor["value"] = (uint8_t)sensor.value(); // convert to char for 1 or 0
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["offset"] = sensor.offset();
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();
} else {
@@ -384,7 +487,7 @@ bool AnalogSensor::command_info(const char * value, const int8_t id, JsonObject
}
// 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)
, name_(name)
, offset_(offset)
@@ -405,28 +508,70 @@ std::string AnalogSensor::Sensor::name() const {
}
// set the counter value, id is gpio-no
-bool AnalogSensor::command_counter(const char * value, const int8_t id) {
- int val;
- if (!Helpers::value2number(value, val)) {
+bool AnalogSensor::command_setvalue(const char * value, const int8_t id) {
+ float val;
+ if (!Helpers::value2float(value, val)) {
return false;
}
for (auto & sensor : sensors_) {
- if (sensor.type() == AnalogType::COUNTER && sensor.id() == id) {
- if (val < 0) { // negative values corrects
- sensor.set_value(sensor.value() + val);
- } else { // positive values are set
+ if (sensor.id() == id) {
+ 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);
+ } else { // positive values are set
+ sensor.set_offset(val);
+ sensor.set_value(val);
+ }
+ publish_sensor(sensor);
+ 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 true;
}
}
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
#ifdef EMSESP_DEBUG
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_.back().set_value(12.4);
diff --git a/src/analogsensor.h b/src/analogsensor.h
index 70e94fd95..e48acd7e9 100644
--- a/src/analogsensor.h
+++ b/src/analogsensor.h
@@ -36,10 +36,10 @@ class AnalogSensor {
public:
class Sensor {
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;
- void set_offset(const uint16_t offset) {
+ void set_offset(const float offset) {
offset_ = offset;
}
@@ -68,7 +68,7 @@ class AnalogSensor {
factor_ = factor;
}
- uint16_t offset() const {
+ float offset() const {
return offset_;
}
@@ -90,16 +90,18 @@ class AnalogSensor {
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
- uint32_t polltime_ = 0; // digital IO & COUNTER debounce time
- int poll_ = 0;
+ 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 id_;
std::string name_;
- uint16_t offset_;
+ float offset_;
float factor_;
uint8_t uom_;
float value_; // float because of the factor is a float
@@ -112,9 +114,15 @@ class AnalogSensor {
enum AnalogType : int8_t {
MARK_DELETED = -1, // mark for deletion
NOTUSED, // 0 - disabled
- DIGITAL_IN, // 1
- COUNTER, // 2
- ADC // 3
+ DIGITAL_IN,
+ COUNTER,
+ ADC,
+ TIMER,
+ RATE,
+ DIGITAL_OUT,
+ PWM_0,
+ PWM_1,
+ PWM_2
};
void start();
@@ -149,7 +157,7 @@ class AnalogSensor {
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);
#ifdef EMSESP_DEBUG
@@ -163,9 +171,10 @@ class AnalogSensor {
static uuid::log::Logger logger_;
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();
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 sensors_; // our list of sensors
diff --git a/src/emsdevicevalue.h b/src/emsdevicevalue.h
index a9b4b029c..c6bf629b6 100644
--- a/src/emsdevicevalue.h
+++ b/src/emsdevicevalue.h
@@ -66,7 +66,9 @@ class DeviceValue {
DBM, // 15
FAHRENHEIT, // 16
MV, // 17
- SQM // 18
+ SQM, // 18 squaremeter
+ M3, // 19 cubic meter
+ L // 20
};
// TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp
diff --git a/src/helpers.cpp b/src/helpers.cpp
index 343b5a01a..0f9b339f3 100644
--- a/src/helpers.cpp
+++ b/src/helpers.cpp
@@ -526,6 +526,10 @@ bool Helpers::value2float(const char * v, float & value) {
value = atof((char *)v);
return true;
}
+ if (v[0] == '+' && (v[1] == '.' || (v[1] >= '0' && v[1] <= '9'))) {
+ value = atof((char *)(v + 1));
+ return true;
+ }
return false;
}
diff --git a/src/locale_DE.h b/src/locale_DE.h
index 82345d198..c57701bfd 100644
--- a/src/locale_DE.h
+++ b/src/locale_DE.h
@@ -70,7 +70,7 @@ MAKE_PSTR_WORD(pin)
MAKE_PSTR_WORD(publish)
MAKE_PSTR_WORD(timeout)
MAKE_PSTR_WORD(board_profile)
-MAKE_PSTR_WORD(counter)
+MAKE_PSTR_WORD(setvalue)
// for commands
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_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
MAKE_PSTR(EMSESP, "EMS-ESP")
@@ -196,6 +196,8 @@ MAKE_PSTR(dbm, "dBm")
MAKE_PSTR(fahrenheit, "°F")
MAKE_PSTR(mv, "mV")
MAKE_PSTR(sqm, "sqm")
+MAKE_PSTR(m3, "m3")
+MAKE_PSTR(l, "l")
// MAKE_PSTR(times, "mal")
// 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(fastheatup, F("fastheatup"), F("fast heatup"))
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(nighttemp, F("nighttemp"), F("Nachttemperatur"))
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(maxflowtemp, F("maxflowtemp"), F("max Flusstemperatur"))
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(targetflowtemp, F("targetflowtemp"), F("berechnete Flusstemperatur"))
MAKE_PSTR_LIST(heatingtype, F("heatingtype"), F("Heizungstyp"))
diff --git a/src/locale_EN.h b/src/locale_EN.h
index 0afdb0b1b..e6908a12c 100644
--- a/src/locale_EN.h
+++ b/src/locale_EN.h
@@ -70,7 +70,7 @@ MAKE_PSTR_WORD(pin)
MAKE_PSTR_WORD(publish)
MAKE_PSTR_WORD(timeout)
MAKE_PSTR_WORD(board_profile)
-MAKE_PSTR_WORD(counter)
+MAKE_PSTR_WORD(setvalue)
// for commands
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_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
MAKE_PSTR(EMSESP, "EMS-ESP")
@@ -196,6 +196,8 @@ MAKE_PSTR(dbm, "dBm")
MAKE_PSTR(fahrenheit, "°F")
MAKE_PSTR(mv, "mV")
MAKE_PSTR(sqm, "sqm")
+MAKE_PSTR(m3, "m3")
+MAKE_PSTR(l, "l")
// MAKE_PSTR(times, "times")
// MAKE_PSTR(oclock, "o'clock")
diff --git a/src/system.cpp b/src/system.cpp
index 6b56724a9..d05dffb29 100644
--- a/src/system.cpp
+++ b/src/system.cpp
@@ -73,18 +73,18 @@ bool System::command_pin(const char * value, const int8_t id) {
} else if (Helpers::value2bool(value, v)) {
pinMode(id, OUTPUT);
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;
} else if (Helpers::value2string(value, v1)) {
if (v1 == "input" || v1 == "in" || v1 == "-1") {
pinMode(id, INPUT);
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;
}
}
- LOG_INFO(F("GPIO %d: invalid value"), id);
+ // LOG_INFO(F("GPIO %d: invalid value"), id);
#endif
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) {
uint8_t s = 0xff;
if (Helpers::value2enum(value, s, FL_(enum_syslog_level))) {
+ bool changed = false;
EMSESP::webSettingsService.update(
[&](WebSettings & settings) {
- settings.syslog_level = (int8_t)s - 1;
+ if (settings.syslog_level != (int8_t)s - 1) {
+ settings.syslog_level = (int8_t)s - 1;
+ changed = true;
+ }
return StateUpdateResult::CHANGED;
},
"local");
- EMSESP::system_.syslog_init();
+ if (changed) {
+ EMSESP::system_.syslog_init();
+ }
return true;
}
return false;
@@ -176,29 +182,35 @@ bool System::command_syslog_level(const char * value, const int8_t id) {
// watch
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 (w == 0 || EMSESP::watch() == EMSESP::Watch::WATCH_OFF) {
EMSESP::watch_id(0);
}
- EMSESP::watch(w);
- if (Mqtt::publish_single()) {
- Mqtt::publish(F("system/watch"), read_flash_string(FL_(enum_watch)[w]).c_str());
+ 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);
return true;
- }
- uint16_t i = Helpers::hextoint(value);
- if (i) {
+ } 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));
+ }
+ }
EMSESP::watch_id(i);
if (EMSESP::watch() == EMSESP::Watch::WATCH_OFF) {
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 false;
@@ -273,13 +285,25 @@ void System::syslog_init() {
}
if (Mqtt::publish_single()) {
- 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) {
- Mqtt::publish(F("system/watch"), read_flash_string(FL_(enum_watch)[EMSESP::watch()]).c_str());
+ if (Mqtt::publish_single2cmd()) {
+ 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) {
+ 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 {
+ Mqtt::publish(F("system/watch"), Helpers::hextoa(EMSESP::watch_id()));
+ }
+
} else {
- char s[10];
- snprintf(s, sizeof(s), "0x%04X", EMSESP::watch_id());
- Mqtt::publish(F("system/watch"), s);
+ 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
@@ -524,7 +548,7 @@ bool System::heartbeat_json(JsonObject & output) {
output["txfails"] = EMSESP::txservice_.telegram_read_fail_count() + EMSESP::txservice_.telegram_write_fail_count();
if (Mqtt::enabled()) {
- output["mqttfails"] = Mqtt::publish_fails();
+ output["mqttcount"] = Mqtt::publish_count();
output["mqttfails"] = Mqtt::publish_fails();
}
output["apicalls"] = WebAPIService::api_count(); // + WebAPIService::api_fails();
@@ -636,16 +660,12 @@ void System::system_check() {
// commands - takes static function pointers
void System::commands_init() {
- Command::add(EMSdevice::DeviceType::SYSTEM,
- 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_(pin), System::command_pin, F("set a GPIO on/off"), 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_(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"));
+ // register syslog command in syslog init
// Command::add(EMSdevice::DeviceType::SYSTEM, F_(syslog), System::command_syslog_level, F("set syslog level"), CommandFlag::ADMIN_ONLY);
if (Mqtt::enabled()) {
@@ -822,7 +842,7 @@ void System::show_system(uuid::console::Shell & shell) {
// show Ethernet if connected
if (ethernet_connected_) {
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(" 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());
@@ -1021,6 +1041,13 @@ bool System::command_customizations(const char * value, const int8_t id, JsonObj
sensorJson["offset"] = sensor.offset;
sensorJson["factor"] = sensor.factor;
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;
}
}
@@ -1154,10 +1181,14 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
for (const auto & device_class : EMSFactory::device_handlers()) {
for (const auto & emsdevice : EMSESP::emsdevices) {
if ((emsdevice) && (emsdevice->device_type() == device_class.first)) {
- JsonObject obj = devices.createNestedObject();
- obj["type"] = emsdevice->device_type_name();
- obj["name"] = emsdevice->to_string();
- obj["entities"] = emsdevice->count_entities();
+ JsonObject obj = devices.createNestedObject();
+ obj["type"] = emsdevice->device_type_name();
+ // 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();
char result[200];
(void)emsdevice->show_telegram_handlers(result, EMSdevice::Handlers::RECEIVED);
if (result[0] != '\0') {
diff --git a/src/web/WebCustomizationService.h b/src/web/WebCustomizationService.h
index 5371e74bb..b2bd869da 100644
--- a/src/web/WebCustomizationService.h
+++ b/src/web/WebCustomizationService.h
@@ -44,7 +44,7 @@ class AnalogCustomization {
public:
uint8_t id;
std::string name;
- uint16_t offset;
+ float offset;
float factor;
uint8_t uom; // 0 is none
int8_t type; // -1 is for deletion
diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp
index a012c2d35..85989b9c7 100644
--- a/src/web/WebDataService.cpp
+++ b/src/web/WebDataService.cpp
@@ -275,7 +275,7 @@ void WebDataService::write_analog(AsyncWebServerRequest * request, JsonVariant &
uint8_t id = analog["id"]; // this is the unique key
std::string name = analog["name"];
float factor = analog["factor"];
- int16_t offset = analog["offset"];
+ float offset = analog["offset"];
uint8_t uom = analog["uom"];
int8_t type = analog["type"];
ok = EMSESP::analogsensor_.update(id, name, offset, factor, uom, type);