368 lines
9.5 KiB
C++
368 lines
9.5 KiB
C++
#include "GreeHeatpumpIR.h"
|
|
|
|
// This is a protected method, i.e. generic Gree instances cannot be created
|
|
GreeHeatpumpIR::GreeHeatpumpIR() : HeatpumpIR()
|
|
{
|
|
}
|
|
|
|
GreeGenericHeatpumpIR::GreeGenericHeatpumpIR() : GreeHeatpumpIR()
|
|
{
|
|
static const char model[] PROGMEM = "gree";
|
|
static const char info[] PROGMEM = "{\"mdl\":\"gree\",\"dn\":\"Gree\",\"mT\":16,\"xT\":30,\"fs\":3}";
|
|
|
|
_model = model;
|
|
_info = info;
|
|
greeModel = GREE_GENERIC;
|
|
}
|
|
|
|
GreeYANHeatpumpIR::GreeYANHeatpumpIR() : GreeHeatpumpIR()
|
|
{
|
|
static const char model[] PROGMEM = "greeyan";
|
|
static const char info[] PROGMEM = "{\"mdl\":\"greeyan\",\"dn\":\"Gree YAN\",\"mT\":16,\"xT\":30,\"fs\":3}";
|
|
|
|
_model = model;
|
|
_info = info;
|
|
greeModel = GREE_YAN;
|
|
}
|
|
|
|
// Support for YAA1FB, FAA1FB1, YB1F2 remotes
|
|
GreeYAAHeatpumpIR::GreeYAAHeatpumpIR() : GreeHeatpumpIR()
|
|
{
|
|
static const char model[] PROGMEM = "greeyaa";
|
|
static const char info[] PROGMEM = "{\"mdl\":\"greeyaa\",\"dn\":\"Gree YAA\",\"mT\":16,\"xT\":30,\"fs\":3}";
|
|
|
|
_model = model;
|
|
_info = info;
|
|
greeModel = GREE_YAA;
|
|
}
|
|
|
|
// Support for YAC1FBF remote
|
|
GreeYACHeatpumpIR::GreeYACHeatpumpIR() : GreeiFeelHeatpumpIR()
|
|
{
|
|
static const char model[] PROGMEM = "greeyac";
|
|
static const char info[] PROGMEM = "{\"mdl\":\"greeyac\",\"dn\":\"Gree YAC\",\"mT\":16,\"xT\":30,\"fs\":3}";
|
|
|
|
_model = model;
|
|
_info = info;
|
|
greeModel = GREE_YAC;
|
|
}
|
|
|
|
// Support for YT1F remote
|
|
GreeYTHeatpumpIR::GreeYTHeatpumpIR() : GreeiFeelHeatpumpIR()
|
|
{
|
|
static const char model[] PROGMEM = "greeyt";
|
|
static const char info[] PROGMEM = "{\"mdl\":\"greeyt\",\"dn\":\"Gree YT\",\"mT\":16,\"xT\":30,\"fs\":3}";
|
|
|
|
_model = model;
|
|
_info = info;
|
|
greeModel = GREE_YT;
|
|
}
|
|
|
|
void GreeHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd)
|
|
{
|
|
send(IR, powerModeCmd, operatingModeCmd, fanSpeedCmd, temperatureCmd, swingVCmd, swingHCmd, false);
|
|
}
|
|
|
|
void GreeHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd, bool turboMode)
|
|
{
|
|
send(IR, powerModeCmd, operatingModeCmd, fanSpeedCmd, temperatureCmd, swingVCmd, swingHCmd, turboMode, false);
|
|
}
|
|
|
|
void GreeHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd, bool turboMode, bool iFeelMode)
|
|
{
|
|
(void)swingVCmd;
|
|
(void)swingHCmd;
|
|
|
|
// Sensible defaults for the heat pump mode
|
|
|
|
uint8_t powerMode = GREE_AIRCON1_POWER_ON;
|
|
uint8_t operatingMode = GREE_AIRCON1_MODE_HEAT;
|
|
uint8_t fanSpeed = GREE_AIRCON1_FAN_AUTO;
|
|
uint8_t temperature = 21;
|
|
uint8_t swingV = GREE_VDIR_AUTO;
|
|
uint8_t swingH = GREE_HDIR_AUTO;
|
|
|
|
|
|
if (powerModeCmd == POWER_OFF)
|
|
{
|
|
powerMode = GREE_AIRCON1_POWER_OFF;
|
|
}
|
|
else
|
|
{
|
|
switch (operatingModeCmd)
|
|
{
|
|
case MODE_AUTO:
|
|
operatingMode = GREE_AIRCON1_MODE_AUTO;
|
|
temperatureCmd = 25;
|
|
break;
|
|
case MODE_HEAT:
|
|
operatingMode = GREE_AIRCON1_MODE_HEAT;
|
|
break;
|
|
case MODE_COOL:
|
|
operatingMode = GREE_AIRCON1_MODE_COOL;
|
|
break;
|
|
case MODE_DRY:
|
|
operatingMode = GREE_AIRCON1_MODE_DRY;
|
|
fanSpeedCmd = FAN_1;
|
|
break;
|
|
case MODE_FAN:
|
|
operatingMode = GREE_AIRCON1_MODE_FAN;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (fanSpeedCmd)
|
|
{
|
|
case FAN_AUTO:
|
|
fanSpeed = GREE_AIRCON1_FAN_AUTO;
|
|
break;
|
|
case FAN_1:
|
|
fanSpeed = GREE_AIRCON1_FAN1;
|
|
break;
|
|
case FAN_2:
|
|
fanSpeed = GREE_AIRCON1_FAN2;
|
|
break;
|
|
case FAN_3:
|
|
fanSpeed = GREE_AIRCON1_FAN3;
|
|
break;
|
|
}
|
|
|
|
|
|
if (greeModel == GREE_YAN)
|
|
{
|
|
switch (swingVCmd)
|
|
{
|
|
case VDIR_AUTO:
|
|
case VDIR_SWING:
|
|
swingV = GREE_VDIR_AUTO;
|
|
break;
|
|
case VDIR_UP:
|
|
swingV = GREE_VDIR_UP;
|
|
break;
|
|
case VDIR_MUP:
|
|
swingV = GREE_VDIR_MUP;
|
|
break;
|
|
case VDIR_MIDDLE:
|
|
swingV = GREE_VDIR_MIDDLE;
|
|
break;
|
|
case VDIR_MDOWN:
|
|
swingV = GREE_VDIR_MDOWN;
|
|
break;
|
|
case VDIR_DOWN:
|
|
swingV = GREE_VDIR_DOWN;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (greeModel == GREE_YAA || greeModel == GREE_YAC || greeModel == GREE_YT)
|
|
{
|
|
switch (swingVCmd)
|
|
{
|
|
case VDIR_AUTO:
|
|
swingV = GREE_VDIR_AUTO;
|
|
break;
|
|
case VDIR_SWING:
|
|
swingV = GREE_VDIR_SWING;
|
|
break;
|
|
case VDIR_UP:
|
|
swingV = GREE_VDIR_UP;
|
|
break;
|
|
case VDIR_MUP:
|
|
swingV = GREE_VDIR_MUP;
|
|
break;
|
|
case VDIR_MIDDLE:
|
|
swingV = GREE_VDIR_MIDDLE;
|
|
break;
|
|
case VDIR_MDOWN:
|
|
swingV = GREE_VDIR_MDOWN;
|
|
break;
|
|
case VDIR_DOWN:
|
|
swingV = GREE_VDIR_DOWN;
|
|
break;
|
|
}
|
|
|
|
if (greeModel == GREE_YAC)
|
|
{
|
|
switch (swingHCmd)
|
|
{
|
|
case HDIR_AUTO:
|
|
case HDIR_SWING:
|
|
swingH = GREE_HDIR_SWING;
|
|
break;
|
|
case HDIR_LEFT:
|
|
swingH = GREE_HDIR_LEFT;
|
|
break;
|
|
case HDIR_MLEFT:
|
|
swingH = GREE_HDIR_MLEFT;
|
|
break;
|
|
case HDIR_MIDDLE:
|
|
swingH = GREE_HDIR_MIDDLE;
|
|
break;
|
|
case HDIR_MRIGHT:
|
|
swingH = GREE_HDIR_MRIGHT;
|
|
break;
|
|
case HDIR_RIGHT:
|
|
swingH = GREE_HDIR_RIGHT;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (temperatureCmd > 15 && temperatureCmd < 31)
|
|
{
|
|
temperature = temperatureCmd - 16;
|
|
}
|
|
|
|
sendGree(IR, powerMode, operatingMode, fanSpeed, temperature, swingV, swingH, turboMode, iFeelMode);
|
|
}
|
|
|
|
// Send the Gree code
|
|
void GreeHeatpumpIR::sendGree(IRSender& IR, uint8_t powerMode, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature, uint8_t swingV, uint8_t swingH, bool turboMode, bool iFeelMode)
|
|
{
|
|
(void)swingH;
|
|
|
|
uint8_t GreeTemplate[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
// 0 1 2 3 4 5 6 7
|
|
|
|
uint8_t i;
|
|
|
|
if (greeModel != GREE_YT) {
|
|
GreeTemplate[5] = 0x20;
|
|
}
|
|
|
|
// Set the Fan speed, operating mode and power state
|
|
GreeTemplate[0] = fanSpeed | operatingMode | powerMode;
|
|
// Set the temperature
|
|
GreeTemplate[1] = temperature;
|
|
|
|
// Gree YAN-specific
|
|
if (greeModel == GREE_YAN)
|
|
{
|
|
GreeTemplate[2] = turboMode ? 0x70 : 0x60;
|
|
GreeTemplate[3] = 0x50;
|
|
GreeTemplate[4] = swingV;
|
|
}
|
|
if (greeModel == GREE_YAC)
|
|
{
|
|
GreeTemplate[4] |= (swingH << 4); // GREE_YT will ignore packets where this is set
|
|
}
|
|
if (greeModel == GREE_YAC || greeModel == GREE_YT)
|
|
{
|
|
if (iFeelMode)
|
|
{
|
|
GreeTemplate[5] |= GREE_IFEEL_BIT;
|
|
}
|
|
}
|
|
if (greeModel == GREE_YT) {
|
|
GreeTemplate[2] = GREE_LIGHT_BIT | GREE_HEALTH_BIT; // HEALTH is always on for GREE_YT
|
|
GreeTemplate[3] = 0x50; // bits 4..7 always 0101
|
|
|
|
if (turboMode)
|
|
{
|
|
GreeTemplate[2] |= GREE_TURBO_BIT;
|
|
}
|
|
if (swingV == GREE_VDIR_SWING)
|
|
{
|
|
GreeTemplate[0] |= GREE_VSWING; // Enable swing by setting bit 6
|
|
GreeTemplate[4] = swingV;
|
|
}
|
|
}
|
|
if (greeModel == GREE_YAA || greeModel == GREE_YAC)
|
|
{
|
|
GreeTemplate[2] = GREE_LIGHT_BIT; // bits 0..3 always 0000, bits 4..7 TURBO,LIGHT,HEALTH,X-FAN
|
|
GreeTemplate[3] = 0x50; // bits 4..7 always 0101
|
|
GreeTemplate[6] = 0x20; // YAA1FB, FAA1FB1, YB1F2 bits 4..7 always 0010
|
|
|
|
if (turboMode)
|
|
{
|
|
GreeTemplate[2] |= GREE_TURBO_BIT;
|
|
}
|
|
if (swingV == GREE_VDIR_SWING)
|
|
{
|
|
GreeTemplate[0] |= GREE_VSWING; // Enable swing by setting bit 6
|
|
}
|
|
else if (swingV != GREE_VDIR_AUTO)
|
|
{
|
|
GreeTemplate[5] = swingV;
|
|
}
|
|
}
|
|
|
|
// Calculate the checksum
|
|
if (greeModel == GREE_YAN)
|
|
{
|
|
GreeTemplate[7] = (
|
|
(GreeTemplate[0] << 4) +
|
|
(GreeTemplate[1] << 4) +
|
|
0xC0);
|
|
}
|
|
else
|
|
{
|
|
GreeTemplate[7] = (((
|
|
(GreeTemplate[0] & 0x0F) +
|
|
(GreeTemplate[1] & 0x0F) +
|
|
(GreeTemplate[2] & 0x0F) +
|
|
(GreeTemplate[3] & 0x0F) +
|
|
((GreeTemplate[5] & 0xF0) >> 4) +
|
|
((GreeTemplate[6] & 0xF0) >> 4) +
|
|
((GreeTemplate[7] & 0xF0) >> 4) +
|
|
0x0A) & 0x0F) << 4) | (GreeTemplate[7] & 0x0F);
|
|
}
|
|
|
|
// 38 kHz PWM frequency
|
|
IR.setFrequency(38);
|
|
|
|
// Send Header mark
|
|
IR.mark(GREE_AIRCON1_HDR_MARK);
|
|
IR.space(GREE_AIRCON1_HDR_SPACE);
|
|
|
|
// Payload part #1
|
|
for (i=0; i<4; i++) {
|
|
IR.sendIRbyte(GreeTemplate[i], GREE_AIRCON1_BIT_MARK, GREE_AIRCON1_ZERO_SPACE, GREE_AIRCON1_ONE_SPACE);
|
|
}
|
|
// Only three first bits of byte 4 are sent, this is always '010'
|
|
IR.mark(GREE_AIRCON1_BIT_MARK);
|
|
IR.space(GREE_AIRCON1_ZERO_SPACE);
|
|
IR.mark(GREE_AIRCON1_BIT_MARK);
|
|
IR.space(GREE_AIRCON1_ONE_SPACE);
|
|
IR.mark(GREE_AIRCON1_BIT_MARK);
|
|
IR.space(GREE_AIRCON1_ZERO_SPACE);
|
|
|
|
// Message space
|
|
IR.mark(GREE_AIRCON1_BIT_MARK);
|
|
IR.space(GREE_AIRCON1_MSG_SPACE);
|
|
|
|
// Payload part #2
|
|
for (i=4; i<8; i++) {
|
|
IR.sendIRbyte(GreeTemplate[i], GREE_AIRCON1_BIT_MARK, GREE_AIRCON1_ZERO_SPACE, GREE_AIRCON1_ONE_SPACE);
|
|
}
|
|
|
|
// End mark
|
|
IR.mark(GREE_AIRCON1_BIT_MARK);
|
|
IR.space(0);
|
|
}
|
|
|
|
// Sends current sensed temperatures, YAC remotes/supporting units only
|
|
void GreeiFeelHeatpumpIR::send(IRSender& IR, uint8_t currentTemperature)
|
|
{
|
|
uint8_t GreeTemplate[] = { 0x00, 0x00 };
|
|
|
|
GreeTemplate[0] = currentTemperature;
|
|
GreeTemplate[1] = 0xA5;
|
|
|
|
// 38 kHz PWM frequency
|
|
IR.setFrequency(38);
|
|
|
|
// Send Header mark
|
|
IR.mark(GREE_YAC_HDR_MARK);
|
|
IR.space(GREE_YAC_HDR_SPACE);
|
|
|
|
// send payload
|
|
IR.sendIRbyte(GreeTemplate[0], GREE_YAC_BIT_MARK, GREE_AIRCON1_ZERO_SPACE, GREE_AIRCON1_ONE_SPACE);
|
|
IR.sendIRbyte(GreeTemplate[1], GREE_YAC_BIT_MARK, GREE_AIRCON1_ZERO_SPACE, GREE_AIRCON1_ONE_SPACE);
|
|
|
|
// End mark
|
|
IR.mark(GREE_YAC_BIT_MARK);
|
|
IR.space(0);
|
|
}
|