mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	RemoteTransmitter fix. Bug from version 2021.10. Some changes. (#2706)
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							04740fbcbb
						
					
				
				
					commit
					d99c5ed890
				
			| @@ -1,10 +1,11 @@ | ||||
| #ifdef USE_ARDUINO | ||||
| 
 | ||||
| #include "esphome/core/log.h" | ||||
| #include "adapter.h" | ||||
| #include "ac_adapter.h" | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace midea { | ||||
| namespace ac { | ||||
| 
 | ||||
| const char *const Constants::TAG = "midea"; | ||||
| const std::string Constants::FREEZE_PROTECTION = "freeze protection"; | ||||
| @@ -171,6 +172,7 @@ void Converters::to_climate_traits(ClimateTraits &traits, const dudanov::midea:: | ||||
|     traits.add_supported_custom_preset(Constants::FREEZE_PROTECTION); | ||||
| } | ||||
| 
 | ||||
| }  // namespace ac
 | ||||
| }  // namespace midea
 | ||||
| }  // namespace esphome
 | ||||
| 
 | ||||
| @@ -2,12 +2,15 @@ | ||||
| 
 | ||||
| #ifdef USE_ARDUINO | ||||
| 
 | ||||
| // MideaUART
 | ||||
| #include <Appliance/AirConditioner/AirConditioner.h> | ||||
| 
 | ||||
| #include "esphome/components/climate/climate_traits.h" | ||||
| #include "appliance_base.h" | ||||
| #include "air_conditioner.h" | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace midea { | ||||
| namespace ac { | ||||
| 
 | ||||
| using MideaMode = dudanov::midea::ac::Mode; | ||||
| using MideaSwingMode = dudanov::midea::ac::SwingMode; | ||||
| @@ -41,6 +44,7 @@ class Converters { | ||||
|   static void to_climate_traits(ClimateTraits &traits, const dudanov::midea::ac::Capabilities &capabilities); | ||||
| }; | ||||
| 
 | ||||
| }  // namespace ac
 | ||||
| }  // namespace midea
 | ||||
| }  // namespace esphome
 | ||||
| 
 | ||||
| @@ -7,6 +7,7 @@ | ||||
| 
 | ||||
