From db02a5cb88921bfa6abb85dae7b5bf9090bf6c08 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Mon, 18 Jul 2022 20:15:41 +0200 Subject: [PATCH 01/32] BOSCH144: Add IRac class support BOSCH144: Add IRac class support Power, Mode, Temp, Fan, Quiet is working I want to add: SwingV, Turbo, Clean, Beep/LED (all separate 96-bit messages) --- src/IRac.cpp | 73 ++++++++++++ src/IRac.h | 7 ++ src/ir_Bosch.cpp | 303 +++++++++++++++++++++++++++++++++++++++++++---- src/ir_Bosch.h | 166 ++++++++++++++++++++++++++ 4 files changed, 529 insertions(+), 20 deletions(-) create mode 100644 src/ir_Bosch.h diff --git a/src/IRac.cpp b/src/IRac.cpp index e14f05b62..397e3c260 100644 --- a/src/IRac.cpp +++ b/src/IRac.cpp @@ -20,6 +20,7 @@ #include "ir_Airwell.h" #include "ir_Amcor.h" #include "ir_Argo.h" +#include "ir_Bosch.h" #include "ir_Carrier.h" #include "ir_Coolix.h" #include "ir_Corona.h" @@ -161,6 +162,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { #if SEND_ARGO case decode_type_t::ARGO: #endif +#if SEND_BOSCH144 + case decode_type_t::BOSCH144: +#endif #if SEND_CARRIER_AC64 case decode_type_t::CARRIER_AC64: #endif // SEND_CARRIER_AC64 @@ -459,6 +463,52 @@ void IRac::argo(IRArgoAC *ac, } #endif // SEND_ARGO +#if SEND_BOSCH144 +/// Send a Bosch144 A/C message with the supplied settings. +/// @note May result in multiple messages being sent. +/// @param[in, out] ac A Ptr to an IRBosch144AC object to use. +/// @param[in] on The power setting. +/// @param[in] mode The operation mode setting. +/// @param[in] degrees The temperature setting in degrees. +/// @param[in] fan The speed setting for the fan. +/// @param[in] swingv The vertical swing setting. *** todo +/// @param[in] quiet Run the device in quiet/silent mode. +/// @param[in] turbo Run the device in turbo/powerful mode. *** todo +/// @param[in] clean Turn on the self-cleaning mode. e.g. Mould, dry filters etc *** todo +/// @note -1 is Off, >= 0 is on. +void IRac::bosch144( IRBosch144AC *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const bool quiet ) { + ac->begin(); + ac->setPower( on ); + if (!on) { + // after turn off AC no more commands should + // be accepted + ac->send(); + return; + } + ac->setTemp( degrees ); + ac->setFan( ac->convertFan( fan ) ); + ac->setMode( ac->convertMode( mode ) ); + ac->setQuiet( quiet ); + ac->setInvertBytes(); + ac->setCheckSumS3(); + ac->send(); // Send the state, which will also power on the unit. + // The following are all options/settings that create their own special + // messages. Often they only make sense to be sent after the unit is turned + // on. For instance, assuming a person wants to have the a/c on and in turbo + // mode. If we send the turbo message, it is ignored if the unit is off. + // Hence we send the special mode/setting messages after a normal message + // which will turn on the device. + // No Filter setting available. + // No Beep setting available. + // No Clock setting available. + // No Econo setting available. + // No Sleep setting available. +} +#endif // SEND_BOSCH144 + #if SEND_CARRIER_AC64 /// Send a Carrier 64-bit A/C message with the supplied settings. /// @param[in, out] ac A Ptr to an IRCarrierAc64 object to use. @@ -2759,6 +2809,14 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { break; } #endif // SEND_ARGO +#if SEND_BOSCH144 + case BOSCH144: + { + IRBosch144AC ac(_pin, _inverted, _modulation); + bosch144(&ac, send.power, send.mode, degC, send.fanspeed, send.quiet); + break; + } +#endif // SEND_AMCOR #if SEND_CARRIER_AC64 case CARRIER_AC64: { @@ -3686,6 +3744,13 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_ARGO +#if DECODE_BOSCH144 + case decode_type_t::BOSCH144: { + IRBosch144AC ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_BOSCH144 #if DECODE_CARRIER_AC64 case decode_type_t::CARRIER_AC64: { IRCarrierAc64 ac(kGpioUnused); @@ -4135,6 +4200,14 @@ namespace IRAcUtils { break; } #endif // DECODE_ARGO +#if DECODE_BOSCH144 + case decode_type_t::BOSCH144: { + IRBosch144AC ac(kGpioUnused); + ac.setRaw(decode->state); + *result = ac.toCommon(); + break; + } +#endif // DECODE_BOSCH144 #if DECODE_CARRIER_AC64 case decode_type_t::CARRIER_AC64: { IRCarrierAc64 ac(kGpioUnused); diff --git a/src/IRac.h b/src/IRac.h index 8e3ef7582..67f7bf768 100644 --- a/src/IRac.h +++ b/src/IRac.h @@ -11,6 +11,7 @@ #include "ir_Airwell.h" #include "ir_Amcor.h" #include "ir_Argo.h" +#include "ir_Bosch.h" #include "ir_Carrier.h" #include "ir_Coolix.h" #include "ir_Corona.h" @@ -134,6 +135,12 @@ class IRac { const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const int16_t sleep = -1); #endif // SEND_ARGO +#if SEND_BOSCH144 + void bosch144(IRBosch144AC *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, + const bool quiet); +#endif // SEND_COOLIX #if SEND_CARRIER_AC64 void carrier64(IRCarrierAc64 *ac, const bool on, const stdAc::opmode_t mode, diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index f6e26eb52..8e8f680b7 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -8,9 +8,11 @@ // Brand: Bosch, Model: RG10A(G2S)BGEF remote #include -#ifndef ARDUINO +/*#ifndef ARDUINO #include -#endif +#endif*/ +#include +#include "ir_Bosch.h" #include "IRrecv.h" #include "IRsend.h" #include "IRtext.h" @@ -25,37 +27,298 @@ const uint16_t kBoschZeroSpace = 571; const uint16_t kBoschFooterSpace = 5235; const uint16_t kBoschFreq = 38000; // Hz. (Guessing the most common frequency.) const uint16_t kBosch144NrOfSections = 3; +const uint16_t kBosch144BytesPerSection = 6; + +using irutils::addBoolToString; +using irutils::addModeToString; +using irutils::addFanToString; +using irutils::addTempToString; #if SEND_BOSCH144 -/// Send a Bosch 144-bit / 18-byte message -/// Status: STABLE / Confirmed Working. +/// Send a Bosch 144-bit / 18-byte message ( 96-bit message are also possible) +/// Status: BETA / Probably Working. /// @param[in] data The message to be sent. /// @param[in] nbytes The number of bytes of message to be sent. /// @param[in] repeat The number of times the command is to be repeated. -void IRsend::sendBosch144(const unsigned char data[], const uint16_t nbytes, - const uint16_t repeat) { - // nbytes is required to be a multiple of kBosch144NrOfSections. - if (nbytes % kBosch144NrOfSections != 0) return; - +void IRsend::sendBosch144( const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat ) +{ + // nbytes is required to be a multiple of kBosch144BytesPerSection. + if( nbytes % kBosch144BytesPerSection != 0 )return; // Set IR carrier frequency - enableIROut(kBoschFreq); + enableIROut( kBoschFreq ); - for (uint16_t r = 0; r <= repeat; r++) { - const uint16_t kSectionByteSize = nbytes / kBosch144NrOfSections; - for (uint16_t offset = 0; offset < nbytes; offset += kSectionByteSize) + for( uint16_t r = 0; r <= repeat; r++ ) + { + for( uint16_t offset = 0; offset < nbytes; offset += kBosch144BytesPerSection ) // Section Header + Data + Footer - sendGeneric(kBoschHdrMark, kBoschHdrSpace, - kBoschBitMark, kBoschOneSpace, - kBoschBitMark, kBoschZeroSpace, - kBoschBitMark, kBoschFooterSpace, - data + offset, kSectionByteSize, - kBoschFreq, true, 0, kDutyDefault); - space(kDefaultMessageGap); // Complete guess + sendGeneric( kBoschHdrMark, kBoschHdrSpace, + kBoschBitMark, kBoschOneSpace, + kBoschBitMark, kBoschZeroSpace, + kBoschBitMark, kBoschFooterSpace, + data + offset, kBosch144BytesPerSection, + kBoschFreq, true, 0, kDutyDefault ); + space( kDefaultMessageGap ); // Complete guess } } #endif // SEND_BOSCH144 +/// Class constructor. +/// @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? +IRBosch144AC::IRBosch144AC( const uint16_t pin, const bool inverted, const bool use_modulation ) + : _irsend( pin, inverted, use_modulation ) + { + stateReset(); + } + +/// Reset the internal state to a fixed known good state. +void IRBosch144AC::stateReset( void ) +{ + setRaw( kBosch144DefaultState ); +} + +/// Set up hardware to be able to send a message. +void IRBosch144AC::begin( void ) +{ + _irsend.begin(); +} + +#if SEND_BOSCH144 +/// Send the current internal state as an IR message. +/// @param[in] repeat Nr. of times the message will be repeated. +void IRBosch144AC::send( const uint16_t repeat ) +{ + if( !powerFlag ) _irsend.sendBosch144( kBosch144Off, sizeof( kBosch144Off ), repeat ); // "Off" is a 96bit message + else _irsend.sendBosch144( getRaw(), kBosch144StateLength, repeat ); + // other 96bit messages are not yet supported +} +#endif // SEND_BOSCH144 + +/// 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. +uint8_t* IRBosch144AC::getRaw( void ) +{ + return _.raw; +} + +/// Set the internal state from a valid code for this protocol. +/// @param[in] new_code A valid code for this protocol. +void IRBosch144AC::setRaw( const uint8_t new_code[] ) +{ + std::memcpy( _.raw, new_code, kBosch144StateLength ); +} + +void IRBosch144AC::setPower( const bool on ) +{ + powerFlag = on; +} + +bool IRBosch144AC::getPower( void ) const +{ + return true; +} + +void IRBosch144AC::setTempRaw( const uint8_t code ) +{ + _.TempS1 = code >> 1; // save 4 bits in Section1 + _.TempS2 = code >> 1; // Section2 = Section1 + _.TempS3 = code & 1; // save 1 bit in Section3 +} + +/// Set the temperature. +/// @param[in] degrees The temperature in degrees celsius. +void IRBosch144AC::setTemp( const uint8_t degrees ) +{ + uint8_t temp = std::max( kBosch144TempMin, degrees ); + temp = std::min( kBosch144TempMax, temp ); + setTempRaw( kBosch144TempMap[ temp - kBosch144TempMin ] ); +} + +uint8_t IRBosch144AC::getTemp( void ) const +{ + uint8_t temp = ( _.TempS1 << 1 ) + _.TempS3; + for( uint8_t i = 0; i < 16; i++ ) + { + if( temp == kBosch144TempMap[ i ] ) return kBosch144TempMin + i; + } +} + +/// Set the speed of the fan. +/// @param[in] speed The desired setting. +void IRBosch144AC::setFan( const uint16_t speed ) +{ + _.FanS1 = speed >> 6; // save 3 bits in Section1 + _.FanS2 = speed >> 6; // Section2 = Section1 + _.FanS3 = speed & 0b111111; // save 6 bits in Section3 +} + +/// Set the desired operation mode. +/// @param[in] mode The desired operation mode. +void IRBosch144AC::setMode( const uint8_t mode ) +{ + _.ModeS1 = mode >> 1; // save 2 bits in Section1 + _.ModeS2 = mode >> 1; // Section2 = Section1 + _.ModeS3 = mode & 0b1; // save 1 bit in Section3 + if( mode == kBosch144Auto || mode == kBosch144Dry ) + { + _.FanS1 = 0b000; // save 3 bits in Section1 + _.FanS2 = _.FanS1; // Section2 = Section1 + _.FanS3 = kBosch144FanAuto0;// save 6 bits in Section3 + } +} + +/// Set the Quiet mode of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRBosch144AC::setQuiet(const bool on) +{ + _.Quiet = on; // save 1 bit in Section3 + setFan( kBosch144FanAuto ); // set Fan -> Auto +} + +/// Get the Quiet mode of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRBosch144AC::getQuiet(void) const { return _.Quiet; } + +/// 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 IRBosch144AC::convertMode( const stdAc::opmode_t mode ) +{ + switch( mode ) + { + case stdAc::opmode_t::kCool: + return kBosch144Cool; + case stdAc::opmode_t::kHeat: + return kBosch144Heat; + case stdAc::opmode_t::kDry: + return kBosch144Dry; + case stdAc::opmode_t::kFan: + return kBosch144Fan; + default: + return kBosch144Auto; + } +} + +/// 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. +uint16_t IRBosch144AC::convertFan( const stdAc::fanspeed_t speed ) +{ + switch( speed ) + { + case stdAc::fanspeed_t::kMin: + return kBosch144Fan20; + case stdAc::fanspeed_t::kLow: + return kBosch144Fan40; + case stdAc::fanspeed_t::kMedium: + return kBosch144Fan60; + case stdAc::fanspeed_t::kHigh: + return kBosch144Fan80; + case stdAc::fanspeed_t::kMax: + return kBosch144Fan100; + default: + return kBosch144FanAuto; + } +} + +/// 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 IRBosch144AC::toCommonMode( const uint8_t mode ) +{ + switch( mode ) + { + case kBosch144Cool: return stdAc::opmode_t::kCool; + case kBosch144Heat: return stdAc::opmode_t::kHeat; + case kBosch144Dry: return stdAc::opmode_t::kDry; + case kBosch144Fan: 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 IRBosch144AC::toCommonFanSpeed( const uint16_t speed ) +{ + switch( speed ) + { + case kBosch144Fan100: return stdAc::fanspeed_t::kMax; + case kBosch144Fan80: return stdAc::fanspeed_t::kHigh; + case kBosch144Fan60: return stdAc::fanspeed_t::kMedium; + case kBosch144Fan40: return stdAc::fanspeed_t::kLow; + case kBosch144Fan20: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; + } +} + +/// Convert the current internal state into its stdAc::state_t equivalent. +/// @return The stdAc equivalent of the native settings. +stdAc::state_t IRBosch144AC::toCommon( void ) const +{ + stdAc::state_t result{}; + result.protocol = decode_type_t::BOSCH144; + result.power = getPower(); + result.mode = toCommonMode( ( _.ModeS1 << 1 ) + _.ModeS3 ); + result.celsius = true; + result.degrees = getTemp(); + result.fanspeed = toCommonFanSpeed( ( _.FanS1 << 6 ) + _.FanS3 ); + result.quiet = getQuiet(); + // 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.clean = false; + result.beep = false; + result.clock = -1; + result.sleep = -1; + return result; +} + +/// Convert the current internal state into a human readable string. +/// @return A human readable string. +String IRBosch144AC::toString( void ) const +{ + uint8_t mode = ( _.ModeS1 << 1 )+_.ModeS3; + uint16_t fan = ( _.FanS1 << 6 ) + _.FanS3; + String result = ""; + result.reserve( 70 ); // Reserve some heap for the string to reduce fragging. + result += addBoolToString( getPower(), kPowerStr, false ); + result += addModeToString( mode, kBosch144Auto, kBosch144Cool, + kBosch144Heat, kBosch144Dry, kBosch144Fan); + result += addFanToString( fan>>1, kBosch144Fan100>>1, kBosch144Fan20>>1, + kBosch144FanAuto>>1, kBosch144FanAuto>>1, + kBosch144Fan60>>1); + result += addTempToString( getTemp() ); + return result; +} + +void IRBosch144AC::setInvertBytes() +{ + _.InnvertS1_1 = ~_.raw[ 0 ]; + _.InnvertS1_2 = ~_.raw[ 2 ]; + _.InnvertS1_3 = ~_.raw[ 4 ]; + _.InnvertS2_1 = ~_.raw[ 6 ]; + _.InnvertS2_2 = ~_.raw[ 8 ]; + _.InnvertS2_3 = ~_.raw[ 10 ]; +} + +void IRBosch144AC::setCheckSumS3() +{ + _.ChecksumS3 = _.raw[ 12 ]; + _.ChecksumS3 += _.raw[ 13 ]; + _.ChecksumS3 += _.raw[ 14 ]; + _.ChecksumS3 += _.raw[ 15 ]; + _.ChecksumS3 += _.raw[ 16 ]; +} + #if DECODE_BOSCH144 /// Decode the supplied Bosch 144-bit / 18-byte A/C message. /// Status: STABLE / Confirmed Working. diff --git a/src/ir_Bosch.h b/src/ir_Bosch.h new file mode 100644 index 000000000..ada051016 --- /dev/null +++ b/src/ir_Bosch.h @@ -0,0 +1,166 @@ +// Copyright 2022 David Conran +/// @file +/// @brief Support for Bosch A/C protocol +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1787 + +// Supports: +// Brand: Bosch, Model: CL3000i-Set 26 E A/C +// Brand: Bosch, Model: RG10A(G2S)BGEF remote + + +#ifndef IR_BOSCH_H_ +#define IR_BOSCH_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + +// Constants +// Modes +const uint8_t kBosch144Cool = 0b000; // Bit[0] to Section 3 Bit[1-2] to Section 1 +const uint8_t kBosch144Dry = 0b011; // ModeS3 ModeS1 +const uint8_t kBosch144Auto = 0b101; +const uint8_t kBosch144Heat = 0b110; +const uint8_t kBosch144Fan = 0b010; +// Fan Control +const uint16_t kBosch144Fan20 = 0b111001010; // Bit[0-5] to Section 3 Bit[6-8] to Section 1 +const uint16_t kBosch144Fan40 = 0b100010100; // FanS3 FanS1 +const uint16_t kBosch144Fan60 = 0b010011110; +const uint16_t kBosch144Fan80 = 0b001101000; +const uint16_t kBosch144Fan100 = 0b001110010; +const uint16_t kBosch144FanAuto = 0b101110011; +const uint16_t kBosch144FanAuto0 = 0b000110011; +// Temperature +const uint8_t kBosch144TempMin = 16; // Celsius +const uint8_t kBosch144TempMax = 30; // Celsius +const uint8_t kBosch144TempRange = kBosch144TempMax - kBosch144TempMin + 1; +const uint8_t kBosch144TempMap[ kBosch144TempRange ] = { + 0b00001, // 16C // Bit[0] to Section 3 Bit[1-4] to Section 1 + 0b00000, // 17C // TempS3 TempS1 + 0b00010, // 18c + 0b00110, // 19C + 0b00100, // 20C + 0b01100, // 21C + 0b01110, // 22C + 0b01010, // 23C + 0b01000, // 24C + 0b11000, // 25C + 0b11010, // 26C + 0b10010, // 27C + 0b10000, // 28C + 0b10100, // 29C + 0b10110 // 30C +}; + +const uint8_t kBosch144Off[] = { 0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F, // 96bit-message the same as Coolix protocol + 0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F }; + + +// On, 25C, Mode: Auto +const uint8_t kBosch144DefaultState[ kBosch144StateLength ] = { 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, + 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, + 0xD5, 0x65, 0x00, 0x00, 0x00, 0x3A }; +/*const uint8_t kBosch144DefaultState[ kBosch144StateLength ] = { 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00 };*/ + +union Bosch144Protocol { + uint8_t raw[ kBosch144StateLength ]; ///< The state in IR code form. + struct { + uint8_t :8; //< Fixed value 0b10110010 / 0xB2. ############ + uint8_t InnvertS1_1:8; // Invert byte 0b01001101 / 0x4D # + uint8_t :5; // not used (without timer use) # + uint8_t FanS1 :3; // Fan speed bits in Section 1 # + uint8_t InnvertS1_2:8; // Invert byte # Section 1 = Sektion 2 + uint8_t :2; // not used (without timer use) # + uint8_t ModeS1 :2; // Operation mode bits S1 # + uint8_t TempS1 :4; // Desired temperature (Celsius) S2 # + uint8_t InnvertS1_3:8; // Invert byte (without timer use) ############ + + uint8_t :8; //< Fixed value 0b10110010 / 0xB2. ############ + uint8_t InnvertS2_1:8; // Invert byte 0b01001101 / 0x4D # + uint8_t :5; // not used (without timer use) # + uint8_t FanS2 :3; // Fan speed bits in Section 2 # + uint8_t InnvertS2_2:8; // Invert byte # Section 2 = Sektion 1 + uint8_t :2; // not used (without timer use) # + uint8_t ModeS2 :2; // Operation mode bits S2 # + uint8_t TempS2 :4; // Desired temperature (Celsius) S2 # + uint8_t InnvertS2_3:8; // Invert byte (without timer use) ########### + + uint8_t :8; //< Fixed value 0b11010101 / 0xD5 ########### + uint8_t ModeS3 :1; // ModeBit in Section 3 # + uint8_t FanS3 :6; // Fan speed bits in Section 3 # + uint8_t :1; // Unknown # + uint8_t :7; // Unknown # + uint8_t Quiet :1; // Silent-Mode # Section 3 + uint8_t :4; // Unknown # + uint8_t TempS3 :1; // Desired temp. Bit in Section3 # + uint8_t :3; // Unknown # + uint8_t :8; // Unknown # + uint8_t ChecksumS3 :8; // Checksum from byte 13-17 ########### + }; +}; + +// Classes + +/// Class for handling detailed Bosch144 A/C messages. +class IRBosch144AC { + public: + explicit IRBosch144AC(const uint16_t pin, const bool inverted = false, + const bool use_modulation = true); + void stateReset(void); +#if SEND_BOSCH144 + void send(const uint16_t repeat = 0); + /// 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(); } +#endif // SEND_BOSCH144 + void begin(); + void setPower(const bool state); + bool getPower(void) const; + void setTemp(const uint8_t temp); + uint8_t getTemp(void) const; + void setFan(const uint16_t speed); + uint16_t getFan(void) const; + void setMode(const uint8_t mode); + uint8_t getMode(void) const; + void setQuiet(const bool on); + bool getQuiet(void) const; + uint8_t* getRaw(void); + void setRaw( const uint8_t new_code[] ); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint16_t convertFan(const stdAc::fanspeed_t speed); + static stdAc::opmode_t toCommonMode(const uint8_t mode); + static stdAc::fanspeed_t toCommonFanSpeed(const uint16_t speed); + stdAc::state_t toCommon(void) const; + String toString(void) const; + void setInvertBytes(); + void setCheckSumS3(); +#ifndef UNIT_TEST + + private: + IRsend _irsend; ///< Instance of the IR send class +#else + /// @cond IGNORE + IRsendTest _irsend; ///< Instance of the testing IR send class + /// @endcond +#endif + Bosch144Protocol _; ///< The state of the IR remote in IR code form. + + // Internal State settings + bool powerFlag; + + void setTempRaw(const uint8_t code); + uint8_t getTempRaw(void) const; +}; + +#endif // IR_BOSCH144_H_ From 407f4455c68ceff52b7861fd4585c853f4605264 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Mon, 18 Jul 2022 21:16:23 +0200 Subject: [PATCH 02/32] Update IRac.cpp correction of a copy/paste error --- src/IRac.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IRac.cpp b/src/IRac.cpp index 397e3c260..a479980a6 100644 --- a/src/IRac.cpp +++ b/src/IRac.cpp @@ -2816,7 +2816,7 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { bosch144(&ac, send.power, send.mode, degC, send.fanspeed, send.quiet); break; } -#endif // SEND_AMCOR +#endif // SEND_BOSCH144 #if SEND_CARRIER_AC64 case CARRIER_AC64: { From b352e910d35e32028ece8150d090f744e2c53b20 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Tue, 19 Jul 2022 16:19:42 +0200 Subject: [PATCH 03/32] Update IRac.cpp Edit coding layout style --- src/IRac.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/IRac.cpp b/src/IRac.cpp index a479980a6..ab8c07956 100644 --- a/src/IRac.cpp +++ b/src/IRac.cpp @@ -471,27 +471,24 @@ void IRac::argo(IRArgoAC *ac, /// @param[in] mode The operation mode setting. /// @param[in] degrees The temperature setting in degrees. /// @param[in] fan The speed setting for the fan. -/// @param[in] swingv The vertical swing setting. *** todo /// @param[in] quiet Run the device in quiet/silent mode. -/// @param[in] turbo Run the device in turbo/powerful mode. *** todo -/// @param[in] clean Turn on the self-cleaning mode. e.g. Mould, dry filters etc *** todo /// @note -1 is Off, >= 0 is on. -void IRac::bosch144( IRBosch144AC *ac, +void IRac::bosch144(IRBosch144AC *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, - const bool quiet ) { + const bool quiet) { ac->begin(); - ac->setPower( on ); + ac->setPower(on); if (!on) { // after turn off AC no more commands should // be accepted ac->send(); return; } - ac->setTemp( degrees ); - ac->setFan( ac->convertFan( fan ) ); - ac->setMode( ac->convertMode( mode ) ); - ac->setQuiet( quiet ); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setMode(ac->convertMode(mode)); + ac->setQuiet(quiet); ac->setInvertBytes(); ac->setCheckSumS3(); ac->send(); // Send the state, which will also power on the unit. From b53f9d08aa48dfddb84ec0c226dd7bf6da47b12b Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Tue, 19 Jul 2022 17:30:56 +0200 Subject: [PATCH 04/32] Update ir_Bosch.h Edit coding layout style --- src/ir_Bosch.h | 113 ++++++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 53 deletions(-) diff --git a/src/ir_Bosch.h b/src/ir_Bosch.h index ada051016..4cd09d7e9 100644 --- a/src/ir_Bosch.h +++ b/src/ir_Bosch.h @@ -1,4 +1,4 @@ -// Copyright 2022 David Conran +// Copyright 2022 Nico Thien /// @file /// @brief Support for Bosch A/C protocol /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1787 @@ -23,27 +23,31 @@ #endif // Constants -// Modes -const uint8_t kBosch144Cool = 0b000; // Bit[0] to Section 3 Bit[1-2] to Section 1 -const uint8_t kBosch144Dry = 0b011; // ModeS3 ModeS1 +// Modes Bit[0] to Section 3 Bit[1-2] to Section 1 +// ModeS3 ModeS1 +const uint8_t kBosch144Cool = 0b000; +const uint8_t kBosch144Dry = 0b011; const uint8_t kBosch144Auto = 0b101; const uint8_t kBosch144Heat = 0b110; -const uint8_t kBosch144Fan = 0b010; -// Fan Control -const uint16_t kBosch144Fan20 = 0b111001010; // Bit[0-5] to Section 3 Bit[6-8] to Section 1 -const uint16_t kBosch144Fan40 = 0b100010100; // FanS3 FanS1 +const uint8_t kBosch144Fan = 0b010; + +// Fan Control Bit[0-5] to Section 3 Bit[6-8] to Section 1 +// FanS3 FanS1 +const uint16_t kBosch144Fan20 = 0b111001010; +const uint16_t kBosch144Fan40 = 0b100010100; const uint16_t kBosch144Fan60 = 0b010011110; const uint16_t kBosch144Fan80 = 0b001101000; const uint16_t kBosch144Fan100 = 0b001110010; const uint16_t kBosch144FanAuto = 0b101110011; -const uint16_t kBosch144FanAuto0 = 0b000110011; +const uint16_t kBosch144FanAuto0 = 0b000110011; + // Temperature const uint8_t kBosch144TempMin = 16; // Celsius const uint8_t kBosch144TempMax = 30; // Celsius const uint8_t kBosch144TempRange = kBosch144TempMax - kBosch144TempMin + 1; -const uint8_t kBosch144TempMap[ kBosch144TempRange ] = { - 0b00001, // 16C // Bit[0] to Section 3 Bit[1-4] to Section 1 - 0b00000, // 17C // TempS3 TempS1 +const uint8_t kBosch144TempMap[kBosch144TempRange] = { + 0b00001, // 16C // Bit[0] to Section 3 Bit[1-4] to Section 1 + 0b00000, // 17C // TempS3 TempS1 0b00010, // 18c 0b00110, // 19C 0b00100, // 20C @@ -59,52 +63,55 @@ const uint8_t kBosch144TempMap[ kBosch144TempRange ] = { 0b10110 // 30C }; -const uint8_t kBosch144Off[] = { 0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F, // 96bit-message the same as Coolix protocol - 0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F }; +// "OFF" is a 96bit-message the same as Coolix protocol +const uint8_t kBosch144Off[] = {0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F, + 0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F}; // On, 25C, Mode: Auto -const uint8_t kBosch144DefaultState[ kBosch144StateLength ] = { 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, - 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, - 0xD5, 0x65, 0x00, 0x00, 0x00, 0x3A }; -/*const uint8_t kBosch144DefaultState[ kBosch144StateLength ] = { 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00 };*/ +const uint8_t kBosch144DefaultState[kBosch144StateLength] = { + 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, + 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, + 0xD5, 0x65, 0x00, 0x00, 0x00, 0x3A}; +/*const uint8_t kBosch144DefaultState[kBosch144StateLength] = { + 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00};*/ union Bosch144Protocol { - uint8_t raw[ kBosch144StateLength ]; ///< The state in IR code form. + uint8_t raw[kBosch144StateLength]; ///< The state in IR code form. struct { - uint8_t :8; //< Fixed value 0b10110010 / 0xB2. ############ - uint8_t InnvertS1_1:8; // Invert byte 0b01001101 / 0x4D # - uint8_t :5; // not used (without timer use) # - uint8_t FanS1 :3; // Fan speed bits in Section 1 # - uint8_t InnvertS1_2:8; // Invert byte # Section 1 = Sektion 2 - uint8_t :2; // not used (without timer use) # - uint8_t ModeS1 :2; // Operation mode bits S1 # - uint8_t TempS1 :4; // Desired temperature (Celsius) S2 # - uint8_t InnvertS1_3:8; // Invert byte (without timer use) ############ - - uint8_t :8; //< Fixed value 0b10110010 / 0xB2. ############ - uint8_t InnvertS2_1:8; // Invert byte 0b01001101 / 0x4D # - uint8_t :5; // not used (without timer use) # - uint8_t FanS2 :3; // Fan speed bits in Section 2 # - uint8_t InnvertS2_2:8; // Invert byte # Section 2 = Sektion 1 - uint8_t :2; // not used (without timer use) # - uint8_t ModeS2 :2; // Operation mode bits S2 # - uint8_t TempS2 :4; // Desired temperature (Celsius) S2 # - uint8_t InnvertS2_3:8; // Invert byte (without timer use) ########### - - uint8_t :8; //< Fixed value 0b11010101 / 0xD5 ########### - uint8_t ModeS3 :1; // ModeBit in Section 3 # - uint8_t FanS3 :6; // Fan speed bits in Section 3 # - uint8_t :1; // Unknown # - uint8_t :7; // Unknown # - uint8_t Quiet :1; // Silent-Mode # Section 3 - uint8_t :4; // Unknown # - uint8_t TempS3 :1; // Desired temp. Bit in Section3 # - uint8_t :3; // Unknown # - uint8_t :8; // Unknown # - uint8_t ChecksumS3 :8; // Checksum from byte 13-17 ########### + uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############ + uint8_t InnvertS1_1:8; // Invert byte 0b01001101 / 0x4D # + uint8_t :5; // not used (without timer use) # + uint8_t FanS1 :3; // Fan speed bits in Section 1 # + uint8_t InnvertS1_2:8; // Invert byte # Section 1 = + uint8_t :2; // not used (without timer use) # Sektion 2 + uint8_t ModeS1 :2; // Operation mode bits S1 # + uint8_t TempS1 :4; // Desired temperature (Celsius) S2 # + uint8_t InnvertS1_3:8; // Invert byte (without timer use) ############ + + uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############ + uint8_t InnvertS2_1:8; // Invert byte 0b01001101 / 0x4D # + uint8_t :5; // not used (without timer use) # + uint8_t FanS2 :3; // Fan speed bits in Section 2 # + uint8_t InnvertS2_2:8; // Invert byte # Section 2 = + uint8_t :2; // not used (without timer use) # Sektion 1 + uint8_t ModeS2 :2; // Operation mode bits S2 # + uint8_t TempS2 :4; // Desired temperature (Celsius) S2 # + uint8_t InnvertS2_3:8; // Invert byte (without timer use) ########### + + uint8_t :8; // Fixed value 0b11010101 / 0xD5 ########### + uint8_t ModeS3 :1; // ModeBit in Section 3 # + uint8_t FanS3 :6; // Fan speed bits in Section 3 # + uint8_t :1; // Unknown # + uint8_t :7; // Unknown # + uint8_t Quiet :1; // Silent-Mode # Section 3 + uint8_t :4; // Unknown # + uint8_t TempS3 :1; // Desired temp. Bit in Section3 # + uint8_t :3; // Unknown # + uint8_t :8; // Unknown # + uint8_t ChecksumS3 :8; // Checksum from byte 13-17 ########### }; }; @@ -136,7 +143,7 @@ class IRBosch144AC { void setQuiet(const bool on); bool getQuiet(void) const; uint8_t* getRaw(void); - void setRaw( const uint8_t new_code[] ); + void setRaw(const uint8_t new_code[]); static uint8_t convertMode(const stdAc::opmode_t mode); static uint16_t convertFan(const stdAc::fanspeed_t speed); static stdAc::opmode_t toCommonMode(const uint8_t mode); From 392dcecb479fac612f82de4b0890b81cf37ff4e1 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Tue, 19 Jul 2022 17:38:42 +0200 Subject: [PATCH 05/32] Update ir_Bosch.h Edit coding layout style --- src/ir_Bosch.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ir_Bosch.h b/src/ir_Bosch.h index 4cd09d7e9..5d7220fec 100644 --- a/src/ir_Bosch.h +++ b/src/ir_Bosch.h @@ -70,20 +70,20 @@ const uint8_t kBosch144Off[] = {0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F, // On, 25C, Mode: Auto const uint8_t kBosch144DefaultState[kBosch144StateLength] = { - 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, - 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, - 0xD5, 0x65, 0x00, 0x00, 0x00, 0x3A}; + 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, + 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, + 0xD5, 0x65, 0x00, 0x00, 0x00, 0x3A}; /*const uint8_t kBosch144DefaultState[kBosch144StateLength] = { - 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00};*/ + 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00};*/ union Bosch144Protocol { uint8_t raw[kBosch144StateLength]; ///< The state in IR code form. struct { uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############ uint8_t InnvertS1_1:8; // Invert byte 0b01001101 / 0x4D # - uint8_t :5; // not used (without timer use) # + uint8_t :5; // not used (without timer use) # uint8_t FanS1 :3; // Fan speed bits in Section 1 # uint8_t InnvertS1_2:8; // Invert byte # Section 1 = uint8_t :2; // not used (without timer use) # Sektion 2 @@ -93,8 +93,8 @@ union Bosch144Protocol { uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############ uint8_t InnvertS2_1:8; // Invert byte 0b01001101 / 0x4D # - uint8_t :5; // not used (without timer use) # - uint8_t FanS2 :3; // Fan speed bits in Section 2 # + uint8_t :5; // not used (without timer use) # + uint8_t FanS2 :3; // Fan speed bits in Section 2 # uint8_t InnvertS2_2:8; // Invert byte # Section 2 = uint8_t :2; // not used (without timer use) # Sektion 1 uint8_t ModeS2 :2; // Operation mode bits S2 # From 7d0aee5e8d2de59a69b8b38ee649bf397b6210db Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Tue, 19 Jul 2022 17:54:42 +0200 Subject: [PATCH 06/32] Update and rename src/ir_Bosch.h to Quelle/ir_Bosch.h Edit coding layout style --- {src => Quelle}/ir_Bosch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename {src => Quelle}/ir_Bosch.h (99%) diff --git a/src/ir_Bosch.h b/Quelle/ir_Bosch.h similarity index 99% rename from src/ir_Bosch.h rename to Quelle/ir_Bosch.h index 5d7220fec..83beb2edb 100644 --- a/src/ir_Bosch.h +++ b/Quelle/ir_Bosch.h @@ -170,4 +170,4 @@ class IRBosch144AC { uint8_t getTempRaw(void) const; }; -#endif // IR_BOSCH144_H_ +#endif // IR_BOSCH_H_ From c42af8899b8033fa1cc78ec70f4858b981279d68 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Tue, 19 Jul 2022 17:57:33 +0200 Subject: [PATCH 07/32] Rename Quelle/ir_Bosch.h to src/ir_Bosch.h --- {Quelle => src}/ir_Bosch.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {Quelle => src}/ir_Bosch.h (100%) diff --git a/Quelle/ir_Bosch.h b/src/ir_Bosch.h similarity index 100% rename from Quelle/ir_Bosch.h rename to src/ir_Bosch.h From 25504b01f3374e00f158b9b8fa8435db8ac2caa6 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Tue, 19 Jul 2022 18:32:01 +0200 Subject: [PATCH 08/32] Update ir_Bosch.cpp Edit coding layout style --- src/ir_Bosch.cpp | 192 +++++++++++++++++++---------------------------- 1 file changed, 77 insertions(+), 115 deletions(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index 8e8f680b7..4cf83baa0 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -35,30 +35,28 @@ using irutils::addFanToString; using irutils::addTempToString; #if SEND_BOSCH144 -/// Send a Bosch 144-bit / 18-byte message ( 96-bit message are also possible) +/// Send a Bosch 144-bit / 18-byte message (96-bit message are also possible) /// Status: BETA / Probably Working. /// @param[in] data The message to be sent. /// @param[in] nbytes The number of bytes of message to be sent. /// @param[in] repeat The number of times the command is to be repeated. -void IRsend::sendBosch144( const unsigned char data[], const uint16_t nbytes, - const uint16_t repeat ) -{ +void IRsend::sendBosch144(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { // nbytes is required to be a multiple of kBosch144BytesPerSection. - if( nbytes % kBosch144BytesPerSection != 0 )return; + if (nbytes % kBosch144BytesPerSection != 0)return; // Set IR carrier frequency - enableIROut( kBoschFreq ); + enableIROut(kBoschFreq); - for( uint16_t r = 0; r <= repeat; r++ ) - { - for( uint16_t offset = 0; offset < nbytes; offset += kBosch144BytesPerSection ) + for (uint16_t r = 0; r <= repeat; r++) { + for (uint16_t offset = 0; offset < nbytes; offset += kBosch144BytesPerSection) // Section Header + Data + Footer - sendGeneric( kBoschHdrMark, kBoschHdrSpace, - kBoschBitMark, kBoschOneSpace, - kBoschBitMark, kBoschZeroSpace, - kBoschBitMark, kBoschFooterSpace, - data + offset, kBosch144BytesPerSection, - kBoschFreq, true, 0, kDutyDefault ); - space( kDefaultMessageGap ); // Complete guess + sendGeneric(kBoschHdrMark, kBoschHdrSpace, + kBoschBitMark, kBoschOneSpace, + kBoschBitMark, kBoschZeroSpace, + kBoschBitMark, kBoschFooterSpace, + data + offset, kBosch144BytesPerSection, + kBoschFreq, true, 0, kDutyDefault); + space(kDefaultMessageGap); // Complete guess } } @@ -68,30 +66,26 @@ void IRsend::sendBosch144( const unsigned char data[], const uint16_t nbytes, /// @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? -IRBosch144AC::IRBosch144AC( const uint16_t pin, const bool inverted, const bool use_modulation ) - : _irsend( pin, inverted, use_modulation ) - { +IRBosch144AC::IRBosch144AC(const uint16_t pin, const bool inverted, const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { stateReset(); } /// Reset the internal state to a fixed known good state. -void IRBosch144AC::stateReset( void ) -{ - setRaw( kBosch144DefaultState ); +void IRBosch144AC::stateReset(void) { + setRaw(kBosch144DefaultState); } /// Set up hardware to be able to send a message. -void IRBosch144AC::begin( void ) -{ - _irsend.begin(); +void IRBosch144AC::begin(void) { + _irsend.begin(); } #if SEND_BOSCH144 /// Send the current internal state as an IR message. /// @param[in] repeat Nr. of times the message will be repeated. -void IRBosch144AC::send( const uint16_t repeat ) -{ - if( !powerFlag ) _irsend.sendBosch144( kBosch144Off, sizeof( kBosch144Off ), repeat ); // "Off" is a 96bit message +void IRBosch144AC::send(const uint16_t repeat) { + if (!powerFlag) _irsend.sendBosch144( kBosch144Off, sizeof(kBosch144Off), repeat); // "Off" is a 96bit message else _irsend.sendBosch144( getRaw(), kBosch144StateLength, repeat ); // other 96bit messages are not yet supported } @@ -99,83 +93,67 @@ void IRBosch144AC::send( const uint16_t repeat ) /// 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. -uint8_t* IRBosch144AC::getRaw( void ) -{ +uint8_t* IRBosch144AC::getRaw(void) { return _.raw; } /// Set the internal state from a valid code for this protocol. /// @param[in] new_code A valid code for this protocol. -void IRBosch144AC::setRaw( const uint8_t new_code[] ) -{ - std::memcpy( _.raw, new_code, kBosch144StateLength ); +void IRBosch144AC::setRaw(const uint8_t new_code[]) { + std::memcpy(_.raw, new_code, kBosch144StateLength); } -void IRBosch144AC::setPower( const bool on ) -{ +void IRBosch144AC::setPower(const bool on) { powerFlag = on; } -bool IRBosch144AC::getPower( void ) const -{ +bool IRBosch144AC::getPower(void) const { return true; } -void IRBosch144AC::setTempRaw( const uint8_t code ) -{ - _.TempS1 = code >> 1; // save 4 bits in Section1 - _.TempS2 = code >> 1; // Section2 = Section1 - _.TempS3 = code & 1; // save 1 bit in Section3 +void IRBosch144AC::setTempRaw(const uint8_t code) { + _.TempS1 = _.TempS2 = code >> 1; // save 4 bits in S1 and S2 + _.TempS3 = code & 1; // save 1 bit in Section3 } /// Set the temperature. /// @param[in] degrees The temperature in degrees celsius. -void IRBosch144AC::setTemp( const uint8_t degrees ) -{ - uint8_t temp = std::max( kBosch144TempMin, degrees ); - temp = std::min( kBosch144TempMax, temp ); - setTempRaw( kBosch144TempMap[ temp - kBosch144TempMin ] ); +void IRBosch144AC::setTemp(const uint8_t degrees) { + uint8_t temp = std::max(kBosch144TempMin, degrees); + temp = std::min(kBosch144TempMax, temp); + setTempRaw(kBosch144TempMap[temp - kBosch144TempMin]); } -uint8_t IRBosch144AC::getTemp( void ) const -{ - uint8_t temp = ( _.TempS1 << 1 ) + _.TempS3; - for( uint8_t i = 0; i < 16; i++ ) - { - if( temp == kBosch144TempMap[ i ] ) return kBosch144TempMin + i; +uint8_t IRBosch144AC::getTemp(void) const { + uint8_t temp = (_.TempS1 << 1) + _.TempS3; + for (uint8_t i = 0; i < 16; i++) { + if (temp == kBosch144TempMap[i]) return kBosch144TempMin + i; } } /// Set the speed of the fan. /// @param[in] speed The desired setting. -void IRBosch144AC::setFan( const uint16_t speed ) -{ - _.FanS1 = speed >> 6; // save 3 bits in Section1 - _.FanS2 = speed >> 6; // Section2 = Section1 - _.FanS3 = speed & 0b111111; // save 6 bits in Section3 +void IRBosch144AC::setFan(const uint16_t speed) { + _.FanS1 = _.FanS2 = speed >> 6; //save 3 bits in S1 and S2 + _.FanS3 = speed & 0b111111; //save 6 bits in Section3 } /// Set the desired operation mode. /// @param[in] mode The desired operation mode. -void IRBosch144AC::setMode( const uint8_t mode ) -{ - _.ModeS1 = mode >> 1; // save 2 bits in Section1 - _.ModeS2 = mode >> 1; // Section2 = Section1 - _.ModeS3 = mode & 0b1; // save 1 bit in Section3 - if( mode == kBosch144Auto || mode == kBosch144Dry ) - { - _.FanS1 = 0b000; // save 3 bits in Section1 - _.FanS2 = _.FanS1; // Section2 = Section1 - _.FanS3 = kBosch144FanAuto0;// save 6 bits in Section3 +void IRBosch144AC::setMode(const uint8_t mode) { + _.ModeS1 = _.ModeS2 = mode >> 1; //save 2 bits in S1 and S2 + _.ModeS3 = mode & 0b1; //save 1 bit in Section3 + if (mode == kBosch144Auto || mode == kBosch144Dry) { + _.FanS1 = _.FanS2 = 0b000; // save 3 bits in S1 and S2 + _.FanS3 = kBosch144FanAuto0; // save 6 bits in Section3 } } /// Set the Quiet mode of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -void IRBosch144AC::setQuiet(const bool on) -{ +void IRBosch144AC::setQuiet(const bool on) { _.Quiet = on; // save 1 bit in Section3 - setFan( kBosch144FanAuto ); // set Fan -> Auto + setFan(kBosch144FanAuto); // set Fan -> Auto } /// Get the Quiet mode of the A/C. @@ -185,10 +163,8 @@ bool IRBosch144AC::getQuiet(void) const { return _.Quiet; } /// 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 IRBosch144AC::convertMode( const stdAc::opmode_t mode ) -{ - switch( mode ) - { +uint8_t IRBosch144AC::convertMode(const stdAc::opmode_t mode) { + switch(mode) { case stdAc::opmode_t::kCool: return kBosch144Cool; case stdAc::opmode_t::kHeat: @@ -205,10 +181,8 @@ uint8_t IRBosch144AC::convertMode( const stdAc::opmode_t mode ) /// 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. -uint16_t IRBosch144AC::convertFan( const stdAc::fanspeed_t speed ) -{ - switch( speed ) - { +uint16_t IRBosch144AC::convertFan(const stdAc::fanspeed_t speed) { + switch(speed) { case stdAc::fanspeed_t::kMin: return kBosch144Fan20; case stdAc::fanspeed_t::kLow: @@ -227,10 +201,8 @@ uint16_t IRBosch144AC::convertFan( const stdAc::fanspeed_t speed ) /// 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 IRBosch144AC::toCommonMode( const uint8_t mode ) -{ - switch( mode ) - { +stdAc::opmode_t IRBosch144AC::toCommonMode(const uint8_t mode) { + switch(mode) { case kBosch144Cool: return stdAc::opmode_t::kCool; case kBosch144Heat: return stdAc::opmode_t::kHeat; case kBosch144Dry: return stdAc::opmode_t::kDry; @@ -242,10 +214,8 @@ stdAc::opmode_t IRBosch144AC::toCommonMode( const uint8_t mode ) /// 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 IRBosch144AC::toCommonFanSpeed( const uint16_t speed ) -{ - switch( speed ) - { +stdAc::fanspeed_t IRBosch144AC::toCommonFanSpeed(const uint16_t speed) { + switch(speed) { case kBosch144Fan100: return stdAc::fanspeed_t::kMax; case kBosch144Fan80: return stdAc::fanspeed_t::kHigh; case kBosch144Fan60: return stdAc::fanspeed_t::kMedium; @@ -257,15 +227,14 @@ stdAc::fanspeed_t IRBosch144AC::toCommonFanSpeed( const uint16_t speed ) /// Convert the current internal state into its stdAc::state_t equivalent. /// @return The stdAc equivalent of the native settings. -stdAc::state_t IRBosch144AC::toCommon( void ) const -{ +stdAc::state_t IRBosch144AC::toCommon(void) const { stdAc::state_t result{}; result.protocol = decode_type_t::BOSCH144; result.power = getPower(); - result.mode = toCommonMode( ( _.ModeS1 << 1 ) + _.ModeS3 ); + result.mode = toCommonMode((_.ModeS1 << 1) + _.ModeS3); result.celsius = true; result.degrees = getTemp(); - result.fanspeed = toCommonFanSpeed( ( _.FanS1 << 6 ) + _.FanS3 ); + result.fanspeed = toCommonFanSpeed((_.FanS1 << 6) + _.FanS3); result.quiet = getQuiet(); // Not supported. result.model = -1; @@ -284,39 +253,32 @@ stdAc::state_t IRBosch144AC::toCommon( void ) const /// Convert the current internal state into a human readable string. /// @return A human readable string. -String IRBosch144AC::toString( void ) const -{ - uint8_t mode = ( _.ModeS1 << 1 )+_.ModeS3; - uint16_t fan = ( _.FanS1 << 6 ) + _.FanS3; +String IRBosch144AC::toString(void) const { + uint8_t mode = (_.ModeS1 << 1)+_.ModeS3; + uint16_t fan = (_.FanS1 << 6) + _.FanS3; String result = ""; - result.reserve( 70 ); // Reserve some heap for the string to reduce fragging. - result += addBoolToString( getPower(), kPowerStr, false ); - result += addModeToString( mode, kBosch144Auto, kBosch144Cool, + result.reserve(70); // Reserve some heap for the string to reduce fragging. + result += addBoolToString(getPower(), kPowerStr, false); + result += addModeToString(mode, kBosch144Auto, kBosch144Cool, kBosch144Heat, kBosch144Dry, kBosch144Fan); - result += addFanToString( fan>>1, kBosch144Fan100>>1, kBosch144Fan20>>1, + result += addFanToString(fan>>1, kBosch144Fan100>>1, kBosch144Fan20>>1, kBosch144FanAuto>>1, kBosch144FanAuto>>1, kBosch144Fan60>>1); - result += addTempToString( getTemp() ); + result += addTempToString(getTemp()); return result; } -void IRBosch144AC::setInvertBytes() -{ - _.InnvertS1_1 = ~_.raw[ 0 ]; - _.InnvertS1_2 = ~_.raw[ 2 ]; - _.InnvertS1_3 = ~_.raw[ 4 ]; - _.InnvertS2_1 = ~_.raw[ 6 ]; - _.InnvertS2_2 = ~_.raw[ 8 ]; - _.InnvertS2_3 = ~_.raw[ 10 ]; +void IRBosch144AC::setInvertBytes() { + _.InnvertS1_1 = ~_.raw[0]; + _.InnvertS1_2 = ~_.raw[2]; + _.InnvertS1_3 = ~_.raw[4]; + _.InnvertS2_1 = ~_.raw[6]; + _.InnvertS2_2 = ~_.raw[8]; + _.InnvertS2_3 = ~_.raw[10]; } -void IRBosch144AC::setCheckSumS3() -{ - _.ChecksumS3 = _.raw[ 12 ]; - _.ChecksumS3 += _.raw[ 13 ]; - _.ChecksumS3 += _.raw[ 14 ]; - _.ChecksumS3 += _.raw[ 15 ]; - _.ChecksumS3 += _.raw[ 16 ]; +void IRBosch144AC::setCheckSumS3() { + _.ChecksumS3 = sumBytes(&(_.raw[12]), 5); } #if DECODE_BOSCH144 From 3f9976b9dfa5252487a9b0beece90e764ed02116 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Tue, 19 Jul 2022 18:45:42 +0200 Subject: [PATCH 09/32] Update ir_Bosch.cpp Edit coding layout style --- src/ir_Bosch.cpp | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index 4cf83baa0..a292ca166 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -48,7 +48,7 @@ void IRsend::sendBosch144(const unsigned char data[], const uint16_t nbytes, enableIROut(kBoschFreq); for (uint16_t r = 0; r <= repeat; r++) { - for (uint16_t offset = 0; offset < nbytes; offset += kBosch144BytesPerSection) + for (uint16_t offset=0; offset < nbytes; offset += kBosch144BytesPerSection) // Section Header + Data + Footer sendGeneric(kBoschHdrMark, kBoschHdrSpace, kBoschBitMark, kBoschOneSpace, @@ -66,27 +66,24 @@ void IRsend::sendBosch144(const unsigned char data[], const uint16_t nbytes, /// @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? -IRBosch144AC::IRBosch144AC(const uint16_t pin, const bool inverted, const bool use_modulation) - : _irsend(pin, inverted, use_modulation) { - stateReset(); - } +IRBosch144AC::IRBosch144AC(const uint16_t pin, const bool inverted, + const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { stateReset(); } /// Reset the internal state to a fixed known good state. -void IRBosch144AC::stateReset(void) { - setRaw(kBosch144DefaultState); -} +void IRBosch144AC::stateReset(void) { setRaw(kBosch144DefaultState); } /// Set up hardware to be able to send a message. -void IRBosch144AC::begin(void) { - _irsend.begin(); -} +void IRBosch144AC::begin(void) { _irsend.begin(); } #if SEND_BOSCH144 /// Send the current internal state as an IR message. /// @param[in] repeat Nr. of times the message will be repeated. void IRBosch144AC::send(const uint16_t repeat) { - if (!powerFlag) _irsend.sendBosch144( kBosch144Off, sizeof(kBosch144Off), repeat); // "Off" is a 96bit message - else _irsend.sendBosch144( getRaw(), kBosch144StateLength, repeat ); + if (!powerFlag) { + _irsend.sendBosch144(kBosch144Off, sizeof(kBosch144Off), repeat); + } // "Off" is a 96bit message + else _irsend.sendBosch144(getRaw(), kBosch144StateLength, repeat); // other 96bit messages are not yet supported } #endif // SEND_BOSCH144 @@ -134,15 +131,15 @@ uint8_t IRBosch144AC::getTemp(void) const { /// Set the speed of the fan. /// @param[in] speed The desired setting. void IRBosch144AC::setFan(const uint16_t speed) { - _.FanS1 = _.FanS2 = speed >> 6; //save 3 bits in S1 and S2 - _.FanS3 = speed & 0b111111; //save 6 bits in Section3 + _.FanS1 = _.FanS2 = speed >> 6; // save 3 bits in S1 and S2 + _.FanS3 = speed & 0b111111; // save 6 bits in Section3 } /// Set the desired operation mode. /// @param[in] mode The desired operation mode. void IRBosch144AC::setMode(const uint8_t mode) { - _.ModeS1 = _.ModeS2 = mode >> 1; //save 2 bits in S1 and S2 - _.ModeS3 = mode & 0b1; //save 1 bit in Section3 + _.ModeS1 = _.ModeS2 = mode >> 1; // save 2 bits in S1 and S2 + _.ModeS3 = mode & 0b1; // save 1 bit in Section3 if (mode == kBosch144Auto || mode == kBosch144Dry) { _.FanS1 = _.FanS2 = 0b000; // save 3 bits in S1 and S2 _.FanS3 = kBosch144FanAuto0; // save 6 bits in Section3 @@ -164,7 +161,7 @@ bool IRBosch144AC::getQuiet(void) const { return _.Quiet; } /// @param[in] mode The enum to be converted. /// @return The native equivalent of the enum. uint8_t IRBosch144AC::convertMode(const stdAc::opmode_t mode) { - switch(mode) { + switch (mode) { case stdAc::opmode_t::kCool: return kBosch144Cool; case stdAc::opmode_t::kHeat: @@ -182,7 +179,7 @@ uint8_t IRBosch144AC::convertMode(const stdAc::opmode_t mode) { /// @param[in] speed The enum to be converted. /// @return The native equivalent of the enum. uint16_t IRBosch144AC::convertFan(const stdAc::fanspeed_t speed) { - switch(speed) { + switch (speed) { case stdAc::fanspeed_t::kMin: return kBosch144Fan20; case stdAc::fanspeed_t::kLow: @@ -202,7 +199,7 @@ uint16_t IRBosch144AC::convertFan(const stdAc::fanspeed_t speed) { /// @param[in] mode The native setting to be converted. /// @return The stdAc equivalent of the native setting. stdAc::opmode_t IRBosch144AC::toCommonMode(const uint8_t mode) { - switch(mode) { + switch (mode) { case kBosch144Cool: return stdAc::opmode_t::kCool; case kBosch144Heat: return stdAc::opmode_t::kHeat; case kBosch144Dry: return stdAc::opmode_t::kDry; @@ -215,7 +212,7 @@ stdAc::opmode_t IRBosch144AC::toCommonMode(const uint8_t mode) { /// @param[in] speed The native setting to be converted. /// @return The stdAc equivalent of the native setting. stdAc::fanspeed_t IRBosch144AC::toCommonFanSpeed(const uint16_t speed) { - switch(speed) { + switch (speed) { case kBosch144Fan100: return stdAc::fanspeed_t::kMax; case kBosch144Fan80: return stdAc::fanspeed_t::kHigh; case kBosch144Fan60: return stdAc::fanspeed_t::kMedium; From 7e6817624b585694f6dcbf1ffb48187d050149b7 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Tue, 19 Jul 2022 18:50:37 +0200 Subject: [PATCH 10/32] Update ir_Bosch.cpp Edit coding layout style --- src/ir_Bosch.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index a292ca166..b88c9b36c 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -83,15 +83,16 @@ void IRBosch144AC::send(const uint16_t repeat) { if (!powerFlag) { _irsend.sendBosch144(kBosch144Off, sizeof(kBosch144Off), repeat); } // "Off" is a 96bit message - else _irsend.sendBosch144(getRaw(), kBosch144StateLength, repeat); - // other 96bit messages are not yet supported + else { + _irsend.sendBosch144(getRaw(), kBosch144StateLength, repeat); + } // other 96bit messages are not yet supported } #endif // SEND_BOSCH144 /// 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. -uint8_t* IRBosch144AC::getRaw(void) { - return _.raw; +uint8_t* IRBosch144AC::getRaw(void) { + return _.raw; } /// Set the internal state from a valid code for this protocol. @@ -109,8 +110,8 @@ bool IRBosch144AC::getPower(void) const { } void IRBosch144AC::setTempRaw(const uint8_t code) { - _.TempS1 = _.TempS2 = code >> 1; // save 4 bits in S1 and S2 - _.TempS3 = code & 1; // save 1 bit in Section3 + _.TempS1 = _.TempS2 = code >> 1; // save 4 bits in S1 and S2 + _.TempS3 = code & 1; // save 1 bit in Section3 } /// Set the temperature. @@ -131,18 +132,18 @@ uint8_t IRBosch144AC::getTemp(void) const { /// Set the speed of the fan. /// @param[in] speed The desired setting. void IRBosch144AC::setFan(const uint16_t speed) { - _.FanS1 = _.FanS2 = speed >> 6; // save 3 bits in S1 and S2 - _.FanS3 = speed & 0b111111; // save 6 bits in Section3 + _.FanS1 = _.FanS2 = speed >> 6; // save 3 bits in S1 and S2 + _.FanS3 = speed & 0b111111; // save 6 bits in Section3 } /// Set the desired operation mode. /// @param[in] mode The desired operation mode. void IRBosch144AC::setMode(const uint8_t mode) { - _.ModeS1 = _.ModeS2 = mode >> 1; // save 2 bits in S1 and S2 - _.ModeS3 = mode & 0b1; // save 1 bit in Section3 + _.ModeS1 = _.ModeS2 = mode >> 1; // save 2 bits in S1 and S2 + _.ModeS3 = mode & 0b1; // save 1 bit in Section3 if (mode == kBosch144Auto || mode == kBosch144Dry) { - _.FanS1 = _.FanS2 = 0b000; // save 3 bits in S1 and S2 - _.FanS3 = kBosch144FanAuto0; // save 6 bits in Section3 + _.FanS1 = _.FanS2 = 0b000; // save 3 bits in S1 and S2 + _.FanS3 = kBosch144FanAuto0; // save 6 bits in Section3 } } From b2be8e0ac7ab881cc4b8db11dd650b57fd4d7305 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Tue, 19 Jul 2022 18:55:49 +0200 Subject: [PATCH 11/32] Update ir_Bosch.cpp Edit coding layout style --- src/ir_Bosch.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index b88c9b36c..320514716 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -80,10 +80,9 @@ void IRBosch144AC::begin(void) { _irsend.begin(); } /// Send the current internal state as an IR message. /// @param[in] repeat Nr. of times the message will be repeated. void IRBosch144AC::send(const uint16_t repeat) { - if (!powerFlag) { + if (!powerFlag) { // "Off" is a 96bit message _irsend.sendBosch144(kBosch144Off, sizeof(kBosch144Off), repeat); - } // "Off" is a 96bit message - else { + } else { _irsend.sendBosch144(getRaw(), kBosch144StateLength, repeat); } // other 96bit messages are not yet supported } From 63ba1f25960f97ac1c30b0af895e3bb4c1bbd955 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Tue, 19 Jul 2022 19:22:07 +0200 Subject: [PATCH 12/32] Update ir_Bosch.cpp --- src/ir_Bosch.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index 320514716..c2eb154fb 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -123,9 +123,11 @@ void IRBosch144AC::setTemp(const uint8_t degrees) { uint8_t IRBosch144AC::getTemp(void) const { uint8_t temp = (_.TempS1 << 1) + _.TempS3; + uint8_t retemp = 0; for (uint8_t i = 0; i < 16; i++) { - if (temp == kBosch144TempMap[i]) return kBosch144TempMin + i; + if (temp == kBosch144TempMap[i]) retemp = kBosch144TempMin + i; } + return retemp; } /// Set the speed of the fan. From 23799e9af54d07694c10a5a996f682b7bce6e957 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Tue, 19 Jul 2022 22:17:43 +0200 Subject: [PATCH 13/32] Update ir_Bosch.cpp add getMode() and grtFan() --- src/ir_Bosch.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index c2eb154fb..2e637d267 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -105,7 +105,7 @@ void IRBosch144AC::setPower(const bool on) { } bool IRBosch144AC::getPower(void) const { - return true; + return powerFlag; } void IRBosch144AC::setTempRaw(const uint8_t code) { @@ -137,6 +137,11 @@ void IRBosch144AC::setFan(const uint16_t speed) { _.FanS3 = speed & 0b111111; // save 6 bits in Section3 } +uint16_t IRBosch144AC::getFan(void) const { + uint16_t speed = (_.FanS1 << 6) + _.FanS3; + return speed; +} + /// Set the desired operation mode. /// @param[in] mode The desired operation mode. void IRBosch144AC::setMode(const uint8_t mode) { @@ -148,6 +153,11 @@ void IRBosch144AC::setMode(const uint8_t mode) { } } +uint8_t IRBosch144AC::getMode(void) const { + uint8_t mode = (_.ModeS1 << 1) + _.ModeS3; + return mode; +} + /// Set the Quiet mode of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. void IRBosch144AC::setQuiet(const bool on) { @@ -268,12 +278,9 @@ String IRBosch144AC::toString(void) const { } void IRBosch144AC::setInvertBytes() { - _.InnvertS1_1 = ~_.raw[0]; - _.InnvertS1_2 = ~_.raw[2]; - _.InnvertS1_3 = ~_.raw[4]; - _.InnvertS2_1 = ~_.raw[6]; - _.InnvertS2_2 = ~_.raw[8]; - _.InnvertS2_3 = ~_.raw[10]; + for (uint8_t i = 0; i <= 10; i += 2) { + _raw[i + 1] = ~_.raw[i]; + } } void IRBosch144AC::setCheckSumS3() { From cfe77e28a6950d73b2a7e37db133f49858abe306 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Tue, 19 Jul 2022 22:21:23 +0200 Subject: [PATCH 14/32] Update ir_Bosch.cpp --- src/ir_Bosch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index 2e637d267..dcb6f9c9f 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -279,7 +279,7 @@ String IRBosch144AC::toString(void) const { void IRBosch144AC::setInvertBytes() { for (uint8_t i = 0; i <= 10; i += 2) { - _raw[i + 1] = ~_.raw[i]; + _.raw[i + 1] = ~_.raw[i]; } } From 871eaf0510f1b0cf9b486074aa1ac48c72b8523a Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Wed, 20 Jul 2022 16:15:58 +0200 Subject: [PATCH 15/32] Update ir_Bosch.cpp powerFlag is now set to "true" in the "state reset". --- src/ir_Bosch.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index dcb6f9c9f..b1cddaedc 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -71,7 +71,10 @@ IRBosch144AC::IRBosch144AC(const uint16_t pin, const bool inverted, : _irsend(pin, inverted, use_modulation) { stateReset(); } /// Reset the internal state to a fixed known good state. -void IRBosch144AC::stateReset(void) { setRaw(kBosch144DefaultState); } +void IRBosch144AC::stateReset(void) { + setRaw(kBosch144DefaultState); + setPower(true); +} /// Set up hardware to be able to send a message. void IRBosch144AC::begin(void) { _irsend.begin(); } From 4850d296073a32aa8eb48d05efe64a8fe8dd7cdc Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Wed, 20 Jul 2022 19:23:46 +0200 Subject: [PATCH 16/32] Update ir_Bosch_test.cpp --- test/ir_Bosch_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ir_Bosch_test.cpp b/test/ir_Bosch_test.cpp index e9b6dc9ce..2df035a5d 100644 --- a/test/ir_Bosch_test.cpp +++ b/test/ir_Bosch_test.cpp @@ -13,7 +13,7 @@ TEST(TestUtils, Housekeeping) { ASSERT_EQ("BOSCH144", typeToString(decode_type_t::BOSCH144)); ASSERT_EQ(decode_type_t::BOSCH144, strToDecodeType("BOSCH144")); ASSERT_TRUE(hasACState(decode_type_t::BOSCH144)); - ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::BOSCH144)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::BOSCH144)); ASSERT_EQ(kBosch144Bits, IRsend::defaultBits(decode_type_t::BOSCH144)); ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::BOSCH144)); } From bf8a63fd89b171dd2d907c4add81dc1a6c02c9a7 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Wed, 20 Jul 2022 19:29:00 +0200 Subject: [PATCH 17/32] Update ir_Bosch_test.cpp --- test/ir_Bosch_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ir_Bosch_test.cpp b/test/ir_Bosch_test.cpp index 2df035a5d..f09f2f75f 100644 --- a/test/ir_Bosch_test.cpp +++ b/test/ir_Bosch_test.cpp @@ -72,7 +72,7 @@ TEST(TestDecodeBosch144, RealExample) { "", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t result, prev; - ASSERT_FALSE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); + ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); } TEST(TestDecodeBosch144, SyntheticSelfDecode) { From 600ee91974049a0fc10d2907e2c6d7a99244486d Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Wed, 20 Jul 2022 19:30:00 +0200 Subject: [PATCH 18/32] Update ir_Bosch_test.cpp --- test/ir_Bosch_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ir_Bosch_test.cpp b/test/ir_Bosch_test.cpp index f09f2f75f..b950f7f59 100644 --- a/test/ir_Bosch_test.cpp +++ b/test/ir_Bosch_test.cpp @@ -96,5 +96,5 @@ TEST(TestDecodeBosch144, SyntheticSelfDecode) { "", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t result, prev; - ASSERT_FALSE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); + ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); } From b613652b7377ff25cfb663a71f8fd2cd696ee2ca Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Wed, 20 Jul 2022 21:00:37 +0200 Subject: [PATCH 19/32] Update ir_Bosch_test.cpp --- test/ir_Bosch_test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/ir_Bosch_test.cpp b/test/ir_Bosch_test.cpp index b950f7f59..70ceb5e7a 100644 --- a/test/ir_Bosch_test.cpp +++ b/test/ir_Bosch_test.cpp @@ -69,7 +69,8 @@ TEST(TestDecodeBosch144, RealExample) { EXPECT_EQ(kBosch144Bits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "", + "Power: On, Mode: 0 (Cool), Fan: 5 (Max), Temp: 16C, " + "Quiet: Off", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t result, prev; ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); From cd1b9e74f0d074bdcb36e195ba02bf8bf3bf1f93 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Thu, 21 Jul 2022 20:26:07 +0200 Subject: [PATCH 20/32] Edit Test From a190b3c2f6e68b8f5f092a5312ccf67fa5e30420 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Thu, 21 Jul 2022 20:39:39 +0200 Subject: [PATCH 21/32] Add files via upload From a8a8d526edbb0fb186762199d1f4856c80f508f4 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Thu, 21 Jul 2022 20:45:00 +0200 Subject: [PATCH 22/32] Add files via upload --- test/ir_Bosch_test.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/ir_Bosch_test.cpp b/test/ir_Bosch_test.cpp index 70ceb5e7a..dd9402b69 100644 --- a/test/ir_Bosch_test.cpp +++ b/test/ir_Bosch_test.cpp @@ -69,8 +69,7 @@ TEST(TestDecodeBosch144, RealExample) { EXPECT_EQ(kBosch144Bits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "Power: On, Mode: 0 (Cool), Fan: 5 (Max), Temp: 16C, " - "Quiet: Off", + "Power: On, Mode: 0 (Cool), Fan: 5 (High), Temp: 16C, Quiet: Off", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t result, prev; ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); @@ -94,7 +93,7 @@ TEST(TestDecodeBosch144, SyntheticSelfDecode) { EXPECT_EQ(kBosch144Bits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "", + "Power: On, Mode: 0 (Cool), Fan: 5 (High), Temp: 16C, Quiet: Off", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t result, prev; ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); From 6bd484f196468fecf8b09aae014073292e81d226 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Thu, 21 Jul 2022 20:47:10 +0200 Subject: [PATCH 23/32] Add files via upload --- src/IRac.cpp | 2 -- src/ir_Bosch.cpp | 19 ++++++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/IRac.cpp b/src/IRac.cpp index ab8c07956..8f6676889 100644 --- a/src/IRac.cpp +++ b/src/IRac.cpp @@ -489,8 +489,6 @@ void IRac::bosch144(IRBosch144AC *ac, ac->setFan(ac->convertFan(fan)); ac->setMode(ac->convertMode(mode)); ac->setQuiet(quiet); - ac->setInvertBytes(); - ac->setCheckSumS3(); ac->send(); // Send the state, which will also power on the unit. // The following are all options/settings that create their own special // messages. Often they only make sense to be sent after the unit is turned diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index b1cddaedc..05c43928e 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -94,6 +94,8 @@ void IRBosch144AC::send(const uint16_t repeat) { /// 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. uint8_t* IRBosch144AC::getRaw(void) { + setInvertBytes(); + setCheckSumS3(); return _.raw; } @@ -243,10 +245,10 @@ stdAc::state_t IRBosch144AC::toCommon(void) const { stdAc::state_t result{}; result.protocol = decode_type_t::BOSCH144; result.power = getPower(); - result.mode = toCommonMode((_.ModeS1 << 1) + _.ModeS3); + result.mode = toCommonMode(getMode()); result.celsius = true; result.degrees = getTemp(); - result.fanspeed = toCommonFanSpeed((_.FanS1 << 6) + _.FanS3); + result.fanspeed = toCommonFanSpeed(getFan()); result.quiet = getQuiet(); // Not supported. result.model = -1; @@ -266,17 +268,20 @@ stdAc::state_t IRBosch144AC::toCommon(void) const { /// Convert the current internal state into a human readable string. /// @return A human readable string. String IRBosch144AC::toString(void) const { - uint8_t mode = (_.ModeS1 << 1)+_.ModeS3; - uint16_t fan = (_.FanS1 << 6) + _.FanS3; + uint8_t mode = getMode(); + uint8_t fan = static_cast(toCommonFanSpeed(getFan())); String result = ""; result.reserve(70); // Reserve some heap for the string to reduce fragging. result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(mode, kBosch144Auto, kBosch144Cool, kBosch144Heat, kBosch144Dry, kBosch144Fan); - result += addFanToString(fan>>1, kBosch144Fan100>>1, kBosch144Fan20>>1, - kBosch144FanAuto>>1, kBosch144FanAuto>>1, - kBosch144Fan60>>1); + result += addFanToString(fan, static_cast(stdAc::fanspeed_t::kMax), + static_cast(stdAc::fanspeed_t::kMin), + static_cast(stdAc::fanspeed_t::kAuto), + static_cast(stdAc::fanspeed_t::kAuto), + static_cast(stdAc::fanspeed_t::kMedium)); result += addTempToString(getTemp()); + result += addBoolToString(_.Quiet, kQuietStr); return result; } From cc16b0c37af71ec19394efc14672ae7a556f947d Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Thu, 21 Jul 2022 21:06:41 +0200 Subject: [PATCH 24/32] Update ir_Bosch.cpp --- src/ir_Bosch.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index 05c43928e..3be704ce3 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -129,8 +129,10 @@ void IRBosch144AC::setTemp(const uint8_t degrees) { uint8_t IRBosch144AC::getTemp(void) const { uint8_t temp = (_.TempS1 << 1) + _.TempS3; uint8_t retemp = 0; - for (uint8_t i = 0; i < 16; i++) { - if (temp == kBosch144TempMap[i]) retemp = kBosch144TempMin + i; + for (uint8_t i = 0; i < kBosch144TempRange; i++) { + if (temp == kBosch144TempMap[i]) { + retemp = kBosch144TempMin + i; + } } return retemp; } From edbfb619d0792e054ea6db76fd7079b6c641961c Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Fri, 22 Jul 2022 15:13:13 +0200 Subject: [PATCH 25/32] Update ir_Bosch.h - commented out lines removed - change setInvertBytes() & setCheckSumS3() to private: --- src/ir_Bosch.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/ir_Bosch.h b/src/ir_Bosch.h index 83beb2edb..156a021fc 100644 --- a/src/ir_Bosch.h +++ b/src/ir_Bosch.h @@ -73,10 +73,6 @@ const uint8_t kBosch144DefaultState[kBosch144StateLength] = { 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, 0xD5, 0x65, 0x00, 0x00, 0x00, 0x3A}; -/*const uint8_t kBosch144DefaultState[kBosch144StateLength] = { - 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00};*/ union Bosch144Protocol { uint8_t raw[kBosch144StateLength]; ///< The state in IR code form. @@ -150,8 +146,6 @@ class IRBosch144AC { static stdAc::fanspeed_t toCommonFanSpeed(const uint16_t speed); stdAc::state_t toCommon(void) const; String toString(void) const; - void setInvertBytes(); - void setCheckSumS3(); #ifndef UNIT_TEST private: @@ -166,6 +160,8 @@ class IRBosch144AC { // Internal State settings bool powerFlag; + void setInvertBytes(); + void setCheckSumS3(); void setTempRaw(const uint8_t code); uint8_t getTempRaw(void) const; }; From b5696c87c00f4c059a8ee252e5abff70a78e9584 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Fri, 22 Jul 2022 16:09:46 +0200 Subject: [PATCH 26/32] Update ir_Bosch.cpp - add copyright - simplify getMode() & getFan() - initial temperature in getTemp() 25 --- src/ir_Bosch.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index 3be704ce3..bf40380b2 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -1,4 +1,5 @@ // Copyright 2022 David Conran +// Copyright 2022 Nico Thien /// @file /// @brief Support for the Bosch A/C / heatpump protocol /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1787 @@ -8,9 +9,9 @@ // Brand: Bosch, Model: RG10A(G2S)BGEF remote #include -/*#ifndef ARDUINO +#ifndef ARDUINO #include -#endif*/ +#endif #include #include "ir_Bosch.h" #include "IRrecv.h" @@ -43,7 +44,7 @@ using irutils::addTempToString; void IRsend::sendBosch144(const unsigned char data[], const uint16_t nbytes, const uint16_t repeat) { // nbytes is required to be a multiple of kBosch144BytesPerSection. - if (nbytes % kBosch144BytesPerSection != 0)return; + if (nbytes % kBosch144BytesPerSection != 0) return; // Set IR carrier frequency enableIROut(kBoschFreq); @@ -128,7 +129,7 @@ void IRBosch144AC::setTemp(const uint8_t degrees) { uint8_t IRBosch144AC::getTemp(void) const { uint8_t temp = (_.TempS1 << 1) + _.TempS3; - uint8_t retemp = 0; + uint8_t retemp = 25; for (uint8_t i = 0; i < kBosch144TempRange; i++) { if (temp == kBosch144TempMap[i]) { retemp = kBosch144TempMin + i; @@ -145,8 +146,7 @@ void IRBosch144AC::setFan(const uint16_t speed) { } uint16_t IRBosch144AC::getFan(void) const { - uint16_t speed = (_.FanS1 << 6) + _.FanS3; - return speed; + return (_.FanS1 << 6) + _.FanS3; } /// Set the desired operation mode. @@ -161,8 +161,7 @@ void IRBosch144AC::setMode(const uint8_t mode) { } uint8_t IRBosch144AC::getMode(void) const { - uint8_t mode = (_.ModeS1 << 1) + _.ModeS3; - return mode; + return (_.ModeS1 << 1) + _.ModeS3; } /// Set the Quiet mode of the A/C. From 8b945ce015604cafcac0db23c74070825ae3bd7e Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Fri, 22 Jul 2022 16:16:11 +0200 Subject: [PATCH 27/32] Update ir_Bosch.cpp removed // Supports: // Brand: Bosch, Model: CL3000i-Set 26 E A/C // Brand: Bosch, Model: RG10A(G2S)BGEF remote --- src/ir_Bosch.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index bf40380b2..33d95d0d8 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -4,10 +4,6 @@ /// @brief Support for the Bosch A/C / heatpump protocol /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1787 -// Supports: -// Brand: Bosch, Model: CL3000i-Set 26 E A/C -// Brand: Bosch, Model: RG10A(G2S)BGEF remote - #include #ifndef ARDUINO #include From c9dde4752f64516833c82e968406b433352b51f6 Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Fri, 5 Aug 2022 12:02:16 +0200 Subject: [PATCH 28/32] Update src/ir_Bosch.cpp --- src/ir_Bosch.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index 33d95d0d8..a1b2bad7c 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -99,7 +99,12 @@ uint8_t* IRBosch144AC::getRaw(void) { /// Set the internal state from a valid code for this protocol. /// @param[in] new_code A valid code for this protocol. void IRBosch144AC::setRaw(const uint8_t new_code[]) { - std::memcpy(_.raw, new_code, kBosch144StateLength); + if (sizeof(new_code) == kBosch144StateLength) { + setPower(true); + std::memcpy(_.raw, new_code, kBosch144StateLength); + } else { + if (new_code == kBosch144Off) setPower(false); + } } void IRBosch144AC::setPower(const bool on) { From f052cdb0f31657a055c7fb4e453fb5b98b48cdfb Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Fri, 5 Aug 2022 14:28:04 +0200 Subject: [PATCH 29/32] Update ir_Bosch.cpp --- src/ir_Bosch.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index a1b2bad7c..6bc9fdf7e 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -99,11 +99,10 @@ uint8_t* IRBosch144AC::getRaw(void) { /// Set the internal state from a valid code for this protocol. /// @param[in] new_code A valid code for this protocol. void IRBosch144AC::setRaw(const uint8_t new_code[]) { - if (sizeof(new_code) == kBosch144StateLength) { - setPower(true); - std::memcpy(_.raw, new_code, kBosch144StateLength); + if (new_code == kBosch144Off) { + setPower(false); } else { - if (new_code == kBosch144Off) setPower(false); + std::memcpy(_.raw, new_code, kBosch144StateLength); } } From 768aa33db9c938a5970e07e6f155bc242c52421b Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Mon, 8 Aug 2022 19:25:36 +0200 Subject: [PATCH 30/32] Add files via upload --- src/ir_Bosch.cpp | 352 ----------------------------------------------- src/ir_Bosch.h | 169 ----------------------- 2 files changed, 521 deletions(-) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index 6bc9fdf7e..e69de29bb 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -1,352 +0,0 @@ -// Copyright 2022 David Conran -// Copyright 2022 Nico Thien -/// @file -/// @brief Support for the Bosch A/C / heatpump protocol -/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1787 - -#include -#ifndef ARDUINO -#include -#endif -#include -#include "ir_Bosch.h" -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtext.h" -#include "IRutils.h" - -// Constants -const uint16_t kBoschHdrMark = 4366; -const uint16_t kBoschBitMark = 502; -const uint16_t kBoschHdrSpace = 4415; -const uint16_t kBoschOneSpace = 1645; -const uint16_t kBoschZeroSpace = 571; -const uint16_t kBoschFooterSpace = 5235; -const uint16_t kBoschFreq = 38000; // Hz. (Guessing the most common frequency.) -const uint16_t kBosch144NrOfSections = 3; -const uint16_t kBosch144BytesPerSection = 6; - -using irutils::addBoolToString; -using irutils::addModeToString; -using irutils::addFanToString; -using irutils::addTempToString; - -#if SEND_BOSCH144 -/// Send a Bosch 144-bit / 18-byte message (96-bit message are also possible) -/// Status: BETA / Probably Working. -/// @param[in] data The message to be sent. -/// @param[in] nbytes The number of bytes of message to be sent. -/// @param[in] repeat The number of times the command is to be repeated. -void IRsend::sendBosch144(const unsigned char data[], const uint16_t nbytes, - const uint16_t repeat) { - // nbytes is required to be a multiple of kBosch144BytesPerSection. - if (nbytes % kBosch144BytesPerSection != 0) return; - // Set IR carrier frequency - enableIROut(kBoschFreq); - - for (uint16_t r = 0; r <= repeat; r++) { - for (uint16_t offset=0; offset < nbytes; offset += kBosch144BytesPerSection) - // Section Header + Data + Footer - sendGeneric(kBoschHdrMark, kBoschHdrSpace, - kBoschBitMark, kBoschOneSpace, - kBoschBitMark, kBoschZeroSpace, - kBoschBitMark, kBoschFooterSpace, - data + offset, kBosch144BytesPerSection, - kBoschFreq, true, 0, kDutyDefault); - space(kDefaultMessageGap); // Complete guess - } -} - -#endif // SEND_BOSCH144 - -/// Class constructor. -/// @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? -IRBosch144AC::IRBosch144AC(const uint16_t pin, const bool inverted, - const bool use_modulation) - : _irsend(pin, inverted, use_modulation) { stateReset(); } - -/// Reset the internal state to a fixed known good state. -void IRBosch144AC::stateReset(void) { - setRaw(kBosch144DefaultState); - setPower(true); -} - -/// Set up hardware to be able to send a message. -void IRBosch144AC::begin(void) { _irsend.begin(); } - -#if SEND_BOSCH144 -/// Send the current internal state as an IR message. -/// @param[in] repeat Nr. of times the message will be repeated. -void IRBosch144AC::send(const uint16_t repeat) { - if (!powerFlag) { // "Off" is a 96bit message - _irsend.sendBosch144(kBosch144Off, sizeof(kBosch144Off), repeat); - } else { - _irsend.sendBosch144(getRaw(), kBosch144StateLength, repeat); - } // other 96bit messages are not yet supported -} -#endif // SEND_BOSCH144 - -/// 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. -uint8_t* IRBosch144AC::getRaw(void) { - setInvertBytes(); - setCheckSumS3(); - return _.raw; -} - -/// Set the internal state from a valid code for this protocol. -/// @param[in] new_code A valid code for this protocol. -void IRBosch144AC::setRaw(const uint8_t new_code[]) { - if (new_code == kBosch144Off) { - setPower(false); - } else { - std::memcpy(_.raw, new_code, kBosch144StateLength); - } -} - -void IRBosch144AC::setPower(const bool on) { - powerFlag = on; -} - -bool IRBosch144AC::getPower(void) const { - return powerFlag; -} - -void IRBosch144AC::setTempRaw(const uint8_t code) { - _.TempS1 = _.TempS2 = code >> 1; // save 4 bits in S1 and S2 - _.TempS3 = code & 1; // save 1 bit in Section3 -} - -/// Set the temperature. -/// @param[in] degrees The temperature in degrees celsius. -void IRBosch144AC::setTemp(const uint8_t degrees) { - uint8_t temp = std::max(kBosch144TempMin, degrees); - temp = std::min(kBosch144TempMax, temp); - setTempRaw(kBosch144TempMap[temp - kBosch144TempMin]); -} - -uint8_t IRBosch144AC::getTemp(void) const { - uint8_t temp = (_.TempS1 << 1) + _.TempS3; - uint8_t retemp = 25; - for (uint8_t i = 0; i < kBosch144TempRange; i++) { - if (temp == kBosch144TempMap[i]) { - retemp = kBosch144TempMin + i; - } - } - return retemp; -} - -/// Set the speed of the fan. -/// @param[in] speed The desired setting. -void IRBosch144AC::setFan(const uint16_t speed) { - _.FanS1 = _.FanS2 = speed >> 6; // save 3 bits in S1 and S2 - _.FanS3 = speed & 0b111111; // save 6 bits in Section3 -} - -uint16_t IRBosch144AC::getFan(void) const { - return (_.FanS1 << 6) + _.FanS3; -} - -/// Set the desired operation mode. -/// @param[in] mode The desired operation mode. -void IRBosch144AC::setMode(const uint8_t mode) { - _.ModeS1 = _.ModeS2 = mode >> 1; // save 2 bits in S1 and S2 - _.ModeS3 = mode & 0b1; // save 1 bit in Section3 - if (mode == kBosch144Auto || mode == kBosch144Dry) { - _.FanS1 = _.FanS2 = 0b000; // save 3 bits in S1 and S2 - _.FanS3 = kBosch144FanAuto0; // save 6 bits in Section3 - } -} - -uint8_t IRBosch144AC::getMode(void) const { - return (_.ModeS1 << 1) + _.ModeS3; -} - -/// Set the Quiet mode of the A/C. -/// @param[in] on true, the setting is on. false, the setting is off. -void IRBosch144AC::setQuiet(const bool on) { - _.Quiet = on; // save 1 bit in Section3 - setFan(kBosch144FanAuto); // set Fan -> Auto -} - -/// Get the Quiet mode of the A/C. -/// @return true, the setting is on. false, the setting is off. -bool IRBosch144AC::getQuiet(void) const { return _.Quiet; } - -/// 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 IRBosch144AC::convertMode(const stdAc::opmode_t mode) { - switch (mode) { - case stdAc::opmode_t::kCool: - return kBosch144Cool; - case stdAc::opmode_t::kHeat: - return kBosch144Heat; - case stdAc::opmode_t::kDry: - return kBosch144Dry; - case stdAc::opmode_t::kFan: - return kBosch144Fan; - default: - return kBosch144Auto; - } -} - -/// 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. -uint16_t IRBosch144AC::convertFan(const stdAc::fanspeed_t speed) { - switch (speed) { - case stdAc::fanspeed_t::kMin: - return kBosch144Fan20; - case stdAc::fanspeed_t::kLow: - return kBosch144Fan40; - case stdAc::fanspeed_t::kMedium: - return kBosch144Fan60; - case stdAc::fanspeed_t::kHigh: - return kBosch144Fan80; - case stdAc::fanspeed_t::kMax: - return kBosch144Fan100; - default: - return kBosch144FanAuto; - } -} - -/// 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 IRBosch144AC::toCommonMode(const uint8_t mode) { - switch (mode) { - case kBosch144Cool: return stdAc::opmode_t::kCool; - case kBosch144Heat: return stdAc::opmode_t::kHeat; - case kBosch144Dry: return stdAc::opmode_t::kDry; - case kBosch144Fan: 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 IRBosch144AC::toCommonFanSpeed(const uint16_t speed) { - switch (speed) { - case kBosch144Fan100: return stdAc::fanspeed_t::kMax; - case kBosch144Fan80: return stdAc::fanspeed_t::kHigh; - case kBosch144Fan60: return stdAc::fanspeed_t::kMedium; - case kBosch144Fan40: return stdAc::fanspeed_t::kLow; - case kBosch144Fan20: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; - } -} - -/// Convert the current internal state into its stdAc::state_t equivalent. -/// @return The stdAc equivalent of the native settings. -stdAc::state_t IRBosch144AC::toCommon(void) const { - stdAc::state_t result{}; - result.protocol = decode_type_t::BOSCH144; - result.power = getPower(); - result.mode = toCommonMode(getMode()); - result.celsius = true; - result.degrees = getTemp(); - result.fanspeed = toCommonFanSpeed(getFan()); - result.quiet = getQuiet(); - // 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.clean = false; - result.beep = false; - result.clock = -1; - result.sleep = -1; - return result; -} - -/// Convert the current internal state into a human readable string. -/// @return A human readable string. -String IRBosch144AC::toString(void) const { - uint8_t mode = getMode(); - uint8_t fan = static_cast(toCommonFanSpeed(getFan())); - String result = ""; - result.reserve(70); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(getPower(), kPowerStr, false); - result += addModeToString(mode, kBosch144Auto, kBosch144Cool, - kBosch144Heat, kBosch144Dry, kBosch144Fan); - result += addFanToString(fan, static_cast(stdAc::fanspeed_t::kMax), - static_cast(stdAc::fanspeed_t::kMin), - static_cast(stdAc::fanspeed_t::kAuto), - static_cast(stdAc::fanspeed_t::kAuto), - static_cast(stdAc::fanspeed_t::kMedium)); - result += addTempToString(getTemp()); - result += addBoolToString(_.Quiet, kQuietStr); - return result; -} - -void IRBosch144AC::setInvertBytes() { - for (uint8_t i = 0; i <= 10; i += 2) { - _.raw[i + 1] = ~_.raw[i]; - } -} - -void IRBosch144AC::setCheckSumS3() { - _.ChecksumS3 = sumBytes(&(_.raw[12]), 5); -} - -#if DECODE_BOSCH144 -/// Decode the supplied Bosch 144-bit / 18-byte A/C message. -/// Status: STABLE / Confirmed Working. -/// @param[in,out] results Ptr to the data to decode & where to store the decode -/// result. -/// @param[in] offset The starting index to use when attempting to decode the -/// raw data. Typically/Defaults to kStartOffset. -/// @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::decodeBosch144(decode_results *results, uint16_t offset, - const uint16_t nbits, const bool strict) { - if (results->rawlen < 2 * nbits + - kBosch144NrOfSections * (kHeader + kFooter) - - 1 + offset) - return false; // Can't possibly be a valid BOSCH144 message. - if (strict && nbits != kBosch144Bits) - return false; // Not strictly a BOSCH144 message. - if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. - return false; - if (nbits % kBosch144NrOfSections != 0) - return false; // nbits has to be a multiple of kBosch144NrOfSections. - const uint16_t kSectionBits = nbits / kBosch144NrOfSections; - const uint16_t kSectionBytes = kSectionBits / 8; - const uint16_t kNBytes = kSectionBytes * kBosch144NrOfSections; - // Capture each section individually - for (uint16_t pos = 0, section = 0; - pos < kNBytes; - pos += kSectionBytes, section++) { - uint16_t used = 0; - // Section Header + Section Data + Section Footer - used = matchGeneric(results->rawbuf + offset, results->state + pos, - results->rawlen - offset, kSectionBits, - kBoschHdrMark, kBoschHdrSpace, - kBoschBitMark, kBoschOneSpace, - kBoschBitMark, kBoschZeroSpace, - kBoschBitMark, kBoschFooterSpace, - section >= kBosch144NrOfSections - 1, - _tolerance, kMarkExcess, true); - if (!used) return false; // Didn't match. - offset += used; - } - - // Compliance - - // Success - results->decode_type = decode_type_t::BOSCH144; - results->bits = nbits; - // No need to record the state as we stored it as we decoded it. - // As we use result->state, we don't record value, address, or command as it - // is a union data type. - return true; -} -#endif // DECODE_BOSCH144 diff --git a/src/ir_Bosch.h b/src/ir_Bosch.h index 156a021fc..e69de29bb 100644 --- a/src/ir_Bosch.h +++ b/src/ir_Bosch.h @@ -1,169 +0,0 @@ -// Copyright 2022 Nico Thien -/// @file -/// @brief Support for Bosch A/C protocol -/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1787 - -// Supports: -// Brand: Bosch, Model: CL3000i-Set 26 E A/C -// Brand: Bosch, Model: RG10A(G2S)BGEF remote - - -#ifndef IR_BOSCH_H_ -#define IR_BOSCH_H_ - -#define __STDC_LIMIT_MACROS -#include -#ifndef UNIT_TEST -#include -#endif -#include "IRremoteESP8266.h" -#include "IRsend.h" -#ifdef UNIT_TEST -#include "IRsend_test.h" -#endif - -// Constants -// Modes Bit[0] to Section 3 Bit[1-2] to Section 1 -// ModeS3 ModeS1 -const uint8_t kBosch144Cool = 0b000; -const uint8_t kBosch144Dry = 0b011; -const uint8_t kBosch144Auto = 0b101; -const uint8_t kBosch144Heat = 0b110; -const uint8_t kBosch144Fan = 0b010; - -// Fan Control Bit[0-5] to Section 3 Bit[6-8] to Section 1 -// FanS3 FanS1 -const uint16_t kBosch144Fan20 = 0b111001010; -const uint16_t kBosch144Fan40 = 0b100010100; -const uint16_t kBosch144Fan60 = 0b010011110; -const uint16_t kBosch144Fan80 = 0b001101000; -const uint16_t kBosch144Fan100 = 0b001110010; -const uint16_t kBosch144FanAuto = 0b101110011; -const uint16_t kBosch144FanAuto0 = 0b000110011; - -// Temperature -const uint8_t kBosch144TempMin = 16; // Celsius -const uint8_t kBosch144TempMax = 30; // Celsius -const uint8_t kBosch144TempRange = kBosch144TempMax - kBosch144TempMin + 1; -const uint8_t kBosch144TempMap[kBosch144TempRange] = { - 0b00001, // 16C // Bit[0] to Section 3 Bit[1-4] to Section 1 - 0b00000, // 17C // TempS3 TempS1 - 0b00010, // 18c - 0b00110, // 19C - 0b00100, // 20C - 0b01100, // 21C - 0b01110, // 22C - 0b01010, // 23C - 0b01000, // 24C - 0b11000, // 25C - 0b11010, // 26C - 0b10010, // 27C - 0b10000, // 28C - 0b10100, // 29C - 0b10110 // 30C -}; - -// "OFF" is a 96bit-message the same as Coolix protocol -const uint8_t kBosch144Off[] = {0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F, - 0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F}; - - -// On, 25C, Mode: Auto -const uint8_t kBosch144DefaultState[kBosch144StateLength] = { - 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, - 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, - 0xD5, 0x65, 0x00, 0x00, 0x00, 0x3A}; - -union Bosch144Protocol { - uint8_t raw[kBosch144StateLength]; ///< The state in IR code form. - struct { - uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############ - uint8_t InnvertS1_1:8; // Invert byte 0b01001101 / 0x4D # - uint8_t :5; // not used (without timer use) # - uint8_t FanS1 :3; // Fan speed bits in Section 1 # - uint8_t InnvertS1_2:8; // Invert byte # Section 1 = - uint8_t :2; // not used (without timer use) # Sektion 2 - uint8_t ModeS1 :2; // Operation mode bits S1 # - uint8_t TempS1 :4; // Desired temperature (Celsius) S2 # - uint8_t InnvertS1_3:8; // Invert byte (without timer use) ############ - - uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############ - uint8_t InnvertS2_1:8; // Invert byte 0b01001101 / 0x4D # - uint8_t :5; // not used (without timer use) # - uint8_t FanS2 :3; // Fan speed bits in Section 2 # - uint8_t InnvertS2_2:8; // Invert byte # Section 2 = - uint8_t :2; // not used (without timer use) # Sektion 1 - uint8_t ModeS2 :2; // Operation mode bits S2 # - uint8_t TempS2 :4; // Desired temperature (Celsius) S2 # - uint8_t InnvertS2_3:8; // Invert byte (without timer use) ########### - - uint8_t :8; // Fixed value 0b11010101 / 0xD5 ########### - uint8_t ModeS3 :1; // ModeBit in Section 3 # - uint8_t FanS3 :6; // Fan speed bits in Section 3 # - uint8_t :1; // Unknown # - uint8_t :7; // Unknown # - uint8_t Quiet :1; // Silent-Mode # Section 3 - uint8_t :4; // Unknown # - uint8_t TempS3 :1; // Desired temp. Bit in Section3 # - uint8_t :3; // Unknown # - uint8_t :8; // Unknown # - uint8_t ChecksumS3 :8; // Checksum from byte 13-17 ########### - }; -}; - -// Classes - -/// Class for handling detailed Bosch144 A/C messages. -class IRBosch144AC { - public: - explicit IRBosch144AC(const uint16_t pin, const bool inverted = false, - const bool use_modulation = true); - void stateReset(void); -#if SEND_BOSCH144 - void send(const uint16_t repeat = 0); - /// 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(); } -#endif // SEND_BOSCH144 - void begin(); - void setPower(const bool state); - bool getPower(void) const; - void setTemp(const uint8_t temp); - uint8_t getTemp(void) const; - void setFan(const uint16_t speed); - uint16_t getFan(void) const; - void setMode(const uint8_t mode); - uint8_t getMode(void) const; - void setQuiet(const bool on); - bool getQuiet(void) const; - uint8_t* getRaw(void); - void setRaw(const uint8_t new_code[]); - static uint8_t convertMode(const stdAc::opmode_t mode); - static uint16_t convertFan(const stdAc::fanspeed_t speed); - static stdAc::opmode_t toCommonMode(const uint8_t mode); - static stdAc::fanspeed_t toCommonFanSpeed(const uint16_t speed); - stdAc::state_t toCommon(void) const; - String toString(void) const; -#ifndef UNIT_TEST - - private: - IRsend _irsend; ///< Instance of the IR send class -#else - /// @cond IGNORE - IRsendTest _irsend; ///< Instance of the testing IR send class - /// @endcond -#endif - Bosch144Protocol _; ///< The state of the IR remote in IR code form. - - // Internal State settings - bool powerFlag; - - void setInvertBytes(); - void setCheckSumS3(); - void setTempRaw(const uint8_t code); - uint8_t getTempRaw(void) const; -}; - -#endif // IR_BOSCH_H_ From ebac3f7ccf4103184002633fecab6e965c24164b Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Mon, 8 Aug 2022 19:31:16 +0200 Subject: [PATCH 31/32] Update ir_Bosch.cpp --- src/ir_Bosch.cpp | 331 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 331 insertions(+) diff --git a/src/ir_Bosch.cpp b/src/ir_Bosch.cpp index e69de29bb..c66a1976b 100644 --- a/src/ir_Bosch.cpp +++ b/src/ir_Bosch.cpp @@ -0,0 +1,331 @@ +// Copyright 2022 David Conran +// Copyright 2022 Nico Thien +/// @file +/// @brief Support for the Bosch A/C / heatpump protocol +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1787 + +#include "ir_Bosch.h" + +#if SEND_BOSCH144 +/// Send a Bosch 144-bit / 18-byte message (96-bit message are also possible) +/// Status: BETA / Probably Working. +/// @param[in] data The message to be sent. +/// @param[in] nbytes The number of bytes of message to be sent. +/// @param[in] repeat The number of times the command is to be repeated. +void IRsend::sendBosch144(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + // nbytes is required to be a multiple of kBosch144BytesPerSection. + if (nbytes % kBosch144BytesPerSection != 0)return; + // Set IR carrier frequency + enableIROut(kBoschFreq); + + for (uint16_t r = 0; r <= repeat; r++) { + for (uint16_t offset=0; offset < nbytes; offset += kBosch144BytesPerSection) + // Section Header + Data + Footer + sendGeneric(kBoschHdrMark, kBoschHdrSpace, + kBoschBitMark, kBoschOneSpace, + kBoschBitMark, kBoschZeroSpace, + kBoschBitMark, kBoschFooterSpace, + data + offset, kBosch144BytesPerSection, + kBoschFreq, true, 0, kDutyDefault); + space(kDefaultMessageGap); // Complete guess + } +} + +#endif // SEND_BOSCH144 + +/// Class constructor. +/// @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? +IRBosch144AC::IRBosch144AC(const uint16_t pin, const bool inverted, + const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { stateReset(); } + +/// Reset the internal state to a fixed known good state. +void IRBosch144AC::stateReset(void) { + setRaw(kBosch144DefaultState, kBosch144StateLength); + setPower(true); +} + +/// Set up hardware to be able to send a message. +void IRBosch144AC::begin(void) { _irsend.begin(); } + +#if SEND_BOSCH144 +/// Send the current internal state as an IR message. +/// @param[in] repeat Nr. of times the message will be repeated. +void IRBosch144AC::send(const uint16_t repeat) { + if (!powerFlag) { // "Off" is a 96bit message + _irsend.sendBosch144(kBosch144Off, sizeof(kBosch144Off), repeat); + } else { + _irsend.sendBosch144(getRaw(), kBosch144StateLength, repeat); + } // other 96bit messages are not yet supported +} +#endif // SEND_BOSCH144 + +/// 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. +unsigned char* IRBosch144AC::getRaw(void) { + setInvertBytes(); + setCheckSumS3(); + return _.raw; +} + +/// Set the internal state from a valid code for this protocol. +/// @param[in] new_code A valid code for this protocol. +/// @param[in] length Size of the array being passed in in bytes. +void IRBosch144AC::setRaw(const uint8_t new_code[], const uint16_t length) { + const uint16_t len = min(length, kBosch144StateLength); + const uint16_t lenOff = sizeof(kBosch144Off); +// Is it an off message? + if (memcmp(kBosch144Off, new_code, min(lenOff, len)) == 0) + setPower(false); // It is. + else + setPower(true); + memcpy(_.raw, new_code, len); +} + +void IRBosch144AC::setPower(const bool on) { + powerFlag = on; +} + +bool IRBosch144AC::getPower(void) const { + return powerFlag; +} + +void IRBosch144AC::setTempRaw(const uint8_t code) { + _.TempS1 = _.TempS2 = code >> 1; // save 4 bits in S1 and S2 + _.TempS3 = code & 1; // save 1 bit in Section3 +} + +/// Set the temperature. +/// @param[in] degrees The temperature in degrees celsius. +void IRBosch144AC::setTemp(const uint8_t degrees) { + uint8_t temp = max(kBosch144TempMin, degrees); + temp = min(kBosch144TempMax, temp); + setTempRaw(kBosch144TempMap[temp - kBosch144TempMin]); +} + +uint8_t IRBosch144AC::getTemp(void) const { + uint8_t temp = (_.TempS1 << 1) + _.TempS3; + uint8_t retemp = 25; + for (uint8_t i = 0; i < kBosch144TempRange; i++) { + if (temp == kBosch144TempMap[i]) { + retemp = kBosch144TempMin + i; + } + } + return retemp; +} + +/// Set the speed of the fan. +/// @param[in] speed The desired setting. +void IRBosch144AC::setFan(const uint16_t speed) { + _.FanS1 = _.FanS2 = speed >> 6; // save 3 bits in S1 and S2 + _.FanS3 = speed & 0b111111; // save 6 bits in Section3 +} + +uint16_t IRBosch144AC::getFan(void) const { + return (_.FanS1 << 6) + _.FanS3; +} + +/// Set the desired operation mode. +/// @param[in] mode The desired operation mode. +void IRBosch144AC::setMode(const uint8_t mode) { + _.ModeS1 = _.ModeS2 = mode >> 1; // save 2 bits in S1 and S2 + _.ModeS3 = mode & 0b1; // save 1 bit in Section3 + if (mode == kBosch144Auto || mode == kBosch144Dry) { + _.FanS1 = _.FanS2 = 0b000; // save 3 bits in S1 and S2 + _.FanS3 = kBosch144FanAuto0; // save 6 bits in Section3 + } +} + +uint8_t IRBosch144AC::getMode(void) const { + return (_.ModeS1 << 1) + _.ModeS3; +} + +/// Set the Quiet mode of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRBosch144AC::setQuiet(const bool on) { + _.Quiet = on; // save 1 bit in Section3 + setFan(kBosch144FanAuto); // set Fan -> Auto +} + +/// Get the Quiet mode of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRBosch144AC::getQuiet(void) const { return _.Quiet; } + +/// 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 IRBosch144AC::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kBosch144Cool; + case stdAc::opmode_t::kHeat: + return kBosch144Heat; + case stdAc::opmode_t::kDry: + return kBosch144Dry; + case stdAc::opmode_t::kFan: + return kBosch144Fan; + default: + return kBosch144Auto; + } +} + +/// 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. +uint16_t IRBosch144AC::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + return kBosch144Fan20; + case stdAc::fanspeed_t::kLow: + return kBosch144Fan40; + case stdAc::fanspeed_t::kMedium: + return kBosch144Fan60; + case stdAc::fanspeed_t::kHigh: + return kBosch144Fan80; + case stdAc::fanspeed_t::kMax: + return kBosch144Fan100; + default: + return kBosch144FanAuto; + } +} + +/// 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 IRBosch144AC::toCommonMode(const uint8_t mode) { + switch (mode) { + case kBosch144Cool: return stdAc::opmode_t::kCool; + case kBosch144Heat: return stdAc::opmode_t::kHeat; + case kBosch144Dry: return stdAc::opmode_t::kDry; + case kBosch144Fan: 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 IRBosch144AC::toCommonFanSpeed(const uint16_t speed) { + switch (speed) { + case kBosch144Fan100: return stdAc::fanspeed_t::kMax; + case kBosch144Fan80: return stdAc::fanspeed_t::kHigh; + case kBosch144Fan60: return stdAc::fanspeed_t::kMedium; + case kBosch144Fan40: return stdAc::fanspeed_t::kLow; + case kBosch144Fan20: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; + } +} + +/// Convert the current internal state into its stdAc::state_t equivalent. +/// @return The stdAc equivalent of the native settings. +stdAc::state_t IRBosch144AC::toCommon(void) const { + stdAc::state_t result{}; + result.protocol = decode_type_t::BOSCH144; + result.power = getPower(); + result.mode = toCommonMode(getMode()); + result.celsius = true; + result.degrees = getTemp(); + result.fanspeed = toCommonFanSpeed(getFan()); + result.quiet = getQuiet(); + // 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.clean = false; + result.beep = false; + result.clock = -1; + result.sleep = -1; + return result; +} + +/// Convert the current internal state into a human readable string. +/// @return A human readable string. +String IRBosch144AC::toString(void) const { + uint8_t mode = getMode(); + uint8_t fan = static_cast(toCommonFanSpeed(getFan())); + String result = ""; + result.reserve(70); // Reserve some heap for the string to reduce fragging. + result += addBoolToString(getPower(), kPowerStr, false); + result += addModeToString(mode, kBosch144Auto, kBosch144Cool, + kBosch144Heat, kBosch144Dry, kBosch144Fan); + result += addFanToString(fan, static_cast(stdAc::fanspeed_t::kMax), + static_cast(stdAc::fanspeed_t::kMin), + static_cast(stdAc::fanspeed_t::kAuto), + static_cast(stdAc::fanspeed_t::kAuto), + static_cast(stdAc::fanspeed_t::kMedium)); + result += addTempToString(getTemp()); + result += addBoolToString(_.Quiet, kQuietStr); + return result; +} + +void IRBosch144AC::setInvertBytes() { + for (uint8_t i = 0; i <= 10; i += 2) { + _.raw[i + 1] = ~_.raw[i]; + } +} + +void IRBosch144AC::setCheckSumS3() { + _.ChecksumS3 = sumBytes(&(_.raw[12]), 5); +} + +#if DECODE_BOSCH144 +/// Decode the supplied Bosch 144-bit / 18-byte A/C message. +/// Status: STABLE / Confirmed Working. +/// @param[in,out] results Ptr to the data to decode & where to store the decode +/// result. +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @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::decodeBosch144(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * nbits + + kBosch144NrOfSections * (kHeader + kFooter) - + 1 + offset) + return false; // Can't possibly be a valid BOSCH144 message. + if (strict && nbits != kBosch144Bits) + return false; // Not strictly a BOSCH144 message. + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + if (nbits % kBosch144NrOfSections != 0) + return false; // nbits has to be a multiple of kBosch144NrOfSections. + const uint16_t kSectionBits = nbits / kBosch144NrOfSections; + const uint16_t kSectionBytes = kSectionBits / 8; + const uint16_t kNBytes = kSectionBytes * kBosch144NrOfSections; + // Capture each section individually + for (uint16_t pos = 0, section = 0; + pos < kNBytes; + pos += kSectionBytes, section++) { + uint16_t used = 0; + // Section Header + Section Data + Section Footer + used = matchGeneric(results->rawbuf + offset, results->state + pos, + results->rawlen - offset, kSectionBits, + kBoschHdrMark, kBoschHdrSpace, + kBoschBitMark, kBoschOneSpace, + kBoschBitMark, kBoschZeroSpace, + kBoschBitMark, kBoschFooterSpace, + section >= kBosch144NrOfSections - 1, + _tolerance, kMarkExcess, true); + if (!used) return false; // Didn't match. + offset += used; + } + + // Compliance + + // Success + results->decode_type = decode_type_t::BOSCH144; + results->bits = nbits; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_BOSCH144 From 5a6db72f7c0f32085de1dabc21464f1e35f069af Mon Sep 17 00:00:00 2001 From: NicoThien <68682400+NicoThien@users.noreply.github.com> Date: Mon, 8 Aug 2022 19:32:00 +0200 Subject: [PATCH 32/32] Update ir_Bosch.h --- src/ir_Bosch.h | 193 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) diff --git a/src/ir_Bosch.h b/src/ir_Bosch.h index e69de29bb..071c132cf 100644 --- a/src/ir_Bosch.h +++ b/src/ir_Bosch.h @@ -0,0 +1,193 @@ +// Copyright 2022 Nico Thien +/// @file +/// @brief Support for Bosch A/C protocol +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1787 + +// Supports: +// Brand: Bosch, Model: CL3000i-Set 26 E A/C +// Brand: Bosch, Model: RG10A(G2S)BGEF remote + + +#ifndef IR_BOSCH_H_ +#define IR_BOSCH_H_ + +#define __STDC_LIMIT_MACROS +#include +#include +#include +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRrecv.h" +#include "IRtext.h" +#include "IRutils.h" +#ifndef UNIT_TEST +#include +#endif +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + +// Constants +const uint16_t kBoschHdrMark = 4366; +const uint16_t kBoschBitMark = 502; +const uint16_t kBoschHdrSpace = 4415; +const uint16_t kBoschOneSpace = 1645; +const uint16_t kBoschZeroSpace = 571; +const uint16_t kBoschFooterSpace = 5235; +const uint16_t kBoschFreq = 38000; // Hz. (Guessing the most common frequency.) +const uint16_t kBosch144NrOfSections = 3; +const uint16_t kBosch144BytesPerSection = 6; + +using irutils::addBoolToString; +using irutils::addModeToString; +using irutils::addFanToString; +using irutils::addTempToString; +using std::min; +using std::max; +using std::memcpy; +using std::memcmp; + +// Modes Bit[0] to Section 3 Bit[1-2] to Section 1 +// ModeS3 ModeS1 +const uint8_t kBosch144Cool = 0b000; +const uint8_t kBosch144Dry = 0b011; +const uint8_t kBosch144Auto = 0b101; +const uint8_t kBosch144Heat = 0b110; +const uint8_t kBosch144Fan = 0b010; + +// Fan Control Bit[0-5] to Section 3 Bit[6-8] to Section 1 +// FanS3 FanS1 +const uint16_t kBosch144Fan20 = 0b111001010; +const uint16_t kBosch144Fan40 = 0b100010100; +const uint16_t kBosch144Fan60 = 0b010011110; +const uint16_t kBosch144Fan80 = 0b001101000; +const uint16_t kBosch144Fan100 = 0b001110010; +const uint16_t kBosch144FanAuto = 0b101110011; +const uint16_t kBosch144FanAuto0 = 0b000110011; + +// Temperature +const uint8_t kBosch144TempMin = 16; // Celsius +const uint8_t kBosch144TempMax = 30; // Celsius +const uint8_t kBosch144TempRange = kBosch144TempMax - kBosch144TempMin + 1; +const uint8_t kBosch144TempMap[kBosch144TempRange] = { + 0b00001, // 16C // Bit[0] to Section 3 Bit[1-4] to Section 1 + 0b00000, // 17C // TempS3 TempS1 + 0b00010, // 18c + 0b00110, // 19C + 0b00100, // 20C + 0b01100, // 21C + 0b01110, // 22C + 0b01010, // 23C + 0b01000, // 24C + 0b11000, // 25C + 0b11010, // 26C + 0b10010, // 27C + 0b10000, // 28C + 0b10100, // 29C + 0b10110 // 30C +}; + +// "OFF" is a 96bit-message the same as Coolix protocol +const uint8_t kBosch144Off[] = {0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F, + 0xB2, 0x4D, 0x7B, 0x84, 0xE0, 0x1F}; + +// On, 25C, Mode: Auto +const uint8_t kBosch144DefaultState[kBosch144StateLength] = { + 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, + 0xB2, 0x4D, 0x1F, 0xE0, 0xC8, 0x37, + 0xD5, 0x65, 0x00, 0x00, 0x00, 0x3A}; + +union Bosch144Protocol { + uint8_t raw[kBosch144StateLength]; ///< The state in IR code form. + struct { + uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############ + uint8_t InnvertS1_1:8; // Invert byte 0b01001101 / 0x4D # + uint8_t :5; // not used (without timer use) # + uint8_t FanS1 :3; // Fan speed bits in Section 1 # + uint8_t InnvertS1_2:8; // Invert byte # Section 1 = + uint8_t :2; // not used (without timer use) # Sektion 2 + uint8_t ModeS1 :2; // Operation mode bits S1 # + uint8_t TempS1 :4; // Desired temperature (Celsius) S2 # + uint8_t InnvertS1_3:8; // Invert byte (without timer use) ############ + + uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############ + uint8_t InnvertS2_1:8; // Invert byte 0b01001101 / 0x4D # + uint8_t :5; // not used (without timer use) # + uint8_t FanS2 :3; // Fan speed bits in Section 2 # + uint8_t InnvertS2_2:8; // Invert byte # Section 2 = + uint8_t :2; // not used (without timer use) # Sektion 1 + uint8_t ModeS2 :2; // Operation mode bits S2 # + uint8_t TempS2 :4; // Desired temperature (Celsius) S2 # + uint8_t InnvertS2_3:8; // Invert byte (without timer use) ########### + + uint8_t :8; // Fixed value 0b11010101 / 0xD5 ########### + uint8_t ModeS3 :1; // ModeBit in Section 3 # + uint8_t FanS3 :6; // Fan speed bits in Section 3 # + uint8_t :1; // Unknown # + uint8_t :7; // Unknown # + uint8_t Quiet :1; // Silent-Mode # Section 3 + uint8_t :4; // Unknown # + uint8_t TempS3 :1; // Desired temp. Bit in Section3 # + uint8_t :3; // Unknown # + uint8_t :8; // Unknown # + uint8_t ChecksumS3 :8; // Checksum from byte 13-17 ########### + }; +}; + +// Classes + +/// Class for handling detailed Bosch144 A/C messages. +class IRBosch144AC { + public: + explicit IRBosch144AC(const uint16_t pin, const bool inverted = false, + const bool use_modulation = true); + void stateReset(void); +#if SEND_BOSCH144 + void send(const uint16_t repeat = 0); + /// 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(); } +#endif // SEND_BOSCH144 + void begin(); + void setPower(const bool state); + bool getPower(void) const; + void setTemp(const uint8_t temp); + uint8_t getTemp(void) const; + void setFan(const uint16_t speed); + uint16_t getFan(void) const; + void setMode(const uint8_t mode); + uint8_t getMode(void) const; + void setQuiet(const bool on); + bool getQuiet(void) const; + uint8_t* getRaw(void); + void setRaw(const uint8_t new_code[], + const uint16_t length = kBosch144StateLength); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint16_t convertFan(const stdAc::fanspeed_t speed); + static stdAc::opmode_t toCommonMode(const uint8_t mode); + static stdAc::fanspeed_t toCommonFanSpeed(const uint16_t speed); + stdAc::state_t toCommon(void) const; + String toString(void) const; +#ifndef UNIT_TEST + + private: + IRsend _irsend; ///< Instance of the IR send class +#else + /// @cond IGNORE + IRsendTest _irsend; ///< Instance of the testing IR send class + /// @endcond +#endif + Bosch144Protocol _; ///< The state of the IR remote in IR code form. + + // Internal State settings + bool powerFlag; + + void setInvertBytes(); + void setCheckSumS3(); + void setTempRaw(const uint8_t code); + uint8_t getTempRaw(void) const; +}; + +#endif // IR_BOSCH_H_