Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development #297

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
36 changes: 32 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,35 @@ 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
-->

# 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.
* 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
* 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 +123,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
Binary file added a.out
Binary file not shown.
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
Loading