Skip to content

Commit c00a919

Browse files
authored
Add support of Toshiba Remote Control B (#2094)
Add support of Toshiba Remote Control B
1 parent aae4528 commit c00a919

File tree

9 files changed

+97
-30
lines changed

9 files changed

+97
-30
lines changed

src/IRsend.h

+7
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,13 @@ enum argo_ac_remote_model_t {
228228
SAC_WREM3 // (2) ARGO WREM3 remote (touch buttons), bit-len vary by cmd
229229
};
230230

231+
/// Toshiba A/C model numbers
232+
enum toshiba_ac_remote_model_t {
233+
kToshibaGenericRemote_A = 0, // Default from existing codebase
234+
kToshibaGenericRemote_B = 1, // Newly discovered remote control b, applies to
235+
// many remote models such as WA-TH03A, WA-TH04A etc.
236+
};
237+
231238
// Classes
232239

233240
/// Class for sending all basic IR protocols.

src/IRtext.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ IRTEXT_CONST_STRING(kDg11j104Str, D_STR_DG11J104); ///< "DG11J104"
295295
IRTEXT_CONST_STRING(kDg11j191Str, D_STR_DG11J191); ///< "DG11J191"
296296
IRTEXT_CONST_STRING(kArgoWrem2Str, D_STR_ARGO_WREM2); ///< "WREM3"
297297
IRTEXT_CONST_STRING(kArgoWrem3Str, D_STR_ARGO_WREM3); ///< "WREM3"
298+
IRTEXT_CONST_STRING(kToshibaGenericRemoteAStr, D_STR_TOSHIBAGENERICREMOTEA);
299+
// "TOSHIBA REMOTE A"
300+
IRTEXT_CONST_STRING(kToshibaGenericRemoteBStr, D_STR_TOSHIBAGENERICREMOTEB);
301+
// "TOSHIBA REMOTE B"
298302

299303
#define D_STR_UNSUPPORTED "?" // Unsupported protocols will be showing as
300304
// a question mark, check for length > 1

src/IRtext.h

+2
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ extern IRTEXT_CONST_PTR(kSetTimerCommandStr);
229229
extern IRTEXT_CONST_PTR(kTimerStr);
230230
extern IRTEXT_CONST_PTR(kToggleStr);
231231
extern IRTEXT_CONST_PTR(kTopStr);
232+
extern IRTEXT_CONST_PTR(kToshibaGenericRemoteAStr);
233+
extern IRTEXT_CONST_PTR(kToshibaGenericRemoteBStr);
232234
extern IRTEXT_CONST_PTR(kTrueStr);
233235
extern IRTEXT_CONST_PTR(kTurboStr);
234236
extern IRTEXT_CONST_PTR(kTurboToggleStr);

src/IRutils.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,15 @@ namespace irutils {
701701
default: return kUnknownStr;
702702
}
703703
break;
704+
case decode_type_t::TOSHIBA_AC:
705+
switch (model) {
706+
case toshiba_ac_remote_model_t::kToshibaGenericRemote_A:
707+
return kToshibaGenericRemoteAStr;
708+
case toshiba_ac_remote_model_t::kToshibaGenericRemote_B:
709+
return kToshibaGenericRemoteBStr;
710+
default:
711+
return kUnknownStr;
712+
}
704713
default: return kUnknownStr;
705714
}
706715
}

src/ir_Toshiba.cpp

+30-3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ using irutils::addModeToString;
4040
using irutils::addTempToString;
4141
using irutils::checkInvertedBytePairs;
4242
using irutils::invertBytePairs;
43+
using irutils::addModelToString;
4344

