mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	BedJet: expose the outlet temperature on the climate and as a sensor (#6633)
This commit is contained in:
		| @@ -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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user