Files
lighthub/lighthub/modules/out_ac.cpp

488 lines
12 KiB
C++

#ifndef AC_DISABLE
#include "modules/out_ac.h"
#include "Arduino.h"
#include "options.h"
#include "Streaming.h"
#include "item.h"
#include "textconst.h"
#include "main.h"
#ifndef AC_Serial
#define AC_Serial Serial3
#endif
#define INTERVAL_AC_POLLING 5000L
static int driverStatus = CST_UNKNOWN;
static int fresh =0;
static int power = 0;
static int swing =0;
static int lock_rem =0;
static int cur_tmp = 0;
static int set_tmp = 0;
static int fan_spd = 0;
static int mode = 0;
long prevPolling = 0;
byte inCheck = 0;
byte qstn[] = {255,255,10,0,0,0,0,0,1,1,77,1,90}; // Команда опроса
byte data[37] = {}; //Массив данных
byte on[] = {255,255,10,0,0,0,0,0,1,1,77,2,91}; // Включение кондиционера
byte off[] = {255,255,10,0,0,0,0,0,1,1,77,3,92}; // Выключение кондиционера
byte lock[] = {255,255,10,0,0,0,0,0,1,3,0,0,14}; // Блокировка пульта
//Extended subItem set
const char LOCK_P[] PROGMEM = "lock";
const char QUIET_P[] PROGMEM = "queit";
const char SWING_P[] PROGMEM = "swing";
const char RAW_P[] PROGMEM = "raw";
//const char IDLE_P[] PROGMEM = "IDLE";
/*
extern const char HEAT_P[] PROGMEM;
extern const char COOL_P[] PROGMEM;
extern const char AUTO_P[] PROGMEM;
extern const char FAN_ONLY_P[] PROGMEM;
extern const char DRY_P[] PROGMEM;
extern const char HIGH_P[] PROGMEM;
extern const char MED_P[] PROGMEM;
extern const char LOW_P[] PROGMEM;
*/
void out_AC::InsertData(byte data[], size_t size){
char s_mode[10];
set_tmp = data[B_SET_TMP]+16;
if (set_tmp>40 || set_tmp<16) return;
cur_tmp = data[B_CUR_TMP];
mode = data[B_MODE];
fan_spd = data[B_FAN_SPD];
swing = data[B_SWING];
power = data[B_POWER];
lock_rem = data[B_LOCK_REM];
fresh = data[B_FRESH];
/////////////////////////////////
if (fresh & 0x01)
publishTopic(item->itemArr->name, "ON","/fresh");
else publishTopic(item->itemArr->name, "OFF","/fresh");
/////////////////////////////////
if (lock_rem == 0x80){
publishTopic(item->itemArr->name, "ON","/lock");
}
if (lock_rem == 0x00){
publishTopic(item->itemArr->name, "OFF","/lock");
}
/////////////////////////////////
/*
if (power == 0x01 || power == 0x11){
publishTopic(item->itemArr->name,"Power", "on");
}
if (power == 0x00 || power == 0x10){
publishTopic(item->itemArr->name,"Power", "off");
}
*/
debugSerial.print ("Power=");
debugSerial.println(power);
if (power & 0x08)
publishTopic(item->itemArr->name, "ON", "/quiet");
else publishTopic(item->itemArr->name, "OFF" , "/quiet");
if (power & 0x02) //Compressor on
publishTopic(item->itemArr->name, "ON","/compressor");
else
publishTopic(item->itemArr->name, "OFF","/compressor");
publishTopic(item->itemArr->name, (long) swing,"/swing");
//publishTopic(item->itemArr->name, (long) fan_spd,"/fan");
/////////////////////////////////
if (fan_spd == 0x00){
publishTopic(item->itemArr->name, "high","/fan");
}
if (fan_spd == 0x01){
publishTopic(item->itemArr->name, "medium","/fan");
}
if (fan_spd == 0x02){
publishTopic(item->itemArr->name, "low","/fan");
}
if (fan_spd == 0x03){
publishTopic(item->itemArr->name, "auto","/fan");
}
if (swing == 0x00)
publishTopic(item->itemArr->name, "OFF","/swing");
else publishTopic(item->itemArr->name, "ON","/swing");
/*
if (swing == 0x01){
publishTopic(item->itemArr->name, "ud","swing");
}
if (swing == 0x02){
publishTopic(item->itemArr->name, "lr","swing");
}
if (swing == 0x03){
publishTopic(item->itemArr->name, "all","swing");
}*/
/////////////////////////////////
publishTopic(item->itemArr->name,(long)set_tmp,"/set");
if (cur_tmp!=255) publishTopic(item->itemArr->name, (long)cur_tmp, "/temp");
////////////////////////////////////
s_mode[0]='\0';
if (mode == 0x00){
strcpy_P(s_mode,AUTO_P);
}
else if (mode == 0x01){
strcpy_P(s_mode,COOL_P);
}
else if (mode == 0x02){
strcpy_P(s_mode,HEAT_P);
}
else if (mode == 0x03){
strcpy_P(s_mode,FAN_ONLY_P);
}
else if (mode == 0x04){
strcpy_P(s_mode,DRY_P);
}
else if (mode == 109){
strcpy_P(s_mode,ERROR_P);
}
publishTopic(item->itemArr->name, (long) mode, "/mode");
if (power & 0x01)
publishTopic(item->itemArr->name, s_mode,"/cmd");
else publishTopic(item->itemArr->name, "OFF","/cmd");
/*
String raw_str;
char raw[75];
for (int i=0; i < 37; i++){
if (data[i] < 10){
raw_str += "0";
raw_str += String(data[i], HEX);
} else {
raw_str += String(data[i], HEX);
}
}
raw_str.toUpperCase();
raw_str.toCharArray(raw,75);
publishTopic(item->itemArr->name, raw,"/raw");
Serial.println(raw);
*/
///////////////////////////////////
}
byte getCRC(byte req[], size_t size){
byte crc = 0;
for (int i=2; i < size; i++){
crc += req[i];
}
return crc;
}
void SendData(byte req[], size_t size){
AC_Serial.write(req, size - 1);
AC_Serial.write(getCRC(req, size-1));
//AC_Serial.flush();
/*
Serial.print("<<");
for (int i=0; i < size-1; i++)
{
if (req[i] < 10){
Serial.print("0");
Serial.print(req[i], HEX);
}
else
{
Serial.print(req[i], HEX);
}
}
Serial.println();
*/
}
inline unsigned char toHex( char ch ){
return ( ( ch >= 'A' ) ? ( ch - 'A' + 0xA ) : ( ch - '0' ) ) & 0x0F;
}
int out_AC::Setup()
{
abstractOut::Setup();
debugSerial<<F("AC Init")<<endl;
AC_Serial.begin(9600);
driverStatus = CST_INITIALIZED;
return 1;
}
int out_AC::Stop()
{
debugSerial<<F("AC De-Init")<<endl;
driverStatus = CST_UNKNOWN;
return 1;
}
int out_AC::Status()
{
return driverStatus;
}
int out_AC::isActive()
{
return (power & 1);
}
int out_AC::Poll(short cause)
{
if (cause!=POLLING_SLOW) return 0;
//long now = millis();
//if (now - prevPolling > INTERVAL_AC_POLLING) {
if (isTimeOver(prevPolling,millis(),INTERVAL_AC_POLLING)) {
prevPolling = millisNZ();
debugSerial.println(F("Polling"));
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
}
///delay(100);
if(AC_Serial.available() >= 37){ //was 0
AC_Serial.readBytes(data, 37);
while(AC_Serial.available()){
delay(2);
AC_Serial.read();
}
if (data[36] != inCheck){
inCheck = data[36];
InsertData(data, 37);
}
}
return INTERVAL_SLOW_POLLING;
};
//int out_AC::Ctrl(short cmd, short n, int * Parameters, int suffixCode, char* subItem)
int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
{char s_mode[10];
int suffixCode = cmd.getSuffix();
// Some additional Subitems
if (strcmp_P(subItem, LOCK_P) == 0) suffixCode = S_LOCK;
else if (strcmp_P(subItem, SWING_P) == 0) suffixCode = S_SWING;
else if (strcmp_P(subItem, QUIET_P) == 0) suffixCode = S_QUIET;
else if (strcmp_P(subItem, RAW_P) == 0) suffixCode = S_RAW;
if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it
//data[B_POWER] = power;
// debugSerial<<F(".");
switch(suffixCode)
{
case S_SET:
set_tmp = cmd.getInt();
if (set_tmp >= 16 && set_tmp <= 40)
{
//if (set_tmp>40 || set_tmp<16) set_temp=21;
data[B_SET_TMP] = set_tmp -16;
publishTopic(item->itemArr->name,(long) set_tmp,"/set");
}
else return -1;
break;
case S_CMD:
s_mode[0]='\0';
switch (cmd.getCmd())
{
case CMD_ON:
case CMD_XON:
data[B_POWER] = power;
data[B_POWER] |= 1;
SendData(on, sizeof(on)/sizeof(byte));
publishTopic(item->itemArr->name,"ON","/cmd");
return 1;
break;
case CMD_OFF:
case CMD_HALT:
data[B_POWER] = power;
data[B_POWER] &= ~1;
SendData(off, sizeof(off)/sizeof(byte));
publishTopic(item->itemArr->name,"OFF","/cmd");
return 1;
break;
case CMD_AUTO:
data[B_MODE] = 0;
data[B_POWER] = power;
data[B_POWER] |= 1;
strcpy_P(s_mode,AUTO_P);
break;
case CMD_COOL:
data[B_MODE] = 1;
data[B_POWER] = power;
data[B_POWER] |= 1;
strcpy_P(s_mode,COOL_P);
break;
case CMD_HEAT:
data[B_MODE] = 2;
data[B_POWER] = power;
data[B_POWER] |= 1;
strcpy_P(s_mode,HEAT_P);
break;
case CMD_DRY:
data[B_MODE] = 4;
data[B_POWER] = power;
data[B_POWER] |= 1;
strcpy_P(s_mode,DRY_P);
break;
case CMD_FAN:
data[B_MODE] = 3;
debugSerial<<"fan\n";
data[B_POWER] = power;
data[B_POWER] |= 1;
strcpy_P(s_mode,FAN_ONLY_P);
break;
case CMD_UNKNOWN:
return -1;
break;
}
publishTopic(item->itemArr->name,s_mode,"/cmd");
break;
case S_FAN:
s_mode[0]='\0';
switch (cmd.getCmd())
{
case CMD_AUTO:
data[B_FAN_SPD] = 3;
strcpy_P(s_mode,AUTO_P);
break;
case CMD_HIGH:
data[B_FAN_SPD] = 0;
strcpy_P(s_mode,HIGH_P);
break;
case CMD_MED:
data[B_FAN_SPD] = 1;
strcpy_P(s_mode,MED_P);
break;
case CMD_LOW:
data[B_FAN_SPD] = 2;
strcpy_P(s_mode,LOW_P);
break;
default:
//if (n) data[B_FAN_SPD] = Parameters[0];
data[B_FAN_SPD] = cmd.getInt();
//TODO - mapping digits to speed
}
publishTopic(item->itemArr->name,s_mode,"/fan");
break;
case S_MODE:
//data[B_MODE] = Parameters[0];
data[B_MODE] = cmd.getInt();
break;
case S_LOCK:
switch (cmd.getCmd())
{
case CMD_ON:
data[B_LOCK_REM] = 80;
break;
case CMD_OFF:
data[B_LOCK_REM] = 0;
break;
}
break;
case S_SWING:
switch (cmd.getCmd())
{
case CMD_ON:
data[B_LOCK_REM] = 3;
break;
case CMD_OFF:
data[B_LOCK_REM] = 0;
break;
default:
//if (n) data[B_SWING] = Parameters[0];
data[B_SWING] = cmd.getInt();
}
break;
case S_QUIET:
switch (cmd.getCmd())
{
case CMD_ON:
data[B_POWER] |= 8;
break;
case CMD_OFF:
data[B_POWER] &= ~8;
break;
}
break;
case S_RAW:
/*
{
char buf[75];
char hexbyte[3] = {0};
strPayload.toCharArray(buf, 75);
int octets[sizeof(buf) / 2] ;
for (int i=0; i < 76; i += 2){
hexbyte[0] = buf[i] ;
hexbyte[1] = buf[i+1] ;
data[i/2] = (toHex(hexbyte[0]) << 4) | toHex(hexbyte[1]);
AC_Serial.write(data, 37);
AC_Serial.flush();
publishTopic("RAW", buf);
}
*/
break;
case S_NOTFOUND:
return -1;
}
/*
//////////
if (strTopic == "/myhome/in/Conditioner/Swing"){
if (strPayload == "off"){
data[B_SWING] = 0;
}
if (strPayload == "ud"){
data[B_SWING] = 1;
}
if (strPayload == "lr"){
data[B_SWING] = 2;
}
if (strPayload == "all"){
data[B_SWING] = 3;
}
}
////////
*/
//if (strTopic == "/myhome/in/Conditioner/RAW")
data[B_CMD] = 0;
data[9] = 1;
data[10] = 77;
data[11] = 95;
SendData(data, sizeof(data)/sizeof(byte));
//InsertData(data, sizeof(data)/sizeof(byte));
return 1;
}
#endif