4445
#if SEND_TOSHIBA_AC
4546
/// Send a Toshiba A/C message.
@@ -104,8 +105,9 @@ void IRToshibaAC::send(const uint16_t repeat) {
104105
uint16_t IRToshibaAC::getInternalStateLength(const uint8_t state[],
105106
const uint16_t size) {
106107
if (size < kToshibaAcLengthByte) return 0;
107-
return std::min((uint16_t)(state[kToshibaAcLengthByte] + kToshibaAcMinLength),
108-
kToshibaACStateLengthLong);
108+
// Fix: Extract the last 4 bits instead
109+
return std::min((uint16_t)((state[kToshibaAcLengthByte] & 0xF)
110+
+ kToshibaAcMinLength), kToshibaACStateLengthLong);
109111
}
110112

111113
/// Get the length of the current internal state per the protocol structure.
@@ -462,7 +464,8 @@ stdAc::state_t IRToshibaAC::toCommon(const stdAc::state_t *prev) const {
462464
String IRToshibaAC::toString(void) const {
463465
String result = "";
464466
result.reserve(95);
465-
result += addTempToString(getTemp(), true, false);
467+
result += addModelToString(decode_type_t::TOSHIBA_AC, getModel(), false);
468+
result += addTempToString(getTemp(), true);
466469
switch (getStateLength()) {
467470
case kToshibaACStateLengthShort:
468471
result += addIntToString(getSwing(true), kSwingVStr);
@@ -493,6 +496,30 @@ String IRToshibaAC::toString(void) const {
493496
return result;
494497
}
495498

499+
/// Get the model information currently known.
500+
/// @return The known model number.
501+
toshiba_ac_remote_model_t IRToshibaAC::getModel(void) const {
502+
switch (_.Model) {
503+
case kToshibaAcRemoteB:
504+
return toshiba_ac_remote_model_t::kToshibaGenericRemote_B;
505+
default:
506+
return toshiba_ac_remote_model_t::kToshibaGenericRemote_A;
507+
}
508+
}
509+
510+
/// Set the current model for the remote.
511+
/// @param[in] model The model number.
512+
void IRToshibaAC::setModel(const toshiba_ac_remote_model_t model) {
513+
switch (model) {
514+
case toshiba_ac_remote_model_t::kToshibaGenericRemote_B:
515+
_.Model = kToshibaAcRemoteB;
516+
break;
517+
default:
518+
_.Model = kToshibaAcRemoteA;
519+
break;
520+
}
521+
}
522+
496523
#if DECODE_TOSHIBA_AC
497524
/// Decode the supplied Toshiba A/C message.
498525
/// Status: STABLE / Working.

src/ir_Toshiba.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ union ToshibaProtocol{
5353
///< 1 (56 bit message)
5454
///< 3 (72 bit message)
5555
///< 4 (80 bit message)
56-
uint8_t Length :8;
56+
uint8_t Length :4;
57+
// Toshiba remote type
58+
// 0 - Remote control A
59+
// 1 - Remote control B
60+
uint8_t Model :4;
5761
// Byte[3] - The bit-inverted value of the "length" byte.
5862
uint8_t :8;
5963
// Byte[4]
@@ -111,6 +115,9 @@ const uint8_t kToshibaAcFanMax = 5; // 0b101
111115
const uint8_t kToshibaAcTurboOn = 1; // 0b01
112116
const uint8_t kToshibaAcEconoOn = 3; // 0b11
113117

118+
const uint8_t kToshibaAcRemoteA = 0; // 0b0000
119+
const uint8_t kToshibaAcRemoteB = 1; // 0b0001
120+
114121
// Legacy defines. (Deprecated)
115122
#define TOSHIBA_AC_AUTO kToshibaAcAuto
116123
#define TOSHIBA_AC_COOL kToshibaAcCool
@@ -140,6 +147,8 @@ class IRToshibaAC {
140147
void begin(void);
141148
void on(void);
142149
void off(void);
150+
void setModel(const toshiba_ac_remote_model_t model);
151+
toshiba_ac_remote_model_t getModel() const;
143152
void setPower(const bool on);
144153
bool getPower(void) const;
145154
void setTemp(const uint8_t degrees);

src/locale/defaults.h

+6
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,12 @@ D_STR_INDIRECT " " D_STR_MODE
11201120
#ifndef D_STR_ZEPEAL
11211121
#define D_STR_ZEPEAL "ZEPEAL"
11221122
#endif // D_STR_ZEPEAL
1123+
#ifndef D_STR_TOSHIBAGENERICREMOTEA
1124+
#define D_STR_TOSHIBAGENERICREMOTEA "TOSHIBA REMOTE A"
1125+
#endif // D_STR_TOSHIBAGENERICREMOTEA
1126+
#ifndef D_STR_TOSHIBAGENERICREMOTEB
1127+
#define D_STR_TOSHIBAGENERICREMOTEB "TOSHIBA REMOTE B"
1128+
#endif // D_STR_TOSHIBAGENERICREMOTEB
11231129

11241130
// IRrecvDumpV2+
11251131
#ifndef D_STR_TIMESTAMP

test/IRac_test.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -2188,8 +2188,8 @@ TEST(TestIRac, Toshiba) {
21882188
IRac irac(kGpioUnused);
21892189
IRrecv capture(kGpioUnused);
21902190
char expected[] =
2191-
"Temp: 29C, Power: On, Mode: 2 (Dry), Fan: 2 (UNKNOWN), "
2192-
"Turbo: Off, Econo: On, Filter: Off";
2191+
"Model: 0 (TOSHIBA REMOTE A), Temp: 29C, Power: On, Mode: 2 (Dry), "
2192+
"Fan: 2 (UNKNOWN), Turbo: Off, Econo: On, Filter: Off";
21932193

21942194
ac.begin();
21952195
irac.toshiba(&ac,
@@ -3175,8 +3175,8 @@ TEST(TestIRac, Issue1250) {
31753175

31763176
// Now send the state so we can actually decode/capture what we sent.
31773177
char expected_on[] =
3178-
"Temp: 19C, Power: On, Mode: 4 (Fan), Fan: 0 (Auto), "
3179-
"Turbo: Off, Econo: Off, Filter: Off";
3178+
"Model: 0 (TOSHIBA REMOTE A), Temp: 19C, Power: On, Mode: 4 (Fan), "
3179+
"Fan: 0 (Auto), Turbo: Off, Econo: Off, Filter: Off";
31803180
ac._irsend.reset();
31813181
irac.toshiba(&ac,
31823182
irac.next.power, // Power
@@ -3202,8 +3202,8 @@ TEST(TestIRac, Issue1250) {
32023202
irac.sendAc();
32033203
// Now send the state so we can actually decode/capture what we sent.
32043204
char expected_off[] =
3205-
"Temp: 19C, Power: Off, Fan: 0 (Auto), Turbo: Off, Econo: Off, "
3206-
"Filter: Off";
3205+
"Model: 0 (TOSHIBA REMOTE A), Temp: 19C, Power: Off, Fan: 0 (Auto), "
3206+
"Turbo: Off, Econo: Off, Filter: Off";
32073207
ac._irsend.reset();
32083208
irac.toshiba(&ac,
32093209
irac.next.power, // Power

test/ir_Toshiba_test.cpp

+23-20
Original file line numberDiff line numberDiff line change
@@ -311,22 +311,25 @@ TEST(TestToshibaACClass, HumanReadableOutput) {
311311
0x00, 0xC1, 0x00, 0xC0};
312312

313313
ac.setRaw(initial_state);
314-
EXPECT_EQ("Temp: 17C, Power: On, Mode: 0 (Auto), Fan: 0 (Auto), "
315-
"Turbo: Off, Econo: Off, Filter: Off",
314+
EXPECT_EQ("Model: 0 (TOSHIBA REMOTE A), Temp: 17C, Power: On, "
315+
"Mode: 0 (Auto), Fan: 0 (Auto), Turbo: Off, Econo: Off, "
316+
"Filter: Off",
316317
ac.toString());
317318
ac.setRaw(modified_state);
318-
EXPECT_EQ("Temp: 17C, Power: On, Mode: 1 (Cool), Fan: 5 (High), "
319-
"Turbo: Off, Econo: Off, Filter: Off",
319+
EXPECT_EQ("Model: 0 (TOSHIBA REMOTE A), Temp: 17C, Power: On, "
320+
"Mode: 1 (Cool), Fan: 5 (High), Turbo: Off, Econo: Off, "
321+
"Filter: Off",
320322
ac.toString());
321323
ac.setTemp(25);
322324
ac.setFan(3);
323325
ac.setMode(kToshibaAcDry);
324-
EXPECT_EQ("Temp: 25C, Power: On, Mode: 2 (Dry), Fan: 3 (Medium), "
325-
"Turbo: Off, Econo: Off, Filter: Off",
326+
EXPECT_EQ("Model: 0 (TOSHIBA REMOTE A), Temp: 25C, Power: On, "
327+
"Mode: 2 (Dry), Fan: 3 (Medium), Turbo: Off, Econo: Off, "
328+
"Filter: Off",
326329
ac.toString());
327330
ac.off();
328-
EXPECT_EQ("Temp: 25C, Power: Off, Fan: 3 (Medium), Turbo: Off, Econo: Off, "
329-
"Filter: Off",
331+
EXPECT_EQ("Model: 0 (TOSHIBA REMOTE A), Temp: 25C, Power: Off, "
332+
"Fan: 3 (Medium), Turbo: Off, Econo: Off, Filter: Off",
330333
ac.toString());
331334
}
332335

@@ -379,8 +382,8 @@ TEST(TestDecodeToshibaAC, SyntheticExample) {
379382
ASSERT_EQ(kToshibaACBits, irsend.capture.bits);
380383
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
381384
EXPECT_EQ(
382-
"Temp: 17C, Power: On, Mode: 0 (Auto), Fan: 0 (Auto), Turbo: Off, "
383-
"Econo: Off, Filter: Off",
385+
"Model: 0 (TOSHIBA REMOTE A), Temp: 17C, Power: On, Mode: 0 (Auto), "
386+
"Fan: 0 (Auto), Turbo: Off, Econo: Off, Filter: Off",
384387
IRAcUtils::resultAcToString(&irsend.capture));
385388
stdAc::state_t r, p;
386389
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
@@ -627,8 +630,8 @@ TEST(TestDecodeToshibaAC, RealLongExample) {
627630
EXPECT_EQ(kToshibaACBitsLong, irsend.capture.bits);
628631
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
629632
EXPECT_EQ(
630-
"Temp: 22C, Power: On, Mode: 0 (Auto), Fan: 0 (Auto), Turbo: On, "
631-
"Econo: Off, Filter: Off",
633+
"Model: 0 (TOSHIBA REMOTE A), Temp: 22C, Power: On, Mode: 0 (Auto), "
634+
"Fan: 0 (Auto), Turbo: On, Econo: Off, Filter: Off",
632635
IRAcUtils::resultAcToString(&irsend.capture));
633636
}
634637

@@ -718,7 +721,7 @@ TEST(TestDecodeToshibaAC, RealShortExample) {
718721
EXPECT_EQ(kToshibaACBitsShort, irsend.capture.bits);
719722
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
720723
EXPECT_EQ(
721-
"Temp: 17C, Swing(V): 0 (Step)",
724+
"Model: 0 (TOSHIBA REMOTE A), Temp: 17C, Swing(V): 0 (Step)",
722725
IRAcUtils::resultAcToString(&irsend.capture));
723726
}
724727

@@ -732,8 +735,8 @@ TEST(TestToshibaACClass, ConstructLongState) {
732735
ac.setTurbo(false);
733736
ac.setEcono(true);
734737
EXPECT_EQ(
735-
"Temp: 29C, Power: On, Mode: 2 (Dry), Fan: 2 (UNKNOWN), "
736-
"Turbo: Off, Econo: On, Filter: Off",
738+
"Model: 0 (TOSHIBA REMOTE A), Temp: 29C, Power: On, Mode: 2 (Dry), "
739+
"Fan: 2 (UNKNOWN), Turbo: Off, Econo: On, Filter: Off",
737740
ac.toString());
738741
EXPECT_EQ(kToshibaACStateLengthLong, ac.getStateLength());
739742
const uint8_t expectedState[kToshibaACStateLengthLong] = {
@@ -783,8 +786,8 @@ TEST(TestDecodeToshibaAC, RealExample_WHUB03NJ) {
783786
EXPECT_EQ(kToshibaACBits, irsend.capture.bits);
784787
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
785788
EXPECT_EQ(
786-
"Temp: 20C, Power: Off, Fan: 0 (Auto), Turbo: Off, Econo: Off, "
787-
"Filter: Off",
789+
"Model: 0 (TOSHIBA REMOTE A), Temp: 20C, Power: Off, Fan: 0 (Auto), "
790+
"Turbo: Off, Econo: Off, Filter: Off",
788791
IRAcUtils::resultAcToString(&irsend.capture));
789792
}
790793

@@ -805,7 +808,7 @@ TEST(TestToshibaACClass, SwingCodes) {
805808
ac.setSwing(kToshibaAcSwingOn);
806809

807810
EXPECT_EQ(
808-
"Temp: 17C, Swing(V): 1 (On)",
811+
"Model: 0 (TOSHIBA REMOTE A), Temp: 17C, Swing(V): 1 (On)",
809812
ac.toString());
810813
EXPECT_EQ(kToshibaACStateLengthShort, ac.getStateLength());
811814
const uint8_t swingOnState[kToshibaACStateLengthShort] = {
@@ -815,7 +818,7 @@ TEST(TestToshibaACClass, SwingCodes) {
815818

816819
ac.setSwing(kToshibaAcSwingOff);
817820
EXPECT_EQ(
818-
"Temp: 17C, Swing(V): 2 (Off)",
821+
"Model: 0 (TOSHIBA REMOTE A), Temp: 17C, Swing(V): 2 (Off)",
819822
ac.toString());
820823
EXPECT_EQ(kToshibaACStateLengthShort, ac.getStateLength());
821824
const uint8_t swingOffState[kToshibaACStateLengthShort] = {
@@ -828,7 +831,7 @@ TEST(TestToshibaACClass, SwingCodes) {
828831
ac.setRaw(swingToggleState, kToshibaACStateLengthShort);
829832
EXPECT_EQ(kToshibaAcSwingToggle, ac.getSwing());
830833
EXPECT_EQ(
831-
"Temp: 17C, Swing(V): 4 (Toggle)",
834+
"Model: 0 (TOSHIBA REMOTE A), Temp: 17C, Swing(V): 4 (Toggle)",
832835
ac.toString());
833836
}
834837

0 commit comments

Comments
 (0)