From 7e0917b2b70f5750b42f11f4cbb7092f49f7ddfd Mon Sep 17 00:00:00 2001 From: StellaLupus Date: Sat, 10 Aug 2024 17:29:54 +0300 Subject: [PATCH] fix: code cleanup --- src/IRac.cpp | 6 +- src/IRac.h | 2 +- src/ir_Electrolux.cpp | 524 +++++++++++++++++++++--------------------- src/ir_Electrolux.h | 145 +++++++----- 4 files changed, 356 insertions(+), 321 deletions(-) diff --git a/src/IRac.cpp b/src/IRac.cpp index 430814887..6065ea650 100644 --- a/src/IRac.cpp +++ b/src/IRac.cpp @@ -244,6 +244,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { #if SEND_ELECTRA_AC case decode_type_t::ELECTRA_AC: #endif +#if SEND_ELECTROLUX_AC + case decode_type_t::ELETROLUX_AC: +#endif // SEND_ELECTROLUX_AC #if SEND_FUJITSU_AC case decode_type_t::FUJITSU_AC: #endif @@ -375,9 +378,6 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { #if SEND_WHIRLPOOL_AC case decode_type_t::WHIRLPOOL_AC: #endif -#if SEND_ELECTROLUX_AC - case decode_type_t::ELETROLUX_AC: -#endif // SEND_ELECTROLUX_AC return true; default: return false; diff --git a/src/IRac.h b/src/IRac.h index 3a32f61b0..3951c63a4 100644 --- a/src/IRac.h +++ b/src/IRac.h @@ -22,6 +22,7 @@ #include "ir_Fujitsu.h" #include "ir_Ecoclim.h" #include "ir_Electra.h" +#include "ir_Electrolux.h" #include "ir_Goodweather.h" #include "ir_Gree.h" #include "ir_Haier.h" @@ -50,7 +51,6 @@ #include "ir_Voltas.h" #include "ir_Whirlpool.h" #include "ir_York.h" -#include "ir_Electrolux.h" // Constants const int8_t kGpioUnused = -1; ///< A placeholder for not using an actual GPIO. diff --git a/src/ir_Electrolux.cpp b/src/ir_Electrolux.cpp index 8b219ec93..66ac9bbcb 100644 --- a/src/ir_Electrolux.cpp +++ b/src/ir_Electrolux.cpp @@ -19,7 +19,7 @@ const uint16_t kElectroluxAcBitMark = 752; const uint16_t kElectroluxAcHdrSpace = 2700; const uint16_t kElectroluxAcOneSpace = 2149; const uint16_t kElectroluxAcZeroSpace = 756; -const uint16_t kElectroluxAcFreq = 38000; // Hz. (Guessing the most common frequency.) +const uint16_t kElectroluxAcFreq = 38000; // Hz. const uint16_t kElectroluxAcOverhead = 3; #if SEND_ELECTROLUX_AC @@ -29,22 +29,27 @@ const uint16_t kElectroluxAcOverhead = 3; /// @param[in] data containing the IR command. /// @param[in] nbits Nr. of bits to send. usually kElectroluxBits /// @param[in] repeat Nr. of times the message is to be repeated. -void IRsend::sendElectroluxAc(const uint64_t data, const uint16_t nbits, const uint16_t repeat) -{ - enableIROut(kElectroluxAcFreq); - for (uint16_t r = 0; r <= repeat; r++) - { - uint64_t send_data = data; - // Header - mark(kElectroluxAcHdrMark); - space(kElectroluxAcHdrSpace); - // Data Section - sendData(kElectroluxAcBitMark, kElectroluxAcOneSpace, kElectroluxAcBitMark, kElectroluxAcZeroSpace, send_data, 32, true); - send_data >>= 32; - // Footer - mark(kElectroluxAcBitMark); - space(kDefaultMessageGap); // A 100% made up guess of the gap between messages. - } +void IRsend::sendElectroluxAc( + const uint64_t data, + const uint16_t nbits, + const uint16_t repeat +) { + enableIROut(kElectroluxAcFreq); + for (uint16_t r = 0; r <= repeat; r++) { + uint64_t send_data = data; + // Header + mark(kElectroluxAcHdrMark); + space(kElectroluxAcHdrSpace); + // Data Section + sendData(kElectroluxAcBitMark, kElectroluxAcOneSpace, + kElectroluxAcBitMark, kElectroluxAcZeroSpace, + send_data, nbits, true); + + send_data >>= 32; + // Footer + mark(kElectroluxAcBitMark); + space(kDefaultMessageGap); // A 100% made up guess of the gap between messages. + } } #endif // SEND_ELECTROLUX @@ -58,45 +63,47 @@ void IRsend::sendElectroluxAc(const uint64_t data, const uint16_t nbits, const u /// @param[in] nbits The number of data bits to expect. /// @param[in] strict Flag indicating if we should perform strict matching. /// @return A boolean. True if it can decode it, false if it can't. -bool IRrecv::decodeElectroluxAc(decode_results *results, uint16_t offset, const uint16_t nbits, const bool strict) -{ - - if (results->rawlen < 2 * nbits + kElectroluxAcOverhead - offset) // rawlen = 68, nbits = 104 - return false; // Too short a message to match. - if (strict && nbits != kElectroluxAcBits) - return false; - - uint64_t data = 0; - match_result_t data_result; - - // Header - if (!matchMark(results->rawbuf[offset++], kElectroluxAcHdrMark)) - return false; - if (!matchSpace(results->rawbuf[offset++], kElectroluxAcHdrSpace)) - return false; - - // Data Section #1 - // e.g. data_result.data = 0xED000004, nbits = 32 - data_result = matchData(&(results->rawbuf[offset]), 32, - kElectroluxAcBitMark, kElectroluxAcOneSpace, - kElectroluxAcBitMark, kElectroluxAcZeroSpace); - offset += data_result.used; - if (data_result.success == false) - return false; // Fail - data <<= 32; // Make room for the new bits of data. - data |= data_result.data; - - // Footer - if (!matchMark(results->rawbuf[offset++], kElectroluxAcBitMark)) - return false; - - // Success - results->decode_type = decode_type_t::ELETROLUX_AC; - results->bits = nbits; - results->value = data; - results->command = data & 0xFFF; - results->address = 0; - return true; +bool IRrecv::decodeElectroluxAc( + decode_results *results, + uint16_t offset, + const uint16_t nbits, + const bool strict +) { + if (results->rawlen < 2 * nbits + kElectroluxAcOverhead - offset) // rawlen = 68, nbits = 104 + return false; // Too short a message to match. + if (strict && nbits != kElectroluxAcBits) + return false; + + uint64_t data = 0; + + // Header + if (!matchMark(results->rawbuf[offset++], kElectroluxAcHdrMark)) + return false; + if (!matchSpace(results->rawbuf[offset++], kElectroluxAcHdrSpace)) + return false; + + // Data Section #1 + // e.g. data_result.data = 0xED000004, nbits = 32 + match_result_t data_result = matchData(&(results->rawbuf[offset]), 32, + kElectroluxAcBitMark, kElectroluxAcOneSpace, + kElectroluxAcBitMark, kElectroluxAcZeroSpace); + offset += data_result.used; + if (data_result.success == false) + return false; // Fail + data <<= 32; // Make room for the new bits of data. + data |= data_result.data; + + // Footer + if (!matchMark(results->rawbuf[offset++], kElectroluxAcBitMark)) + return false; + + // Success + results->decode_type = decode_type_t::ELETROLUX_AC; + results->bits = nbits; + results->value = data; + results->command = data & 0xFFF; + results->address = 0; + return true; } #endif // DECODE_ELECTROLUX @@ -104,25 +111,29 @@ bool IRrecv::decodeElectroluxAc(decode_results *results, uint16_t offset, const /// @param[in] pin GPIO to be used when sending. /// @param[in] inverted Is the output signal to be inverted? /// @param[in] use_modulation Is frequency modulation to be used? -IRElectroluxAc::IRElectroluxAc(const uint16_t pin, const bool inverted, - const bool use_modulation) - : _irsend(pin, inverted, use_modulation) { stateReset(); } +IRElectroluxAc::IRElectroluxAc( + const uint16_t pin, + const bool inverted, + const bool use_modulation +): _irsend(pin, inverted, use_modulation) { + _ = ElectroluxAcProtocol(); + stateReset(); +} /// Reset the internal state to a fixed known good state. /// @note The state is powered off. -void IRElectroluxAc::stateReset(void) { _.raw = 0xF3008005; } +void IRElectroluxAc::stateReset() { _.raw = 0xF3008005; } #if SEND_ELECTROLUX_AC /// Send the current internal state as an IR message. /// @param[in] repeat Nr. of times the message will be repeated. -void IRElectroluxAc::send(const uint16_t repeat) -{ - _irsend.sendElectroluxAc(getRaw(), kElectroluxAcBits, repeat); +void IRElectroluxAc::send(const uint16_t repeat) { + _irsend.sendElectroluxAc(getRaw(), kElectroluxAcBits, repeat); } #endif // SEND_ELECTROLUX_AC /// Set up hardware to be able to send a message. -void IRElectroluxAc::begin(void) { _irsend.begin(); } +void IRElectroluxAc::begin() { _irsend.begin(); } /// Turn on/off the Power Airwell setting. /// @param[in] on The desired setting state. @@ -130,7 +141,7 @@ void IRElectroluxAc::setPower(const bool on) { _.Power = on; } /// Get the power toggle setting from the internal state. /// @return A boolean indicating the setting. -bool IRElectroluxAc::getPower(void) const { return _.Power; } +bool IRElectroluxAc::getPower() const { return _.Power; } /// Turn on/off the fahrenheit temp mode. /// @param[in] on The desired setting state. @@ -138,105 +149,94 @@ void IRElectroluxAc::setTempModeFahrenheit(const bool on) { _.TempModeFahrenheit /// Get the fahrenheit temp mode set from the internal state. /// @return A boolean indicating the setting. -bool IRElectroluxAc::getTempModeFahrenheit(void) const { return _.TempModeFahrenheit; } +bool IRElectroluxAc::getTempModeFahrenheit() const { return _.TempModeFahrenheit; } /// Set the temperature. /// @param[in] degrees The temperature in celsius or fahrenheit. -void IRElectroluxAc::setTemp(const uint8_t degrees) -{ - if (getTempModeFahrenheit()) - { - uint8_t temp = max(kElectroluxAcMinFTemp, degrees); - temp = min(kElectroluxAcMaxFTemp, temp); - _.Temp = (temp - kElectroluxAcMinFTemp); - } - else - { - uint8_t temp = max(kElectroluxAcMinTemp, degrees); - temp = min(kElectroluxAcMaxTemp, temp); +void IRElectroluxAc::setTemp(const uint8_t degrees) { + if (getTempModeFahrenheit()) { + uint8_t temp = max(kElectroluxAcMinFTemp, degrees); + temp = min(kElectroluxAcMaxFTemp, temp); + _.Temp = (temp - kElectroluxAcMinFTemp); + } else { + uint8_t temp = max(kElectroluxAcMinTemp, degrees); + temp = min(kElectroluxAcMaxTemp, temp); #ifndef UNIT_TEST - temp = map(temp, kElectroluxAcMinTemp, kElectroluxAcMaxTemp, kElectroluxAcMinFTemp, kElectroluxAcMaxFTemp); + temp = map(temp, kElectroluxAcMinTemp, kElectroluxAcMaxTemp, kElectroluxAcMinFTemp, kElectroluxAcMaxFTemp); #else temp = temp * 9 / 5 + 32; #endif - _.Temp = temp - kElectroluxAcMinFTemp; - } + _.Temp = temp - kElectroluxAcMinFTemp; + } } /// Get the current temperature from the internal state. /// @return The current temperature in Celsius. -uint8_t IRElectroluxAc::getTemp(void) const -{ - if (getTempModeFahrenheit()) - { - return _.Temp + kElectroluxAcMinFTemp; - } - else - { +uint8_t IRElectroluxAc::getTemp() const { + if (getTempModeFahrenheit()) { + return _.Temp + kElectroluxAcMinFTemp; + } else { #ifndef UNIT_TEST - uint8_t temp = map(_.Temp + kElectroluxAcMinFTemp, kElectroluxAcMinFTemp, kElectroluxAcMaxFTemp, kElectroluxAcMinTemp, kElectroluxAcMaxTemp); + uint8_t temp = map(_.Temp + kElectroluxAcMinFTemp, kElectroluxAcMinFTemp, kElectroluxAcMaxFTemp, + kElectroluxAcMinTemp, kElectroluxAcMaxTemp); #else uint8_t temp = ((_.Temp + kElectroluxAcMinFTemp) - 32) * 5 / 9; #endif - return temp; - } + return temp; + } } /// Set the speed of the fan. /// @param[in] speed The desired setting. /// @note The speed is locked to Low when in Dry mode. -void IRElectroluxAc::setFan(const uint8_t speed) -{ - _.Fan = (_.Mode == kElectroluxModeAuto) ? kElectroluxFanAuto - : std::min(speed, kElectroluxFanAuto); +void IRElectroluxAc::setFan(const uint8_t speed) { + _.Fan = (_.Mode == kElectroluxModeAuto) + ? kElectroluxFanAuto + : std::min(speed, kElectroluxFanAuto); } /// Get the current fan speed setting. /// @return The current fan speed. -uint8_t IRElectroluxAc::getFan(void) const { return _.Fan; } +uint8_t IRElectroluxAc::getFan() const { return _.Fan; } /// Set the desired operation mode. /// @param[in] mode The desired operation mode. -void IRElectroluxAc::setMode(const uint8_t mode) -{ - switch (mode) - { - case kElectroluxModeCool: - case kElectroluxModeDry: - case kElectroluxModeFan: - case kElectroluxModeAuto: - _.Mode = mode; - break; - default: - _.Mode = kElectroluxModeAuto; - } +void IRElectroluxAc::setMode(const uint8_t mode) { + switch (mode) { + case kElectroluxModeCool: + case kElectroluxModeDry: + case kElectroluxModeFan: + case kElectroluxModeAuto: + _.Mode = mode; + break; + default: + _.Mode = kElectroluxModeAuto; + } } /// Get the operating mode setting of the A/C. /// @return The current operating mode setting. -uint8_t IRElectroluxAc::getMode(void) const { return _.Mode; } +uint8_t IRElectroluxAc::getMode() const { return _.Mode; } /// Set the On/Off Timer time. /// @param[in] nr_of_mins Number of minutes to set the timer to. /// (< 60 is disable). /// @note The A/C protocol only supports one hour increments. -void IRElectroluxAc::setOnOffTimer(const uint16_t nr_of_mins) -{ - uint8_t hours = std::min((uint8_t)(nr_of_mins / 60), kElectroluxTimerMax); - // The time can be changed in sleep mode, but doesn't set the flag. - _.TimerEnable = hours > 0; - _.Timer = std::max(kElectroluxTimerMin, hours); // Hours +void IRElectroluxAc::setOnOffTimer(const uint16_t nr_of_mins) { + const uint8_t hours = std::min( + static_cast(nr_of_mins / 60), + kElectroluxTimerMax + ); + // The time can be changed in sleep mode, but doesn't set the flag. + _.TimerEnabled = hours > 0; + _.Timer = std::max(kElectroluxTimerMin, hours); // Hours } /// Get the current On/Off Timer time. /// @return The number of minutes it is set for. 0 means it's off. /// @note The A/C protocol only supports one hour increments. -uint16_t IRElectroluxAc::getOnOffTimer(void) const -{ - if (_.TimerEnable) - return _.Timer * 60; - else - return 0; +uint16_t IRElectroluxAc::getOnOffTimer() const { + return _.TimerEnabled > 0 ? _.Timer * 60 : 0; } /// Set the Quiet setting of the A/C. @@ -245,14 +245,13 @@ void IRElectroluxAc::setQuiet(const bool on) { _.Quiet = on; } /// Get the Quiet setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRElectroluxAc::getQuiet(void) const { return _.Quiet; } +bool IRElectroluxAc::getQuiet() const { return _.Quiet; } /// Get a copy of the internal state as a valid code for this protocol. /// @return A valid code for this protocol based on the current internal state. -uint64_t IRElectroluxAc::getRaw(void) -{ - checksum(); // Ensure correct settings before sending. - return _.raw; +uint64_t IRElectroluxAc::getRaw() { + checksum(); // Ensure correct settings before sending. + return _.raw; } /// Set the internal state from a valid code for this protocol. @@ -262,175 +261,184 @@ void IRElectroluxAc::setRaw(const uint64_t state) { _.raw = state; } /// Calculate the checksum for a given state. /// @param[in] state The value to calc the checksum of. /// @return The 4-bit checksum stored in a uint_8. -uint8_t IRElectroluxAc::calcChecksum(const uint64_t state) -{ - uint32_t data = GETBITS64(state, kElectroluxAcChecksumSize + kElectroluxAcChecksumOffset, kElectroluxAcBits - 4); - uint8_t result = 0; - for (; data; data >>= 4) // Add each nibble together. - result += GETBITS8(data, 0, 4); - return (result ^ 0xF) & 0xF; +uint8_t IRElectroluxAc::calcChecksum(const uint64_t state) { + uint32_t data = GETBITS64( + state, + kElectroluxAcChecksumSize + kElectroluxAcChecksumOffset, + kElectroluxAcBits - 4 + ); + uint8_t result = 0; + for (; data; data >>= 4) // Add each nibble together. + result += GETBITS8(data, 0, 4); + return (result ^ 0xF) & 0xF; } /// Verify the checksum is valid for a given state. /// @param[in] state The array to verify the checksum of. /// @return true, if the state has a valid checksum. Otherwise, false. -bool IRElectroluxAc::validChecksum(const uint64_t state) -{ - // Validate the checksum of the given state. - return (GETBITS8(state, kElectroluxAcChecksumOffset, - kElectroluxAcChecksumSize) == calcChecksum(state)); +bool IRElectroluxAc::validChecksum(const uint64_t state) { + // Validate the checksum of the given state. + return (GETBITS8(state, kElectroluxAcChecksumOffset, + kElectroluxAcChecksumSize) == calcChecksum(state)); } /// Convert a stdAc::opmode_t enum into its native mode. /// @param[in] mode The enum to be converted. /// @return The native equivalent of the enum. -uint8_t IRElectroluxAc::convertMode(const stdAc::opmode_t mode) -{ - switch (mode) - { - case stdAc::opmode_t::kCool: - return kElectroluxModeCool; - case stdAc::opmode_t::kDry: - return kElectroluxModeDry; - case stdAc::opmode_t::kFan: - return kElectroluxModeFan; - default: - return kElectroluxModeAuto; - } +uint8_t IRElectroluxAc::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kElectroluxModeCool; + case stdAc::opmode_t::kDry: + return kElectroluxModeDry; + case stdAc::opmode_t::kFan: + return kElectroluxModeFan; + default: + return kElectroluxModeAuto; + } } /// Convert a stdAc::fanspeed_t enum into it's native speed. /// @param[in] speed The enum to be converted. /// @return The native equivalent of the enum. -uint8_t IRElectroluxAc::convertFan(const stdAc::fanspeed_t speed) -{ - switch (speed) - { - case stdAc::fanspeed_t::kMin: - case stdAc::fanspeed_t::kLow: - return kElectroluxFanLow; - case stdAc::fanspeed_t::kMedium: - case stdAc::fanspeed_t::kMediumHigh: - return kElectroluxFanMedium; - case stdAc::fanspeed_t::kHigh: - case stdAc::fanspeed_t::kMax: - return kElectroluxFanHigh; - default: - return kElectroluxFanAuto; - } +uint8_t IRElectroluxAc::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kElectroluxFanLow; + case stdAc::fanspeed_t::kMedium: + case stdAc::fanspeed_t::kMediumHigh: + return kElectroluxFanMedium; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kElectroluxFanHigh; + default: + return kElectroluxFanAuto; + } } /// Convert a native mode into its stdAc equivalent. /// @param[in] mode The native setting to be converted. /// @return The stdAc equivalent of the native setting. -stdAc::opmode_t IRElectroluxAc::toCommonMode(const uint8_t mode) -{ - switch (mode) - { - case kElectroluxModeCool: - return stdAc::opmode_t::kCool; - case kElectroluxModeDry: - return stdAc::opmode_t::kDry; - case kElectroluxModeFan: - return stdAc::opmode_t::kFan; - default: - return stdAc::opmode_t::kAuto; - } +stdAc::opmode_t IRElectroluxAc::toCommonMode(const uint8_t mode) { + switch (mode) { + case kElectroluxModeCool: + return stdAc::opmode_t::kCool; + case kElectroluxModeDry: + return stdAc::opmode_t::kDry; + case kElectroluxModeFan: + return stdAc::opmode_t::kFan; + default: + return stdAc::opmode_t::kAuto; + } } /// Convert a native fan speed into its stdAc equivalent. /// @param[in] speed The native setting to be converted. /// @return The stdAc equivalent of the native setting. -stdAc::fanspeed_t IRElectroluxAc::toCommonFanSpeed(const uint8_t speed) -{ - switch (speed) - { - case kElectroluxFanHigh: - return stdAc::fanspeed_t::kMax; - case kElectroluxFanMedium: - return stdAc::fanspeed_t::kMedium; - case kElectroluxFanLow: - return stdAc::fanspeed_t::kMin; - default: - return stdAc::fanspeed_t::kAuto; - } +stdAc::fanspeed_t IRElectroluxAc::toCommonFanSpeed(const uint8_t speed) { + switch (speed) { + case kElectroluxFanHigh: + return stdAc::fanspeed_t::kMax; + case kElectroluxFanMedium: + return stdAc::fanspeed_t::kMedium; + case kElectroluxFanLow: + return stdAc::fanspeed_t::kMin; + default: + return stdAc::fanspeed_t::kAuto; + } } /// Convert the current internal state into its stdAc::state_t equivalent. /// @param[in] prev Ptr to the previous state if required. /// @return The stdAc equivalent of the native settings. -stdAc::state_t IRElectroluxAc::toCommon(const stdAc::state_t *prev) const -{ - stdAc::state_t result{}; - // Start with the previous state if given it. - if (prev != NULL) - { - result = *prev; - } - else - { - // Set defaults for non-zero values that are not implicitly set for when - // there is no previous state. - // e.g. Any setting that toggles should probably go here. - result.power = false; - } - result.protocol = decode_type_t::ELETROLUX_AC; - result.power = _.Power; - result.mode = toCommonMode(_.Mode); - result.celsius = !getTempModeFahrenheit(); - result.degrees = getTemp(); - result.fanspeed = toCommonFanSpeed(_.Fan); - // Not supported. - result.model = -1; - result.turbo = false; - result.swingv = stdAc::swingv_t::kOff; - result.swingh = stdAc::swingh_t::kOff; - result.light = false; - result.filter = false; - result.econo = false; - result.quiet = getQuiet(); - result.clean = false; - result.beep = false; - result.sleep = -1; - result.clock = -1; - return result; +stdAc::state_t IRElectroluxAc::toCommon(const stdAc::state_t *prev) const { + stdAc::state_t result{}; + // Start with the previous state if given it. + if (prev != nullptr) { + result = *prev; + } else { + // Set defaults for non-zero values that are not implicitly set for when + // there is no previous state. + // e.g. Any setting that toggles should probably go here. + result.power = false; + } + result.protocol = ELETROLUX_AC; + result.power = _.Power; + result.mode = toCommonMode(_.Mode); + result.celsius = !getTempModeFahrenheit(); + result.degrees = getTemp(); + result.fanspeed = toCommonFanSpeed(_.Fan); + // Not supported. + result.model = -1; + result.turbo = false; + result.swingv = stdAc::swingv_t::kOff; + result.swingh = stdAc::swingh_t::kOff; + result.light = false; + result.filter = false; + result.econo = false; + result.quiet = getQuiet(); + result.clean = false; + result.beep = false; + result.sleep = -1; + result.clock = -1; + return result; } /// Convert the internal state into a human readable string. /// @return The current internal state expressed as a human readable String. -String IRElectroluxAc::toString(void) const -{ - String result = ""; - result.reserve(120); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(_.Power, kPowerStr, false); - result += addModeToString(_.Mode, kElectroluxModeAuto, kElectroluxModeCool, - 0xFF, kElectroluxModeDry, kElectroluxModeFan); - result += addTempToString(getTemp(), !getTempModeFahrenheit()); - result += addFanToString(_.Fan, kElectroluxFanHigh, kElectroluxFanLow, - kElectroluxFanAuto, kElectroluxFanAuto, - kElectroluxFanMedium); - - result += addBoolToString(getQuiet(), kQuietStr); - - if (getPower()) - { - result += irutils::addLabeledString(irutils::minsToString(getOnOffTimer()), kOffTimerStr); - } - else - { - result += irutils::addLabeledString(irutils::minsToString(getOnOffTimer()), kOnTimerStr); - } - return result; +String IRElectroluxAc::toString() const { + String result = ""; + result.reserve(120); // Reserve some heap for the string to reduce fragging. + result += addBoolToString( + _.Power, + kPowerStr, + false + ); + result += addModeToString( + _.Mode, + kElectroluxModeAuto, + kElectroluxModeCool, + 0xFF, + kElectroluxModeDry, + kElectroluxModeFan + ); + result += addTempToString( + getTemp(), + !getTempModeFahrenheit() + ); + result += addFanToString( + _.Fan, + kElectroluxFanHigh, + kElectroluxFanLow, + kElectroluxFanAuto, + kElectroluxFanAuto, + kElectroluxFanMedium + ); + + result += addBoolToString(getQuiet(), kQuietStr); + + if (getPower()) { + result += irutils::addLabeledString( + irutils::minsToString(getOnOffTimer()), + kOffTimerStr + ); + } else { + result += irutils::addLabeledString( + irutils::minsToString(getOnOffTimer()), + kOnTimerStr + ); + } + return result; } /// Calculate and set the checksum values for the internal state. -void IRElectroluxAc::checksum(void) -{ - _.Sum = calcChecksum(_.raw); +void IRElectroluxAc::checksum() { + _.Sum = calcChecksum(_.raw); } /// Set the requested power state of the A/C to on. -void IRElectroluxAc::on(void) { setPower(true); } +void IRElectroluxAc::on() { setPower(true); } /// Set the requested power state of the A/C to off. -void IRElectroluxAc::off(void) { setPower(false); } \ No newline at end of file +void IRElectroluxAc::off() { setPower(false); } diff --git a/src/ir_Electrolux.h b/src/ir_Electrolux.h index 64d89c11a..5278e7907 100644 --- a/src/ir_Electrolux.h +++ b/src/ir_Electrolux.h @@ -8,8 +8,8 @@ #ifndef IR_ELECTROLUX_AC_H_ #define IR_ELECTROLUX_AC_H_ -#define __STDC_LIMIT_MACROS -#include +#define STDC_LIMIT_MACROS +#include #ifndef UNIT_TEST #include #endif @@ -19,93 +19,119 @@ #include "IRsend_test.h" #endif -union ElectroluxAcProtocol -{ +union ElectroluxAcProtocol { uint64_t raw; // The state of the IR remote in native IR code form. - struct - { - uint8_t Sum : 4; + struct { + uint8_t Sum: 4; uint8_t : 4; uint8_t : 5; - uint8_t TempModeFahrenheit : 1; + uint8_t TempModeFahrenheit: 1; uint8_t : 1; - uint8_t Quiet : 1; - uint8_t Timer : 4; - uint8_t TimerEnable : 1; - uint8_t Mode : 3; - uint8_t Temp : 5; - uint8_t Fan : 2; - uint8_t Power : 1; + uint8_t Quiet: 1; + uint8_t Timer: 4; + uint8_t TimerEnabled: 1; + uint8_t Mode: 3; + uint8_t Temp: 5; + uint8_t Fan: 2; + uint8_t Power: 1; uint64_t : 0; }; }; // Constants -const uint8_t kElectroluxAcMinTemp = 16; // 16C -const uint8_t kElectroluxAcMaxTemp = 32; // 32C +const uint8_t kElectroluxAcMinTemp = 16; // 16C +const uint8_t kElectroluxAcMaxTemp = 32; // 32C const uint8_t kElectroluxAcMinFTemp = 60; // 60F const uint8_t kElectroluxAcMaxFTemp = 90; // 90F -const uint8_t kElectroluxTimerMax = 12; // 12H -const uint8_t kElectroluxTimerMin = 1; // 1H +const uint8_t kElectroluxTimerMax = 12; // 12H +const uint8_t kElectroluxTimerMin = 1; // 1H const uint64_t kElectroluxAcKnownGoodState = 0xF3008005; const uint8_t kElectroluxAcChecksumOffset = 0; const uint8_t kElectroluxAcChecksumSize = 4; // Fan -const uint8_t kElectroluxFanLow = 2; // 0b11 +const uint8_t kElectroluxFanLow = 2; // 0b11 const uint8_t kElectroluxFanMedium = 1; // 0b01 -const uint8_t kElectroluxFanHigh = 0; // 0b00 -const uint8_t kElectroluxFanAuto = 3; // 0b11 +const uint8_t kElectroluxFanHigh = 0; // 0b00 +const uint8_t kElectroluxFanAuto = 3; // 0b11 // Modes const uint8_t kElectroluxModeCool = 0; // 0b000 -const uint8_t kElectroluxModeDry = 1; // 0b001 -const uint8_t kElectroluxModeFan = 2; // 0b010 +const uint8_t kElectroluxModeDry = 1; // 0b001 +const uint8_t kElectroluxModeFan = 2; // 0b010 const uint8_t kElectroluxModeAuto = 4; // 0b100 -class IRElectroluxAc -{ +class IRElectroluxAc { public: - explicit IRElectroluxAc(const uint16_t pin, const bool inverted = false, - const bool use_modulation = true); + explicit IRElectroluxAc(uint16_t pin, bool inverted = false, + bool use_modulation = true); + void stateReset(); #if SEND_ELECTROLUX_AC - void send(const uint16_t repeat = kElectroluxAcDefaultRepeat); + void send(uint16_t repeat = kElectroluxAcDefaultRepeat); + /// Run the calibration to calculate uSec timing offsets for this platform. /// @return The uSec timing offset needed per modulation of the IR Led. /// @note This will produce a 65ms IR signal pulse at 38kHz. /// Only ever needs to be run once per object instantiation, if at all. - int8_t calibrate(void) { return _irsend.calibrate(); } + int8_t calibrate() { return _irsend.calibrate(); } #endif // SEND_ELECTROLUX_AC void begin(); - void on(void); - void off(void); - void setPower(const bool on); - bool getPower(void) const; - void setTemp(const uint8_t temp); - uint8_t getTemp(void) const; - void setFan(const uint8_t speed); - uint8_t getFan(void) const; - void setMode(const uint8_t mode); - uint8_t getMode(void) const; - void setOnOffTimer(const uint16_t nr_of_mins); - uint16_t getOnOffTimer(void) const; - void setQuiet(const bool on); - bool getQuiet(void) const; - void setTempModeFahrenheit(const bool on); - bool getTempModeFahrenheit(void) const; - uint64_t getRaw(void); - void setRaw(const uint64_t state); - static uint8_t calcChecksum(const uint64_t state); - static bool validChecksum(const uint64_t state); - static uint8_t convertMode(const stdAc::opmode_t mode); - static uint8_t convertFan(const stdAc::fanspeed_t speed); - static stdAc::opmode_t toCommonMode(const uint8_t mode); - static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); - stdAc::state_t toCommon(const stdAc::state_t *prev = NULL) const; - String toString(void) const; + + void on(); + + void off(); + + void setPower(bool on); + + bool getPower() const; + + void setTemp(uint8_t temp); + + uint8_t getTemp() const; + + void setFan(uint8_t speed); + + uint8_t getFan() const; + + void setMode(uint8_t mode); + + uint8_t getMode() const; + + void setOnOffTimer(uint16_t nr_of_mins); + + uint16_t getOnOffTimer() const; + + void setQuiet(bool on); + + bool getQuiet() const; + + void setTempModeFahrenheit(bool on); + + bool getTempModeFahrenheit() const; + + uint64_t getRaw(); + + void setRaw(uint64_t state); + + static uint8_t calcChecksum(uint64_t state); + + static bool validChecksum(uint64_t state); + + static uint8_t convertMode(stdAc::opmode_t mode); + + static uint8_t convertFan(stdAc::fanspeed_t speed); + + static stdAc::opmode_t toCommonMode(uint8_t mode); + + static stdAc::fanspeed_t toCommonFanSpeed(uint8_t speed); + + stdAc::state_t toCommon(const stdAc::state_t *prev = nullptr) const; + + String toString() const; #ifndef UNIT_TEST + private: IRsend _irsend; ///< Instance of the IR send class #else // UNIT_TEST @@ -113,8 +139,9 @@ class IRElectroluxAc IRsendTest _irsend; ///< Instance of the testing IR send class /// @endcond #endif // UNIT_TEST - ElectroluxAcProtocol _; - void checksum(void); + ElectroluxAcProtocol _{}; + + void checksum(); }; -#endif // IR_ELECTROLUX_AC_H_ \ No newline at end of file +#endif // IR_ELECTROLUX_AC_H_