Skip to content

Commit

Permalink
Update v3.2.5
Browse files Browse the repository at this point in the history
  • Loading branch information
sfeakes committed May 22, 2024
1 parent 675b0f5 commit dbbd0dd
Show file tree
Hide file tree
Showing 88 changed files with 2,156 additions and 268 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ AQ_PDA = true
AQ_ONETOUCH = true
AQ_IAQTOUCH = true
AQ_MANAGER =true

#AQ_RS_EXTRA_OPTS = false
#AQ_CONTAINER = false // this is for compiling for containers
#AQ_MEMCMP = true // Not implimented correctly yet.
Expand Down Expand Up @@ -76,7 +77,7 @@ endif
# Main source files
SRCS = aqualinkd.c utils.c config.c aq_serial.c aq_panel.c aq_programmer.c net_services.c json_messages.c rs_msg_utils.c\
devices_jandy.c packetLogger.c devices_pentair.c color_lights.c serialadapter.c aq_timer.c aq_scheduler.c web_config.c\
serial_logger.c mongoose.c simulator.c timespec_subtract.c
serial_logger.c mongoose.c hassio.c simulator.c timespec_subtract.c


AQ_FLAGS =
Expand Down
40 changes: 36 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Designed to mimic AqualinkRS devices, used to fully configure the master control
* Full support for homekit scenes: ie: Create a "Spa scene" to: "turn spa on, set spa heater to X temperature and turn spa blower on", etc etc).

### In Home Assistant
<img src="extras/HomeAssistant2.png?raw=true" width="800"></img>
<img src="extras/HASSIO.png?raw=true" width="800"></img>

## All Web interfaces.
* http://aqualink.ip/ <- (Standard WEB UI
Expand All @@ -83,7 +83,39 @@ Designed to mimic AqualinkRS devices, used to fully configure the master control
* 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.

