-
Notifications
You must be signed in to change notification settings - Fork 816
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Experimental basic support for Bosch 144bit protocol. (#1822)
* Added `sendBosch144()` & `decodeBosch144()` * TODO: Add integrity (strict) checks. * Add basic unit test coverage. For #1787
- Loading branch information
1 parent
cdacb95
commit 4888fd7
Showing
10 changed files
with
255 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// Copyright 2022 David Conran | ||
/// @file | ||
/// @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 <algorithm> | ||
#ifndef ARDUINO | ||
#include <string> | ||
#endif | ||
#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; | ||
|
||
#if SEND_BOSCH144 | ||
/// Send a Bosch 144-bit / 18-byte message | ||
/// Status: STABLE / Confirmed 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; | ||
|
||
// Set IR carrier frequency | ||
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) | ||
// Section Header + Data + Footer | ||
sendGeneric(kBoschHdrMark, kBoschHdrSpace, | ||
kBoschBitMark, kBoschOneSpace, | ||
kBoschBitMark, kBoschZeroSpace, | ||
kBoschBitMark, kBoschFooterSpace, | ||
data + offset, kSectionByteSize, | ||
kBoschFreq, true, 0, kDutyDefault); | ||
space(kDefaultMessageGap); // Complete guess | ||
} | ||
} | ||
|
||
#endif // SEND_BOSCH144 | ||
|
||
#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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// Copyright 2022 David Conran | ||
|
||
#include "IRac.h" | ||
#include "IRrecv.h" | ||
#include "IRrecv_test.h" | ||
#include "IRsend.h" | ||
#include "IRsend_test.h" | ||
#include "gtest/gtest.h" | ||
|
||
|
||
TEST(TestUtils, Housekeeping) { | ||
// Bosch144 | ||
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_EQ(kBosch144Bits, IRsend::defaultBits(decode_type_t::BOSCH144)); | ||
ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::BOSCH144)); | ||
} | ||
|
||
// Tests for decodeBosch144(). | ||
|
||
// Decode normal Bosch144 messages. | ||
TEST(TestDecodeBosch144, RealExample) { | ||
IRsendTest irsend(kGpioUnused); | ||
IRrecv irrecv(kGpioUnused); | ||
|
||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1787#issuecomment-1099993189 | ||
// Mode: Cool; Fan: 100% ; Temp: 16°C | ||
const uint16_t rawData[299] = { | ||
4380, 4400, | ||
528, 1646, 504, 570, 504, 1646, 504, 1646, 504, 572, 502, 570, 504, 1646, | ||
504, 570, 504, 572, 502, 1646, 504, 570, 502, 570, 502, 1648, 502, 1646, | ||
502, 570, 502, 1646, 504, 572, 502, 572, 502, 1644, 504, 1646, 504, 1646, | ||
504, 1646, 502, 1648, 500, 1646, 504, 1646, 504, 1646, 504, 572, 502, 570, | ||
504, 570, 504, 570, 504, 570, 504, 570, 506, 570, 502, 572, 502, 570, 502, | ||
572, 502, 572, 502, 572, 502, 572, 502, 572, 500, 1648, 502, 1644, 502, | ||
1646, 504, 1646, 502, 1646, 504, 1646, 504, 1644, 504, 1646, | ||
504, 5234, | ||
4360, 4422, | ||
504, 1646, 502, 596, 478, 1670, 478, 1646, 504, 570, 504, 572, 500, 1646, | ||
502, 572, 502, 572, 502, 1644, 506, 570, 502, 570, 504, 1644, 506, 1644, | ||
502, 574, 502, 1644, 504, 570, 504, 570, 504, 1644, 504, 1646, 504, 1644, | ||
506, 1644, 504, 1646, 504, 1646, 504, 1644, 504, 1646, 502, 570, 504, 570, | ||
504, 570, 504, 570, 502, 570, 504, 570, 502, 572, 502, 570, 504, 570, 504, | ||
570, 504, 570, 502, 572, 502, 570, 506, 570, 504, 1646, 502, 1646, 504, | ||
1646, 504, 1646, 504, 1646, 502, 1644, 504, 1644, 504, 1646, | ||
502, 5236, | ||
4360, 4424, | ||
504, 1646, 504, 1646, 502, 572, 504, 1644, 504, 570, 504, 1646, 504, 570, | ||
502, 1644, 504, 570, 504, 1644, 506, 1646, 502, 572, 502, 572, 502, 1646, | ||
504, 570, 504, 570, 504, 570, 502, 572, 504, 570, 504, 570, 504, 570, 502, | ||
572, 502, 570, 504, 570, 502, 570, 504, 572, 502, 572, 502, 1646, 504, | ||
570, 504, 570, 504, 570, 502, 574, 502, 572, 502, 572, 502, 572, 502, 572, | ||
502, 572, 502, 570, 504, 572, 502, 572, 502, 572, 502, 1646, 504, 572, | ||
502, 570, 502, 1646, 504, 572, 504, 570, 504, 1644, | ||
504}; // COOLIX B23F00 | ||
const uint8_t expectedState[kBosch144StateLength] = { | ||
0xB2, 0x4D, 0x3F, 0xC0, 0x00, 0xFF, | ||
0xB2, 0x4D, 0x3F, 0xC0, 0x00, 0xFF, | ||
0xD5, 0x64, 0x00, 0x10, 0x00, 0x49}; | ||
irsend.begin(); | ||
irsend.reset(); | ||
|
||
irsend.sendRaw(rawData, 299, 38000); | ||
irsend.makeDecodeResult(); | ||
ASSERT_TRUE(irrecv.decode(&irsend.capture)); | ||
EXPECT_EQ(decode_type_t::BOSCH144, irsend.capture.decode_type); | ||
EXPECT_EQ(kBosch144Bits, irsend.capture.bits); | ||
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); | ||
EXPECT_EQ( | ||
"", | ||
IRAcUtils::resultAcToString(&irsend.capture)); | ||
stdAc::state_t result, prev; | ||
ASSERT_FALSE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); | ||
} | ||
|
||
TEST(TestDecodeBosch144, SyntheticSelfDecode) { | ||
IRsendTest irsend(kGpioUnused); | ||
IRrecv irrecv(kGpioUnused); | ||
irsend.begin(); | ||
|
||
irsend.reset(); | ||
const uint8_t expectedState[kBosch144StateLength] = { | ||
0xB2, 0x4D, 0x3F, 0xC0, 0x00, 0xFF, | ||
0xB2, 0x4D, 0x3F, 0xC0, 0x00, 0xFF, | ||
0xD5, 0x64, 0x00, 0x10, 0x00, 0x49}; | ||
irsend.sendBosch144(expectedState); | ||
irsend.makeDecodeResult(); | ||
|
||
ASSERT_TRUE(irrecv.decode(&irsend.capture)); | ||
EXPECT_EQ(decode_type_t::BOSCH144, irsend.capture.decode_type); | ||
EXPECT_EQ(kBosch144Bits, irsend.capture.bits); | ||
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); | ||
EXPECT_EQ( | ||
"", | ||
IRAcUtils::resultAcToString(&irsend.capture)); | ||
stdAc::state_t result, prev; | ||
ASSERT_FALSE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); | ||
} |