Skip to content

Commit

Permalink
Version 2.4.1
Browse files Browse the repository at this point in the history
  • Loading branch information
sfeakes committed Sep 13, 2024
1 parent 2d717fb commit e3dc3db
Show file tree
Hide file tree
Showing 31 changed files with 356 additions and 94 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ ifeq ($(AQ_ONETOUCH), true)
endif

ifeq ($(AQ_IAQTOUCH), true)
SRCS := $(SRCS) iaqtouch.c iaqtouch_aq_programmer.c
SRCS := $(SRCS) iaqtouch.c iaqtouch_aq_programmer.c iaqualink.c
AQ_FLAGS := $(AQ_FLAGS) -D AQ_IAQTOUCH
endif

Expand Down
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,22 +114,33 @@ 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
* look at using 0x00 for no exit on serial errors / startup
* 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)
* add config for homekit_f (panel in F homekin in C), F to F or C to C is fine.
* deprecate extended_device_id_programming
* show error is vbutton and no extended_device_id
# Updates in 2.3.9
* 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 change hassio.c to use rpm speed/percent
# pickup speed faster on iaqualinktouch after change
-->

# Updates in 2.4.1 (under development)
* PDA panel Rev 6.0 or newer that do not have a Jandy iAqualink device attached can use the AqualinkTouch protocol rather than PDA protocol.
* This is faster, more reliable and does not intefear with the physical PDA device (like existing implimentation)
* Please consider this very much BETA at the moment.
* use `device_id=0x33` in aqualinkd.conf
* Added MQTT vsp_pump/speed/set for setting speed (RPM/GPM) by %, for automation hubs.
* cleaned up code for spa_mode and spa for newer pannels.
* Allow VSP to be asigned to virtual button.
* Fixed bug with timer not starting.

# 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.
4 changes: 2 additions & 2 deletions release/aqualinkd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ use_panel_aux_labels=no
# Below are settings for standard buttons on RS-8 Combo panel used as example.
button_01_label=Filter Pump

button_02_label=Spa Mode
button_02_label=Spa

button_03_label=Cleaner

Expand Down Expand Up @@ -305,4 +305,4 @@ button_12_label=Solar Heater
#virtual_button_02_label=Clean Mode
#virtual_button_03_label = OneTouch 4
#virtual_button_04_label = OneTouch 5
#virtual_button_05_label = OneTouch 6
#virtual_button_05_label = OneTouch 6
4 changes: 2 additions & 2 deletions release/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ fi
# V2.3.9 has kind-a breaking change for config.js, so check existing and rename if needed
# we added Aux_V? to the button list
if [ -f "$WEBLocation/config.js" ]; then
# Test is if has AUX_V1 in file
if ! grep -q Aux_V1 $WEBLocation/config.js; then
# Test is if has AUX_V1 in file AND "Spa" is in file (Spa_mode changed to Spa)
if ! grep -q 'Aux_V1' $WEBLocation/$file || ! grep -q '"Spa"' $WEBLocation/$file; then
dateext=`date +%Y%m%d_%H_%M_%S`
echo "AqualinkD web config is old, making copy to $WEBLocation/config.js.$dateext"
echo "Please make changes to new version $WEBLocation/config.js"
Expand Down
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.
1 change: 1 addition & 0 deletions source/aq_mqtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#define PUMP_MODE_TOPIC "/Mode"
#define PUMP_STATUS_TOPIC "/Status"
#define PUMP_PPC_TOPIC "/PPC"
#define PUMP_SPEED_TOPIC "/Speed"