<!--
* NEED TO FIX for PDA and iAQT protocol.
* Not always doing on/off
* Heaters are slow to turn on, need to hit extra button
* Spa turns on Spa Heat (first button on home page ???)
* SWG Stays on
* serial_logger
* Add wiki documentation
* about Heat vs Heater
* 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.
* The only Jandy devices I have not decoded yet are LX heater & Chemical Feeder. If you have either of these devices and are willing to post some logs, please let me know, or post in the [Discussions area](https://github.com/sfeakes/AqualinkD/discussions)

# Update in Release 2.3.5
* Added Home Assistant integration through MQTT discover
* Please read the Wiki section on this [Wiki - HASSIO](https://github.com/sfeakes/AqualinkD/wiki#HASSIO)
* There are still some enhacments to come on this.
* Added support for reading extended information for Jandy JXi heaters.
* Added Color Light to iAqualinkTouch protocol.
* Fixed issue mqtt_timed_update (1~2 min rather than between 2 & 20 min)

# Update in Release 2.3.4
* Changes for Docker
* Updated simulator code base and added new simulators for AllButton, OneTouch & PDA.
Expand All @@ -95,11 +127,11 @@ Designed to mimic AqualinkRS devices, used to fully configure the master control

# Update in Release 2.3.3
* Introduced Aqualink Manager UI http://aqualink.ip/aqmanager.html
* [AqualinkD Manager](#AQManager)
* [AqualinkD Manager](https://github.com/sfeakes/AqualinkD/wiki#AQManager)
* Moved logging into systemd/journal (journalctl) from syslog
* [AqualinkD Log](#Log)
* [AqualinkD Log](https://github.com/sfeakes/AqualinkD/wiki#Log)
* Updated to scheduler
* [AqualinkD Scheduler](#Scheduler)
* [AqualinkD Scheduler](https://github.com/sfeakes/AqualinkD/wiki#Scheduler)
* Introduced RS485 frame delay / timer.
* Improve PDA panels reliability (PDA pannels are slower than RS panels)
* Potentially fixed Pentair VSP / SWG problems since Pentair VSP use a different protocol, this will allow a timed delay for the VSP to post a status messages. Seems to only effect RS485 bus when both a Pentair VSP and Jandy SWG are present.
Expand Down
12 changes: 10 additions & 2 deletions aq_mqtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,28 @@
#define SWG_SETPOINT_TOPIC SWG_TOPIC "/setpoint"
#define SWG_EXTENDED_TOPIC SWG_TOPIC "/fullstatus"
#define SWG_BOOST_TOPIC SWG_TOPIC "/Boost"
#define SWG_BOOST_DURATION_TOPIC SWG_BOOST_TOPIC "/duration"

#define SWG_STATUS_MSG_TOPIC SWG_TOPIC "/Display_Message"

#define CHEM_TOPIC "CHEM"
#define CHEM_PH_TOPIC CHEM_TOPIC "/pH"
#define CHRM_PH_F_TOPIC CHEM_TOPIC "/pH_f"
#define CHEM_ORP_TOPIC CHEM_TOPIC "/ORP"
#define CHRM_ORP_F_TOPIC CHEM_TOPIC "/ORP_f"

#define LXI_TOPIC "LXi"
#define LXI_STATUS LXI_TOPIC "/Status"
#define LXI_ERROR_CODE LXI_TOPIC "/Error"
#define LXI_ERROR_MESSAGE LXI_TOPIC "/Error_Message"

#define FREEZE_PROTECT "Freeze_Protect"
#define FREEZE_PROTECT_ENABELED FREEZE_PROTECT ENABELED_SUBT

#define BATTERY_STATE "Battery"

#define POOL_THERMO_TEMP_TOPIC BTN_POOL_HTR "/Temperature"
#define SPA_THERMO_TEMP_TOPIC BTN_SPA_HTR "/Temperature"
//#define POOL_THERMO_TEMP_TOPIC BTN_POOL_HTR "/Temperature"
//#define SPA_THERMO_TEMP_TOPIC BTN_SPA_HTR "/Temperature"

//#define PUMP_TOPIC "Pump_"
#define PUMP_RPM_TOPIC "/RPM"
Expand Down
15 changes: 10 additions & 5 deletions aq_panel.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,9 +525,14 @@ bool setDeviceState(struct aqualinkdata *aqdata, int deviceIndex, bool isON)
LOG(AQUA_LOG, LOG_INFO, "received '%s' for '%s', turning '%s'\n", (isON == false ? "OFF" : "ON"), button->name, (isON == false ? "OFF" : "ON"));
#ifdef AQ_PDA
if (isPDA_PANEL) {
char msg[PTHREAD_ARG];
sprintf(msg, "%-5d%-5d", deviceIndex, (isON == false ? OFF : ON));
aq_programmer(AQ_PDA_DEVICE_ON_OFF, msg, aqdata);
if (button->special_mask & PROGRAM_LIGHT && isPDA_IAQT) {
// AqualinkTouch in PDA mode, we can program light. (if turing off, use standard AQ_PDA_DEVICE_ON_OFF below)
programDeviceLightMode(aqdata, (isON?0:-1), deviceIndex); // -1 means off 0 means use current light mode
} else {
char msg[PTHREAD_ARG];
sprintf(msg, "%-5d%-5d", deviceIndex, (isON == false ? OFF : ON));
aq_programmer(AQ_PDA_DEVICE_ON_OFF, msg, aqdata);
}
} else
#endif
{
Expand Down Expand Up @@ -598,7 +603,7 @@ void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int button)
int i;
clight_detail *light = NULL;
#ifdef AQ_PDA
if (isPDA_PANEL) {
if (isPDA_PANEL && !isPDA_IAQT) {
LOG(AQUA_LOG,LOG_ERR, "Light mode control not supported in PDA mode\n");
return;
}
Expand Down Expand Up @@ -642,7 +647,7 @@ void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int button)
//bool panel_device_request(struct aqualinkdata *aqdata, action_type type, int deviceIndex, int value, int subIndex, bool fromMQTT)
bool panel_device_request(struct aqualinkdata *aqdata, action_type type, int deviceIndex, int value, request_source source)
{
//LOG(AQUA_LOG,LOG_NOTICE, "Device request type %d for deviceindex %d of value %d from %d\n",type,deviceIndex, value, source);
LOG(AQUA_LOG,LOG_INFO, "Device request type %d for deviceindex %d of value %d from %d\n",type,deviceIndex, value, source);
switch (type) {
case ON_OFF:
//setDeviceState(&aqdata->aqbuttons[deviceIndex], value<=0?false:true, deviceIndex );
Expand Down
69 changes: 58 additions & 11 deletions aq_programmer.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,15 @@ void queueGetProgramData(emulation_type source_type, struct aqualinkdata *aq_dat
}
}
#ifdef AQ_PDA
} else if ( source_type == AQUAPDA) {
} else if ( isPDA_PANEL && source_type == AQUAPDA) {
aq_programmer(AQ_PDA_INIT, NULL, aq_data);
} else if ( isPDA_PANEL && source_type == IAQTOUCH) {
//aq_programmer(AQ_PDA_INIT, NULL, aq_data);
if (_aqconfig_.use_panel_aux_labels) {
aq_programmer(AQ_GET_AUX_LABELS, NULL, aq_data);
}
aq_programmer(AQ_GET_IAQTOUCH_SETPOINTS, NULL, aq_data);

#endif
} else { // Must be all button only
aq_programmer(AQ_GET_POOL_SPA_HEATER_TEMPS, NULL, aq_data);
Expand Down Expand Up @@ -468,7 +475,8 @@ bool in_light_programming_mode(struct aqualinkdata *aq_data)
{
if ( ( aq_data->active_thread.thread_id != 0 ) &&
( aq_data->active_thread.ptype == AQ_SET_LIGHTPROGRAM_MODE ||
aq_data->active_thread.ptype == AQ_SET_LIGHTCOLOR_MODE)
aq_data->active_thread.ptype == AQ_SET_LIGHTCOLOR_MODE ||
aq_data->active_thread.ptype == AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE)
) {
return true;
}
Expand Down Expand Up @@ -527,7 +535,9 @@ bool in_iaqt_programming_mode(struct aqualinkdata *aq_data)
aq_data->active_thread.ptype == AQ_SET_IAQTOUCH_POOL_HEATER_TEMP ||
aq_data->active_thread.ptype == AQ_SET_IAQTOUCH_SPA_HEATER_TEMP ||
aq_data->active_thread.ptype == AQ_SET_IAQTOUCH_SET_TIME ||
aq_data->active_thread.ptype == AQ_SET_IAQTOUCH_PUMP_VS_PROGRAM)
aq_data->active_thread.ptype == AQ_SET_IAQTOUCH_PUMP_VS_PROGRAM ||
aq_data->active_thread.ptype == AQ_SET_IAQTOUCH_DEVICE_ON_OFF ||
aq_data->active_thread.ptype == AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE)
) {
return true;
}
Expand Down Expand Up @@ -580,14 +590,14 @@ void kick_aq_program_thread(struct aqualinkdata *aq_data, emulation_type source_
LOG(ONET_LOG, LOG_DEBUG, "Kicking OneTouch thread %d,%p\n",aq_data->active_thread.ptype, aq_data->active_thread.thread_id);
pthread_cond_broadcast(&aq_data->active_thread.thread_cond);
}
else if (source_type == ALLBUTTON && !in_ot_programming_mode(aq_data)) {
LOG(PROG_LOG, LOG_DEBUG, "Kicking RS thread %d,%p message '%s'\n",aq_data->active_thread.ptype, aq_data->active_thread.thread_id,aq_data->last_message);
pthread_cond_broadcast(&aq_data->active_thread.thread_cond);
}
else if (source_type == IAQTOUCH && in_iaqt_programming_mode(aq_data)) {
LOG(IAQT_LOG, LOG_DEBUG, "Kicking IAQ Touch thread %d,%p\n",aq_data->active_thread.ptype, aq_data->active_thread.thread_id);
pthread_cond_broadcast(&aq_data->active_thread.thread_cond);
}
else if (source_type == ALLBUTTON && !in_ot_programming_mode(aq_data) && !in_iaqt_programming_mode(aq_data)) {
LOG(PROG_LOG, LOG_DEBUG, "Kicking RS Allbutton thread %d,%p message '%s'\n",aq_data->active_thread.ptype, aq_data->active_thread.thread_id,aq_data->last_message);
pthread_cond_broadcast(&aq_data->active_thread.thread_cond);
}
#ifdef AQ_PDA
else if (source_type == AQUAPDA && !in_ot_programming_mode(aq_data)) {
LOG(PDA_LOG, LOG_DEBUG, "Kicking PDA thread %d,%p\n",aq_data->active_thread.ptype, aq_data->active_thread.thread_id);
Expand Down Expand Up @@ -671,7 +681,7 @@ void _aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_dat
else if (r_type == AQ_SET_SPA_HEATER_TEMP)
type = AQ_SET_RSSADAPTER_SPA_HEATER_TEMP;
} else if (r_type == AQ_SET_PUMP_RPM) {
if (isONET_ENABLED)
if (isONET_ENABLED || isPDA_IAQT)
type = AQ_SET_ONETOUCH_PUMP_RPM;
else if (isIAQT_ENABLED)
type = AQ_SET_IAQTOUCH_PUMP_RPM;
Expand Down Expand Up @@ -719,7 +729,7 @@ void _aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_dat
}
#endif
#ifdef AQ_IAQTOUCH
else if (isIAQT_ENABLED && isEXTP_ENABLED) {
else if ((isIAQT_ENABLED && isEXTP_ENABLED) || isPDA_IAQT) {
// IAQ Touch programming modes that should overite standard ones.
switch (r_type){
case AQ_GET_POOL_SPA_HEATER_TEMPS:
Expand All @@ -741,15 +751,30 @@ void _aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_dat
case AQ_SET_TIME:
type = AQ_SET_IAQTOUCH_SET_TIME;
break;
case AQ_PDA_DEVICE_ON_OFF:
if (isPDA_IAQT) {
type = AQ_SET_IAQTOUCH_DEVICE_ON_OFF;
}
break;
// This isn;t going to work outside of PDA mode, if the labels are incorrect.
case AQ_SET_LIGHTCOLOR_MODE:
if (isPDA_IAQT) {
type = AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE;
}
break;
default:
type = r_type;
break;
}
}
#endif



#ifdef AQ_PDA
// Check we are doing something valid request
if (isPDA_PANEL) {
if (isPDA_PANEL && !isPDA_IAQT)
{
pda_reset_sleep();
if (type != AQ_PDA_INIT &&
type != AQ_PDA_WAKE_INIT &&
Expand Down Expand Up @@ -1028,6 +1053,12 @@ void _aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_dat
return;
}
break;
case AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE:
if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_iaqtouch_light_colormode, (void*)programmingthread) < 0) {
LOG(PROG_LOG, LOG_ERR, "could not create thread\n");
return;
}
break;
#endif
#ifdef AQ_PDA
case AQ_PDA_INIT:
Expand All @@ -1054,6 +1085,12 @@ void _aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_dat
return;
}
break;
case AQ_SET_IAQTOUCH_DEVICE_ON_OFF:
if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_iaqtouch_device_on_off, (void*)programmingthread) < 0) {
LOG(PROG_LOG, LOG_ERR, "could not create thread\n");
return;
}
break;
#endif

default:
Expand Down Expand Up @@ -1522,7 +1559,7 @@ void *set_aqualink_light_colormode( void *ptr )
use_current_mode = true;
LOG(PROG_LOG, LOG_INFO, "Light Programming #: %d, on button: %s, color light type: %d, using current mode\n", val, button->label, typ);
} else {
mode_name = light_mode_name(typ, val-1);
mode_name = light_mode_name(typ, val-1, ALLBUTTON);
use_current_mode = false;
if (mode_name == NULL) {
LOG(PROG_LOG, LOG_ERR, "Light Programming #: %d, on button: %s, color light type: %d, couldn't find mode name '%s'\n", val, button->label, typ, mode_name);
Expand Down Expand Up @@ -2615,6 +2652,12 @@ const char *ptypeName(program_type type)
case AQ_SET_IAQTOUCH_SET_TIME:
return "Set iAqualink Set Time";
break;
case AQ_SET_IAQTOUCH_DEVICE_ON_OFF:
return "Set iAqualink Device On/Off";
break;
case AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE:
return "Set iAqualink Light Color (using panel)";
break;
#endif
#ifdef AQ_PDA
case AQ_PDA_INIT:
Expand Down Expand Up @@ -2680,6 +2723,7 @@ const char *programtypeDisplayName(program_type type)
break;
case AQ_SET_LIGHTPROGRAM_MODE:
case AQ_SET_LIGHTCOLOR_MODE:
case AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE:
return "Programming: setting light color";
break;
case AQ_SET_SWG_PERCENT:
Expand Down Expand Up @@ -2709,6 +2753,9 @@ const char *programtypeDisplayName(program_type type)
case AQ_GET_IAQTOUCH_VSP_ASSIGNMENT:
return "Get Pump Assignment";
break;
case AQ_SET_IAQTOUCH_DEVICE_ON_OFF:
return "Programming: setting device on/off";
break;
#ifdef AQ_PDA
case AQ_PDA_DEVICE_STATUS:
return "Programming: retrieving PDA Device status";
Expand Down
2 changes: 2 additions & 0 deletions aq_programmer.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ typedef enum {
AQ_SET_IAQTOUCH_POOL_HEATER_TEMP,
AQ_SET_IAQTOUCH_SPA_HEATER_TEMP,
AQ_SET_IAQTOUCH_SET_TIME,
AQ_SET_IAQTOUCH_DEVICE_ON_OFF,
AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE,
AQ_GET_RSSADAPTER_SETPOINTS,
AQ_SET_RSSADAPTER_POOL_HEATER_TEMP,
AQ_SET_RSSADAPTER_SPA_HEATER_TEMP,
Expand Down
19 changes: 19 additions & 0 deletions aq_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ const char* get_packet_type(unsigned char* packet , int length)
case CMD_IAQ_STARTUP:
return "iAq init";
break;
case CMD_IAQ_TITLE_MESSAGE:
return "iAq ProductName";
break;
case CMD_IAQ_MSG_LONG:
return "iAq Popup message";
break;
case RSSA_DEV_STATUS:
// This is a fail reply 0x10|0x02|0x48|0x13|0x02|0x00|0x10|0x00|0x7f|0x10|0x03|
// Rather than check all, just check 0x02 and checksum sin't I'm not sure 0x10 means faiure without 0x00 around it.
Expand All @@ -165,6 +171,19 @@ const char* get_packet_type(unsigned char* packet , int length)
case CMD_EPUMP_WATTS:
return "ePump get Watts";
break;
case CMD_JXI_PING:
if (packet[4] == 0x19)
return "LXi heater on";
else // 0x11 is normal off
return "LXi heater ping";
break;
case CMD_JXI_STATUS:
if (packet[6] == 0x10)
return "LXi error";
else
return "LXi status";
break;

default:
sprintf(buf, "Unknown '0x%02hhx'", packet[PKT_CMD]);
return buf;
Expand Down
Loading

0 comments on commit dbbd0dd

Please sign in to comment.