mirror of
https://github.com/esphome/esphome.git
synced 2024-11-25 00:18:11 +01:00
BedJet: expose the outlet temperature on the climate and as a sensor (#6633)
This commit is contained in:
parent
1f29023c92
commit
773951d85e
12 changed files with 168 additions and 9 deletions
|
@ -51,6 +51,7 @@ esphome/components/bang_bang/* @OttoWinter
|
||||||
esphome/components/bedjet/* @jhansche
|
esphome/components/bedjet/* @jhansche
|
||||||
esphome/components/bedjet/climate/* @jhansche
|
esphome/components/bedjet/climate/* @jhansche
|
||||||
esphome/components/bedjet/fan/* @jhansche
|
esphome/components/bedjet/fan/* @jhansche
|
||||||
|
esphome/components/bedjet/sensor/* @javawizard @jhansche
|
||||||
esphome/components/bh1750/* @OttoWinter
|
esphome/components/bh1750/* @OttoWinter
|
||||||
esphome/components/binary_sensor/* @esphome/core
|
esphome/components/binary_sensor/* @esphome/core
|
||||||
esphome/components/bk72xx/* @kuba2k2
|
esphome/components/bk72xx/* @kuba2k2
|
||||||
|
|
|
@ -31,7 +31,7 @@ CONFIG_SCHEMA = (
|
||||||
|
|
||||||
BEDJET_CLIENT_SCHEMA = cv.Schema(
|
BEDJET_CLIENT_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_BEDJET_ID): cv.use_id(BedJetHub),
|
cv.GenerateID(CONF_BEDJET_ID): cv.use_id(BedJetHub),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -157,5 +157,11 @@ bool BedjetCodec::compare(const uint8_t *data, uint16_t length) {
|
||||||
return explicit_fields_changed;
|
return explicit_fields_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts a BedJet temp step into degrees Celsius.
|
||||||
|
float bedjet_temp_to_c(uint8_t temp) {
|
||||||
|
// BedJet temp is "C*2"; to get C, divide by 2.
|
||||||
|
return temp / 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace bedjet
|
} // namespace bedjet
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -187,5 +187,8 @@ class BedjetCodec {
|
||||||
BedjetStatusPacket buf_;
|
BedjetStatusPacket buf_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Converts a BedJet temp step into degrees Celsius.
|
||||||
|
float bedjet_temp_to_c(uint8_t temp);
|
||||||
|
|
||||||
} // namespace bedjet
|
} // namespace bedjet
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -40,6 +40,14 @@ enum BedjetHeatMode {
|
||||||
HEAT_MODE_EXTENDED,
|
HEAT_MODE_EXTENDED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Which temperature to use as the climate entity's current temperature reading
|
||||||
|
enum BedjetTemperatureSource {
|
||||||
|
// Use the temperature of the air the BedJet is putting out
|
||||||
|
TEMPERATURE_SOURCE_OUTLET,
|
||||||
|
// Use the ambient temperature of the room the BedJet is in
|
||||||
|
TEMPERATURE_SOURCE_AMBIENT
|
||||||
|
};
|
||||||
|
|
||||||
enum BedjetButton : uint8_t {
|
enum BedjetButton : uint8_t {
|
||||||
/// Turn BedJet off
|
/// Turn BedJet off
|
||||||
BTN_OFF = 0x1,
|
BTN_OFF = 0x1,
|
||||||
|
|
|
@ -7,6 +7,7 @@ from esphome.const import (
|
||||||
CONF_HEAT_MODE,
|
CONF_HEAT_MODE,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_RECEIVE_TIMEOUT,
|
CONF_RECEIVE_TIMEOUT,
|
||||||
|
CONF_TEMPERATURE_SOURCE,
|
||||||
CONF_TIME_ID,
|
CONF_TIME_ID,
|
||||||
)
|
)
|
||||||
from .. import (
|
from .. import (
|
||||||
|
@ -21,10 +22,15 @@ DEPENDENCIES = ["bedjet"]
|
||||||
|
|
||||||
BedJetClimate = bedjet_ns.class_("BedJetClimate", climate.Climate, cg.PollingComponent)
|
BedJetClimate = bedjet_ns.class_("BedJetClimate", climate.Climate, cg.PollingComponent)
|
||||||
BedjetHeatMode = bedjet_ns.enum("BedjetHeatMode")
|
BedjetHeatMode = bedjet_ns.enum("BedjetHeatMode")
|
||||||
|
BedjetTemperatureSource = bedjet_ns.enum("BedjetTemperatureSource")
|
||||||
BEDJET_HEAT_MODES = {
|
BEDJET_HEAT_MODES = {
|
||||||
"heat": BedjetHeatMode.HEAT_MODE_HEAT,
|
"heat": BedjetHeatMode.HEAT_MODE_HEAT,
|
||||||
"extended": BedjetHeatMode.HEAT_MODE_EXTENDED,
|
"extended": BedjetHeatMode.HEAT_MODE_EXTENDED,
|
||||||
}
|
}
|
||||||
|
BEDJET_TEMPERATURE_SOURCES = {
|
||||||
|
"outlet": BedjetTemperatureSource.TEMPERATURE_SOURCE_OUTLET,
|
||||||
|
"ambient": BedjetTemperatureSource.TEMPERATURE_SOURCE_AMBIENT,
|
||||||
|
}
|
||||||
|
|
||||||
CONFIG_SCHEMA = (
|
CONFIG_SCHEMA = (
|
||||||
climate.CLIMATE_SCHEMA.extend(
|
climate.CLIMATE_SCHEMA.extend(
|
||||||
|
@ -33,6 +39,9 @@ CONFIG_SCHEMA = (
|
||||||
cv.Optional(CONF_HEAT_MODE, default="heat"): cv.enum(
|
cv.Optional(CONF_HEAT_MODE, default="heat"): cv.enum(
|
||||||
BEDJET_HEAT_MODES, lower=True
|
BEDJET_HEAT_MODES, lower=True
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_TEMPERATURE_SOURCE, default="ambient"): cv.enum(
|
||||||
|
BEDJET_TEMPERATURE_SOURCES, lower=True
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.extend(cv.polling_component_schema("60s"))
|
.extend(cv.polling_component_schema("60s"))
|
||||||
|
@ -63,3 +72,4 @@ async def to_code(config):
|
||||||
await register_bedjet_child(var, config)
|
await register_bedjet_child(var, config)
|
||||||
|
|
||||||
cg.add(var.set_heating_mode(config[CONF_HEAT_MODE]))
|
cg.add(var.set_heating_mode(config[CONF_HEAT_MODE]))
|
||||||
|
cg.add(var.set_temperature_source(config[CONF_TEMPERATURE_SOURCE]))
|
||||||
|
|
|
@ -8,12 +8,6 @@ namespace bedjet {
|
||||||
|
|
||||||
using namespace esphome::climate;
|
using namespace esphome::climate;
|
||||||
|
|
||||||
/// Converts a BedJet temp step into degrees Celsius.
|
|
||||||
float bedjet_temp_to_c(const uint8_t temp) {
|
|
||||||
// BedJet temp is "C*2"; to get C, divide by 2.
|
|
||||||
return temp / 2.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const std::string *bedjet_fan_step_to_fan_mode(const uint8_t fan_step) {
|
static const std::string *bedjet_fan_step_to_fan_mode(const uint8_t fan_step) {
|
||||||
if (fan_step < BEDJET_FAN_SPEED_COUNT)
|
if (fan_step < BEDJET_FAN_SPEED_COUNT)
|
||||||
return &BEDJET_FAN_STEP_NAME_STRINGS[fan_step];
|
return &BEDJET_FAN_STEP_NAME_STRINGS[fan_step];
|
||||||
|
@ -236,9 +230,14 @@ void BedJetClimate::on_status(const BedjetStatusPacket *data) {
|
||||||
if (converted_temp > 0)
|
if (converted_temp > 0)
|
||||||
this->target_temperature = converted_temp;
|
this->target_temperature = converted_temp;
|
||||||
|
|
||||||
converted_temp = bedjet_temp_to_c(data->ambient_temp_step);
|
if (this->temperature_source_ == TEMPERATURE_SOURCE_OUTLET) {
|
||||||
if (converted_temp > 0)
|
converted_temp = bedjet_temp_to_c(data->actual_temp_step);
|
||||||
|
} else {
|
||||||
|
converted_temp = bedjet_temp_to_c(data->ambient_temp_step);
|
||||||
|
}
|
||||||
|
if (converted_temp > 0) {
|
||||||
this->current_temperature = converted_temp;
|
this->current_temperature = converted_temp;
|
||||||
|
}
|
||||||
|
|
||||||
const auto *fan_mode_name = bedjet_fan_step_to_fan_mode(data->fan_step);
|
const auto *fan_mode_name = bedjet_fan_step_to_fan_mode(data->fan_step);
|
||||||
if (fan_mode_name != nullptr) {
|
if (fan_mode_name != nullptr) {
|
||||||
|
|
|
@ -28,6 +28,8 @@ class BedJetClimate : public climate::Climate, public BedJetClient, public Polli
|
||||||
|
|
||||||
/** Sets the default strategy to use for climate::CLIMATE_MODE_HEAT. */
|
/** Sets the default strategy to use for climate::CLIMATE_MODE_HEAT. */
|
||||||
void set_heating_mode(BedjetHeatMode mode) { this->heating_mode_ = mode; }
|
void set_heating_mode(BedjetHeatMode mode) { this->heating_mode_ = mode; }
|
||||||
|
/** Sets the temperature source to use for the climate entity's current temperature */
|
||||||
|
void set_temperature_source(BedjetTemperatureSource source) { this->temperature_source_ = source; }
|
||||||
|
|
||||||
climate::ClimateTraits traits() override {
|
climate::ClimateTraits traits() override {
|
||||||
auto traits = climate::ClimateTraits();
|
auto traits = climate::ClimateTraits();
|
||||||
|
@ -74,6 +76,7 @@ class BedJetClimate : public climate::Climate, public BedJetClient, public Polli
|
||||||
void control(const climate::ClimateCall &call) override;
|
void control(const climate::ClimateCall &call) override;
|
||||||
|
|
||||||
BedjetHeatMode heating_mode_ = HEAT_MODE_HEAT;
|
BedjetHeatMode heating_mode_ = HEAT_MODE_HEAT;
|
||||||
|
BedjetTemperatureSource temperature_source_ = TEMPERATURE_SOURCE_AMBIENT;
|
||||||
|
|
||||||
void reset_state_();
|
void reset_state_();
|
||||||
bool update_status_();
|
bool update_status_();
|
||||||
|
|
55
esphome/components/bedjet/sensor/__init__.py
Normal file
55
esphome/components/bedjet/sensor/__init__.py
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import sensor
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_ID,
|
||||||
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
UNIT_CELSIUS,
|
||||||
|
)
|
||||||
|
from .. import (
|
||||||
|
BEDJET_CLIENT_SCHEMA,
|
||||||
|
bedjet_ns,
|
||||||
|
register_bedjet_child,
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
CODEOWNERS = ["@jhansche", "@javawizard"]
|
||||||
|
DEPENDENCIES = ["bedjet"]
|
||||||
|
|
||||||
|
CONF_OUTLET_TEMPERATURE = "outlet_temperature"
|
||||||
|
CONF_AMBIENT_TEMPERATURE = "ambient_temperature"
|
||||||
|
|
||||||
|
BedjetSensor = bedjet_ns.class_("BedjetSensor", cg.Component)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(BedjetSensor),
|
||||||
|
cv.Optional(CONF_OUTLET_TEMPERATURE): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_CELSIUS,
|
||||||
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_AMBIENT_TEMPERATURE): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_CELSIUS,
|
||||||
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
).extend(BEDJET_CLIENT_SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await register_bedjet_child(var, config)
|
||||||
|
|
||||||
|
if outlet_temperature_sensor := config.get(CONF_OUTLET_TEMPERATURE):
|
||||||
|
sensor_var = await sensor.new_sensor(outlet_temperature_sensor)
|
||||||
|
cg.add(var.set_outlet_temperature_sensor(sensor_var))
|
||||||
|
|
||||||
|
if ambient_temperature_sensor := config.get(CONF_AMBIENT_TEMPERATURE):
|
||||||
|
sensor_var = await sensor.new_sensor(ambient_temperature_sensor)
|
||||||
|
cg.add(var.set_ambient_temperature_sensor(sensor_var))
|
34
esphome/components/bedjet/sensor/bedjet_sensor.cpp
Normal file
34
esphome/components/bedjet/sensor/bedjet_sensor.cpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#include "bedjet_sensor.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace bedjet {
|
||||||
|
|
||||||
|
std::string BedjetSensor::describe() { return "BedJet Sensor"; }
|
||||||
|
|
||||||
|
void BedjetSensor::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "BedJet Sensor:");
|
||||||
|
LOG_SENSOR(" ", "Outlet Temperature", this->outlet_temperature_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Ambient Temperature", this->ambient_temperature_sensor_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedjetSensor::on_bedjet_state(bool is_ready) {}
|
||||||
|
|
||||||
|
void BedjetSensor::on_status(const BedjetStatusPacket *data) {
|
||||||
|
if (this->outlet_temperature_sensor_ != nullptr) {
|
||||||
|
float converted_temp = bedjet_temp_to_c(data->actual_temp_step);
|
||||||
|
if (converted_temp > 0) {
|
||||||
|
this->outlet_temperature_sensor_->publish_state(converted_temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->ambient_temperature_sensor_ != nullptr) {
|
||||||
|
float converted_temp = bedjet_temp_to_c(data->ambient_temp_step);
|
||||||
|
if (converted_temp > 0) {
|
||||||
|
this->ambient_temperature_sensor_->publish_state(converted_temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace bedjet
|
||||||
|
} // namespace esphome
|
32
esphome/components/bedjet/sensor/bedjet_sensor.h
Normal file
32
esphome/components/bedjet/sensor/bedjet_sensor.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/components/bedjet/bedjet_child.h"
|
||||||
|
#include "esphome/components/bedjet/bedjet_codec.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace bedjet {
|
||||||
|
|
||||||
|
class BedjetSensor : public BedJetClient, public Component {
|
||||||
|
public:
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
void on_status(const BedjetStatusPacket *data) override;
|
||||||
|
void on_bedjet_state(bool is_ready) override;
|
||||||
|
std::string describe() override;
|
||||||
|
|
||||||
|
void set_outlet_temperature_sensor(sensor::Sensor *outlet_temperature_sensor) {
|
||||||
|
this->outlet_temperature_sensor_ = outlet_temperature_sensor;
|
||||||
|
}
|
||||||
|
void set_ambient_temperature_sensor(sensor::Sensor *ambient_temperature_sensor) {
|
||||||
|
this->ambient_temperature_sensor_ = ambient_temperature_sensor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
sensor::Sensor *outlet_temperature_sensor_{nullptr};
|
||||||
|
sensor::Sensor *ambient_temperature_sensor_{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace bedjet
|
||||||
|
} // namespace esphome
|
|
@ -26,8 +26,16 @@ climate:
|
||||||
name: My Bedjet
|
name: My Bedjet
|
||||||
bedjet_id: bedjet_hub
|
bedjet_id: bedjet_hub
|
||||||
heat_mode: extended
|
heat_mode: extended
|
||||||
|
temperature_source: ambient
|
||||||
|
|
||||||
fan:
|
fan:
|
||||||
- platform: bedjet
|
- platform: bedjet
|
||||||
name: My Bedjet fan
|
name: My Bedjet fan
|
||||||
bedjet_id: bedjet_hub
|
bedjet_id: bedjet_hub
|
||||||
|
|
||||||
|
sensor:
|
||||||
|
- platform: bedjet
|
||||||
|
ambient_temperature:
|
||||||
|
name: My BedJet Ambient Temperature
|
||||||
|
outlet_temperature:
|
||||||
|
name: My BedJet Outlet Temperature
|
||||||
|
|
Loading…
Reference in a new issue