#define LIGHT_PROGRAM_TOPIC "/program"
/*
Expand Down
33 changes: 33 additions & 0 deletions source/aq_panel.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,32 @@ aqkey *addVirtualButton(struct aqualinkdata *aqdata, char *label, int vindex) {
return button;
}

// So the 0-100% should be 600-3450 RPM and 15-130 GPM (ie 1% would = 600 & 0%=off)
// (value-600) / (3450-600) * 100
// (value) / 100 * (3450-600) + 600

//{{ (((value | float(0) - %d) / %d) * 100) | int }} - minspeed, (maxspeed - minspeed),
//{{ ((value | float(0) / 100) * %d) + %d | int }} - (maxspeed - minspeed), minspeed)

int getPumpSpeedAsPercent(pump_detail *pump) {
int pValue = pump->pumpType==VFPUMP?pump->gpm:pump->rpm;

if (pValue < pump->minSpeed) {
return 0;
}

// Below will return 0% if pump is at min, so return max (caculation, 1)
return AQ_MAX( (int)((float)(pValue - pump->minSpeed) / (float)(pump->maxSpeed - pump->minSpeed) * 100) + 0.5, 1);
}

int convertPumpPercentToSpeed(pump_detail *pump, int pValue) {
if (pValue >= 100)
return pump->maxSpeed;
else if (pValue <= 0)
return pump->minSpeed;

return ( ((float)(pValue / (float)100) * (pump->maxSpeed - pump->minSpeed) + pump->minSpeed)) + 0.5;
}

// 4,6,8,10,12,14
void initPanelButtons(struct aqualinkdata *aqdata, bool rs, int size, bool combo, bool dual) {
Expand Down Expand Up @@ -717,6 +743,13 @@ bool setDeviceState(struct aqualinkdata *aqdata, int deviceIndex, bool isON, req
{
aqkey *button = &aqdata->aqbuttons[deviceIndex];

if (button->special_mask & VIRTUAL_BUTTON && button->special_mask & VS_PUMP) {
// Virtual Button with VSP is always on.
LOG(PANL_LOG, LOG_INFO, "received '%s' for '%s', virtual pump is always on, ignoring", (isON == false ? "OFF" : "ON"), button->name);
button->led->state = ON;
return false;
}

if ((button->led->state == OFF && isON == false) ||
(isON > 0 && (button->led->state == ON || button->led->state == FLASH ||
button->led->state == ENABLE))) {
Expand Down
3 changes: 3 additions & 0 deletions source/aq_panel.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ void addPanelIAQTouchInterface();
void addPanelRSserialAdapterInterface();
void changePanelToExtendedIDProgramming();

int getPumpSpeedAsPercent(pump_detail *pump);
int convertPumpPercentToSpeed(pump_detail *pump, int value); // This is probable only needed internally

uint16_t getPanelSupport( char *rev_string, int rev_len);

aqkey *addVirtualButton(struct aqualinkdata *aqdata, char *label, int vindex);
Expand Down
1 change: 1 addition & 0 deletions source/aq_programmer.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ typedef enum emulation_type{
ONETOUCH,
IAQTOUCH,
AQUAPDA, // AQUAPALM and PDA are taken as specific type.
IAQUALNK, // iAqualink (wifi extra ID)
JANDY_DEVICE, // Very rarley used.
SIMULATOR
} emulation_type;
Expand Down
6 changes: 6 additions & 0 deletions source/aq_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ emulation_type getJandyDeviceType(unsigned char ID) {
return AQUAPDA;
if (ID >= 0x30 && ID <= 0x33)
return IAQTOUCH;
if (ID >= 0xa0 && ID <= 0xa3)
return IAQUALNK;

/*
if (ID >= 0x00 && ID <= 0x03)
Expand Down Expand Up @@ -286,6 +288,10 @@ const char* get_jandy_packet_type(unsigned char* packet , int length)
return "LXi status";
break;

case 0x53:
return "iAqalnk Poll";
break;

default:
sprintf(buf, "Unknown '0x%02hhx'", packet[PKT_CMD]);
return buf;
Expand Down
2 changes: 1 addition & 1 deletion source/aq_serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ DEV_UNKNOWN_MASK = 0xF8; // Unknown mask, used to reset values
#endif

#define BTN_PUMP "Filter_Pump"
#define BTN_SPA "Spa_Mode"
#define BTN_SPA "Spa"
#define BTN_AUX1 "Aux_1"
#define BTN_AUX2 "Aux_2"
#define BTN_AUX3 "Aux_3"
Expand Down
1 change: 1 addition & 0 deletions source/aq_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ void start_timer(struct aqualinkdata *aq_data, /*aqkey *button,*/ int deviceInde
tmthread->thread_id = 0;
tmthread->duration_min = duration;
tmthread->next = NULL;
tmthread->started_at = time(0); // This will get reset once we actually start. But need it here incase someone calls get_timer_left() before we start

