mirror of
https://github.com/esphome/esphome.git
synced 2024-11-25 00:18:11 +01:00
Add BedJet Fan child component (#3735)
This commit is contained in:
parent
768490089e
commit
6d5cb866db
9 changed files with 203 additions and 14 deletions
|
@ -29,6 +29,8 @@ esphome/components/b_parasite/* @rbaron
|
||||||
esphome/components/ballu/* @bazuchan
|
esphome/components/ballu/* @bazuchan
|
||||||
esphome/components/bang_bang/* @OttoWinter
|
esphome/components/bang_bang/* @OttoWinter
|
||||||
esphome/components/bedjet/* @jhansche
|
esphome/components/bedjet/* @jhansche
|
||||||
|
esphome/components/bedjet/climate/* @jhansche
|
||||||
|
esphome/components/bedjet/fan/* @jhansche
|
||||||
esphome/components/bh1750/* @OttoWinter
|
esphome/components/bh1750/* @OttoWinter
|
||||||
esphome/components/binary_sensor/* @esphome/core
|
esphome/components/binary_sensor/* @esphome/core
|
||||||
esphome/components/bl0939/* @ziceva
|
esphome/components/bl0939/* @ziceva
|
||||||
|
|
|
@ -89,8 +89,10 @@ enum BedjetCommand : uint8_t {
|
||||||
"85%", "90%", "95%", "100%" \
|
"85%", "90%", "95%", "100%" \
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *const BEDJET_FAN_STEP_NAMES[20] = BEDJET_FAN_STEP_NAMES_;
|
static const uint8_t BEDJET_FAN_SPEED_COUNT = 20;
|
||||||
static const std::string BEDJET_FAN_STEP_NAME_STRINGS[20] = BEDJET_FAN_STEP_NAMES_;
|
|
||||||
|
static const char *const BEDJET_FAN_STEP_NAMES[BEDJET_FAN_SPEED_COUNT] = BEDJET_FAN_STEP_NAMES_;
|
||||||
|
static const std::string BEDJET_FAN_STEP_NAME_STRINGS[BEDJET_FAN_SPEED_COUNT] = BEDJET_FAN_STEP_NAMES_;
|
||||||
static const std::set<std::string> BEDJET_FAN_STEP_NAMES_SET BEDJET_FAN_STEP_NAMES_;
|
static const std::set<std::string> BEDJET_FAN_STEP_NAMES_SET BEDJET_FAN_STEP_NAMES_;
|
||||||
|
|
||||||
} // namespace bedjet
|
} // namespace bedjet
|
||||||
|
|
|
@ -9,19 +9,17 @@ from esphome.const import (
|
||||||
CONF_RECEIVE_TIMEOUT,
|
CONF_RECEIVE_TIMEOUT,
|
||||||
CONF_TIME_ID,
|
CONF_TIME_ID,
|
||||||
)
|
)
|
||||||
from . import (
|
from .. import (
|
||||||
BEDJET_CLIENT_SCHEMA,
|
BEDJET_CLIENT_SCHEMA,
|
||||||
|
bedjet_ns,
|
||||||
register_bedjet_child,
|
register_bedjet_child,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
CODEOWNERS = ["@jhansche"]
|
CODEOWNERS = ["@jhansche"]
|
||||||
DEPENDENCIES = ["ble_client"]
|
DEPENDENCIES = ["bedjet"]
|
||||||
|
|
||||||
bedjet_ns = cg.esphome_ns.namespace("bedjet")
|
BedJetClimate = bedjet_ns.class_("BedJetClimate", climate.Climate, cg.PollingComponent)
|
||||||
BedJetClimate = bedjet_ns.class_(
|
|
||||||
"BedJetClimate", climate.Climate, ble_client.BLEClientNode, cg.PollingComponent
|
|
||||||
)
|
|
||||||
BedjetHeatMode = bedjet_ns.enum("BedjetHeatMode")
|
BedjetHeatMode = bedjet_ns.enum("BedjetHeatMode")
|
||||||
BEDJET_HEAT_MODES = {
|
BEDJET_HEAT_MODES = {
|
||||||
"heat": BedjetHeatMode.HEAT_MODE_HEAT,
|
"heat": BedjetHeatMode.HEAT_MODE_HEAT,
|
|
@ -15,13 +15,13 @@ float bedjet_temp_to_c(const uint8_t temp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 <= 19)
|
if (fan_step < BEDJET_FAN_SPEED_COUNT)
|
||||||
return &BEDJET_FAN_STEP_NAME_STRINGS[fan_step];
|
return &BEDJET_FAN_STEP_NAME_STRINGS[fan_step];
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t bedjet_fan_speed_to_step(const std::string &fan_step_percent) {
|
static uint8_t bedjet_fan_speed_to_step(const std::string &fan_step_percent) {
|
||||||
for (int i = 0; i < sizeof(BEDJET_FAN_STEP_NAME_STRINGS); i++) {
|
for (int i = 0; i < BEDJET_FAN_SPEED_COUNT; i++) {
|
||||||
if (fan_step_percent == BEDJET_FAN_STEP_NAME_STRINGS[i]) {
|
if (fan_step_percent == BEDJET_FAN_STEP_NAME_STRINGS[i]) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "esphome/components/climate/climate.h"
|
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
#include "esphome/core/hal.h"
|
#include "esphome/core/hal.h"
|
||||||
#include "bedjet_child.h"
|
#include "esphome/components/bedjet/bedjet_child.h"
|
||||||
#include "bedjet_codec.h"
|
#include "esphome/components/bedjet/bedjet_codec.h"
|
||||||
#include "bedjet_hub.h"
|
#include "esphome/components/bedjet/bedjet_hub.h"
|
||||||
|
#include "esphome/components/climate/climate.h"
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
36
esphome/components/bedjet/fan/__init__.py
Normal file
36
esphome/components/bedjet/fan/__init__.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import fan
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_ID,
|
||||||
|
)
|
||||||
|
from .. import (
|
||||||
|
BEDJET_CLIENT_SCHEMA,
|
||||||
|
bedjet_ns,
|
||||||
|
register_bedjet_child,
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
CODEOWNERS = ["@jhansche"]
|
||||||
|
DEPENDENCIES = ["bedjet"]
|
||||||
|
|
||||||
|
BedJetFan = bedjet_ns.class_("BedJetFan", fan.Fan, cg.PollingComponent)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
fan.FAN_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(BedJetFan),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(cv.polling_component_schema("60s"))
|
||||||
|
.extend(BEDJET_CLIENT_SCHEMA)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await fan.register_fan(var, config)
|
||||||
|
await register_bedjet_child(var, config)
|
108
esphome/components/bedjet/fan/bedjet_fan.cpp
Normal file
108
esphome/components/bedjet/fan/bedjet_fan.cpp
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
#include "bedjet_fan.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace bedjet {
|
||||||
|
|
||||||
|
using namespace esphome::fan;
|
||||||
|
|
||||||
|
void BedJetFan::dump_config() { LOG_FAN("", "BedJet Fan", this); }
|
||||||
|
std::string BedJetFan::describe() { return "BedJet Fan"; }
|
||||||
|
|
||||||
|
void BedJetFan::control(const fan::FanCall &call) {
|
||||||
|
ESP_LOGD(TAG, "Received BedJetFan::control");
|
||||||
|
if (!this->parent_->is_connected()) {
|
||||||
|
ESP_LOGW(TAG, "Not connected, cannot handle control call yet.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool did_change = false;
|
||||||
|
|
||||||
|
if (call.get_state().has_value() && this->state != *call.get_state()) {
|
||||||
|
// Turning off is easy:
|
||||||
|
if (this->state && this->parent_->button_off()) {
|
||||||
|
this->state = false;
|
||||||
|
this->publish_state();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turning on, we have to choose a specific mode; for now, use "COOL" mode
|
||||||
|
// In the future we could configure the mode to use for fan.turn_on.
|
||||||
|
if (this->parent_->button_cool()) {
|
||||||
|
this->state = true;
|
||||||
|
did_change = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore speed changes if not on or turning on
|
||||||
|
if (this->state && call.get_speed().has_value()) {
|
||||||
|
this->speed = *call.get_speed();
|
||||||
|
this->parent_->set_fan_index(this->speed);
|
||||||
|
did_change = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (did_change) {
|
||||||
|
this->publish_state();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedJetFan::on_status(const BedjetStatusPacket *data) {
|
||||||
|
ESP_LOGVV(TAG, "[%s] Handling on_status with data=%p", this->get_name().c_str(), (void *) data);
|
||||||
|
bool did_change = false;
|
||||||
|
bool new_state = data->mode != MODE_STANDBY && data->mode != MODE_WAIT;
|
||||||
|
|
||||||
|
if (new_state != this->state) {
|
||||||
|
this->state = new_state;
|
||||||
|
did_change = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->fan_step != this->speed) {
|
||||||
|
this->speed = data->fan_step;
|
||||||
|
did_change = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (did_change) {
|
||||||
|
this->publish_state();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Attempts to update the fan device from the last received BedjetStatusPacket.
|
||||||
|
*
|
||||||
|
* This will be called from #on_status() when the parent dispatches new status packets,
|
||||||
|
* and from #update() when the polling interval is triggered.
|
||||||
|
*
|
||||||
|
* @return `true` if the status has been applied; `false` if there is nothing to apply.
|
||||||
|
*/
|
||||||
|
bool BedJetFan::update_status_() {
|
||||||
|
if (!this->parent_->is_connected())
|
||||||
|
return false;
|
||||||
|
if (!this->parent_->has_status())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto *status = this->parent_->get_status_packet();
|
||||||
|
|
||||||
|
if (status == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this->on_status(status);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedJetFan::update() {
|
||||||
|
ESP_LOGD(TAG, "[%s] update()", this->get_name().c_str());
|
||||||
|
// TODO: if the hub component is already polling, do we also need to include polling?
|
||||||
|
// We're already going to get on_status() at the hub's polling interval.
|
||||||
|
auto result = this->update_status_();
|
||||||
|
ESP_LOGD(TAG, "[%s] update_status result=%s", this->get_name().c_str(), result ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resets states to defaults. */
|
||||||
|
void BedJetFan::reset_state_() {
|
||||||
|
this->state = false;
|
||||||
|
this->publish_state();
|
||||||
|
}
|
||||||
|
} // namespace bedjet
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif
|
40
esphome/components/bedjet/fan/bedjet_fan.h
Normal file
40
esphome/components/bedjet/fan/bedjet_fan.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/defines.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
#include "esphome/components/bedjet/bedjet_child.h"
|
||||||
|
#include "esphome/components/bedjet/bedjet_codec.h"
|
||||||
|
#include "esphome/components/bedjet/bedjet_hub.h"
|
||||||
|
#include "esphome/components/fan/fan.h"
|
||||||
|
|
||||||
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace bedjet {
|
||||||
|
|
||||||
|
class BedJetFan : public fan::Fan, public BedJetClient, public PollingComponent {
|
||||||
|
public:
|
||||||
|
void update() override;
|
||||||
|
void dump_config() override;
|
||||||
|
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||||
|
|
||||||
|
/* BedJetClient status update */
|
||||||
|
void on_status(const BedjetStatusPacket *data) override;
|
||||||
|
void on_bedjet_state(bool is_ready) override{};
|
||||||
|
std::string describe() override;
|
||||||
|
|
||||||
|
fan::FanTraits get_traits() override { return fan::FanTraits(false, true, false, BEDJET_FAN_SPEED_COUNT); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void control(const fan::FanCall &call) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void reset_state_();
|
||||||
|
bool update_status_();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace bedjet
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif
|
|
@ -2219,6 +2219,9 @@ fan:
|
||||||
on_speed_set:
|
on_speed_set:
|
||||||
then:
|
then:
|
||||||
- logger.log: "Fan speed was changed!"
|
- logger.log: "Fan speed was changed!"
|
||||||
|
- platform: bedjet
|
||||||
|
name: My Bedjet fan
|
||||||
|
bedjet_id: my_bedjet_client
|
||||||
- platform: copy
|
- platform: copy
|
||||||
source_id: fan_speed
|
source_id: fan_speed
|
||||||
name: "Fan Speed Copy"
|
name: "Fan Speed Copy"
|
||||||
|
|
Loading…
Reference in a new issue