mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	add tcl112 support for dry, fan and swing (#939)
This commit is contained in:
		
				
					committed by
					
						 Otto Winter
						Otto Winter
					
				
			
			
				
	
			
			
			
						parent
						
							d7a2816c58
						
					
				
				
					commit
					92d93d658c
				
			| @@ -15,6 +15,12 @@ const uint8_t TCL112_COOL = 3; | |||||||
| const uint8_t TCL112_FAN = 7; | const uint8_t TCL112_FAN = 7; | ||||||
| const uint8_t TCL112_AUTO = 8; | const uint8_t TCL112_AUTO = 8; | ||||||
|  |  | ||||||
|  | const uint8_t TCL112_FAN_AUTO = 0; | ||||||
|  | const uint8_t TCL112_FAN_LOW = 2; | ||||||
|  | const uint8_t TCL112_FAN_MED = 3; | ||||||
|  | const uint8_t TCL112_FAN_HIGH = 5; | ||||||
|  |  | ||||||
|  | const uint8_t TCL112_VSWING_MASK = 0x38; | ||||||
| const uint8_t TCL112_POWER_MASK = 0x04; | const uint8_t TCL112_POWER_MASK = 0x04; | ||||||
|  |  | ||||||
| const uint8_t TCL112_HALF_DEGREE = 0b00100000; | const uint8_t TCL112_HALF_DEGREE = 0b00100000; | ||||||
| @@ -53,6 +59,14 @@ void Tcl112Climate::transmit_state() { | |||||||
|       remote_state[6] &= 0xF0; |       remote_state[6] &= 0xF0; | ||||||
|       remote_state[6] |= TCL112_HEAT; |       remote_state[6] |= TCL112_HEAT; | ||||||
|       break; |       break; | ||||||
|  |     case climate::CLIMATE_MODE_DRY: | ||||||
|  |       remote_state[6] &= 0xF0; | ||||||
|  |       remote_state[6] |= TCL112_DRY; | ||||||
|  |       break; | ||||||
|  |     case climate::CLIMATE_MODE_FAN_ONLY: | ||||||
|  |       remote_state[6] &= 0xF0; | ||||||
|  |       remote_state[6] |= TCL112_FAN; | ||||||
|  |       break; | ||||||
|     case climate::CLIMATE_MODE_OFF: |     case climate::CLIMATE_MODE_OFF: | ||||||
|     default: |     default: | ||||||
|       remote_state[5] &= ~TCL112_POWER_MASK; |       remote_state[5] &= ~TCL112_POWER_MASK; | ||||||
| @@ -72,6 +86,29 @@ void Tcl112Climate::transmit_state() { | |||||||
|   remote_state[7] &= 0xF0;                    // Clear temp bits. |   remote_state[7] &= 0xF0;                    // Clear temp bits. | ||||||
|   remote_state[7] |= ((uint8_t) TCL112_TEMP_MAX - half_degrees / 2); |   remote_state[7] |= ((uint8_t) TCL112_TEMP_MAX - half_degrees / 2); | ||||||
|  |  | ||||||
|  |   // Set fan | ||||||
|  |   uint8_t selected_fan; | ||||||
|  |   switch (this->fan_mode) { | ||||||
|  |     case climate::CLIMATE_FAN_HIGH: | ||||||
|  |       selected_fan = TCL112_FAN_HIGH; | ||||||
|  |       break; | ||||||
|  |     case climate::CLIMATE_FAN_MEDIUM: | ||||||
|  |       selected_fan = TCL112_FAN_MED; | ||||||
|  |       break; | ||||||
|  |     case climate::CLIMATE_FAN_LOW: | ||||||
|  |       selected_fan = TCL112_FAN_LOW; | ||||||
|  |       break; | ||||||
|  |     case climate::CLIMATE_FAN_AUTO: | ||||||
|  |     default: | ||||||
|  |       selected_fan = TCL112_FAN_AUTO; | ||||||
|  |   } | ||||||
|  |   remote_state[8] |= selected_fan; | ||||||
|  |  | ||||||
|  |   // Set swing | ||||||
|  |   if (this->swing_mode == climate::CLIMATE_SWING_VERTICAL) { | ||||||
|  |     remote_state[8] |= TCL112_VSWING_MASK; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Calculate & set the checksum for the current internal state of the remote. |   // Calculate & set the checksum for the current internal state of the remote. | ||||||
|   // Stored the checksum value in the last byte. |   // Stored the checksum value in the last byte. | ||||||
|   for (uint8_t checksum_byte = 0; checksum_byte < TCL112_STATE_LENGTH - 1; checksum_byte++) |   for (uint8_t checksum_byte = 0; checksum_byte < TCL112_STATE_LENGTH - 1; checksum_byte++) | ||||||
| @@ -107,7 +144,7 @@ void Tcl112Climate::transmit_state() { | |||||||
| bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) { | bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) { | ||||||
|   // Validate header |   // Validate header | ||||||
|   if (!data.expect_item(TCL112_HEADER_MARK, TCL112_HEADER_SPACE)) { |   if (!data.expect_item(TCL112_HEADER_MARK, TCL112_HEADER_SPACE)) { | ||||||
|     ESP_LOGV(TAG, "Header fail"); |     ESP_LOGVV(TAG, "Header fail"); | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -119,14 +156,14 @@ bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) { | |||||||
|       if (data.expect_item(TCL112_BIT_MARK, TCL112_ONE_SPACE)) |       if (data.expect_item(TCL112_BIT_MARK, TCL112_ONE_SPACE)) | ||||||
|         remote_state[i] |= 1 << j; |         remote_state[i] |= 1 << j; | ||||||
|       else if (!data.expect_item(TCL112_BIT_MARK, TCL112_ZERO_SPACE)) { |       else if (!data.expect_item(TCL112_BIT_MARK, TCL112_ZERO_SPACE)) { | ||||||
|         ESP_LOGV(TAG, "Byte %d bit %d fail", i, j); |         ESP_LOGVV(TAG, "Byte %d bit %d fail", i, j); | ||||||
|         return false; |         return false; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   // Validate footer |   // Validate footer | ||||||
|   if (!data.expect_mark(TCL112_BIT_MARK)) { |   if (!data.expect_mark(TCL112_BIT_MARK)) { | ||||||
|     ESP_LOGV(TAG, "Footer fail"); |     ESP_LOGVV(TAG, "Footer fail"); | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -136,7 +173,7 @@ bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) { | |||||||
|   for (uint8_t checksum_byte = 0; checksum_byte < TCL112_STATE_LENGTH - 1; checksum_byte++) |   for (uint8_t checksum_byte = 0; checksum_byte < TCL112_STATE_LENGTH - 1; checksum_byte++) | ||||||
|     checksum += remote_state[checksum_byte]; |     checksum += remote_state[checksum_byte]; | ||||||
|   if (checksum != remote_state[TCL112_STATE_LENGTH - 1]) { |   if (checksum != remote_state[TCL112_STATE_LENGTH - 1]) { | ||||||
|     ESP_LOGV(TAG, "Checksum fail"); |     ESP_LOGVV(TAG, "Checksum fail"); | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -161,7 +198,11 @@ bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) { | |||||||
|         this->mode = climate::CLIMATE_MODE_COOL; |         this->mode = climate::CLIMATE_MODE_COOL; | ||||||
|         break; |         break; | ||||||
|       case TCL112_DRY: |       case TCL112_DRY: | ||||||
|  |         this->mode = climate::CLIMATE_MODE_DRY; | ||||||
|  |         break; | ||||||
|       case TCL112_FAN: |       case TCL112_FAN: | ||||||
|  |         this->mode = climate::CLIMATE_MODE_FAN_ONLY; | ||||||
|  |         break; | ||||||
|       case TCL112_AUTO: |       case TCL112_AUTO: | ||||||
|         this->mode = climate::CLIMATE_MODE_AUTO; |         this->mode = climate::CLIMATE_MODE_AUTO; | ||||||
|         break; |         break; | ||||||
| @@ -171,6 +212,28 @@ bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) { | |||||||
|   if (remote_state[12] & TCL112_HALF_DEGREE) |   if (remote_state[12] & TCL112_HALF_DEGREE) | ||||||
|     temp += .5f; |     temp += .5f; | ||||||
|   this->target_temperature = temp; |   this->target_temperature = temp; | ||||||
|  |   auto fan = remote_state[8] & 0x7; | ||||||
|  |   switch (fan) { | ||||||
|  |     case TCL112_FAN_HIGH: | ||||||
|  |       this->fan_mode = climate::CLIMATE_FAN_HIGH; | ||||||
|  |       break; | ||||||
|  |     case TCL112_FAN_MED: | ||||||
|  |       this->fan_mode = climate::CLIMATE_FAN_MEDIUM; | ||||||
|  |       break; | ||||||
|  |     case TCL112_FAN_LOW: | ||||||
|  |       this->fan_mode = climate::CLIMATE_FAN_LOW; | ||||||
|  |       break; | ||||||
|  |     case TCL112_FAN_AUTO: | ||||||
|  |     default: | ||||||
|  |       this->fan_mode = climate::CLIMATE_FAN_AUTO; | ||||||
|  |       break; | ||||||
|  |   } | ||||||
|  |   if ((remote_state[8] & TCL112_VSWING_MASK) == TCL112_VSWING_MASK) { | ||||||
|  |     this->swing_mode = climate::CLIMATE_SWING_VERTICAL; | ||||||
|  |   } else { | ||||||
|  |     this->swing_mode = climate::CLIMATE_SWING_OFF; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   this->publish_state(); |   this->publish_state(); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,7 +11,11 @@ const float TCL112_TEMP_MIN = 16.0; | |||||||
|  |  | ||||||
| class Tcl112Climate : public climate_ir::ClimateIR { | class Tcl112Climate : public climate_ir::ClimateIR { | ||||||
|  public: |  public: | ||||||
|   Tcl112Climate() : climate_ir::ClimateIR(TCL112_TEMP_MIN, TCL112_TEMP_MAX, .5f) {} |   Tcl112Climate() | ||||||
|  |       : climate_ir::ClimateIR(TCL112_TEMP_MIN, TCL112_TEMP_MAX, .5f, true, true, | ||||||
|  |                               {climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM, | ||||||
|  |                                climate::CLIMATE_FAN_HIGH}, | ||||||
|  |                               {climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL}) {} | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   /// Transmit via IR the state of this climate controller. |   /// Transmit via IR the state of this climate controller. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user