if( pthread_create( &tmthread->thread_id , NULL , timer_worker, (void*)tmthread) < 0) {
LOG(TIMR_LOG, LOG_ERR, "could not create timer thread for button '%s'\n",button->name);
Expand Down
8 changes: 8 additions & 0 deletions source/aqualink.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ bool checkAqualinkTime(); // Only need to externalise this for PDA

bool isVirtualButtonEnabled();

#define PUMP_RPM_MAX 3450
#define PUMP_RPM_MIN 600
#define PUMP_GPM_MAX 130
#define PUMP_GPM_MIN 15


enum {
FAHRENHEIT,
CELSIUS,
Expand Down Expand Up @@ -179,6 +185,8 @@ typedef struct pumpd
int rpm;
int gpm;
int watts;
int maxSpeed; // Max rpm or gpm depending on pump
int minSpeed;
unsigned char pumpID;
int pumpIndex;
char pumpName[PUMP_NAME_LENGTH];
Expand Down
66 changes: 63 additions & 3 deletions source/aqualinkd.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "onetouch_aq_programmer.h"
#include "iaqtouch.h"
#include "iaqtouch_aq_programmer.h"
#include "iaqualink.h"
#include "version.h"
#include "rs_msg_utils.h"
#include "serialadapter.h"
Expand Down Expand Up @@ -697,6 +698,12 @@ int startup(char *self, char *cfgFile)
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) &&
(_aqconfig_.extended_device_id < 0x30 || _aqconfig_.extended_device_id > 0x33 ) ){
LOG(AQUA_LOG,LOG_WARNING, "Config error, extended_device_id must be on of the folowing (0x30,0x31,0x32,0x33) to use virtual button : '%s'",_aqualink_data.aqbuttons[i].label);
}
}
/*
for (i=0; i < _aqualink_data.total_buttons; i++)
Expand Down Expand Up @@ -766,6 +773,41 @@ void caculate_ack_packet(int rs_fd, unsigned char *packet_buffer, emulation_type
}
//DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"AquaTouch Emulation type Processed packet in");
break;
case IAQUALNK:
/*
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] == 0x53) {
/*
static int cnt=0;
if (cnt++ > 10) {
cnt=0;
LOG(IAQL_LOG,LOG_NOTICE, "Sending get bigass packet\n");
send_extended_ack(rs_fd, 0x3f, 0x18);
} else*/ {
// Use 0x3f
send_extended_ack(rs_fd, 0x3f, 0x00);
}
send_jandy_command(rs_fd, get_rssa_cmd(packet_buffer[PKT_CMD]), 4);
} else {
// Use packet_buffer[PKT_CMD]
send_extended_ack(rs_fd, packet_buffer[PKT_CMD], 0x00);
}
break;
#endif
#ifdef AQ_PDA
case AQUAPDA:
Expand Down Expand Up @@ -879,7 +921,8 @@ void main_loop()
pthread_mutex_init(&_aqualink_data.active_thread.thread_mutex, NULL);
pthread_cond_init(&_aqualink_data.active_thread.thread_cond, NULL);

for (i=0; i < MAX_PUMPS; i++) {
//for (i=0; i < MAX_PUMPS; i++) {
for (i=0; i < _aqualink_data.num_pumps; i++) {
_aqualink_data.pumps[i].rpm = TEMP_UNKNOWN;
_aqualink_data.pumps[i].gpm = TEMP_UNKNOWN;
_aqualink_data.pumps[i].watts = TEMP_UNKNOWN;
Expand All @@ -888,6 +931,15 @@ void main_loop()
_aqualink_data.pumps[i].status = TEMP_UNKNOWN;
_aqualink_data.pumps[i].pStatus = PS_OFF;
_aqualink_data.pumps[i].pressureCurve = TEMP_UNKNOWN;

if (_aqualink_data.pumps[i].maxSpeed <= 0) {
_aqualink_data.pumps[i].maxSpeed = (_aqualink_data.pumps[i].pumpType==VFPUMP?PUMP_GPM_MAX:PUMP_RPM_MAX);
}
if (_aqualink_data.pumps[i].minSpeed <= 0) {
_aqualink_data.pumps[i].minSpeed = (_aqualink_data.pumps[i].pumpType==VFPUMP?PUMP_GPM_MIN:PUMP_RPM_MIN);
}

//printf("arrayindex=%d, pump=%d, min=%d, max=%d\n",i,_aqualink_data.pumps[i].pumpIndex, _aqualink_data.pumps[i].minSpeed ,_aqualink_data.pumps[i].maxSpeed);
}

for (i=0; i < MAX_LIGHTS; i++) {
Expand Down Expand Up @@ -1241,10 +1293,14 @@ void main_loop()
}

// Process and packets of devices we are acting as
if (packet_length > 0 && getProtocolType(packet_buffer) == JANDY &&
if (packet_length > 0 && getProtocolType(packet_buffer) == JANDY && packet_buffer[PKT_DEST] != 0x00 &&
(packet_buffer[PKT_DEST] == _aqconfig_.device_id ||
packet_buffer[PKT_DEST] == _aqconfig_.rssa_device_id ||
packet_buffer[PKT_DEST] == _aqconfig_.extended_device_id ))
#if defined AQ_ONETOUCH || defined AQ_IAQTOUCH
packet_buffer[PKT_DEST] == _aqconfig_.extended_device_id ||
packet_buffer[PKT_DEST] == _aqconfig_.extended_device_id2
#endif
))
{
switch(getJandyDeviceType(packet_buffer[PKT_DEST])){
case ALLBUTTON:
Expand All @@ -1267,6 +1323,10 @@ void main_loop()
_aqualink_data.updated = process_pda_packet(packet_buffer, packet_length);
caculate_ack_packet(rs_fd, packet_buffer, AQUAPDA);
break;
case IAQUALNK:
_aqualink_data.updated = process_iaqualink_packet(packet_buffer, packet_length, &_aqualink_data);
caculate_ack_packet(rs_fd, packet_buffer, IAQUALNK);
break;
default:
break;
}
Expand Down
Loading

0 comments on commit e3dc3db

Please sign in to comment.