m5stack co2 sensor

This commit is contained in:
Martin Bauer
2024-03-01 15:01:56 +01:00
parent 513cab32b7
commit 55ec47e3af
10 changed files with 3414 additions and 9 deletions

View File

@@ -0,0 +1,80 @@
from esphome.components import select
import esphome.config_validation as cv
import esphome.codegen as cg
from esphome.const import CONF_ID, CONF_ADDRESS
from esphome.components.modbus_controller import (
add_modbus_base_properties,
modbus_controller_ns,
modbus_calc_properties,
validate_modbus_register,
ModbusItemBaseSchema,
SensorItem,
MODBUS_REGISTER_TYPE,
)
from ..const import (
CONF_BITMASK,
CONF_FORCE_NEW_RANGE,
CONF_MODBUS_CONTROLLER_ID,
CONF_REGISTER_TYPE,
CONF_SKIP_UPDATES,
CONF_USE_WRITE_MULTIPLE,
CONF_WRITE_LAMBDA,
)
DEPENDENCIES = ["modbus_controller"]
CODEOWNERS = ["@mabau"]
NeopoolFiltrationMode = modbus_controller_ns.class_(
"NeopoolFiltrationMode", cg.Component, select.Select, SensorItem
)
CONFIG_SCHEMA = cv.All(
select.select_schema(NeopoolFiltrationMode)
.extend(cv.COMPONENT_SCHEMA)
#.extend(ModbusItemBaseSchema)
#.extend(
# {
# cv.Required(CONF)
# cv.Optional(CONF_REGISTER_TYPE): cv.enum(MODBUS_REGISTER_TYPE),
# cv.Optional(CONF_USE_WRITE_MULTIPLE, default=False): cv.boolean,
# cv.Optional(CONF_WRITE_LAMBDA): cv.returning_lambda,
# }
#),
#validate_modbus_register,
)
async def to_code(config):
byte_offset, _ = modbus_calc_properties(config)
var = cg.new_Pvariable(
config[CONF_ID],
config[CONF_REGISTER_TYPE],
config[CONF_ADDRESS],
byte_offset,
config[CONF_BITMASK],
config[CONF_SKIP_UPDATES],
config[CONF_FORCE_NEW_RANGE],
)
await cg.register_component(var, config)
await switch.register_switch(var, config)
paren = await cg.get_variable(config[CONF_MODBUS_CONTROLLER_ID])
cg.add(var.set_parent(paren))
cg.add(var.set_use_write_mutiple(config[CONF_USE_WRITE_MULTIPLE]))
cg.add(paren.add_sensor_item(var))
if CONF_WRITE_LAMBDA in config:
template_ = await cg.process_lambda(
config[CONF_WRITE_LAMBDA],
[
(ModbusSwitch.operator("ptr"), "item"),
(cg.bool_, "x"),
(cg.std_vector.template(cg.uint8).operator("ref"), "payload"),
],
return_type=cg.optional.template(bool),
)
cg.add(var.set_write_template(template_))
await add_modbus_base_properties(var, config, ModbusSwitch, bool, bool)

View File

@@ -0,0 +1,89 @@
#include "filtration_mode.h"
#include "esphome/core/log.h"
namespace esphome {
namespace neopool {
void FiltrationSelect::dump_config() { LOG_SELECT(TAG, "Modbus Neopool Filtration Select", this); }
void FiltrationSelect::parse_and_publish(const std::vector<uint8_t> &data)
{
int64_t value = payload_to_number(data, this->sensor_value_type, this->offset, this->bitmask);
ESP_LOGD(TAG, "New select value %lld from payload", value);
optional<std::string> new_state;
if (this->transform_func_.has_value()) {
auto val = (*this->transform_func_)(this, value, data);
if (val.has_value()) {
new_state = *val;
ESP_LOGV(TAG, "lambda returned option %s", new_state->c_str());
}
}
if (!new_state.has_value()) {
auto map_it = std::find(this->mapping_.cbegin(), this->mapping_.cend(), value);
if (map_it != this->mapping_.cend()) {
size_t idx = std::distance(this->mapping_.cbegin(), map_it);
new_state = this->traits.get_options()[idx];
ESP_LOGV(TAG, "Found option %s for value %lld", new_state->c_str(), value);
} else {
ESP_LOGE(TAG, "No option found for mapping %lld", value);
}
}
if (new_state.has_value()) {
this->publish_state(new_state.value());
}
}
void FiltrationSelect::control(const std::string &value) {
auto options = this->traits.get_options();
auto opt_it = std::find(options.cbegin(), options.cend(), value);
size_t idx = std::distance(options.cbegin(), opt_it);
optional<int64_t> mapval = this->mapping_[idx];
ESP_LOGD(TAG, "Found value %lld for option '%s'", *mapval, value.c_str());
std::vector<uint16_t> data;
if (this->write_transform_func_.has_value()) {
auto val = (*this->write_transform_func_)(this, value, *mapval, data);
if (val.has_value()) {
mapval = *val;
ESP_LOGV(TAG, "write_lambda returned mapping value %lld", *mapval);
} else {
ESP_LOGD(TAG, "Communication handled by write_lambda - exiting control");
return;
}
}
if (data.empty()) {
number_to_payload(data, *mapval, this->sensor_value_type);
} else {
ESP_LOGV(TAG, "Using payload from write lambda");
}
if (data.empty()) {
ESP_LOGW(TAG, "No payload was created for updating select");
return;
}
const uint16_t write_address = this->start_address + this->offset / 2;
ModbusCommandItem write_cmd;
if ((this->register_count == 1) && (!this->use_write_multiple_)) {
write_cmd = ModbusCommandItem::create_write_single_command(parent_, write_address, data[0]);
} else {
write_cmd = ModbusCommandItem::create_write_multiple_command(parent_, write_address, this->register_count, data);
}
parent_->queue_command(write_cmd);
if (this->optimistic_)
this->publish_state(value);
}
}
}

View File

@@ -0,0 +1,56 @@
#pragma once
#include <utility>
#include <vector>
#include "esphome/components/modbus_controller/modbus_controller.h"
#include "esphome/components/select/select.h"
#include "esphome/core/component.h"
namespace esphome {
namespace neopool {
/**
* @brief Controls the filtration mode of the Neopool device connected via modbus
*
* Possible states:
* - automatic
* - off
* - slow
* - medium
* - fast
*
* To read the state:
* reads relay register 0x010E, with bitmasks
* - 0x0100 slow
* - 0x0200 medium
* - 0x0400 high
* - 0x0010 filtering
* auto / non-auto: 0x0411:
* - MBV_PAR_FILT_MANUAL = 0, // This mode allows to turn the filtration (and all other systems that depend on it) on and off manually.
* MBV_PAR_FILT_AUTO = 1, // This mode allows filtering to be turned on and off according to the settings of the TIMER1, TIMER2 and TIMER3 timers.
*
* To set the manual state:
* set filtration speed to addr 0x050F (MBF_PAR_FILTRATION_CONF), register needs to be read first to be correctly modified
* set MBF_EXEC to 1
* set filtration mode to manual (=0) via MBF_PAR_FILT_MODE (0x0411)
* set manual mode filtration to on 0x0413 to 0, 1, 2, ?
*
*/
class FiltrationMode : public Component, public select::Select {
public:
void set_parent(ModbusController *const parent) { this->parent_ = parent; }
void dump_config() override;
void control(const std::string &value) override;
protected:
ModbusController *parent_;
};
} // namespace modbus_controller
} // namespace esphome