Skip to content

Commit

Permalink
Experimental basic support for EcoClim 56 & 15 bit protocols. (#1410)
Browse files Browse the repository at this point in the history
* Basic support for 56 & 15 bit protocols.
  - `sendEcoclim()` & `decodeEcoclim()`.
* Unit tests coverage.
  - Housekeeping.
  - sending
  - selfdecode
  - Real example

For #1397
  • Loading branch information
crankyoldgit authored Feb 11, 2021
1 parent 067a3fe commit 03cb629
Show file tree
Hide file tree
Showing 9 changed files with 353 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,11 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
if (decodePanasonicAC32(results, offset, kPanasonicAc32Bits / 2))
return true;
#endif // DECODE_PANASONIC_AC32
#if DECODE_ECOCLIM
DPRINTLN("Attempting Ecoclim decode");
if (decodeEcoclim(results, offset, kEcoclimBits) ||
decodeEcoclim(results, offset, kEcoclimShortBits)) return true;
#endif // DECODE_ECOCLIM
// 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 @@ -714,6 +714,11 @@ class IRrecv {
const uint16_t nbits = kEliteScreensBits,
const bool strict = true);
#endif // DECODE_ELITESCREENS
#if DECODE_ECOCLIM
bool decodeEcoclim(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kEcoclimBits,
const bool strict = true);
#endif // DECODE_ECOCLIM
};

#endif // IRRECV_H_
12 changes: 11 additions & 1 deletion src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,13 @@
#define SEND_MILESTAG2 _IR_ENABLE_DEFAULT_
#endif // SEND_MILESTAG2

#ifndef DECODE_ECOCLIM
#define DECODE_ECOCLIM _IR_ENABLE_DEFAULT_
#endif // DECODE_ECOCLIM
#ifndef SEND_ECOCLIM
#define SEND_ECOCLIM _IR_ENABLE_DEFAULT_
#endif // SEND_ECOCLIM

#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 @@ -875,8 +882,9 @@ enum decode_type_t {
ELITESCREENS, // 95
PANASONIC_AC32,
MILESTAG2,
ECOCLIM,
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = MILESTAG2,
kLastDecodeType = ECOCLIM,
};

