Skip to content

Commit

Permalink
2.5.0 (Dev 0.2)
Browse files Browse the repository at this point in the history
  • Loading branch information
sfeakes committed Oct 20, 2024
1 parent c1675b9 commit 6bba146
Show file tree
Hide file tree
Showing 24 changed files with 338 additions and 114 deletions.
22 changes: 10 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ Designed to mimic AqualinkRS devices, used to fully configure the master control
* http://aqualink.ip/aquapda_sim.html <- (PDA simulator)
#<a name="release"></a>
# ToDo (future release)
* Allow selecting of pre-defined VSP programs (Aqualink Touch & OneTouch protocols.)
* Add set time to OneTouch protocol.
* Update AqualinkD Management console to manage configuration
* Create iAqualink Touch Simulator
* Probably decoded enough protocols for AuqlinkD to self configure.
Expand All @@ -100,12 +98,6 @@ Designed to mimic AqualinkRS devices, used to fully configure the master control
* Panel version
* can't use iaquatouch panel / wireless
* Added iAqualinkTouch support for PDA only panels that can use that protocol.
* PDA panel needs to be Rev 6.0 or newer.
* This makes the PDA only panels quicker and less error prone.
* Introduces color light support and VSP
* Consider this PDA support Beta.
* Read PDA Wiki
-->

# Call for Help.
Expand All @@ -115,21 +107,25 @@ Designed to mimic AqualinkRS devices, used to fully configure the master control
<!--
NEED TO FIX FOR THIS RELEASE.
***** FIX NET_SERVICES.C action_uri() spa and spa_mode get confused. check EVERY strncmp
* MQTT filter_pump/percent/set, maybe add max/min to pump config. / print protocol on startup
* Pump by name and not ID. clean up code
* DONE MQTT filter_pump/percent/set, maybe add max/min to pump config. / print protocol on startup
* DONE Pump by name and not ID. clean up code
* DONE look at using 0x00 for no exit on serial errors / startup
* DONE look at virtual button support
* vbuton will need the PDA on iAQT protocol working.
* change dimmer to % from steps. (will make HASIO & Homekit easier)
* DONE change dimmer to % from steps. (will make HASIO & Homekit easier)
* add config for homekit_f (panel in F homekin in C), F to F or C to C is fine.
* deprecate (hide and default to yes) extended_device_id_programming
* Move following to main and not config.c - show error is vbutton and no extended_device_id, vbutton w/ pump can be onetouch.
* check panel version reported against config.
# Updates in 2.4.1
# install.sh change spa_mode to spa in config.js
# DONE install.sh change spa_mode to spa in config.js
# DONE change hassio.c to use rpm speed/percent
# pickup speed faster on iaqualinktouch after change
* with iaqualink2 no need to poll iaqtouch devices as frequently
* update documentation on how vbutton / vpump / pump_max & min / enable_iauqalink2
* check rs serial adapter is active if light color mode 11 is used.
-->

# Updates in 2.5.0 (under development)
Expand All @@ -146,6 +142,8 @@ NEED TO FIX FOR THIS RELEASE.
* Allow VSP to be asigned to virtual button.
* Fixed bug with timer not starting.
* Increase Speed of detecting device state changes.
* Added iAqualink2 protocol support.
* Faster OneTouch device support

