mirror of https://github.com/sfeakes/AqualinkD.git
638 lines
22 KiB
C
638 lines
22 KiB
C
/*
|
|
* Copyright (c) 2017 Shaun Feakes - All rights reserved
|
|
*
|
|
* You may use redistribute and/or modify this code under the terms of
|
|
* the GNU General Public License version 2 as published by the
|
|
* Free Software Foundation. For the terms of this license,
|
|
* see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* You are free to use this software under the terms of the GNU General
|
|
* Public License, but WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License for more details.
|
|
*
|
|
* https://github.com/sfeakes/aqualinkd
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "aq_serial.h"
|
|
#include "aqualink.h"
|
|
#include "iaqualink.h"
|
|
#include "packetLogger.h"
|
|
#include "aq_serial.h"
|
|
#include "serialadapter.h"
|
|
#include "rs_msg_utils.h"
|
|
|
|
#define IAQUA_QLEN 20
|
|
|
|
typedef struct iaqulnkcmd
|
|
{
|
|
unsigned char command[20];
|
|
int length;
|
|
} iaqualink_cmd;
|
|
|
|
iaqualink_cmd _iqaua_queue[IAQUA_QLEN];
|
|
unsigned char _std_cmd[2];
|
|
int _iaqua_q_length = 0;
|
|
bool _aqua_last_cmdfrom_queue = false;
|
|
|
|
|
|
unsigned char _cmd_readyCommand[] = {0x3f, 0x20};
|
|
unsigned char _fullcmd[] = {0x00, 0x24, 0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
|
|
bool push_iaqualink_cmd(unsigned char *cmd, int length) {
|
|
if (_iaqua_q_length >= IAQUA_QLEN ) {
|
|
LOG(IAQL_LOG,LOG_ERR, "Queue overflow, last command ignored!\n");
|
|
return false;
|
|
}
|
|
|
|
memcpy(_iqaua_queue[_iaqua_q_length].command, cmd, length);
|
|
_iqaua_queue[_iaqua_q_length].length = length;
|
|
_iaqua_q_length++;
|
|
|
|
LOG(IAQL_LOG, LOG_INFO, "Queue cmd, size %d, queu length=%d\n",length, _iaqua_q_length);
|
|
|
|
//LOG(IAQL_LOG,LOG_DEBUG, "Added to message queue, position %d 0x%02hhx|0x%02hhx|0x%02hhx|0x%02hhx\n",_rssa_q_length-1,_rssa_queue[_rssa_q_length-1][0],_rssa_queue[_rssa_q_length-1][1],_rssa_queue[_rssa_q_length-1][2],_rssa_queue[_rssa_q_length-1][3]);
|
|
return true;
|
|
|
|
}
|
|
|
|
//unsigned char *get_iaqualink_cmd(unsigned char source_message_type, unsigned char *dest_message, int *len) {
|
|
int get_iaqualink_cmd(unsigned char source_message_type, unsigned char **dest_message) {
|
|
|
|
//LOG(IAQL_LOG, LOG_INFO, "Caculating cmd\n");
|
|
|
|
_aqua_last_cmdfrom_queue = false;
|
|
|
|
_std_cmd[0] = source_message_type;
|
|
_std_cmd[1] = 0x00;
|
|
*dest_message = _std_cmd;
|
|
int len = 2;
|
|
|
|
if (source_message_type == 0x73 && _iaqua_q_length > 0)
|
|
{ // Send big/long message
|
|
if ( _iqaua_queue[0].length >= 19 ) {
|
|
*dest_message = _iqaua_queue[0].command;
|
|
len = _iqaua_queue[0].length;
|
|
_aqua_last_cmdfrom_queue = true;
|
|
} else {
|
|
LOG(IAQL_LOG,LOG_WARNING,"Next command in queue is not full command, ignoring\n");
|
|
}
|
|
}
|
|
else if (source_message_type == 0x53 && _iaqua_q_length > 0)
|
|
{ // Send small command
|
|
if ( _iqaua_queue[0].length <= 2 ) {
|
|
*dest_message = _iqaua_queue[0].command;
|
|
len = _iqaua_queue[0].length;
|
|
_aqua_last_cmdfrom_queue = true;
|
|
} else {
|
|
LOG(IAQL_LOG,LOG_WARNING,"Next command in queue is too large, ignoring\n");
|
|
LOG(IAQL_LOG,LOG_ERR,"Re sending get prepare frame\n");
|
|
*dest_message = _cmd_readyCommand;
|
|
}
|
|
}
|
|
|
|
//LOG(IAQL_LOG, LOG_INFO, "Return cmd size %d\n",len);
|
|
|
|
return len;
|
|
}
|
|
|
|
void remove_iaqualink_cmd() {
|
|
if (_iaqua_q_length > 0 && _aqua_last_cmdfrom_queue == true) {
|
|
LOG(IAQL_LOG,LOG_DEBUG, "Remove from message queue, length %d\n",_iaqua_q_length-1);
|
|
memmove(&_iqaua_queue[0], &_iqaua_queue[1], (sizeof(iaqualink_cmd)) * _iaqua_q_length);
|
|
_iaqua_q_length--;
|
|
}
|
|
}
|
|
|
|
|
|
unsigned char iAqalnkDevID(aqkey *button) {
|
|
|
|
// For the 3 actual vbuttons that exist, we have already set their codes so just return it with no conversion
|
|
if ( ((button->special_mask & VIRTUAL_BUTTON) == VIRTUAL_BUTTON) && button->rssd_code != NUL ) {
|
|
return button->rssd_code;
|
|
}
|
|
|
|
switch (button->rssd_code) {
|
|
case RS_SA_PUMP:
|
|
return IAQ_PUMP;
|
|
break;
|
|
case RS_SA_SPA:
|
|
return IAQ_SPA;
|
|
break;
|
|
case RS_SA_POOLHT:
|
|
return IAQ_POOL_HTR;
|
|
break;
|
|
case RS_SA_SPAHT:
|
|
return IAQ_SPA_HTR;
|
|
break;
|
|
case RS_SA_AUX1:
|
|
return IAQ_AUX1;
|
|
break;
|
|
case RS_SA_AUX2:
|
|
return IAQ_AUX2;
|
|
break;
|
|
case RS_SA_AUX3:
|
|
return IAQ_AUX3;
|
|
break;
|
|
case RS_SA_AUX4:
|
|
return IAQ_AUX4;
|
|
break;
|
|
case RS_SA_AUX5:
|
|
return IAQ_AUX5;
|
|
break;
|
|
case RS_SA_AUX6:
|
|
return IAQ_AUX6;
|
|
break;
|
|
case RS_SA_AUX7:
|
|
return IAQ_AUX7;
|
|
break;
|
|
case RS_SA_AUX8:
|
|
return IAQ_AUXB1;
|
|
break;
|
|
case RS_SA_AUX9:
|
|
return IAQ_AUXB2;
|
|
break;
|
|
case RS_SA_AUX10:
|
|
return IAQ_AUXB3;
|
|
break;
|
|
case RS_SA_AUX11:
|
|
return IAQ_AUXB4;
|
|
break;
|
|
case RS_SA_AUX12:
|
|
return IAQ_AUXB5;
|
|
break;
|
|
case RS_SA_AUX13:
|
|
return IAQ_AUXB6;
|
|
break;
|
|
case RS_SA_AUX14:
|
|
return IAQ_AUXB7;
|
|
break;
|
|
case RS_SA_AUX15:
|
|
return IAQ_AUXB8;
|
|
break;
|
|
}
|
|
|
|
return 0xFF;
|
|
}
|
|
|
|
void lastchecksum(unsigned char *packet, int length)
|
|
{
|
|
if (getLogLevel(IAQL_LOG) >= LOG_DEBUG)
|
|
{
|
|
static unsigned char last70checksum = 0x00;
|
|
static unsigned char last71checksum = 0x00;
|
|
static unsigned char last72checksum = 0x00;
|
|
|
|
switch (packet[PKT_CMD])
|
|
{
|
|
case 0x70:
|
|
if (last70checksum != packet[length - 3] && last70checksum != 0x00)
|
|
{
|
|
LOG(IAQL_LOG, LOG_INFO, "*****************************************\n");
|
|
LOG(IAQL_LOG, LOG_INFO, "******* CHECKSUM CHANGED for 0x70 *******\n");
|
|
LOG(IAQL_LOG, LOG_INFO, "*****************************************\n");
|
|
}
|
|
last70checksum = packet[length - 3];
|
|
break;
|
|
case 0x71:
|
|
if (last71checksum != packet[length - 3] && last71checksum != 0x00)
|
|
{
|
|
LOG(IAQL_LOG, LOG_INFO, "*****************************************\n");
|
|
LOG(IAQL_LOG, LOG_INFO, "******* CHECKSUM CHANGED for 0x71 *******\n");
|
|
LOG(IAQL_LOG, LOG_INFO, "*****************************************\n");
|
|
}
|
|
last71checksum = packet[length - 3];
|
|
break;
|
|
case 0x72:
|
|
if (last72checksum != packet[length - 3] && last72checksum != 0x00)
|
|
{
|
|
LOG(IAQL_LOG, LOG_INFO, "*****************************************\n");
|
|
LOG(IAQL_LOG, LOG_INFO, "******* CHECKSUM CHANGED for 0x72 *******\n");
|
|
LOG(IAQL_LOG, LOG_INFO, "*****************************************\n");
|
|
}
|
|
last72checksum = packet[length - 3];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
|
|
All taken from panel Yg, but only heater setpoints seem to work.
|
|
Only setpoints seem to work,
|
|
|
|
Can't get to work on T2 panel
|
|
RPM to 2750
|
|
Bit 6 = 0x5e
|
|
Bit 10 * 256 + Bit 11
|
|
Bit 7 or 9 probably pump index.
|
|
HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x5e|0x04|0x00|0x01|0x0a|0xbe|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xd5|0x10|0x03|
|
|
|
|
RPM to 2995
|
|
HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x5e|0x04|0x00|0x01|0x0b|0xb3|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xcb|0x10|0x03|
|
|
|
|
|
|
Can't get to work on T2 panel
|
|
SWG 50%
|
|
Byte 6 = 0x19
|
|
Byte 7 = 50%
|
|
Byte 9 & 10 ????
|
|
HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x19|0x32|0x00|0x18|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x0e|0x10|0x03|
|
|
|
|
SWG 51%
|
|
Byte 7 = 51%
|
|
HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x19|0x33|0x00|0x18|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x0f|0x10|0x03|
|
|
|
|
Works on T2
|
|
Spa Setpoint 102
|
|
Byte 6 = 0x06
|
|
Byte 8 = 0x66=102
|
|
HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x06|0x00|0x66|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x16|0x10|0x03|
|
|
|
|
Works on T2
|
|
Pool Setpoint 72
|
|
Byte 6 = 0x05
|
|
Byte 8 = 0x48=72
|
|
HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x05|0x00|0x48|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xf7|0x10|0x03|
|
|
|
|
*/
|
|
|
|
|
|
void set_iaqualink_aux_state(aqkey *button, bool isON) {
|
|
|
|
_fullcmd[4] = iAqalnkDevID(button);
|
|
|
|
if (_fullcmd[4] != 0xFF) {
|
|
push_iaqualink_cmd(_cmd_readyCommand, 2);
|
|
push_iaqualink_cmd(_fullcmd, 19);
|
|
} else {
|
|
LOG(IAQL_LOG, LOG_ERR, "Couldn't find iaqualink keycode for button %s\n",button->label);
|
|
}
|
|
|
|
// reset
|
|
_fullcmd[4] = 0x00;
|
|
}
|
|
|
|
void set_iaqualink_heater_setpoint(int value, bool isPool) {
|
|
|
|
|
|
if (isPool) {
|
|
_fullcmd[4] = 0x05;
|
|
} else {
|
|
_fullcmd[4] = 0x06;
|
|
}
|
|
|
|
// Should check value is valid here.
|
|
_fullcmd[6] = value;
|
|
|
|
push_iaqualink_cmd(_cmd_readyCommand, 2);
|
|
push_iaqualink_cmd(_fullcmd, 19);
|
|
|
|
// reset
|
|
_fullcmd[4] = 0x00;
|
|
_fullcmd[6] = 0x00;
|
|
}
|
|
|
|
void iAqSetButtonState(struct aqualinkdata *aq_data, int index, const unsigned char byte)
|
|
{
|
|
if ( aq_data->aqbuttons[index].led->state != OFF && byte == 0x00) {
|
|
aq_data->aqbuttons[index].led->state = OFF;
|
|
LOG(IAQL_LOG, LOG_INFO, "Set %s off\n",aq_data->aqbuttons[index].label);
|
|
} else if ( aq_data->aqbuttons[index].led->state != ON && byte == 0x01) {
|
|
aq_data->aqbuttons[index].led->state = ON;
|
|
LOG(IAQL_LOG, LOG_INFO, "Set %s on\n",aq_data->aqbuttons[index].label);
|
|
} else if ( aq_data->aqbuttons[index].led->state != ENABLE && byte == 0x03) {
|
|
aq_data->aqbuttons[index].led->state = ENABLE;
|
|
LOG(IAQL_LOG, LOG_INFO, "Set %s enabled\n",aq_data->aqbuttons[index].label);
|
|
}
|
|
}
|
|
|
|
/*
|
|
Status packets are requested on iAqualink ID 0xA? but received on AqualinkTouch ID 0x3?
|
|
They are also sent when iAqualink is connected and a device changes.
|
|
So good to catch in PDA mode when a physical iAqualink device is connected to PDA panel.
|
|
packet has cmd of 0x70, 0x71, 0x72
|
|
*/
|
|
bool process_iAqualinkStatusPacket(unsigned char *packet, int length, struct aqualinkdata *aq_data)
|
|
{
|
|
if (packet[PKT_CMD] == CMD_IAQ_MAIN_STATUS)
|
|
{
|
|
logPacket(IAQL_LOG, LOG_INFO, packet, length, true);
|
|
int startIndex = 4 + 1;
|
|
int numberBytes = packet[4];
|
|
int offsetIndex = startIndex + numberBytes;
|
|
bool foundSpaSP = false;
|
|
bool foundWaterTemp = false;
|
|
bool foundAirTemp = false;
|
|
|
|
for (int i = 0; i <= numberBytes; i++)
|
|
{
|
|
int byteType = packet[5 + i];
|
|
int byte = packet[offsetIndex + i];
|
|
char *label;
|
|
|
|
// Some panels have blanks for the last 3 buys, the first of which is "water temp" (not sure on others 0x20, 0x21)
|
|
// So if we saw 0x1d break loop if not force next as water temp.
|
|
if (foundWaterTemp && i == numberBytes)
|
|
{
|
|
break;
|
|
}
|
|
else if (i == numberBytes)
|
|
{
|
|
byteType = 0x1d;
|
|
}
|
|
|
|
if (byteType == 0) {
|
|
label = "Filter Pump ";
|
|
if (isPDA_PANEL) { iAqSetButtonState(aq_data, 0, byte); }
|
|
} else if (byteType == 1) {
|
|
label = "Pool Heater "; // 0x00 off 0x01=on&heating, 0x03=enabled
|
|
if (isPDA_PANEL) { iAqSetButtonState(aq_data, aq_data->pool_heater_index , byte); }
|
|
} else if (byteType == 2) {
|
|
label = "Spa ";
|
|
} else if (byteType == 3) {
|
|
label = "Spa Heater "; // 0x01=on&heating, 0x03=ena
|
|
if (isPDA_PANEL) { iAqSetButtonState(aq_data, aq_data->spa_heater_index , byte); }
|
|
} else if (byteType == 6) {
|
|
label = "Pool Htr setpoint";
|
|
} else if (byteType == 8 || byteType == 9) {// 8 usually, also get 9 & 14 (different spa/heater modes not sorted out yet. 14 sometimes blank as well)
|
|
label = "Spa Htr setpoint ";
|
|
foundSpaSP=true;
|
|
} else if ( (/*byteType == 14 ||*/ byteType == 12) && foundSpaSP==false && byte != 0) {
|
|
label = "Spa Htr setpoint ";
|
|
} else if ( (byteType == 14 || byteType == 15 || byteType == 26) && byte != 0 && byte != 255 && foundAirTemp == false ) {// 0x0f
|
|
label = "Air Temp "; // we also see this as 14 (RS16) ONLY
|
|
foundAirTemp = true;
|
|
} else if ( (byteType == 27 || byteType == 28 || byteType == 29) && byte != 0 && byte != 255 && foundWaterTemp == false) {
|
|
// Last 3 bytes don't have type on some panels
|
|
label = "Water Temp ";
|
|
foundWaterTemp = true;
|
|
}
|
|
else
|
|
label = " ";
|
|
|
|
LOG(IAQL_LOG, LOG_INFO, "%-17s = %3d | index=%d type=(%0.2d 0x%02hhx) value=0x%02hhx offset=%d\n", label, byte, i, byteType, byteType, byte, (offsetIndex + i));
|
|
}
|
|
LOG(IAQL_LOG, LOG_INFO, "Status from other protocols Pump %s, Spa %s, SWG %d, PumpRPM %d, PoolSP=%d, SpaSP=%d, WaterTemp=%d, AirTemp=%d\n",
|
|
aq_data->aqbuttons[0].led->state == OFF ? "Off" : "On ",
|
|
aq_data->aqbuttons[1].led->state == OFF ? "Off" : "On ",
|
|
aq_data->swg_percent,
|
|
aq_data->pumps[0].rpm,
|
|
aq_data->pool_htr_set_point,
|
|
aq_data->spa_htr_set_point,
|
|
(aq_data->aqbuttons[1].led->state == OFF ? aq_data->pool_temp : aq_data->spa_temp),
|
|
aq_data->air_temp);
|
|
}
|
|
else if (packet[PKT_CMD] == CMD_IAQ_1TOUCH_STATUS)
|
|
{
|
|
logPacket(IAQL_LOG, LOG_INFO, packet, length, true);
|
|
int numLabels = packet[4];
|
|
int start = numLabels + 4 + 1;
|
|
|
|
if (numLabels == 1)
|
|
{
|
|
// This just seem to list a ton of pump (names)
|
|
LOG(IAQL_LOG, LOG_INFO, "**** !!! haven't decoded above packet yet !!! *****\n");
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < numLabels; i++)
|
|
{
|
|
int status = packet[start];
|
|
int length = packet[start + 1];
|
|
int byteType = packet[5 + i];
|
|
LOG(IAQL_LOG, LOG_INFO, "%-15.*s = %s | index %d type=(%0.2d 0x%02hhx) status=0x%02hhx start=%d length=%d\n", length, &packet[start + 2], (status == 0x00 ? "Off" : "On "), i, byteType, byteType, status, start, length);
|
|
// Check against virtual onetouch buttons.
|
|
for (int bi=aq_data->virtual_button_start ; bi < aq_data->total_buttons ; bi++) {
|
|
if (rsm_strcmp((char *)&packet[start + 2], aq_data->aqbuttons[bi].label) == 0) {
|
|
//LOG(IAQL_LOG, LOG_INFO, "Status for %s is %s\n",aq_data->aqbuttons[bi].label,(status == 0x00 ? "Off" : "On "));
|
|
// == means doesn;t match, RS 1=on 0=off / LED enum 1=off 0=on
|
|
if (aq_data->aqbuttons[bi].led->state == status) {
|
|
LOG(IAQL_LOG, LOG_INFO, "Updated Status for %s is %s\n",aq_data->aqbuttons[bi].label,(status == 0x00 ? "Off" : "On "));
|
|
aq_data->aqbuttons[bi].led->state = (status == 0x00 ? OFF:ON);
|
|
aq_data->updated = true;
|
|
}
|
|
}
|
|
}
|
|
start = start + packet[start + 1] + 2;
|
|
}
|
|
}
|
|
else if (packet[PKT_CMD] == CMD_IAQ_AUX_STATUS)
|
|
{
|
|
logPacket(IAQL_LOG, LOG_INFO, packet, length, true);
|
|
// Look at notes in iaqualink.c for how this packet is made up
|
|
// Since this is so similar to above CMD_IAQ_1TOUCH_STATUS, we should look at using same logic for both.
|
|
int start = packet[4];
|
|
start = start + 5;
|
|
for (int i = start; i < length - 3; i = i)
|
|
{
|
|
int status = i;
|
|
int labelstart = status + 5;
|
|
int labellen = packet[status + 4];
|
|
if (labelstart + labellen < length)
|
|
{
|
|
LOG(IAQL_LOG, LOG_INFO, "%-15.*s = %s | bit1=0x%02hhx bit2=0x%02hhx bit3=0x%02hhx bit4=0x%02hhx\n", labellen, &packet[labelstart], (packet[status] == 0x00 ? "Off" : "On "), packet[status], packet[status + 1], packet[status + 2], packet[status + 3]);
|
|
}
|
|
if (isPDA_PANEL) {
|
|
for (int bi=2 ; bi < aq_data->total_buttons ; bi++) {
|
|
if (rsm_strcmp((char *)&packet[labelstart], aq_data->aqbuttons[bi].label) == 0) {
|
|
if (aq_data->aqbuttons[bi].led->state == packet[status]) {
|
|
LOG(IAQL_LOG, LOG_INFO, "Updated Status for %s is %s\n",aq_data->aqbuttons[bi].label,(packet[status] == 0x00 ? "Off" : "On "));
|
|
aq_data->aqbuttons[bi].led->state = (packet[status] == 0x00 ? OFF:ON);
|
|
aq_data->updated = true;
|
|
}
|
|
//LOG(IAQL_LOG, LOG_INFO, "Match %s to %.*s state(aqd=%d pnl=%d)\n",aq_data->aqbuttons[bi].label, labellen, (char *)&packet[labelstart], aq_data->aqbuttons[bi].led->state, packet[status]);
|
|
}
|
|
}
|
|
}
|
|
|
|
i = labelstart + labellen;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool process_iaqualink_packet(unsigned char *packet, int length, struct aqualinkdata *aq_data)
|
|
{
|
|
|
|
lastchecksum(packet, length);
|
|
|
|
unsigned char cmd_getMainstatus[] = {0x3f, 0x08};
|
|
unsigned char cmd_getTouchstatus[] = {0x3f, 0x10};
|
|
unsigned char cmd_getAuxstatus[] = {0x3f, 0x18};
|
|
//unsigned char cmd_readyCommand[] = {0x3f, 0x20};
|
|
//unsigned char fullcmd[] = {0x00, 0x24, 0x73, 0x01, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
// byte 4 is ID. 0x00 pump, 0x02 spa etc
|
|
|
|
|
|
if (packet[PKT_DEST] == _aqconfig_.extended_device_id2)
|
|
{
|
|
static int cnt = 0;
|
|
//static unsigned char ID = 0;
|
|
//static cur_swg = 0;
|
|
//static unsigned char sendid = 0x00;
|
|
|
|
if (packet[PKT_CMD] == 0x53)
|
|
{
|
|
cnt++;
|
|
if (cnt == 20) {
|
|
cnt=0;
|
|
/*
|
|
sendid=sendid==0x18?0x60:0x18;
|
|
_fullcmd[4] = sendid;
|
|
push_iaqualink_cmd(_cmd_readyCommand, 2);
|
|
push_iaqualink_cmd(_fullcmd, 19);
|
|
_fullcmd[4] = 0x00;
|
|
*/
|
|
push_iaqualink_cmd(cmd_getMainstatus, 2);
|
|
push_iaqualink_cmd(cmd_getTouchstatus, 2);
|
|
push_iaqualink_cmd(cmd_getAuxstatus, 2);
|
|
/*
|
|
LOG(IAQL_LOG, LOG_INFO,"*****************************************\n");
|
|
LOG(IAQL_LOG, LOG_INFO,"********** Send %d 0x%02hhx ************\n",ID,ID);
|
|
LOG(IAQL_LOG, LOG_INFO,"*****************************************\n");
|
|
|
|
_fullcmd[4] = ID++;
|
|
push_iaqualink_cmd(_cmd_readyCommand, 2);
|
|
push_iaqualink_cmd(_fullcmd, 19);
|
|
|
|
push_iaqualink_cmd(cmd_getMainstatus, 2);
|
|
push_iaqualink_cmd(cmd_getTouchstatus, 2);
|
|
push_iaqualink_cmd(cmd_getAuxstatus, 2);
|
|
|
|
push_iaqualink_cmd(_cmd_readyCommand, 2);
|
|
push_iaqualink_cmd(_fullcmd, 19);
|
|
*/
|
|
|
|
//fullcmd[4] = ID;
|
|
//fullcmd[4] = ID;
|
|
//fullcmd[5] = 0x32;
|
|
|
|
//fullcmd[7] = ID;
|
|
//fullcmd[8] = 0x01;
|
|
|
|
|
|
//set_iaqualink_heater_setpoint(50, true);
|
|
|
|
//push_iaqualink_cmd(cmd_getMainstatus, 2);
|
|
//push_iaqualink_cmd(cmd_getTouchstatus, 2);
|
|
//push_iaqualink_cmd(cmd_getAuxstatus, 2);
|
|
/*
|
|
if (aq_data->swg_percent != cur_swg && cur_swg != 0) {
|
|
LOG(IAQL_LOG, LOG_INFO,"*****************************************\n");
|
|
LOG(IAQL_LOG, LOG_INFO,"********** SWG Changed to %d ************\n",aq_data->swg_percent);
|
|
LOG(IAQL_LOG, LOG_INFO,"*****************************************\n");
|
|
exit(0);
|
|
}
|
|
cur_swg = aq_data->swg_percent;
|
|
LOG(IAQL_LOG, LOG_INFO,"******* QUEUE SWG Comand of %d | 0x%02hhx *************\n",ID,ID);
|
|
ID++;*/
|
|
|
|
}
|
|
}
|
|
// Packets sent to iAqualink protocol
|
|
// debuglogPacket(IAQL_LOG, packet, length, true, true);
|
|
}
|
|
else if (packet[PKT_DEST] == _aqconfig_.extended_device_id || (isPDA_PANEL && packet[PKT_DEST] == _aqconfig_.device_id) )
|
|
{
|
|
process_iAqualinkStatusPacket(packet, length, aq_data);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#ifdef DONOTCOMPILE
|
|
|
|
// This is onle here temporarly until we figure out the protocol.
|
|
void send_iaqualink_ack(int rs_fd, unsigned char *packet_buffer)
|
|
{
|
|
/*
|
|
Probe | HEX: 0x10|0x02|0xa3|0x00|0xb5|0x10|0x03|
|
|
Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x00|0x13|0x10|0x03|
|
|
Unknown '0x61' | HEX: 0x10|0x02|0xa3|0x61|0x00|0x00|0x00|0x04|0x00|0x27|0x41|0x10|0x03|
|
|
Ack | HEX: 0x10|0x02|0x00|0x01|0x61|0x00|0x74|0x10|0x03|
|
|
Unknown '0x50' | HEX: 0x10|0x02|0xa3|0x50|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x00|0x25|0x10|0x03|
|
|
Ack | HEX: 0x10|0x02|0x00|0x01|0x50|0x00|0x63|0x10|0x03|
|
|
Unknown '0x51' | HEX: 0x10|0x02|0xa3|0x51|0x00|0x06|0x10|0x03|
|
|
Ack | HEX: 0x10|0x02|0x00|0x01|0x51|0x00|0x64|0x10|0x03|
|
|
Unknown '0x59' | HEX: 0x10|0x02|0xa3|0x59|0x00|0x0e|0x10|0x03|
|
|
Ack | HEX: 0x10|0x02|0x00|0x01|0x59|0x00|0x6c|0x10|0x03|
|
|
Unknown '0x52' | HEX: 0x10|0x02|0xa3|0x52|0x00|0x07|0x10|0x03|
|
|
Ack | HEX: 0x10|0x02|0x00|0x01|0x52|0x00|0x65|0x10|0x03|
|
|
Unknown '0x53' | HEX: 0x10|0x02|0xa3|0x53|0x08|0x10|0x03|
|
|
Ack | HEX: 0x10|0x02|0x00|0x01|0x3f|0x00|0x52|0x10|0x03|
|
|
Use byte 3 as return ack, except for 0x53=0x3f
|
|
*/
|
|
if (packet_buffer[PKT_CMD] == CMD_PROBE)
|
|
{
|
|
LOG(IAQL_LOG, LOG_INFO, "Got probe on '0x%02hhx' 2nd iAqualink Protocol\n", packet_buffer[PKT_DEST]);
|
|
send_extended_ack(rs_fd, packet_buffer[PKT_CMD], 0x00);
|
|
}
|
|
else if (packet_buffer[PKT_CMD] == 0x53)
|
|
{
|
|
static int cnt = 0;
|
|
cnt++;
|
|
if (cnt == 10)
|
|
{
|
|
//cnt = 5;
|
|
LOG(IAQL_LOG, LOG_INFO, "Sent accept next packet Comand\n");
|
|
send_extended_ack(rs_fd, 0x3f, 0x20);
|
|
}
|
|
if (cnt == 20)
|
|
{
|
|
LOG(IAQL_LOG, LOG_INFO, "Sending get status\n");
|
|
send_extended_ack(rs_fd, 0x3f, 0x08);
|
|
}
|
|
else if (cnt == 22)
|
|
{
|
|
LOG(IAQL_LOG, LOG_INFO, "Sending get other status\n");
|
|
send_extended_ack(rs_fd, 0x3f, 0x10);
|
|
}
|
|
else if (cnt == 24)
|
|
{
|
|
LOG(IAQL_LOG, LOG_INFO, "Sending get aux button status\n");
|
|
send_extended_ack(rs_fd, 0x3f, 0x18);
|
|
}
|
|
else
|
|
{
|
|
// Use 0x3f
|
|
if (cnt > 24)
|
|
{
|
|
cnt = 0;
|
|
}
|
|
send_extended_ack(rs_fd, 0x3f, 0x00);
|
|
}
|
|
// send_jandy_command(rs_fd, get_rssa_cmd(packet_buffer[PKT_CMD]), 4);
|
|
}
|
|
else if (packet_buffer[PKT_CMD] == 0x73)
|
|
{
|
|
static int id = 10;
|
|
// unsigned char pb1[] = {PCOL_JANDY,0x10,0x02,0x00,0x24,0x73,0x01,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0x10,0x03,0x00};
|
|
// unsigned char pb2[] = {PCOL_JANDY,0x10,0x02,0x00,0x24,0x73,0x01,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x10,0x03,0x00};
|
|
// 0x21 turns on filter_pump and aux 1
|
|
//unsigned char pb3[] = {0x00, 0x24, 0x73, 0x01, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
unsigned char swg[] = {0x00, 0x24, 0x73, 0x01, 0x19, 0x32, 0x00, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
//unsigned char swg[] = {0x00, 0x24, 0x73, 0x01, 0x19, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
unsigned char rpm[] = {0x00,0x24,0x73,0x01,0x5e,0x04,0x00,0x01,0x0a,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd5,0x10,0x03};
|
|
//pb3[4] = id++;
|
|
//swg[5] = ++id;
|
|
|
|
LOG(IAQL_LOG, LOG_INFO, "*** Sending SWG dec=%d hex=0x%02hhx\n", swg[5], swg[5]);
|
|
// send_packet(rs_fd, pb2, 25);
|
|
send_jandy_command(rs_fd, swg, 19);
|
|
}
|
|
else
|
|
{
|
|
// Use packet_buffer[PKT_CMD]
|
|
send_extended_ack(rs_fd, packet_buffer[PKT_CMD], 0x00);
|
|
}
|
|
}
|
|
#endif
|
|
|