arduino-heatpumpir/GreeHeatpumpIR.cpp

267 lines
6.7 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;
}
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)
{
(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)
{
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 (temperatureCmd > 15 && temperatureCmd < 31)
{
temperature = temperatureCmd - 16;
}
sendGree(IR, powerMode, operatingMode, fanSpeed, temperature, swingV, swingH, false);
}
// 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)
{
(void)swingH;
uint8_t GreeTemplate[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00 };
// 0 1 2 3 4 5 6 7
uint8_t i;
// 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] = 0x60;
GreeTemplate[2] = 0x50;
if (turboMode)
{
GreeTemplate[2]=0x70;
}
GreeTemplate[4] = swingV;
}
if (greeModel == GREE_YAA)
{
// GreeTemplate[2] = 0xE0; // bits 0..3 always 0000, bits 4..7 TURBO,LIGHT,HEALTH,X-FAN
GreeTemplate[2] = 0x20; // 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] |= (1 << 4); // Set bit 4 (TURBO)
}
if (swingV == GREE_VDIR_SWING)
{
GreeTemplate[0] |= (1 << 6); // 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);
}