Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
DPRINTLN("Attempting Daikin 312-bit decode");
if (decodeDaikin312(results, offset)) return true;
#endif // DECODE_DAIKIN312
#if DECODE_GORENJE
DPRINTLN("Attempting GORENJE decode");
if (decodeGorenje(results, offset)) return true;
#endif // DECODE_GORENJE
// Typically new protocols are added above this line.
}
#if DECODE_HASH
Expand Down
5 changes: 5 additions & 0 deletions src/IRrecv.h
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,11 @@ class IRrecv {
const uint16_t nbits = kGoodweatherBits,
const bool strict = true);
#endif // DECODE_GOODWEATHER
#if DECODE_GORENJE
bool decodeGorenje(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kGorenjeBits,
const bool strict = true);
#endif // DECODE_GORENJE
#if DECODE_GREE
bool decodeGree(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kGreeBits,
Expand Down
11 changes: 10 additions & 1 deletion src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,13 @@
#define SEND_DAIKIN312 _IR_ENABLE_DEFAULT_
#endif // SEND_DAIKIN312

#ifndef DECODE_GORENJE
#define DECODE_GORENJE _IR_ENABLE_DEFAULT_
#endif // DECODE_GORENJE
#ifndef SEND_GORENJE
#define SEND_GORENJE _IR_ENABLE_DEFAULT_
#endif // SEND_GORENJE

#if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \
DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \
DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \
Expand Down Expand Up @@ -1104,8 +1111,9 @@ enum decode_type_t {
BOSCH144, // 120
SANYO_AC152,
DAIKIN312,
GORENJE,
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = DAIKIN312,
kLastDecodeType = GORENJE,
};

// Message lengths & required repeat values
Expand Down Expand Up @@ -1203,6 +1211,7 @@ const uint16_t kGicableBits = 16;
const uint16_t kGicableMinRepeat = kSingleRepeat;
const uint16_t kGoodweatherBits = 48;
const uint16_t kGoodweatherMinRepeat = kNoRepeat;
const uint16_t kGorenjeBits = 8;
const uint16_t kGreeStateLength = 8;
const uint16_t kGreeBits = kGreeStateLength * 8;
const uint16_t kGreeDefaultRepeat = kNoRepeat;
Expand Down
6 changes: 6 additions & 0 deletions src/IRsend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) {
uint16_t IRsend::defaultBits(const decode_type_t protocol) {
switch (protocol) {
case MULTIBRACKETS:
case GORENJE:
return 8;
case RC5:
case SYMPHONY:
Expand Down Expand Up @@ -916,6 +917,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
sendGoodweather(data, nbits, min_repeat);
break;
#endif
#if SEND_GORENJE
case GORENJE:
sendGorenje(data, nbits, min_repeat);
break;
#endif
#if SEND_GREE
case GREE:
sendGree(data, nbits, min_repeat);
Expand Down
4 changes: 4 additions & 0 deletions src/IRsend.h
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,10 @@ class IRsend {
const uint16_t nbits = kGoodweatherBits,
const uint16_t repeat = kGoodweatherMinRepeat);
#endif // SEND_GOODWEATHER
#if SEND_GORENJE
void sendGorenje(const uint64_t data, const uint16_t nbits = kGorenjeBits,
const uint16_t repeat = kNoRepeat);
#endif // SEND_GORENJE
#if SEND_PRONTO
void sendPronto(uint16_t data[], uint16_t len, uint16_t repeat = kNoRepeat);
#endif
Expand Down
2 changes: 2 additions & 0 deletions src/IRtext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,8 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
D_STR_SANYO_AC152, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_DAIKIN312 || SEND_DAIKIN312,
D_STR_DAIKIN312, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_GORENJE || SEND_GORENJE,
D_STR_GORENJE, D_STR_UNSUPPORTED) "\x0"
///< New protocol (macro) strings should be added just above this line.
"\x0" ///< This string requires double null termination.
};
Expand Down
71 changes: 71 additions & 0 deletions src/ir_Gorenje.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright 2022 Mateusz Bronk (mbronk)
/// @file
/// @brief Support for the Gorenje cooker hood IR protocols.
/// @see https://techfresh.pl/wp-content/uploads/2017/08/Gorenje-DKF-2600-MWT.pdf
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1887

// Supports:
// Brand: Gorenje, Model: DKF 2600 MWT Cooker Hood

#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"

const uint32_t kGorenjeMinGap = 100000U; // 0.1s
const uint16_t kGorenjeHdrMark = 0;
const uint32_t kGorenjeHdrSpace = 0;
const uint16_t kGorenjeBitMark = 1300;
const uint32_t kGorenjeOneSpace = 5700;
const uint32_t kGorenjeZeroSpace = 1700;
const uint16_t kGorenjeFreq = 38000; // Hz
const uint16_t kGorenjeTolerance = 7; // %

#if SEND_GORENJE
/// Send a Gorenje Cooker Hood formatted message.
/// Status: STABLE / Known working.
/// @param[in] data containing the IR command to be sent.
/// @param[in] nbits Nr. of bits of the message to send. usually kGorenjeBits
/// @param[in] repeat Nr. of times the message is to be repeated.
void IRsend::sendGorenje(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
sendGeneric(kGorenjeHdrMark, kGorenjeHdrSpace,
kGorenjeBitMark, kGorenjeOneSpace,
kGorenjeBitMark, kGorenjeZeroSpace,
kGorenjeBitMark, kGorenjeMinGap,
data, nbits, kGorenjeFreq, true, repeat, kDutyDefault);
}
#endif // SEND_GORENJE

#if DECODE_GORENJE
/// Decode the supplied Gorenje Cooker Hood message.
/// Status: STABLE / Known working.
/// @param[in,out] results Ptr to the data to decode & where to store the
/// decoded 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::decodeGorenje(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (strict && nbits != kGorenjeBits)
return false; // We expect Gorenje to be a certain sized message.

uint64_t data = 0;
if (!matchGeneric(results->rawbuf + offset, &data,
results->rawlen - offset, nbits,
kGorenjeHdrMark, kGorenjeHdrSpace,
kGorenjeBitMark, kGorenjeOneSpace,
kGorenjeBitMark, kGorenjeZeroSpace,
kGorenjeBitMark, kGorenjeMinGap,
true, kGorenjeTolerance)) return false;

// Matched!
results->bits = nbits;
results->value = data;
results->decode_type = decode_type_t::GORENJE;
results->command = 0;
results->address = 0;
return true;
}
#endif // DECODE_GORENJE
3 changes: 3 additions & 0 deletions src/locale/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,9 @@ D_STR_INDIRECT " " D_STR_MODE
#ifndef D_STR_GOODWEATHER
#define D_STR_GOODWEATHER "GOODWEATHER"
#endif // D_STR_GOODWEATHER
#ifndef D_STR_GORENJE
#define D_STR_GORENJE "GORENJE"
#endif // D_STR_GORENJE
#ifndef D_STR_GREE
#define D_STR_GREE "GREE"
#endif // D_STR_GREE
Expand Down
203 changes: 203 additions & 0 deletions test/ir_Gorenje_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
// Copyright 2022 Mateusz Bronk (mbronk)