# Updates in Release 2.4.0
* <b>WARNING</b> Breaking change if you use dimmer (please change button_??_lightMode from 6 to 10)
Expand Down
Binary file modified release/aqualinkd-amd64
Binary file not shown.
Binary file modified release/aqualinkd-arm64
Binary file not shown.
Binary file modified release/aqualinkd-armhf
Binary file not shown.
Binary file modified release/serial_logger-amd64
Binary file not shown.
Binary file modified release/serial_logger-arm64
Binary file not shown.
Binary file modified release/serial_logger-armhf
Binary file not shown.
48 changes: 42 additions & 6 deletions source/aq_panel.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,10 @@ aqkey *addVirtualButton(struct aqualinkdata *aqdata, char *label, int vindex) {
//aqdata->aqbuttons[index].dz_idx = DZ_NULL_IDX;
//aqdata->aqbuttons[index].special_mask = 0;

aqled *led = malloc(sizeof(aqled));
button->led = led;
//aqled *led = malloc(sizeof(aqled));
//button->led = led;

button->led = malloc(sizeof(aqled));

char *name = malloc(sizeof(char*) * 10);
snprintf(name, 9, "%s%d", BTN_VAUX, vindex);
Expand All @@ -362,6 +364,8 @@ aqkey *addVirtualButton(struct aqualinkdata *aqdata, char *label, int vindex) {
button->rssd_code = IAQ_SPA_MODE;
} else if (strncasecmp (button->label, "Clean Mode", 10) == 0) {
button->rssd_code = IAQ_CLEAN_MODE;
} else if (strncasecmp (button->label, "Day Party", 9) == 0) {
button->rssd_code = IAQ_ONETOUCH_4;
} else {
button->rssd_code = NUL;
}
Expand Down Expand Up @@ -810,17 +814,27 @@ bool setDeviceState(struct aqualinkdata *aqdata, int deviceIndex, bool isON, req
}
} else if (isVBUTTON(button->special_mask)) {
// Virtual buttons only supported with Aqualink Touch
LOG(PANL_LOG, LOG_NOTICE, "********** %s code=0x%02hhx iaq enabled=%s *****\n",button->name, button->rssd_code, isIAQT_ENABLED?"Yes":"No");
LOG(PANL_LOG, LOG_INFO, "Set state for Vitrual Button %s code=0x%02hhx iAqualink2 enabled=%sn",button->name, button->rssd_code, isIAQT_ENABLED?"Yes":"No");
if (isIAQT_ENABLED) {
// If it's one of the pre-defined onces & iaqualink is enabled, we can set it easile with button.
if ( isIAQL_ACTIVE && button->rssd_code != NUL)

if ( isIAQL_ACTIVE && button->rssd_code && button->rssd_code != NUL)
{
//LOG(PANL_LOG, LOG_NOTICE, "********** USE iaqualink2 ********\n");
set_iaqualink_aux_state(button, isON);
} else {
char msg[PTHREAD_ARG];
sprintf(msg, "%-5d%-5d", deviceIndex, (isON == false ? OFF : ON));
aq_programmer(AQ_SET_IAQTOUCH_DEVICE_ON_OFF, msg, aqdata);
}
//if (button->rssd_code != VBUTTON_RSSD) {
//LOG(PANL_LOG, LOG_NOTICE, "********** USE AQ_SET_IAQTOUCH_DEVICE_ON_OFF ********\n");
aq_programmer(AQ_SET_IAQTOUCH_DEVICE_ON_OFF, msg, aqdata);
//} else if (button->rssd_code != VBUTTON_ONETOUCH_RSSD) {
// LOG(PANL_LOG, LOG_NOTICE, "********** USE AQ_SET_IAQTOUCH_ONETOUCH_ON_OFF ********\n");
// aq_programmer(AQ_SET_IAQTOUCH_ONETOUCH_ON_OFF, msg, aqdata);
//} else {
// LOG(PANL_LOG, LOG_ERR, "Configuration! do not understand code for Virtual Buttons");
//}
}
} else {
LOG(PANL_LOG, LOG_ERR, "Can only use Aqualink Touch protocol for Virtual Buttons");
}
Expand Down Expand Up @@ -965,6 +979,25 @@ void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int button)
_aqconfig_.light_programming_initial_off,
_aqconfig_.light_programming_mode );
aq_programmer(AQ_SET_LIGHTPROGRAM_MODE, buf, aqdata);
} else if (isRSSA_ENABLED) {
// If we are using rs-serial then turn light on first.
if (light->button->led->state != ON) {
set_aqualink_rssadapter_aux_extended_state(light->button, RS_SA_ON);
}
if (light->lightType == LC_DIMMER) {
// Value 1 = 25, 2 = 50, 3 = 75, 4 = 100 (need to convert value into binary)
if (value >= 1 && value <= 4) {
unsigned char rssd_value = value * 25;
set_aqualink_rssadapter_aux_extended_state(light->button, rssd_value);
} else {
LOG(PANL_LOG,LOG_ERR, "Light mode %d is not valid for '%s'\n",value, light->button->label);
set_aqualink_rssadapter_aux_extended_state(light->button, 100);
}
} else {
// Dimmer or any color light can simply be set with value
set_aqualink_rssadapter_aux_extended_state(light->button, value);
}
/*
} else if (isRSSA_ENABLED && light->lightType == LC_DIMMER2) {
// Dimmer needs to be turned on before you set dimmer level
if (light->button->led->state != ON) {
Expand All @@ -984,6 +1017,9 @@ void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int button)
} else {
LOG(PANL_LOG,LOG_ERR, "Light mode %d is not valid for '%s'\n",value, light->button->label);
}
} else if (isRSSA_ENABLED && light->lightType != LC_PROGRAMABLE) {
// Any programmable COLOR light (that's programmed by panel)
set_aqualink_rssadapter_aux_extended_state(light->button, value);*/
} else {
//sprintf(buf, "%-5s%-5d%-5d",value, button, light->lightType);
sprintf(buf, "%-5d%-5d%-5d",value, button, light->lightType);
Expand Down
3 changes: 3 additions & 0 deletions source/aq_panel.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#define SPA_HEAT_INDEX 10
*/

//#define VBUTTON_ONETOUCH_RSSD 0xFF
//#define VBUTTON_RSSD 0xFE

// Defined as int16_t so 16 bits to mask
#define RSP_4 (1 << 0) // 1
#define RSP_6 (1 << 1) // 16
Expand Down
5 changes: 5 additions & 0 deletions source/aq_programmer.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ const func_ptr _prog_functions[AQP_RSSADAPTER_MAX] = {
[AQ_SET_IAQTOUCH_PUMP_VS_PROGRAM] = set_aqualink_iaqtouch_pump_vs_program,
[AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE] = set_aqualink_iaqtouch_light_colormode,
[AQ_SET_IAQTOUCH_DEVICE_ON_OFF] = set_aqualink_iaqtouch_device_on_off,
[AQ_SET_IAQTOUCH_ONETOUCH_ON_OFF] = set_aqualink_iaqtouch_onetouch_on_off,
[AQ_PDA_INIT] = set_aqualink_PDA_init,
[AQ_PDA_WAKE_INIT] = set_aqualink_PDA_wakeinit,
[AQ_PDA_DEVICE_STATUS] = get_aqualink_PDA_device_status,
Expand Down Expand Up @@ -867,6 +868,9 @@ const char *ptypeName(program_type type)
case AQ_SET_IAQTOUCH_DEVICE_ON_OFF:
return "Set AqualinkTouch Device On/Off";
break;
case AQ_SET_IAQTOUCH_ONETOUCH_ON_OFF:
return "Set AqualinkTouch OneTouch On/Off";
break;
case AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE:
return "Set AqualinkTouch Light Color (using panel)";
break;
Expand Down Expand Up @@ -1006,6 +1010,7 @@ const char *programtypeDisplayName(program_type type)
return "Get Pump Assignment";
break;
case AQ_SET_IAQTOUCH_DEVICE_ON_OFF:
case AQ_SET_IAQTOUCH_ONETOUCH_ON_OFF:
return "Programming: setting device on/off";
break;
#ifdef AQ_PDA
Expand Down
1 change: 1 addition & 0 deletions source/aq_programmer.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ typedef enum {
AQ_SET_IAQTOUCH_SWG_BOOST,
AQ_SET_IAQTOUCH_SET_TIME,
AQ_SET_IAQTOUCH_DEVICE_ON_OFF,
AQ_SET_IAQTOUCH_ONETOUCH_ON_OFF,
AQ_SET_IAQTOUCH_POOL_HEATER_TEMP,
AQ_SET_IAQTOUCH_SPA_HEATER_TEMP,
AQ_SET_IAQLINK_POOL_HEATER_TEMP, // Same as above but using iAqualink not AqualinkTouch
Expand Down
27 changes: 12 additions & 15 deletions source/aqualinkd.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ int startup(char *self, char *cfgFile)
LOG(AQUA_LOG,LOG_NOTICE, "Config rssa_device_id = 0x%02hhx\n", _aqconfig_.rssa_device_id);
#if defined AQ_ONETOUCH || defined AQ_IAQTOUCH
LOG(AQUA_LOG,LOG_NOTICE, "Config extra_device_id = 0x%02hhx\n", _aqconfig_.extended_device_id);
if (_aqconfig_.enable_iaqualink) {
if (_aqconfig_.extended_device_id >= JANDY_DEV_AQLNK_MIN && _aqconfig_.extended_device_id <= JANDY_DEV_AQLNK_MAX) {
LOG(AQUA_LOG,LOG_NOTICE, "Config enable_iaqualink = %s\n", bool2text(_aqconfig_.enable_iaqualink));
}
LOG(AQUA_LOG,LOG_NOTICE, "Config extra_device_prog = %s\n", bool2text(_aqconfig_.extended_device_id_programming));
Expand Down Expand Up @@ -697,21 +697,18 @@ int startup(char *self, char *cfgFile)
sprintf(ext,"Light Progm | CTYPE %-1d |",_aqualink_data.lights[j].lightType);
}
}
if (_aqualink_data.aqbuttons[i].dz_idx > 0)
if (isVBUTTON(_aqualink_data.aqbuttons[i].special_mask)) {
if (_aqualink_data.aqbuttons[i].rssd_code != NUL) {
sprintf(ext,"OneTouch %d |",_aqualink_data.aqbuttons[i].rssd_code - 15);
}
}
if (_aqualink_data.aqbuttons[i].dz_idx > 0) {
sprintf(ext+strlen(ext), "dzidx %-3d", _aqualink_data.aqbuttons[i].dz_idx);
/*
#ifdef AQ_PDA
if (isPDA_PANEL) {
LOG(AQUA_LOG,LOG_NOTICE, "Config BTN %-13s = label %-15s | PDAlabel %-15s | %s\n",
_aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label,
_aqualink_data.aqbuttons[i].pda_label, ext);
} else
#endif
*/
{
LOG(AQUA_LOG,LOG_NOTICE, "Config BTN %-13s = label %-15s | %s\n",
_aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label, ext);
}

LOG(AQUA_LOG,LOG_NOTICE, "Config BTN %-13s = label %-15s | %s\n",
_aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label, ext);


if ( ((_aqualink_data.aqbuttons[i].special_mask & VIRTUAL_BUTTON) == VIRTUAL_BUTTON) &&
((_aqualink_data.aqbuttons[i].special_mask & VS_PUMP ) != VS_PUMP) &&
Expand Down Expand Up @@ -1177,7 +1174,7 @@ void main_loop()
//printf("rs_fd =% d\n",rs_fd);
if (rs_fd < 0)
{
// sleep(1);
sleep(1);
sprintf(_aqualink_data.last_display_message, CONNECTION_ERROR);
LOG(AQUA_LOG,LOG_ERR, "Aqualink daemon waiting to connect to master device...\n");
_aqualink_data.updated = true;
Expand Down
88 changes: 73 additions & 15 deletions source/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "aq_serial.h"
#include "aq_panel.h"
#include "aqualink.h"
#include "iaqualink.h"

#define MAXCFGLINE 256

Expand All @@ -49,6 +50,7 @@ char *generate_mqtt_id(char *buf, int len);
pump_detail *getpump(struct aqualinkdata *aqdata, int button);
bool populatePumpData(struct aqualinkdata *aqdata, char *pumpcfg ,aqkey *button, char *value);
pump_detail *getPumpFromButtonID(struct aqualinkdata *aqdata, aqkey *button);
aqkey *getVirtualButton(struct aqualinkdata *aqdata, int num);

struct tmpPanelInfo {
int size;
Expand Down Expand Up @@ -415,6 +417,10 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
rtn=true;
} else if (strncasecmp(param, "extended_device_id", 18) == 0) {
_aqconfig_.extended_device_id = strtoul(cleanalloc(value), NULL, 16);
// Enable enable_iaqualink by default and let people turn it off
//if (_aqconfig_.extended_device_id >= JANDY_DEV_AQLNK_MIN && _aqconfig_.extended_device_id <= JANDY_DEV_AQLNK_MAX) {
// _aqconfig_.enable_iaqualink = true;
//}
rtn=true;
} else if (strncasecmp(param, "enable_iaqualink", 16) == 0) {
_aqconfig_.enable_iaqualink = text2bool(value);
Expand Down Expand Up @@ -701,7 +707,11 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
aqdata->lights[aqdata->num_lights].lightType = type;
aqdata->aqbuttons[num].special_mask |= PROGRAM_LIGHT;
aqdata->aqbuttons[num].special_mask_ptr = &aqdata->lights[aqdata->num_lights];

if ( aqdata->lights[aqdata->num_lights].lightType == LC_DIMMER2 && _aqconfig_.rssa_device_id != 0x48 ) {
LOG(AQUA_LOG,LOG_ERR, "Config error, button '%s' has light mode '%d' set. This only supported when 'rssa_device_id' is enabled, changing to light mode '%d'\n",
aqdata->aqbuttons[num].label, LC_DIMMER2,LC_DIMMER);
aqdata->lights[aqdata->num_lights].lightType = LC_DIMMER;
}
aqdata->num_lights++;
}
} else {
Expand Down Expand Up @@ -731,26 +741,56 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
aqkey *button = addVirtualButton(aqdata, label, num);
if (button != NULL) {
button->special_mask |= VIRTUAL_BUTTON;
button->led->state = OFF;
} else {
LOG(AQUA_LOG,LOG_WARNING, "Error with '%s', total buttons=%d, config has %d already, ignoring!\n",param, TOTAL_BUTTONS, aqdata->total_buttons+1);
}
} else if (strncasecmp(param + 17, "_pump", 5) == 0) {
char *vbname = malloc(sizeof(char*) * 10);
snprintf(vbname, 9, "%s%d", BTN_VAUX, num);
aqkey *vbutton = NULL;
for (int i = aqdata->virtual_button_start; i < aqdata->total_buttons; i++) {
//printf("Checking %s agasinsdt %s\n",aqdata->aqbuttons[i].name, vbname);
if ( strcmp( aqdata->aqbuttons[i].name, vbname) == 0 ) {
vbutton = &aqdata->aqbuttons[i];
vbutton->led->state = ON; //Virtual pump is always on
if ( ! populatePumpData(aqdata, param + 18, vbutton, value) )
{
LOG(AQUA_LOG,LOG_ERR, "Config error, VSP Pumps limited to %d, ignoring : %s",MAX_PUMPS,param);
}
break;
aqkey *vbutton = getVirtualButton(aqdata, num);
if (vbutton != NULL) {
vbutton->led->state = ON; //Virtual pump default to on
if ( ! populatePumpData(aqdata, param + 18, vbutton, value) )
{
LOG(AQUA_LOG,LOG_ERR, "Config error, VSP Pumps limited to %d, ignoring : %s",MAX_PUMPS,param);
}
} else {
LOG(AQUA_LOG,LOG_ERR, "Config error, could not find vitrual button for `%s`",param);
}
if (vbutton == NULL) {
} else if (strncasecmp(param + 17, "_onetouchID", 11) == 0) {
aqkey *vbutton = getVirtualButton(aqdata, num);
if (vbutton != NULL) {
switch (strtoul(value, NULL, 10)) {
case 1:
vbutton->code = IAQ_ONETOUCH_1;
vbutton->rssd_code = IAQ_ONETOUCH_1;
break;
case 2:
vbutton->code = IAQ_ONETOUCH_2;
vbutton->rssd_code = IAQ_ONETOUCH_2;
break;
case 3:
vbutton->code = IAQ_ONETOUCH_3;
vbutton->rssd_code = IAQ_ONETOUCH_3;
break;
case 4:
vbutton->code = IAQ_ONETOUCH_4;
vbutton->rssd_code = IAQ_ONETOUCH_4;
break;
case 5:
vbutton->code = IAQ_ONETOUCH_5;
vbutton->rssd_code = IAQ_ONETOUCH_5;
break;
case 6:
vbutton->code = IAQ_ONETOUCH_5;
vbutton->rssd_code = IAQ_ONETOUCH_5;
break;
default:
vbutton->code = NUL;
vbutton->rssd_code = NUL;
break;
}

} else {
LOG(AQUA_LOG,LOG_ERR, "Config error, could not find vitrual button for `%s`",param);
}
}
Expand All @@ -760,6 +800,24 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
return rtn;
}

aqkey *getVirtualButton(struct aqualinkdata *aqdata, int num)
{
aqkey *vbutton = NULL;
char vbname[10];
snprintf(vbname, 9, "%s%d", BTN_VAUX, num);

for (int i = aqdata->virtual_button_start; i < aqdata->total_buttons; i++)
{
// printf("Checking %s agasinsdt %s\n",aqdata->aqbuttons[i].name, vbname);
if (strcmp(aqdata->aqbuttons[i].name, vbname) == 0)
{
vbutton = &aqdata->aqbuttons[i];
break;
}
}
return vbutton;
}

// pumpcfg is pointer to pumpIndex, pumpName, pumpType pumpID, (ie pull off button_??_ or vurtual_button_??_)
bool populatePumpData(struct aqualinkdata *aqdata, char *pumpcfg ,aqkey *button, char *value)
{
Expand Down
Loading

0 comments on commit 6bba146

Please sign in to comment.