mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
analogsensors, outputs PWM, DAC, digital
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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"))
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user