mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	[BedJet] Add configurable heating strategy (#3519)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		| @@ -36,6 +36,14 @@ static uint8_t bedjet_fan_speed_to_step(const std::string &fan_step_percent) { | ||||
|   return -1; | ||||
| } | ||||
|  | ||||
| static BedjetButton heat_button(BedjetHeatMode mode) { | ||||
|   BedjetButton btn = BTN_HEAT; | ||||
|   if (mode == HEAT_MODE_EXTENDED) { | ||||
|     btn = BTN_EXTHT; | ||||
|   } | ||||
|   return btn; | ||||
| } | ||||
|  | ||||
| void Bedjet::upgrade_firmware() { | ||||
|   auto *pkt = this->codec_->get_button_request(MAGIC_UPDATE); | ||||
|   auto status = this->write_bedjet_packet_(pkt); | ||||
| @@ -117,7 +125,7 @@ void Bedjet::control(const ClimateCall &call) { | ||||
|         pkt = this->codec_->get_button_request(BTN_OFF); | ||||
|         break; | ||||
|       case climate::CLIMATE_MODE_HEAT: | ||||
|         pkt = this->codec_->get_button_request(BTN_HEAT); | ||||
|         pkt = this->codec_->get_button_request(heat_button(this->heating_mode_)); | ||||
|         break; | ||||
|       case climate::CLIMATE_MODE_FAN_ONLY: | ||||
|         pkt = this->codec_->get_button_request(BTN_COOL); | ||||
| @@ -186,6 +194,8 @@ void Bedjet::control(const ClimateCall &call) { | ||||
|       pkt = this->codec_->get_button_request(BTN_M2); | ||||
|     } else if (preset == "M3") { | ||||
|       pkt = this->codec_->get_button_request(BTN_M3); | ||||
|     } else if (preset == "LTD HT") { | ||||
|       pkt = this->codec_->get_button_request(BTN_HEAT); | ||||
|     } else if (preset == "EXT HT") { | ||||
|       pkt = this->codec_->get_button_request(BTN_EXTHT); | ||||
|     } else { | ||||
| @@ -557,11 +567,25 @@ bool Bedjet::update_status_() { | ||||
|       break; | ||||
|  | ||||
|     case MODE_HEAT: | ||||
|       this->mode = climate::CLIMATE_MODE_HEAT; | ||||
|       this->action = climate::CLIMATE_ACTION_HEATING; | ||||
|       this->preset.reset(); | ||||
|       if (this->heating_mode_ == HEAT_MODE_EXTENDED) { | ||||
|         this->set_custom_preset_("LTD HT"); | ||||
|       } else { | ||||
|         this->custom_preset.reset(); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case MODE_EXTHT: | ||||
|       this->mode = climate::CLIMATE_MODE_HEAT; | ||||
|       this->action = climate::CLIMATE_ACTION_HEATING; | ||||
|       this->custom_preset.reset(); | ||||
|       this->preset.reset(); | ||||
|       if (this->heating_mode_ == HEAT_MODE_EXTENDED) { | ||||
|         this->custom_preset.reset(); | ||||
|       } else { | ||||
|         this->set_custom_preset_("EXT HT"); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case MODE_COOL: | ||||
|   | ||||
| @@ -40,6 +40,8 @@ class Bedjet : public climate::Climate, public esphome::ble_client::BLEClientNod | ||||
|   void set_time_id(time::RealTimeClock *time_id) { this->time_id_ = time_id; } | ||||
| #endif | ||||
|   void set_status_timeout(uint32_t timeout) { this->timeout_ = timeout; } | ||||
|   /** Sets the default strategy to use for climate::CLIMATE_MODE_HEAT. */ | ||||
|   void set_heating_mode(BedjetHeatMode mode) { this->heating_mode_ = mode; } | ||||
|  | ||||
|   /** Attempts to check for and apply firmware updates. */ | ||||
|   void upgrade_firmware(); | ||||
| @@ -68,12 +70,15 @@ class Bedjet : public climate::Climate, public esphome::ble_client::BLEClientNod | ||||
|         // We could fetch biodata from bedjet and set these names that way. | ||||
|         // But then we have to invert the lookup in order to send the right preset. | ||||
|         // For now, we can leave them as M1-3 to match the remote buttons. | ||||
|         // EXT HT added to match remote button. | ||||
|         "EXT HT", | ||||
|         "M1", | ||||
|         "M2", | ||||
|         "M3", | ||||
|     }); | ||||
|     if (this->heating_mode_ == HEAT_MODE_EXTENDED) { | ||||
|       traits.add_supported_custom_preset("LTD HT"); | ||||
|     } else { | ||||
|       traits.add_supported_custom_preset("EXT HT"); | ||||
|     } | ||||
|     traits.set_visual_min_temperature(19.0); | ||||
|     traits.set_visual_max_temperature(43.0); | ||||
|     traits.set_visual_temperature_step(1.0); | ||||
| @@ -90,6 +95,7 @@ class Bedjet : public climate::Climate, public esphome::ble_client::BLEClientNod | ||||
| #endif | ||||
|  | ||||
|   uint32_t timeout_{DEFAULT_STATUS_TIMEOUT}; | ||||
|   BedjetHeatMode heating_mode_ = HEAT_MODE_HEAT; | ||||
|  | ||||
|   static const uint32_t MIN_NOTIFY_THROTTLE = 5000; | ||||
|   static const uint32_t NOTIFY_WARN_THRESHOLD = 300000; | ||||
|   | ||||
| @@ -24,6 +24,14 @@ enum BedjetMode : uint8_t { | ||||
|   MODE_WAIT = 6, | ||||
| }; | ||||
|  | ||||
| /** Optional heating strategies to use for climate::CLIMATE_MODE_HEAT. */ | ||||
| enum BedjetHeatMode { | ||||
|   /// HVACMode.HEAT is handled using BTN_HEAT (default) | ||||
|   HEAT_MODE_HEAT, | ||||
|   /// HVACMode.HEAT is handled using BTN_EXTHT | ||||
|   HEAT_MODE_EXTENDED, | ||||
| }; | ||||
|  | ||||
| enum BedjetButton : uint8_t { | ||||
|   /// Turn BedJet off | ||||
|   BTN_OFF = 0x1, | ||||
|   | ||||
| @@ -2,6 +2,7 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import climate, ble_client, time | ||||
| from esphome.const import ( | ||||
|     CONF_HEAT_MODE, | ||||
|     CONF_ID, | ||||
|     CONF_RECEIVE_TIMEOUT, | ||||
|     CONF_TIME_ID, | ||||
| @@ -14,11 +15,19 @@ bedjet_ns = cg.esphome_ns.namespace("bedjet") | ||||
| Bedjet = bedjet_ns.class_( | ||||
|     "Bedjet", climate.Climate, ble_client.BLEClientNode, cg.PollingComponent | ||||
| ) | ||||
| BedjetHeatMode = bedjet_ns.enum("BedjetHeatMode") | ||||
| BEDJET_HEAT_MODES = { | ||||
|     "heat": BedjetHeatMode.HEAT_MODE_HEAT, | ||||
|     "extended": BedjetHeatMode.HEAT_MODE_EXTENDED, | ||||
| } | ||||
|  | ||||
| CONFIG_SCHEMA = ( | ||||
|     climate.CLIMATE_SCHEMA.extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(Bedjet), | ||||
|             cv.Optional(CONF_HEAT_MODE, default="heat"): cv.enum( | ||||
|                 BEDJET_HEAT_MODES, lower=True | ||||
|             ), | ||||
|             cv.Optional(CONF_TIME_ID): cv.use_id(time.RealTimeClock), | ||||
|             cv.Optional( | ||||
|                 CONF_RECEIVE_TIMEOUT, default="0s" | ||||
| @@ -35,6 +44,7 @@ async def to_code(config): | ||||
|     await cg.register_component(var, config) | ||||
|     await climate.register_climate(var, config) | ||||
|     await ble_client.register_ble_node(var, config) | ||||
|     cg.add(var.set_heating_mode(config[CONF_HEAT_MODE])) | ||||
|     if CONF_TIME_ID in config: | ||||
|         time_ = await cg.get_variable(config[CONF_TIME_ID]) | ||||
|         cg.add(var.set_time_id(time_)) | ||||
|   | ||||
| @@ -1886,6 +1886,7 @@ climate: | ||||
|   - platform: bedjet | ||||
|     name: My Bedjet | ||||
|     ble_client_id: my_bedjet_ble_client | ||||
|     heat_mode: extended | ||||
|  | ||||
| script: | ||||
|   - id: climate_custom | ||||
|   | ||||
		Reference in New Issue
	
	Block a user