more to psram, names for sensors, schedule, custom as char[20]

This commit is contained in:
MichaelDvP
2025-12-11 16:00:24 +01:00
parent ac982cbb15
commit 7a683d3637
20 changed files with 371 additions and 439 deletions

View File

@@ -108,7 +108,7 @@ void TemperatureSensor::loop() {
last_activity_ = time_now;
}
} else if (state_ == State::READING) {
if (temperature_convert_complete() && (time_now - last_activity_ > CONVERSION_MS)) {
if (temperature_convert_complete(time_now - last_activity_)) {
#ifdef EMSESP_DEBUG_SENSOR
LOG_DEBUG("Scanning for temperature sensors");
#endif
@@ -181,12 +181,12 @@ void TemperatureSensor::loop() {
default:
sensorfails_++;
LOG_ERROR("Unknown sensor %s", Sensor(addr).id().c_str());
LOG_ERROR("Unknown sensor %s", Sensor(addr).id());
break;
}
} else {
sensorfails_++;
LOG_ERROR("Invalid sensor %s", Sensor(addr).id().c_str());
LOG_ERROR("Invalid sensor %s", Sensor(addr).id());
}
} else {
if (!parasite_) {
@@ -219,13 +219,13 @@ void TemperatureSensor::loop() {
s->set_name("gateway_temperature");
s->set_is_system(true); // mark as internal system temperature sensor
if (!EMSESP::nvs_.isKey("intTemp")) {
EMSESP::nvs_.putString("intTemp", s->id().c_str());
EMSESP::nvs_.putString("intTemp", s->id());
}
// LOG_NOTICE("Adding system sensor for gateway temperature %s", s->id().c_str());
EMSESP::webCustomizationService.update([&](WebCustomization & settings) {
auto newSensor = SensorCustomization();
newSensor.id = s->id();
newSensor.name = s->name();
auto newSensor = SensorCustomization();
strlcpy(newSensor.id, s->id(), sizeof(newSensor.id));
strlcpy(newSensor.name, s->name(), sizeof(newSensor.name));
newSensor.offset = 0;
newSensor.is_system = s->is_system(); // always true
settings.sensorCustomizations.push_back(newSensor);
@@ -244,21 +244,21 @@ void TemperatureSensor::loop() {
#endif
}
bool TemperatureSensor::temperature_convert_complete() {
bool TemperatureSensor::temperature_convert_complete(const uint32_t time) {
#ifndef EMSESP_STANDALONE
if (parasite_) {
return true; // don't care, use the minimum time in loop
return time > CONVERSION_MS; // don't care, use the datasheet time
}
return bus_.read_bit() == 1;
#else
return true;
return time > CONVERSION_MS;
#endif
}
int16_t TemperatureSensor::get_temperature_c(const uint8_t addr[]) {
#ifndef EMSESP_STANDALONE
if (!bus_.reset()) {
LOG_ERROR("Bus reset failed before reading scratchpad from %s", Sensor(addr).id().c_str());
LOG_ERROR("Bus reset failed before reading scratchpad from %s", Sensor(addr).id());
return EMS_VALUE_INT16_NOTSET;
}
YIELD;
@@ -270,7 +270,7 @@ int16_t TemperatureSensor::get_temperature_c(const uint8_t addr[]) {
YIELD;
if (!bus_.reset()) {
LOG_ERROR("Bus reset failed after reading scratchpad from %s", Sensor(addr).id().c_str());
LOG_ERROR("Bus reset failed after reading scratchpad from %s", Sensor(addr).id());
return EMS_VALUE_INT16_NOTSET;
}
YIELD;
@@ -286,7 +286,7 @@ int16_t TemperatureSensor::get_temperature_c(const uint8_t addr[]) {
scratchpad[6],
scratchpad[7],
scratchpad[8],
Sensor(addr).id().c_str());
Sensor(addr).id());
return EMS_VALUE_INT16_NOTSET;
}
@@ -319,10 +319,10 @@ int16_t TemperatureSensor::get_temperature_c(const uint8_t addr[]) {
}
// update temperature sensor information name and offset
bool TemperatureSensor::update(const std::string & id, const std::string & name, int16_t offset, bool is_system) {
bool TemperatureSensor::update(const char * id, const char * name, int16_t offset, bool hide, bool is_system) {
// find the sensor
for (auto & sensor : sensors_) {
if (sensor.id() == id) {
if (!strcmp(id, sensor.id())) {
// found a match, update the sensor object
// if HA is enabled then delete the old record
@@ -336,27 +336,27 @@ bool TemperatureSensor::update(const std::string & id, const std::string & name,
sensor.set_is_system(is_system);
// store the new name and offset in our configuration
EMSESP::webCustomizationService.update([&id, &name, &offset, &is_system, &sensor](WebCustomization & settings) {
EMSESP::webCustomizationService.update([&id, &name, &offset, &sensor, &hide, &is_system](WebCustomization & settings) {
// look it up to see if it exists
bool found = false;
for (auto & SensorCustomization : settings.sensorCustomizations) {
if (SensorCustomization.id == id) {
SensorCustomization.name = name;
if (!strcmp(id, SensorCustomization.id)) {
strlcpy(SensorCustomization.name, name, sizeof(SensorCustomization.name));
SensorCustomization.offset = offset;
SensorCustomization.is_system = is_system;
found = true;
LOG_DEBUG("Customizing existing sensor ID %s", id.c_str());
LOG_DEBUG("Customizing existing sensor ID %s", id);
break;
}
}
if (!found) {
auto newSensor = SensorCustomization();
newSensor.id = id;
newSensor.name = name;
auto newSensor = SensorCustomization();
strlcpy(newSensor.id, id, sizeof(newSensor.id));
strlcpy(newSensor.name, name, sizeof(newSensor.name));
newSensor.offset = offset;
newSensor.is_system = is_system; // is user defined, not system
settings.sensorCustomizations.push_back(newSensor);
LOG_DEBUG("Adding new customization for sensor ID %s", id.c_str());
LOG_DEBUG("Adding new customization for sensor ID %s", id);
}
sensor.ha_registered = false; // it's changed so we may need to recreate the HA config
return StateUpdateResult::CHANGED;
@@ -438,30 +438,27 @@ void TemperatureSensor::publish_sensor(const Sensor & sensor) {
if (Mqtt::enabled() && Mqtt::publish_single()) {
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
if (Mqtt::publish_single2cmd()) {
snprintf(topic, sizeof(topic), "%s/%s", F_(temperaturesensor), sensor.name().c_str());
snprintf(topic, sizeof(topic), "%s/%s", F_(temperaturesensor), sensor.name());
} else {
snprintf(topic, sizeof(topic), "%s%s/%s", F_(temperaturesensor), "_data", sensor.name().c_str());
snprintf(topic, sizeof(topic), "%s%s/%s", F_(temperaturesensor), "_data", sensor.name());
}
char payload[10];
Mqtt::queue_publish(topic, Helpers::render_value(payload, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
}
char cmd[COMMAND_MAX_LENGTH];
snprintf(cmd, sizeof(cmd), "%s/%s", F_(temperaturesensor), sensor.name().c_str());
snprintf(cmd, sizeof(cmd), "%s/%s", F_(temperaturesensor), sensor.name());
EMSESP::webSchedulerService.onChange(cmd);
}
// send empty config topic to remove the entry from HA
void TemperatureSensor::remove_ha_topic(const std::string & id) {
void TemperatureSensor::remove_ha_topic(const char * id) {
if (!Mqtt::ha_enabled()) {
return;
}
LOG_DEBUG("Removing HA config for temperature sensor ID %s", id.c_str());
// use '_' as HA doesn't like '-' in the topic name
std::string sensorid = id;
std::replace(sensorid.begin(), sensorid.end(), '-', '_');
LOG_DEBUG("Removing HA config for temperature sensor ID %s", id);
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf(topic, sizeof(topic), "sensor/%s/temperaturesensor_%s/config", Mqtt::basename().c_str(), sensorid.c_str());
snprintf(topic, sizeof(topic), "sensor/%s/temperaturesensor_%s/config", Mqtt::basename().c_str(), id);
Mqtt::queue_remove_topic(topic);
}
@@ -504,7 +501,7 @@ void TemperatureSensor::publish_values(const bool force) {
remove_ha_topic(sensor.id());
sensor.ha_registered = false;
} else if (!sensor.ha_registered || force) {
LOG_DEBUG("Recreating HA config for sensor ID %s", sensor.id().c_str());
LOG_DEBUG("Recreating HA config for sensor ID %s", sensor.id());
JsonDocument config;
config["~"] = Mqtt::base();
@@ -520,10 +517,10 @@ void TemperatureSensor::publish_values(const bool force) {
char val_obj[70];
char val_cond[170];
if (Mqtt::is_nested()) {
snprintf(val_obj, sizeof(val_obj), "value_json['%s']['temp']", sensor.id().c_str());
snprintf(val_cond, sizeof(val_cond), "value_json['%s'] is defined and %s is defined", sensor.id().c_str(), val_obj);
snprintf(val_obj, sizeof(val_obj), "value_json['%s']['temp']", sensor.id());
snprintf(val_cond, sizeof(val_cond), "value_json['%s'] is defined and %s is defined", sensor.id(), val_obj);
} else {
snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str());
snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name());
snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj);
}
@@ -537,17 +534,14 @@ void TemperatureSensor::publish_values(const bool force) {
char uniq_s[70];
if (Mqtt::entity_format() == Mqtt::entityFormat::MULTI_SHORT) {
snprintf(uniq_s, sizeof(uniq_s), "%s_%s_%s", Mqtt::basename().c_str(), F_(temperaturesensor), sensor.id().c_str());
snprintf(uniq_s, sizeof(uniq_s), "%s_%s_%s", Mqtt::basename().c_str(), F_(temperaturesensor), sensor.id());
} else {
snprintf(uniq_s, sizeof(uniq_s), "%s_%s", F_(temperaturesensor), sensor.id().c_str());
snprintf(uniq_s, sizeof(uniq_s), "%s_%s", F_(temperaturesensor), sensor.id());
}
config["uniq_id"] = uniq_s;
config["def_ent_id"] = (std::string) "sensor." + uniq_s;
char name[50];
snprintf(name, sizeof(name), "%s", sensor.name().c_str());
config["name"] = name;
config["name"] = sensor.name();
// see if we need to create the [devs] discovery section, as this needs only to be done once for all sensors
bool is_ha_device_created = false;
@@ -562,7 +556,7 @@ void TemperatureSensor::publish_values(const bool force) {
Mqtt::add_ha_avail_section(config.as<JsonObject>(), stat_t, !is_ha_device_created, val_cond);
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf(topic, sizeof(topic), "sensor/%s/%s_%s/config", Mqtt::basename().c_str(), F_(temperaturesensor), sensor.id().c_str());
snprintf(topic, sizeof(topic), "sensor/%s/%s_%s/config", Mqtt::basename().c_str(), F_(temperaturesensor), sensor.id());
sensor.ha_registered = Mqtt::queue_ha(topic, config.as<JsonObject>());
}
@@ -579,17 +573,15 @@ TemperatureSensor::Sensor::Sensor(const uint8_t addr[])
: internal_id_(((uint64_t)addr[0] << 48) | ((uint64_t)addr[1] << 40) | ((uint64_t)addr[2] << 32) | ((uint64_t)addr[3] << 24) | ((uint64_t)addr[4] << 16)
| ((uint64_t)addr[5] << 8) | ((uint64_t)addr[6])) {
// create ID string
char id_s[20];
snprintf(id_s,
sizeof(id_s),
snprintf(id_,
sizeof(id_),
"%02X_%04X_%04X_%04X",
(unsigned int)(internal_id_ >> 48) & 0xFF,
(unsigned int)(internal_id_ >> 32) & 0xFFFF,
(unsigned int)(internal_id_ >> 16) & 0xFFFF,
(unsigned int)(internal_id_) & 0xFFFF);
id_ = std::string(id_s);
name_ = std::string{}; // name (alias) is empty
offset_ = 0; // 0 degrees offset
name_[0] = '\0';
offset_ = 0; // 0 degrees offset
}
uint64_t TemperatureSensor::get_id(const uint8_t addr[]) {
@@ -599,8 +591,8 @@ uint64_t TemperatureSensor::get_id(const uint8_t addr[]) {
// find the name from the customization service
// if empty, return the ID as a string
std::string TemperatureSensor::Sensor::name() const {
if (name_.empty()) {
const char * TemperatureSensor::Sensor::name() const {
if (name_[0] == '\0') {
return id_;
}
return name_;
@@ -613,8 +605,8 @@ bool TemperatureSensor::Sensor::apply_customization() {
auto const & sensors = settings.sensorCustomizations;
if (!sensors.empty()) {
for (const auto & sensor : sensors) {
if (id_ == sensor.id) {
LOG_DEBUG("Loading customization for temperature sensor %s", sensor.id.c_str());
if (!strcmp(sensor.id, id_)) {
LOG_DEBUG("Loading customization for temperature sensor %s", id_);
set_name(sensor.name);
set_offset(sensor.offset);
set_is_system(sensor.is_system);