// Message lengths & required repeat values
Expand Down Expand Up @@ -941,6 +949,8 @@ const uint16_t kDenonLegacyBits = 14;
const uint16_t kDishBits = 16;
const uint16_t kDishMinRepeat = 3;
const uint16_t kDoshishaBits = 40;
const uint16_t kEcoclimBits = 56;
const uint16_t kEcoclimShortBits = 15;
const uint16_t kEpsonBits = 32;
const uint16_t kEpsonMinRepeat = 2;
const uint16_t kElectraAcStateLength = 13;
Expand Down
6 changes: 6 additions & 0 deletions src/IRsend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
case MIDEA:
case PANASONIC:
return 48;
case ECOCLIM:
case MAGIQUEST:
case VESTEL_AC:
case TECHNIBEL_AC:
Expand Down Expand Up @@ -821,6 +822,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
sendDoshisha(data, nbits, min_repeat);
break;
#endif
#if SEND_ECOCLIM
case ECOCLIM:
sendEcoclim(data, nbits, min_repeat);
break;
#endif // SEND_ECOCLIM
#if SEND_ELITESCREENS
case ELITESCREENS:
sendElitescreens(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 @@ -694,6 +694,10 @@ class IRsend {
const uint16_t nbits = kMilesTag2ShotBits,
const uint16_t repeat = kMilesMinRepeat);
#endif // SEND_MILESTAG2
#if SEND_ECOCLIM
void sendEcoclim(const uint64_t data, const uint16_t nbits = kEcoclimBits,
const uint16_t repeat = kNoRepeat);
#endif // SEND_ECOCLIM

protected:
#ifdef UNIT_TEST
Expand Down
1 change: 1 addition & 0 deletions src/IRtext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,5 +279,6 @@ const PROGMEM char *kAllProtocolNamesStr =
D_STR_ELITESCREENS "\x0"
D_STR_PANASONIC_AC32 "\x0"
D_STR_MILESTAG2 "\x0"
D_STR_ECOCLIM "\x0"
///< New protocol strings should be added just above this line.
"\x0"; ///< This string requires double null termination.
114 changes: 114 additions & 0 deletions src/ir_EcoClim.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright 2021 David Conran

/// @file
/// @brief EcoClim A/C protocol.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1397

// Supports:
// Brand: EcoClim, Model: HYSFR-P348 remote
// Brand: EcoClim, Model: ZC200DPO A/C

#include <algorithm>
#include <cstring>
#include "IRrecv.h"
#include "IRsend.h"
#include "IRtext.h"
#include "IRutils.h"

// Constants
const uint8_t kEcoclimSections = 3;
const uint8_t kEcoclimExtraTolerance = 5; ///< Percentage (extra)
const uint16_t kEcoclimHdrMark = 5730; ///< uSeconds
const uint16_t kEcoclimHdrSpace = 1935; ///< uSeconds
const uint16_t kEcoclimBitMark = 440; ///< uSeconds
const uint16_t kEcoclimOneSpace = 1739; ///< uSeconds
const uint16_t kEcoclimZeroSpace = 637; ///< uSeconds
const uint16_t kEcoclimFooterMark = 7820; ///< uSeconds
const uint32_t kEcoclimGap = kDefaultMessageGap; // Just a guess.

#if SEND_ECOCLIM
/// Send a EcoClim A/C formatted message.
/// Status: Alpha / Completely untested.
/// @param[in] data The message to be sent.
/// @param[in] nbits The number of bits of message to be sent.
/// @param[in] repeat The number of times the command is to be repeated.
void IRsend::sendEcoclim(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
enableIROut(38, kDutyDefault);
for (uint16_t r = 0; r <= repeat; r++) {
for (uint8_t section = 0; section < kEcoclimSections; section++) {
// Header + Data
sendGeneric(kEcoclimHdrMark, kEcoclimHdrSpace,
kEcoclimBitMark, kEcoclimOneSpace,
kEcoclimBitMark, kEcoclimZeroSpace,
0, 0, data, nbits, 38, true, 0, kDutyDefault);
}
mark(kEcoclimFooterMark);
space(kEcoclimGap);
}
}
#endif // SEND_ECOCLIM

#if DECODE_ECOCLIM
/// Decode the supplied EcoClim A/C message.
/// Status: STABLE / Confirmed working on real remote.
/// @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::decodeEcoclim(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (results->rawlen < (2 * nbits + kHeader) * kEcoclimSections +
kFooter - 1 + offset)
return false; // Can't possibly be a valid Ecoclim message.
if (strict) {
switch (nbits) {
case kEcoclimShortBits:
case kEcoclimBits:
break;
default:
return false; // Unexpected bit size.
}
}

for (uint8_t section = 0; section < kEcoclimSections; section++) {
uint16_t used;
uint64_t data;
// Header + Data Block
used = matchGeneric(results->rawbuf + offset, &data,
results->rawlen - offset, nbits,
kEcoclimHdrMark, kEcoclimHdrSpace,
kEcoclimBitMark, kEcoclimOneSpace,
kEcoclimBitMark, kEcoclimZeroSpace,
0, 0, // No footer.
false, _tolerance + kEcoclimExtraTolerance);
if (!used) return false;
DPRINTLN("DEBUG: Data section matched okay.");
offset += used;
// Compliance
if (strict) {
if (section) { // Each section should contain the same data.
if (data != results->value) return false;
} else {
results->value = data;
}
}
}

// Footer
if (!matchMark(results->rawbuf[offset++], kEcoclimFooterMark,
_tolerance + kEcoclimExtraTolerance))
return false;
if (results->rawlen <= offset && !matchAtLeast(results->rawbuf[offset++],
kEcoclimGap))
return false;
// Success
results->bits = nbits;
results->decode_type = ECOCLIM;
// No need to record the value as we stored it as we decoded it.
return true;
}
#endif // DECODE_ECOCLIM
3 changes: 3 additions & 0 deletions src/locale/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,9 @@
#ifndef D_STR_DOSHISHA
#define D_STR_DOSHISHA "DOSHISHA"
#endif // D_STR_DOSHISHA
#ifndef D_STR_ECOCLIM
#define D_STR_ECOCLIM "ECOCLIM"
#endif // D_STR_ECOCLIM
#ifndef D_STR_ELECTRA_AC
#define D_STR_ELECTRA_AC "ELECTRA_AC"
#endif // D_STR_ELECTRA_AC
Expand Down
Loading

0 comments on commit 03cb629

Please sign in to comment.