| namespace esphome { | ||||
| namespace midea { | ||||
| namespace ac { | ||||
| 
 | ||||
| template<typename... Ts> class MideaActionBase : public Action<Ts...> { | ||||
|  public: | ||||
| @@ -55,6 +56,7 @@ template<typename... Ts> class PowerOffAction : public MideaActionBase<Ts...> { | ||||
|   void play(Ts... x) override { this->parent_->do_power_off(); } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace ac
 | ||||
| }  // namespace midea
 | ||||
| }  // namespace esphome
 | ||||
| 
 | ||||
| @@ -2,13 +2,11 @@ | ||||
|  | ||||
| #include "esphome/core/log.h" | ||||
| #include "air_conditioner.h" | ||||
| #include "adapter.h" | ||||
| #ifdef USE_REMOTE_TRANSMITTER | ||||
| #include "midea_ir.h" | ||||
| #endif | ||||
| #include "ac_adapter.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace midea { | ||||
| namespace ac { | ||||
|  | ||||
| static void set_sensor(Sensor *sensor, float value) { | ||||
|   if (sensor != nullptr && (!sensor->has_state() || sensor->get_raw_state() != value)) | ||||
| @@ -122,7 +120,7 @@ void AirConditioner::dump_config() { | ||||
| void AirConditioner::do_follow_me(float temperature, bool beeper) { | ||||
| #ifdef USE_REMOTE_TRANSMITTER | ||||
|   IrFollowMeData data(static_cast<uint8_t>(lroundf(temperature)), beeper); | ||||
|   this->transmit_ir(data); | ||||
|   this->transmitter_.transmit(data); | ||||
| #else | ||||
|   ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component"); | ||||
| #endif | ||||
| @@ -131,7 +129,7 @@ void AirConditioner::do_follow_me(float temperature, bool beeper) { | ||||
| void AirConditioner::do_swing_step() { | ||||
| #ifdef USE_REMOTE_TRANSMITTER | ||||
|   IrSpecialData data(0x01); | ||||
|   this->transmit_ir(data); | ||||
|   this->transmitter_.transmit(data); | ||||
| #else | ||||
|   ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component"); | ||||
| #endif | ||||
| @@ -143,13 +141,14 @@ void AirConditioner::do_display_toggle() { | ||||
|   } else { | ||||
| #ifdef USE_REMOTE_TRANSMITTER | ||||
|     IrSpecialData data(0x08); | ||||
|     this->transmit_ir(data); | ||||
|     this->transmitter_.transmit(data); | ||||
| #else | ||||
|     ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component"); | ||||
| #endif | ||||
|   } | ||||
| } | ||||
|  | ||||
| }  // namespace ac | ||||
| }  // namespace midea | ||||
| }  // namespace esphome | ||||
|  | ||||
|   | ||||
| @@ -2,17 +2,25 @@ | ||||
|  | ||||
| #ifdef USE_ARDUINO | ||||
|  | ||||
| // MideaUART | ||||
| #include <Appliance/AirConditioner/AirConditioner.h> | ||||
|  | ||||
| #include "appliance_base.h" | ||||
| #include "esphome/components/sensor/sensor.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace midea { | ||||
| namespace ac { | ||||
|  | ||||
| using sensor::Sensor; | ||||
| using climate::ClimateCall; | ||||
| using climate::ClimatePreset; | ||||
| using climate::ClimateTraits; | ||||
| using climate::ClimateMode; | ||||
| using climate::ClimateSwingMode; | ||||
| using climate::ClimateFanMode; | ||||
|  | ||||
| class AirConditioner : public ApplianceBase<dudanov::midea::ac::AirConditioner> { | ||||
| class AirConditioner : public ApplianceBase<dudanov::midea::ac::AirConditioner>, public climate::Climate { | ||||
|  public: | ||||
|   void dump_config() override; | ||||
|   void set_outdoor_temperature_sensor(Sensor *sensor) { this->outdoor_sensor_ = sensor; } | ||||
| @@ -31,15 +39,26 @@ class AirConditioner : public ApplianceBase<dudanov::midea::ac::AirConditioner> | ||||
|   void do_beeper_off() { this->set_beeper_feedback(false); } | ||||
|   void do_power_on() { this->base_.setPowerState(true); } | ||||
|   void do_power_off() { this->base_.setPowerState(false); } | ||||
|   void set_supported_modes(const std::set<ClimateMode> &modes) { this->supported_modes_ = modes; } | ||||
|   void set_supported_swing_modes(const std::set<ClimateSwingMode> &modes) { this->supported_swing_modes_ = modes; } | ||||
|   void set_supported_presets(const std::set<ClimatePreset> &presets) { this->supported_presets_ = presets; } | ||||
|   void set_custom_presets(const std::set<std::string> &presets) { this->supported_custom_presets_ = presets; } | ||||
|   void set_custom_fan_modes(const std::set<std::string> &modes) { this->supported_custom_fan_modes_ = modes; } | ||||
|  | ||||
|  protected: | ||||
|   void control(const ClimateCall &call) override; | ||||
|   ClimateTraits traits() override; | ||||
|   std::set<ClimateMode> supported_modes_{}; | ||||
|   std::set<ClimateSwingMode> supported_swing_modes_{}; | ||||
|   std::set<ClimatePreset> supported_presets_{}; | ||||
|   std::set<std::string> supported_custom_presets_{}; | ||||
|   std::set<std::string> supported_custom_fan_modes_{}; | ||||
|   Sensor *outdoor_sensor_{nullptr}; | ||||
|   Sensor *humidity_sensor_{nullptr}; | ||||
|   Sensor *power_sensor_{nullptr}; | ||||
| }; | ||||
|  | ||||
| }  // namespace ac | ||||
| }  // namespace midea | ||||
| }  // namespace esphome | ||||
|  | ||||
|   | ||||
| @@ -2,84 +2,97 @@ | ||||
|  | ||||
| #ifdef USE_ARDUINO | ||||
|  | ||||
| // MideaUART | ||||
| #include <Appliance/ApplianceBase.h> | ||||
| #include <Helpers/Logger.h> | ||||
|  | ||||
| // Include global defines | ||||
| #include "esphome/core/defines.h" | ||||
|  | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/components/uart/uart.h" | ||||
| #include "esphome/components/climate/climate.h" | ||||
| #ifdef USE_REMOTE_TRANSMITTER | ||||
| #include "esphome/components/remote_base/midea_protocol.h" | ||||
| #include "esphome/components/remote_transmitter/remote_transmitter.h" | ||||
| #endif | ||||
| #include <Appliance/ApplianceBase.h> | ||||
| #include <Helpers/Logger.h> | ||||
| #include "ir_transmitter.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace midea { | ||||
|  | ||||
| using climate::ClimatePreset; | ||||
| using climate::ClimateTraits; | ||||
| using climate::ClimateMode; | ||||
| using climate::ClimateSwingMode; | ||||
| using climate::ClimateFanMode; | ||||
| /* Stream from UART component */ | ||||
| class UARTStream : public Stream { | ||||
|  public: | ||||
|   void set_uart(uart::UARTComponent *uart) { this->uart_ = uart; } | ||||
|  | ||||
| template<typename T> | ||||
| class ApplianceBase : public Component, public uart::UARTDevice, public climate::Climate, public Stream { | ||||
|   /* Stream interface implementation */ | ||||
|  | ||||
|   int available() override { return this->uart_->available(); } | ||||
|   int read() override { | ||||
|     uint8_t data; | ||||
|     this->uart_->read_byte(&data); | ||||
|     return data; | ||||
|   } | ||||
|   int peek() override { | ||||
|     uint8_t data; | ||||
|     this->uart_->peek_byte(&data); | ||||
|     return data; | ||||
|   } | ||||
|   size_t write(uint8_t data) override { | ||||
|     this->uart_->write_byte(data); | ||||
|     return 1; | ||||
|   } | ||||
|   size_t write(const uint8_t *data, size_t size) override { | ||||
|     this->uart_->write_array(data, size); | ||||
|     return size; | ||||
|   } | ||||
|   void flush() override { this->uart_->flush(); } | ||||
|  | ||||
|  protected: | ||||
|   uart::UARTComponent *uart_; | ||||
| }; | ||||
|  | ||||
| template<typename T> class ApplianceBase : public Component { | ||||
|   static_assert(std::is_base_of<dudanov::midea::ApplianceBase, T>::value, | ||||
|                 "T must derive from dudanov::midea::ApplianceBase class"); | ||||
|  | ||||
|  public: | ||||
|   ApplianceBase() { | ||||
|     this->base_.setStream(this); | ||||
|     this->base_.setStream(&this->stream_); | ||||
|     this->base_.addOnStateCallback(std::bind(&ApplianceBase::on_status_change, this)); | ||||
|     dudanov::midea::ApplianceBase::setLogger( | ||||
|         [](int level, const char *tag, int line, const String &format, va_list args) { | ||||
|           esp_log_vprintf_(level, tag, line, format.c_str(), args); | ||||
|         }); | ||||
|   } | ||||
|   bool can_proceed() override { | ||||
|     return this->base_.getAutoconfStatus() != dudanov::midea::AutoconfStatus::AUTOCONF_PROGRESS; | ||||
|   } | ||||
|   float get_setup_priority() const override { return setup_priority::BEFORE_CONNECTION; } | ||||
|   void setup() override { this->base_.setup(); } | ||||
|   void loop() override { this->base_.loop(); } | ||||
|  | ||||
| #ifdef USE_REMOTE_TRANSMITTER | ||||
|   void set_transmitter(RemoteTransmitterBase *transmitter) { this->transmitter_.set_transmitter(transmitter); } | ||||
| #endif | ||||
|  | ||||
|   /* UART communication */ | ||||
|  | ||||
|   void set_uart_parent(uart::UARTComponent *parent) { this->stream_.set_uart(parent); } | ||||
|   void set_period(uint32_t ms) { this->base_.setPeriod(ms); } | ||||
|   void set_response_timeout(uint32_t ms) { this->base_.setTimeout(ms); } | ||||
|   void set_request_attempts(uint32_t attempts) { this->base_.setNumAttempts(attempts); } | ||||
|  | ||||
|   /* Component methods */ | ||||
|  | ||||
|   void setup() override { this->base_.setup(); } | ||||
|   void loop() override { this->base_.loop(); } | ||||
|   float get_setup_priority() const override { return setup_priority::BEFORE_CONNECTION; } | ||||
|   bool can_proceed() override { | ||||
|     return this->base_.getAutoconfStatus() != dudanov::midea::AutoconfStatus::AUTOCONF_PROGRESS; | ||||
|   } | ||||
|  | ||||
|   void set_beeper_feedback(bool state) { this->base_.setBeeper(state); } | ||||
|   void set_autoconf(bool value) { this->base_.setAutoconf(value); } | ||||
|   void set_supported_modes(const std::set<ClimateMode> &modes) { this->supported_modes_ = modes; } | ||||
|   void set_supported_swing_modes(const std::set<ClimateSwingMode> &modes) { this->supported_swing_modes_ = modes; } | ||||
|   void set_supported_presets(const std::set<ClimatePreset> &presets) { this->supported_presets_ = presets; } | ||||
|   void set_custom_presets(const std::set<std::string> &presets) { this->supported_custom_presets_ = presets; } | ||||
|   void set_custom_fan_modes(const std::set<std::string> &modes) { this->supported_custom_fan_modes_ = modes; } | ||||
|   virtual void on_status_change() = 0; | ||||
| #ifdef USE_REMOTE_TRANSMITTER | ||||
|   void set_transmitter(remote_transmitter::RemoteTransmitterComponent *transmitter) { | ||||
|     this->transmitter_ = transmitter; | ||||
|   } | ||||
|   void transmit_ir(remote_base::MideaData &data) { | ||||
|     data.finalize(); | ||||
|     auto transmit = this->transmitter_->transmit(); | ||||
|     remote_base::MideaProtocol().encode(transmit.get_data(), data); | ||||
|     transmit.perform(); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   int available() override { return uart::UARTDevice::available(); } | ||||
|   int read() override { return uart::UARTDevice::read(); } | ||||
|   int peek() override { return uart::UARTDevice::peek(); } | ||||
|   void flush() override { uart::UARTDevice::flush(); } | ||||
|   size_t write(uint8_t data) override { return uart::UARTDevice::write(data); } | ||||
|  | ||||
|  protected: | ||||
|   T base_; | ||||
|   std::set<ClimateMode> supported_modes_{}; | ||||
|   std::set<ClimateSwingMode> supported_swing_modes_{}; | ||||
|   std::set<ClimatePreset> supported_presets_{}; | ||||
|   std::set<std::string> supported_custom_presets_{}; | ||||
|   std::set<std::string> supported_custom_fan_modes_{}; | ||||
|   UARTStream stream_; | ||||
| #ifdef USE_REMOTE_TRANSMITTER | ||||
|   remote_transmitter::RemoteTransmitterComponent *transmitter_{nullptr}; | ||||
|   IrTransmitter transmitter_; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -40,9 +40,9 @@ AUTO_LOAD = ["sensor"] | ||||
| CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature" | ||||
| CONF_POWER_USAGE = "power_usage" | ||||
| CONF_HUMIDITY_SETPOINT = "humidity_setpoint" | ||||
| midea_ns = cg.esphome_ns.namespace("midea") | ||||
| AirConditioner = midea_ns.class_("AirConditioner", climate.Climate, cg.Component) | ||||
| Capabilities = midea_ns.namespace("Constants") | ||||
| midea_ac_ns = cg.esphome_ns.namespace("midea").namespace("ac") | ||||
| AirConditioner = midea_ac_ns.class_("AirConditioner", climate.Climate, cg.Component) | ||||
| Capabilities = midea_ac_ns.namespace("Constants") | ||||
|  | ||||
|  | ||||
| def templatize(value): | ||||
| @@ -156,13 +156,13 @@ CONFIG_SCHEMA = cv.All( | ||||
| ) | ||||
|  | ||||
| # Actions | ||||
| FollowMeAction = midea_ns.class_("FollowMeAction", automation.Action) | ||||
| DisplayToggleAction = midea_ns.class_("DisplayToggleAction", automation.Action) | ||||
| SwingStepAction = midea_ns.class_("SwingStepAction", automation.Action) | ||||
| BeeperOnAction = midea_ns.class_("BeeperOnAction", automation.Action) | ||||
| BeeperOffAction = midea_ns.class_("BeeperOffAction", automation.Action) | ||||
| PowerOnAction = midea_ns.class_("PowerOnAction", automation.Action) | ||||
| PowerOffAction = midea_ns.class_("PowerOffAction", automation.Action) | ||||
| FollowMeAction = midea_ac_ns.class_("FollowMeAction", automation.Action) | ||||
| DisplayToggleAction = midea_ac_ns.class_("DisplayToggleAction", automation.Action) | ||||
| SwingStepAction = midea_ac_ns.class_("SwingStepAction", automation.Action) | ||||
| BeeperOnAction = midea_ac_ns.class_("BeeperOnAction", automation.Action) | ||||
| BeeperOffAction = midea_ac_ns.class_("BeeperOffAction", automation.Action) | ||||
| PowerOnAction = midea_ac_ns.class_("PowerOnAction", automation.Action) | ||||
| PowerOffAction = midea_ac_ns.class_("PowerOffAction", automation.Action) | ||||
|  | ||||
| MIDEA_ACTION_BASE_SCHEMA = cv.Schema( | ||||
|     { | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
| namespace esphome { | ||||
| namespace midea { | ||||
| 
 | ||||
| using remote_base::RemoteTransmitterBase; | ||||
| using IrData = remote_base::MideaData; | ||||
| 
 | ||||
| class IrFollowMeData : public IrData { | ||||
| @@ -38,6 +39,20 @@ class IrSpecialData : public IrData { | ||||
|   IrSpecialData(uint8_t code) : IrData({MIDEA_TYPE_SPECIAL, code, 0xFF, 0xFF, 0xFF}) {} | ||||
| }; | ||||
| 
 | ||||
| class IrTransmitter { | ||||
|  public: | ||||
|   void set_transmitter(RemoteTransmitterBase *transmitter) { this->transmitter_ = transmitter; } | ||||
|   void transmit(IrData &data) { | ||||
|     data.finalize(); | ||||
|     auto transmit = this->transmitter_->transmit(); | ||||
|     remote_base::MideaProtocol().encode(transmit.get_data(), data); | ||||
|     transmit.perform(); | ||||
|   } | ||||
| 
 | ||||
|  protected: | ||||
|   RemoteTransmitterBase *transmitter_{nullptr}; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace midea
 | ||||
| }  // namespace esphome
 | ||||
| 
 | ||||
		Reference in New Issue
	
	Block a user