mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Add climate IR Samsung component.
This commit is contained in:
		
							
								
								
									
										0
									
								
								esphome/components/climate_ir_samsung/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								esphome/components/climate_ir_samsung/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										22
									
								
								esphome/components/climate_ir_samsung/climate.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								esphome/components/climate_ir_samsung/climate.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | from esphome.components import climate_ir | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import CONF_ID | ||||||
|  |  | ||||||
|  | CODEOWNERS = ["@jorofi"] | ||||||
|  |  | ||||||
|  | AUTO_LOAD = ["climate_ir"] | ||||||
|  |  | ||||||
|  | samsung_ns = cg.esphome_ns.namespace("samsung") | ||||||
|  | SamsungClimate = samsung_ns.class_("SamsungClimate", climate_ir.ClimateIR) | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( | ||||||
|  |     { | ||||||
|  |         cv.GenerateID(): cv.declare_id(SamsungClimate) | ||||||
|  |     } | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|  |  | ||||||
|  |     await climate_ir.register_climate_ir(var, config) | ||||||
							
								
								
									
										240
									
								
								esphome/components/climate_ir_samsung/climate_ir_samsung.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								esphome/components/climate_ir_samsung/climate_ir_samsung.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,240 @@ | |||||||
|  | #include "climate_ir_samsung.h" | ||||||
|  | #include <thread> | ||||||
|  | #include <chrono> | ||||||
|  |  | ||||||
|  | /// Count the number of bits of a certain type in an array. | ||||||
|  | /// @param[in] start A ptr to the start of the byte array to calculate over. | ||||||
|  | /// @param[in] length How many bytes to use in the calculation. | ||||||
|  | /// @param[in] ones Count the binary nr of `1` bits. False is count the `0`s. | ||||||
|  | /// @param[in] init Starting value of the calculation to use. (Default is 0) | ||||||
|  | /// @return The nr. of bits found of the given type found in the array. | ||||||
|  | uint16_t countBits(const uint8_t * const start, const uint16_t length, const bool ones, const uint16_t init) { | ||||||
|  |     uint16_t count = init; | ||||||
|  |      | ||||||
|  |     for (uint16_t offset = 0; offset < length; offset++) | ||||||
|  |         for (uint8_t currentbyte = *(start + offset); currentbyte; currentbyte >>= 1) | ||||||
|  |             if (currentbyte & 1) count++; | ||||||
|  |  | ||||||
|  |     if (ones || length == 0) | ||||||
|  |         return count; | ||||||
|  |     else | ||||||
|  |         return (length * 8) - count; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// Count the number of bits of a certain type in an Integer. | ||||||
|  | /// @param[in] data The value you want bits counted for. Starting from the LSB. | ||||||
|  | /// @param[in] length How many bits to use in the calculation? Starts at the LSB | ||||||
|  | /// @param[in] ones Count the binary nr of `1` bits. False is count the `0`s. | ||||||
|  | /// @param[in] init Starting value of the calculation to use. (Default is 0) | ||||||
|  | /// @return The nr. of bits found of the given type found in the Integer. | ||||||
|  | uint16_t countBits(const uint64_t data, const uint8_t length, const bool ones, const uint16_t init) { | ||||||
|  |     uint16_t count = init; | ||||||
|  |     uint8_t bitsSoFar = length; | ||||||
|  |      | ||||||
|  |     for (uint64_t remainder = data; remainder && bitsSoFar; remainder >>= 1, bitsSoFar--) | ||||||
|  |         if (remainder & 1) count++; | ||||||
|  |  | ||||||
|  |     if (ones || length == 0) | ||||||
|  |         return count; | ||||||
|  |     else | ||||||
|  |         return length - count; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace climate_ir_samsung { | ||||||
|  |  | ||||||
|  |     void SamsungClimateIR::transmit_state() { | ||||||
|  |         if(current_climate_mode != climate::ClimateMode::CLIMATE_MODE_OFF && this->mode == climate::ClimateMode::CLIMATE_MODE_OFF) { | ||||||
|  |             setAndSendPowerState(false); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(current_climate_mode == climate::ClimateMode::CLIMATE_MODE_OFF && this->mode != climate::ClimateMode::CLIMATE_MODE_OFF) { | ||||||
|  |             setAndSendPowerState(true); | ||||||
|  |             std::this_thread::sleep_for(std::chrono::seconds(2)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         current_climate_mode = this->mode; | ||||||
|  |  | ||||||
|  |         setMode(this->mode); | ||||||
|  |         setTemp(this->target_temperature); | ||||||
|  |         setSwing(this->swing_mode); | ||||||
|  |         setFan(this->fan_mode.has_value() ? this->fan_mode.value() : climate::CLIMATE_FAN_AUTO); | ||||||
|  |          | ||||||
|  |         send(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Send the current state of the climate object. | ||||||
|  |     void SamsungClimateIR::send() { | ||||||
|  |          | ||||||
|  |         checksum(); | ||||||
|  |  | ||||||
|  |         auto transmit = this->transmitter_->transmit(); | ||||||
|  |         auto *data = transmit.get_data(); | ||||||
|  |         data->set_carrier_frequency(SAMSUNG_IR_FREQUENCY); | ||||||
|  |  | ||||||
|  |         // Header | ||||||
|  |         data->mark(SAMSUNG_AIRCON1_HDR_MARK); | ||||||
|  |         data->space(SAMSUNG_AIRCON1_HDR_SPACE); | ||||||
|  |  | ||||||
|  |         for (int i = 0; i < 21; i++) | ||||||
|  |         { | ||||||
|  |  | ||||||
|  |             if (i == 7 || i == 14) | ||||||
|  |             { | ||||||
|  |                 data->mark(SAMSUNG_AIRCON1_BIT_MARK); | ||||||
|  |                 data->space(SAMSUNG_AIRCON1_MSG_SPACE); | ||||||
|  |  | ||||||
|  |                 data->mark(SAMSUNG_AIRCON1_HDR_MARK); | ||||||
|  |                 data->space(SAMSUNG_AIRCON1_HDR_SPACE); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             uint8_t sendByte = protocol.raw[i]; | ||||||
|  |  | ||||||
|  |             for (int y = 0; y < 8; y++) | ||||||
|  |             { | ||||||
|  |                 if (sendByte & 0x01) | ||||||
|  |                 { | ||||||
|  |                     // ESP_LOGI(TAG, "For Y %d 1", y); | ||||||
|  |                     data->mark(SAMSUNG_AIRCON1_BIT_MARK); | ||||||
|  |                     data->space(SAMSUNG_AIRCON1_ONE_SPACE); | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     // ESP_LOGI(TAG, "For Y %d 0", y); | ||||||
|  |                     data->mark(SAMSUNG_AIRCON1_BIT_MARK); | ||||||
|  |                     data->space(SAMSUNG_AIRCON1_ZERO_SPACE); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 sendByte >>= 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         data->mark(SAMSUNG_AIRCON1_BIT_MARK); | ||||||
|  |         data->space(0); | ||||||
|  |  | ||||||
|  |         transmit.perform(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Set the vertical swing setting of the A/C. | ||||||
|  |     void SamsungClimateIR::setSwing(const climate::ClimateSwingMode swingMode) { | ||||||
|  |         switch (swingMode) { | ||||||
|  |             case climate::ClimateSwingMode::CLIMATE_SWING_BOTH: | ||||||
|  |                 protocol.Swing = kSamsungAcSwingBoth; | ||||||
|  |                 break; | ||||||
|  |             case climate::ClimateSwingMode::CLIMATE_SWING_HORIZONTAL: | ||||||
|  |                 protocol.Swing = kSamsungAcSwingH;; | ||||||
|  |                 break; | ||||||
|  |             case climate::ClimateSwingMode::CLIMATE_SWING_VERTICAL: | ||||||
|  |                 protocol.Swing = kSamsungAcSwingV;; | ||||||
|  |                 break; | ||||||
|  |             case climate::ClimateSwingMode::CLIMATE_SWING_OFF: | ||||||
|  |             default: | ||||||
|  |                 protocol.Swing = kSamsungAcSwingOff;; | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Set the operating mode of the A/C. | ||||||
|  |     /// @param[in] climateMode The desired operating mode. | ||||||
|  |     void SamsungClimateIR::setMode(const climate::ClimateMode climateMode) { | ||||||
|  |         switch (climateMode) { | ||||||
|  |             case climate::ClimateMode::CLIMATE_MODE_HEAT: | ||||||
|  |                 protocol.Mode = kSamsungAcHeat; | ||||||
|  |                 break; | ||||||
|  |             case climate::ClimateMode::CLIMATE_MODE_DRY: | ||||||
|  |                 protocol.Mode = kSamsungAcDry; | ||||||
|  |                 break; | ||||||
|  |             case climate::ClimateMode::CLIMATE_MODE_COOL: | ||||||
|  |                 protocol.Mode = kSamsungAcCool; | ||||||
|  |                 break; | ||||||
|  |             case climate::ClimateMode::CLIMATE_MODE_FAN_ONLY: | ||||||
|  |                 protocol.Mode = kSamsungAcFan; | ||||||
|  |                 break; | ||||||
|  |             case climate::ClimateMode::CLIMATE_MODE_HEAT_COOL: | ||||||
|  |             case climate::ClimateMode::CLIMATE_MODE_AUTO: | ||||||
|  |             default: | ||||||
|  |                 protocol.Mode = kSamsungAcAuto; | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Set the temperature. | ||||||
|  |     /// @param[in] temp The temperature in degrees celsius. | ||||||
|  |     void SamsungClimateIR::setTemp(const uint8_t temp) { | ||||||
|  |         uint8_t newtemp = std::max(kSamsungAcMinTemp, temp); | ||||||
|  |         newtemp = std::min(kSamsungAcMaxTemp, newtemp); | ||||||
|  |         protocol.Temp = newtemp - kSamsungAcMinTemp; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Change the AC power state. | ||||||
|  |     /// @param[in] on true, the AC is on. false, the AC is off. | ||||||
|  |     void SamsungClimateIR::setAndSendPowerState(const bool on) { | ||||||
|  |  | ||||||
|  |         static const uint8_t kOn[kSamsungAcExtendedStateLength] = { | ||||||
|  |             0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, | ||||||
|  |             0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |             0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0}; | ||||||
|  |  | ||||||
|  |         static const uint8_t kOff[kSamsungAcExtendedStateLength] = { | ||||||
|  |             0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, | ||||||
|  |             0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |             0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0}; | ||||||
|  |              | ||||||
|  |         std::memcpy(protocol.raw, on ? kOn : kOff, kSamsungAcExtendedStateLength); | ||||||
|  |  | ||||||
|  |         send(); | ||||||
|  |  | ||||||
|  |         std::memcpy(protocol.raw, kReset, kSamsungAcExtendedStateLength); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Set the fan speed. | ||||||
|  |     void SamsungClimateIR::setFan(const climate::ClimateFanMode fanMode) { | ||||||
|  |         switch (fanMode) { | ||||||
|  |             case climate::ClimateFanMode::CLIMATE_FAN_LOW: | ||||||
|  |                 protocol.Fan = kSamsungAcFanAuto; | ||||||
|  |                 break; | ||||||
|  |             case climate::ClimateFanMode::CLIMATE_FAN_MEDIUM: | ||||||
|  |                 protocol.Fan = kSamsungAcFanMed; | ||||||
|  |                 break; | ||||||
|  |             case climate::ClimateFanMode::CLIMATE_FAN_HIGH: | ||||||
|  |                 protocol.Fan = kSamsungAcFanHigh; | ||||||
|  |                 break; | ||||||
|  |             case climate::ClimateFanMode::CLIMATE_FAN_AUTO: | ||||||
|  |             default: | ||||||
|  |                 protocol.Fan = kSamsungAcFanAuto; | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Calculate the checksum for a given state section. | ||||||
|  |     /// @param[in] section The array to calc the checksum of. | ||||||
|  |     /// @return The calculated checksum value. | ||||||
|  |     /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1538#issuecomment-894645947 | ||||||
|  |     uint8_t SamsungClimateIR::calcSectionChecksum(const uint8_t *section) { | ||||||
|  |         uint8_t sum = 0; | ||||||
|  |  | ||||||
|  |         sum += countBits(*section, 8);  // Include the entire first byte | ||||||
|  |         // The lower half of the second byte. | ||||||
|  |         sum += countBits(GETBITS8(*(section + 1), kLowNibble, kNibbleSize), 8); | ||||||
|  |         // The upper half of the third byte. | ||||||
|  |         sum += countBits(GETBITS8(*(section + 2), kHighNibble, kNibbleSize), 8); | ||||||
|  |         // The next 4 bytes. | ||||||
|  |         sum += countBits(section + 3, 4); | ||||||
|  |         // Bitwise invert the result. | ||||||
|  |         return sum ^ UINT8_MAX; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Update the checksum for the internal state. | ||||||
|  |     void SamsungClimateIR::checksum(void) { | ||||||
|  |         uint8_t sectionsum = calcSectionChecksum(protocol.raw); | ||||||
|  |         protocol.Sum1Upper = GETBITS8(sectionsum, kHighNibble, kNibbleSize); | ||||||
|  |         protocol.Sum1Lower = GETBITS8(sectionsum, kLowNibble, kNibbleSize); | ||||||
|  |         sectionsum = calcSectionChecksum(protocol.raw + kSamsungAcSectionLength); | ||||||
|  |         protocol.Sum2Upper = GETBITS8(sectionsum, kHighNibble, kNibbleSize); | ||||||
|  |         protocol.Sum2Lower = GETBITS8(sectionsum, kLowNibble, kNibbleSize); | ||||||
|  |         sectionsum = calcSectionChecksum(protocol.raw + kSamsungAcSectionLength * 2); | ||||||
|  |         protocol.Sum3Upper = GETBITS8(sectionsum, kHighNibble, kNibbleSize); | ||||||
|  |         protocol.Sum3Lower = GETBITS8(sectionsum, kLowNibble, kNibbleSize); | ||||||
|  |     } | ||||||
|  | }} | ||||||
							
								
								
									
										208
									
								
								esphome/components/climate_ir_samsung/climate_ir_samsung.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								esphome/components/climate_ir_samsung/climate_ir_samsung.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/climate/climate_mode.h" | ||||||
|  | #include "esphome/components/climate_ir/climate_ir.h" | ||||||
|  |  | ||||||
|  | #define SAMSUNG_AIRCON1_HDR_MARK   3000 | ||||||
|  | #define SAMSUNG_AIRCON1_HDR_SPACE  9000 | ||||||
|  | #define SAMSUNG_AIRCON1_BIT_MARK   500 | ||||||
|  | #define SAMSUNG_AIRCON1_ONE_SPACE  1500 | ||||||
|  | #define SAMSUNG_AIRCON1_ZERO_SPACE 500 | ||||||
|  | #define SAMSUNG_AIRCON1_MSG_SPACE  2000 | ||||||
|  | #define GETBITS8(data, offset, size) \ | ||||||
|  |     (((data) & (((uint8_t)UINT8_MAX >> (8 - (size))) << (offset))) >> (offset)) | ||||||
|  |  | ||||||
|  | uint16_t countBits(const uint8_t * const start, const uint16_t length, const bool ones = true, const uint16_t init = 0); | ||||||
|  | uint16_t countBits(const uint64_t data, const uint8_t length, const bool ones = true, const uint16_t init = 0); | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace climate_ir_samsung { | ||||||
|  |  | ||||||
|  |     static const char *const TAG = "samsung.climate"; | ||||||
|  |     static const uint32_t SAMSUNG_IR_FREQUENCY = 38000; | ||||||
|  |     const uint16_t kSamsungAcExtendedStateLength = 21; | ||||||
|  |     const uint16_t kSamsungAcSectionLength = 7; | ||||||
|  |  | ||||||
|  |     // Temperature | ||||||
|  |     const uint8_t kSamsungAcMinTemp  = 16;  // C   Mask 0b11110000 | ||||||
|  |     const uint8_t kSamsungAcMaxTemp  = 30;  // C   Mask 0b11110000 | ||||||
|  |     const uint8_t kSamsungAcAutoTemp = 25;  // C   Mask 0b11110000 | ||||||
|  |      | ||||||
|  |     // Mode | ||||||
|  |     const uint8_t kSamsungAcAuto = 0; | ||||||
|  |     const uint8_t kSamsungAcCool = 1; | ||||||
|  |     const uint8_t kSamsungAcDry = 2; | ||||||
|  |     const uint8_t kSamsungAcFan = 3; | ||||||
|  |     const uint8_t kSamsungAcHeat = 4; | ||||||
|  |  | ||||||
|  |     // Fan | ||||||
|  |     const uint8_t kSamsungAcFanAuto = 0; | ||||||
|  |     const uint8_t kSamsungAcFanLow = 2; | ||||||
|  |     const uint8_t kSamsungAcFanMed = 4; | ||||||
|  |     const uint8_t kSamsungAcFanHigh = 5; | ||||||
|  |     const uint8_t kSamsungAcFanAuto2 = 6; | ||||||
|  |     const uint8_t kSamsungAcFanTurbo = 7; | ||||||
|  |  | ||||||
|  |     // Swing | ||||||
|  |     const uint8_t kSamsungAcSwingV =        0b010; | ||||||
|  |     const uint8_t kSamsungAcSwingH =        0b011; | ||||||
|  |     const uint8_t kSamsungAcSwingBoth =     0b100; | ||||||
|  |     const uint8_t kSamsungAcSwingOff =      0b111; | ||||||
|  |  | ||||||
|  |     // Power | ||||||
|  |     const uint8_t kNibbleSize = 4; | ||||||
|  |     const uint8_t kLowNibble = 0; | ||||||
|  |     const uint8_t kHighNibble = 4; | ||||||
|  |     const uint8_t kModeBitsSize = 3; | ||||||
|  |  | ||||||
|  |     // static const uint8_t kReset[kSamsungAcExtendedStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0x02, 0xAE, 0x71, 0x00, 0x15, 0xF0}; | ||||||
|  |     static const uint8_t kReset[kSamsungAcExtendedStateLength] = { | ||||||
|  |         0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, | ||||||
|  |         0x01, 0x02, 0xAE, 0x71, 0x00, 0x15, 0xF0}; | ||||||
|  |  | ||||||
|  |     /// Native representation of a Samsung A/C message. | ||||||
|  |     union SamsungProtocol { | ||||||
|  |         uint8_t raw[kSamsungAcExtendedStateLength];  ///< State in code form. | ||||||
|  |         struct {  // Standard message map | ||||||
|  |             // Byte 0 | ||||||
|  |             uint8_t         :8; | ||||||
|  |             // Byte 1 | ||||||
|  |             uint8_t         :4; | ||||||
|  |             uint8_t         :4;  // Sum1Lower | ||||||
|  |             // Byte 2 | ||||||
|  |             uint8_t         :4;  // Sum1Upper | ||||||
|  |             uint8_t         :4; | ||||||
|  |             // Byte 3 | ||||||
|  |             uint8_t         :8; | ||||||
|  |             // Byte 4 | ||||||
|  |             uint8_t         :8; | ||||||
|  |             // Byte 5 | ||||||
|  |             uint8_t         :4; | ||||||
|  |             uint8_t Sleep5  :1; | ||||||
|  |             uint8_t Quiet   :1; | ||||||
|  |             uint8_t         :2; | ||||||
|  |             // Byte 6 | ||||||
|  |             uint8_t         :4; | ||||||
|  |             uint8_t Power1  :2; | ||||||
|  |             uint8_t         :2; | ||||||
|  |             // Byte 7 | ||||||
|  |             uint8_t         :8; | ||||||
|  |             // Byte 8 | ||||||
|  |             uint8_t         :4; | ||||||
|  |             uint8_t         :4;  // Sum2Lower | ||||||
|  |             // Byte 9 | ||||||
|  |             uint8_t         :4;  // Sum1Upper | ||||||
|  |             uint8_t Swing   :3; | ||||||
|  |             uint8_t         :1; | ||||||
|  |             // Byte 10 | ||||||
|  |             uint8_t               :1; | ||||||
|  |             uint8_t FanSpecial    :3;  // Powerful, Breeze/WindFree, Econo | ||||||
|  |             uint8_t Display       :1; | ||||||
|  |             uint8_t               :2; | ||||||
|  |             uint8_t CleanToggle10 :1; | ||||||
|  |             // Byte 11 | ||||||
|  |             uint8_t Ion           :1; | ||||||
|  |             uint8_t CleanToggle11 :1; | ||||||
|  |             uint8_t               :2; | ||||||
|  |             uint8_t Temp          :4; | ||||||
|  |             // Byte 12 | ||||||
|  |             uint8_t       :1; | ||||||
|  |             uint8_t Fan   :3; | ||||||
|  |             uint8_t Mode  :3; | ||||||
|  |             uint8_t       :1; | ||||||
|  |             // Byte 13 | ||||||
|  |             uint8_t            :2; | ||||||
|  |             uint8_t BeepToggle :1; | ||||||
|  |             uint8_t            :1; | ||||||
|  |             uint8_t Power2     :2; | ||||||
|  |             uint8_t            :2; | ||||||
|  |         }; | ||||||
|  |         struct {  // Extended message map | ||||||
|  |             // 1st Section | ||||||
|  |             // Byte 0 | ||||||
|  |             uint8_t                :8; | ||||||
|  |             // Byte 1 | ||||||
|  |             uint8_t                :4; | ||||||
|  |             uint8_t Sum1Lower      :4; | ||||||
|  |             // Byte 2 | ||||||
|  |             uint8_t Sum1Upper      :4; | ||||||
|  |             uint8_t                :4; | ||||||
|  |             // Byte 3 | ||||||
|  |             uint8_t                :8; | ||||||
|  |             // Byte 4 | ||||||
|  |             uint8_t                :8; | ||||||
|  |             // Byte 5 | ||||||
|  |             uint8_t                :8; | ||||||
|  |             // Byte 6 | ||||||
|  |             uint8_t                :8; | ||||||
|  |             // 2nd Section | ||||||
|  |             // Byte 7 | ||||||
|  |             uint8_t                :8; | ||||||
|  |             // Byte 8 | ||||||
|  |             uint8_t                :4; | ||||||
|  |             uint8_t Sum2Lower      :4; | ||||||
|  |             // Byte 9 | ||||||
|  |             uint8_t Sum2Upper      :4; | ||||||
|  |             uint8_t OffTimeMins    :3;  // In units of 10's of mins | ||||||
|  |             uint8_t OffTimeHrs1    :1;  // LSB of the number of hours. | ||||||
|  |             // Byte 10 | ||||||
|  |             uint8_t OffTimeHrs2    :4;  // MSBs of the number of hours. | ||||||
|  |             uint8_t OnTimeMins     :3;  // In units of 10's of mins | ||||||
|  |             uint8_t OnTimeHrs1     :1;  // LSB of the number of hours. | ||||||
|  |             // Byte 11 | ||||||
|  |             uint8_t OnTimeHrs2     :4;  // MSBs of the number of hours. | ||||||
|  |             uint8_t                :4; | ||||||
|  |             // Byte 12 | ||||||
|  |             uint8_t OffTimeDay     :1; | ||||||
|  |             uint8_t OnTimerEnable  :1; | ||||||
|  |             uint8_t OffTimerEnable :1; | ||||||
|  |             uint8_t Sleep12        :1; | ||||||
|  |             uint8_t OnTimeDay      :1; | ||||||
|  |             uint8_t                :3; | ||||||
|  |             // Byte 13 | ||||||
|  |             uint8_t                :8; | ||||||
|  |             // 3rd Section | ||||||
|  |             // Byte 14 | ||||||
|  |             uint8_t                :8; | ||||||
|  |             // Byte 15 | ||||||
|  |             uint8_t                :4; | ||||||
|  |             uint8_t Sum3Lower      :4; | ||||||
|  |             // Byte 16 | ||||||
|  |             uint8_t Sum3Upper      :4; | ||||||
|  |             uint8_t                :4; | ||||||
|  |             // Byte 17 | ||||||
|  |             uint8_t                :8; | ||||||
|  |             // Byte 18 | ||||||
|  |             uint8_t                :8; | ||||||
|  |             // Byte 19 | ||||||
|  |             uint8_t                :8; | ||||||
|  |             // Byte 20 | ||||||
|  |             uint8_t                :8; | ||||||
|  |         }; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     class SamsungClimate : public climate_ir::ClimateIR { | ||||||
|  |          | ||||||
|  |         SamsungProtocol protocol; | ||||||
|  |         climate::ClimateMode current_climate_mode; | ||||||
|  |  | ||||||
|  |         public: SamsungClimate() :  | ||||||
|  |             climate_ir::ClimateIR( | ||||||
|  |                 kSamsungAcMinTemp, kSamsungAcMaxTemp, 1.0f, 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, climate::CLIMATE_SWING_HORIZONTAL, climate::CLIMATE_SWING_BOTH}) { } | ||||||
|  |  | ||||||
|  |         protected: | ||||||
|  |             void transmit_state() override; | ||||||
|  |              | ||||||
|  |             void send(); | ||||||
|  |             void setSwing(const climate::ClimateSwingMode swingMode); | ||||||
|  |             void setMode(const climate::ClimateMode mode); | ||||||
|  |             void setTemp(const uint8_t temp); | ||||||
|  |             void setAndSendPowerState(const bool on); | ||||||
|  |             void setFan(const climate::ClimateFanMode fanMode); | ||||||
|  |              | ||||||
|  |             void checksum(void); | ||||||
|  |             static uint8_t calcSectionChecksum(const uint8_t *section); | ||||||
|  |     }; | ||||||
|  | }} | ||||||
		Reference in New Issue
	
	Block a user