#include "IRac.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"

class TestDecodeGorenjeSyntheticSendTestFixture
: public ::testing::TestWithParam<uint64_t> {};
class TestDecodeGorenjeReceiveTestFixture
: public ::testing::TestWithParam<std::tuple<std::vector<uint16_t>,
uint64_t>> {};

TEST(TestGorenje, Settings) {
ASSERT_EQ("GORENJE", typeToString(decode_type_t::GORENJE));
ASSERT_EQ(decode_type_t::GORENJE, strToDecodeType("GORENJE"));
ASSERT_FALSE(hasACState(decode_type_t::GORENJE));
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::GORENJE));
ASSERT_EQ(kGorenjeBits,
IRsendTest::defaultBits(decode_type_t::GORENJE));
}

// Test sending typical data (cooker hood light toggle)
TEST(TestSendGorenje, SendLightToggle) {
IRsendTest irsend(kGpioUnused);
irsend.begin();

irsend.reset();
irsend.sendGorenje(0x10); // Light toggle
EXPECT_EQ(
"f38000d50"
"m1300s1700m1300s1700m1300s1700m1300s5700m1300s1700m1300s1700m1300s1700"
"m1300s1700"
"m1300s100000",
irsend.outputStr());
}

// Test sending with different repeats.
TEST(TestSendGorenje, SendWithRepeats) {
IRsendTest irsend(kGpioUnused);
irsend.begin();

irsend.reset();
irsend.sendGorenje(0x8, kGorenjeBits, 0); // 0 repeats.
EXPECT_EQ(
"f38000d50"
"m1300s1700m1300s1700m1300s1700m1300s1700m1300s5700m1300s1700m1300s1700"
"m1300s1700"
"m1300s100000",
irsend.outputStr());
irsend.sendGorenje(0x8, kGorenjeBits, 2); // 2 repeats.
EXPECT_EQ(
"f38000d50"
"m1300s1700m1300s1700m1300s1700m1300s1700m1300s5700m1300s1700m1300s1700"
"m1300s1700"
"m1300s100000"
"m1300s1700m1300s1700m1300s1700m1300s1700m1300s5700m1300s1700m1300s1700"
"m1300s1700"
"m1300s100000"
"m1300s1700m1300s1700m1300s1700m1300s1700m1300s5700m1300s1700m1300s1700"
"m1300s1700"
"m1300s100000",
irsend.outputStr());
}


