From d779f1e929e0e43424ddf7e948aefb7c883ae9c6 Mon Sep 17 00:00:00 2001 From: Pieter Kokx Date: Sun, 17 Nov 2024 16:25:42 +0100 Subject: [PATCH] Created CO2 sensor --- esphome/components/duco/sensor/__init__.py | 49 ++++++++++++++++++++++ esphome/components/duco/sensor/sensor.cpp | 37 ++++++++++++++++ esphome/components/duco/sensor/sensor.h | 27 ++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 esphome/components/duco/sensor/__init__.py create mode 100644 esphome/components/duco/sensor/sensor.cpp create mode 100644 esphome/components/duco/sensor/sensor.h diff --git a/esphome/components/duco/sensor/__init__.py b/esphome/components/duco/sensor/__init__.py new file mode 100644 index 0000000000..abd697e705 --- /dev/null +++ b/esphome/components/duco/sensor/__init__.py @@ -0,0 +1,49 @@ +import esphome.codegen as cg +from esphome.components import sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_ADDRESS, + CONF_CO2, + CONF_ID, + DEVICE_CLASS_CARBON_DIOXIDE, + STATE_CLASS_MEASUREMENT, + UNIT_PARTS_PER_MILLION, +) + +from .. import CONF_DUCO_ID, DUCO_COMPONENT_SCHEMA + +DEPENDENCIES = ["duco"] +CODEOWNERS = ["@kokx"] + +duco_ns = cg.esphome_ns.namespace("duco") +DucoCo2Sensor = duco_ns.class_("DucoCo2Sensor", cg.PollingComponent, sensor.Sensor) + +CONFIG_SCHEMA = cv.Schema( + { + cv.Optional(CONF_CO2): cv.ensure_list( + sensor.sensor_schema( + unit_of_measurement=UNIT_PARTS_PER_MILLION, + accuracy_decimals=0, + device_class=DEVICE_CLASS_CARBON_DIOXIDE, + state_class=STATE_CLASS_MEASUREMENT, + ) + .extend( + { + cv.GenerateID(): cv.declare_id(DucoCo2Sensor), + cv.Required(CONF_ADDRESS): cv.int_range(0, 68), + } + ) + .extend(cv.polling_component_schema("60s")) + ) + } +).extend(DUCO_COMPONENT_SCHEMA) + + +async def to_code(config): + parent = await cg.get_variable(config[CONF_DUCO_ID]) + for co2_sensor_config in config[CONF_CO2]: + sensvar = cg.new_Pvariable(co2_sensor_config[CONF_ID]) + await cg.register_component(sensvar, co2_sensor_config) + await sensor.register_sensor(sensvar, co2_sensor_config) + cg.add(sensvar.set_parent(parent)) + cg.add(sensvar.set_address(co2_sensor_config[CONF_ADDRESS])) diff --git a/esphome/components/duco/sensor/sensor.cpp b/esphome/components/duco/sensor/sensor.cpp new file mode 100644 index 0000000000..b0a7168ceb --- /dev/null +++ b/esphome/components/duco/sensor/sensor.cpp @@ -0,0 +1,37 @@ +#include "sensor.h" +#include "../duco.h" +#include + +namespace esphome { +namespace duco { + +static const char *const TAG = "duco sensor"; + +void DucoCo2Sensor::setup() {} + +void DucoCo2Sensor::update() { + // ask for current mode + ESP_LOGD(TAG, "CO2: Get sensor information"); + + std::vector message = {0x01, address_, 0x00, 0x49, 0x04}; + this->parent_->send(0x10, message, this); +} + +float DucoCo2Sensor::get_setup_priority() const { + // After DUCO + return setup_priority::BUS - 2.0f; +} + +void DucoCo2Sensor::receive_response(std::vector message) { + if (message[1] == 0x12) { + uint16_t co2_value = (message[8] << 8) + message[7]; + publish_state(co2_value); + + this->parent_->stop_waiting(message[2]); + } +} + +void DucoCo2Sensor::set_address(uint8_t address) { this->address_ = address; } + +} // namespace duco +} // namespace esphome diff --git a/esphome/components/duco/sensor/sensor.h b/esphome/components/duco/sensor/sensor.h new file mode 100644 index 0000000000..a423f74b2f --- /dev/null +++ b/esphome/components/duco/sensor/sensor.h @@ -0,0 +1,27 @@ +#pragma once + +#include "esphome/core/log.h" +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "../duco.h" + +namespace esphome { +namespace duco { + +class DucoCo2Sensor : public DucoDevice, public PollingComponent, public sensor::Sensor { + public: + void setup() override; + void update() override; + + float get_setup_priority() const override; + + void receive_response(std::vector message) override; + + void set_address(uint8_t address); + + protected: + uint8_t address_; +}; + +} // namespace duco +} // namespace esphome