// Decode a Synthetic example
TEST_P(TestDecodeGorenjeSyntheticSendTestFixture, SyntheticExample) {
uint64_t commandToTest = GetParam();
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

irsend.reset();
irsend.sendGorenje(commandToTest);
irsend.makeDecodeResult();

ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(GORENJE, irsend.capture.decode_type);
EXPECT_EQ(kGorenjeBits, irsend.capture.bits);
EXPECT_EQ(commandToTest, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x0, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);
}

INSTANTIATE_TEST_CASE_P(
TestDecodeGorenje,
TestDecodeGorenjeSyntheticSendTestFixture,
::testing::Values(0x2, 0x8, 0x4, 0x10, 0x20, 0x1));


// Decode a real example (codes captured from original remote)
TEST_P(TestDecodeGorenjeReceiveTestFixture, RealExample) {
const std::vector<uint16_t> rawDataInput = std::get<0>(GetParam());
const uint64_t expectedValue = std::get<1>(GetParam());

IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

irsend.reset();
irsend.sendRaw(&rawDataInput[0], rawDataInput.size(), 38000);
irsend.makeDecodeResult();

ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(decode_type_t::GORENJE, irsend.capture.decode_type);
EXPECT_EQ(kGorenjeBits, irsend.capture.bits);
EXPECT_EQ(expectedValue, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x0, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);
}

INSTANTIATE_TEST_CASE_P(
TestDecodeGorenje,
TestDecodeGorenjeReceiveTestFixture,
::testing::Values(
// POWER
std::make_tuple(std::vector<uint16_t> {
1292, 1716, 1300, 1708, 1296, 1712,
1294, 1714, 1302, 1708, 1298, 1710,
1294, 5752, 1294, 1714, 1302
},
0x2),
std::make_tuple(std::vector<uint16_t> {
1302, 1706, 1298, 1710, 1294, 1714,
1292, 1716, 1300, 1708, 1296, 1712,
1294, 5754, 1292, 1716, 1300
},
0x2),

// FAN-
std::make_tuple(std::vector<uint16_t> {
1328, 1680, 1324, 1684, 1320, 1688,
1328, 1680, 1324, 5724, 1322, 1684,
1330, 1678, 1326, 1682, 1324
},
0x8),
std::make_tuple(std::vector<uint16_t> {
1296, 1712, 1292, 1718, 1298, 1710,
1294, 1714, 1292, 5756, 1300, 1708,
1296, 1712, 1294, 1714, 1300
},
0x8),

// FAN+
std::make_tuple(std::vector<uint16_t> {
1324, 1684, 1320, 1688, 1328, 1680,
1324, 1684, 1322, 1688, 1328, 5718,
1326, 1682, 1322, 1686, 1352
},
0x4),
std::make_tuple(std::vector<uint16_t> {
1296, 1714, 1292, 1716, 1298, 1710,
1296, 1714, 1292, 1716, 1300, 5748,
1296, 1712, 1292, 1716, 1300
},
0x4),

// Light toggle
std::make_tuple(std::vector<uint16_t> {
1326, 1682, 1322, 1686, 1328, 1680,
1324, 5722, 1322, 1686, 1330, 1680,
1326, 1682, 1322, 1686, 1328
},
0x10),
std::make_tuple(std::vector<uint16_t> {
1328, 1680, 1324, 1684, 1330, 1678,
1326, 5722, 1324, 1684, 1330, 1678,
1326, 1682, 1322, 1686, 1330
},
0x10),

// Light-
std::make_tuple(std::vector<uint16_t> {
1328, 1680, 1324, 1686, 1330, 5716,
1328, 1680, 1324, 1684, 1330, 1678,
1326, 1682, 1354, 1654, 1328
},
0x20),
std::make_tuple(std::vector<uint16_t> {
1322, 1686, 1318, 1690, 1326, 5722,
1322, 1686, 1330, 1678, 1326, 1682,
1322, 1686, 1328, 1680, 1324
},
0x20),

// Light+
std::make_tuple(std::vector<uint16_t> {
1328, 1680, 1326, 1682, 1322, 1688,
1328, 1680, 1324, 1686, 1330, 1678,
1326, 1682, 1322, 5724, 1330
},
0x1),
std::make_tuple(std::vector<uint16_t> {
1298, 1710, 1294, 1714, 1302, 1708,
1298, 1710, 1294, 1716, 1300, 1708,
1296, 1712, 1292, 5756, 1300
},
0x1)
)
);