diff --git a/Makefile b/Makefile
index 55fe38e..c56513a 100755
--- a/Makefile
+++ b/Makefile
@@ -11,9 +11,10 @@ LIBS := -l pthread -l m
#LIBS := -lpthread -lwebsockets
# debug of not
-#DBG = -g -O0 -fsanitize=address -static-libasan
-#DBG = -g
-DBG =
+#DBG = -g -O0 -fsanitize=address
+DBG = -g
+#DBG = -D ONETOUCH
+#DBG =
# USe below to remove unused functions and global variables.
#LFLAGS = -Wl,--gc-sections,--print-gc-sections
@@ -32,7 +33,7 @@ CFLAGS = $(GCCFLAGS) $(DBG) $(LIBS) -D MG_DISABLE_MD5 -D MG_DISABLE_HTTP_DIGEST_
# Add inputs and outputs from these tool invocations to the build variables
# define the C source files
-SRCS = aqualinkd.c utils.c config.c aq_serial.c init_buttons.c aq_programmer.c net_services.c json_messages.c pda.c pda_menu.c pda_aq_programmer.c aquapure.c packetLogger.c pentair_messages.c mongoose.c
+SRCS = aqualinkd.c utils.c config.c aq_serial.c init_buttons.c aq_programmer.c net_services.c json_messages.c pda.c pda_menu.c pda_aq_programmer.c aquapure.c onetouch.c onetouch_aq_programmer.c packetLogger.c pentair_messages.c mongoose.c
DBG_SRC = timespec_subtract.c
# If run with `make DEBUG=true` add debug files and pass parameter for compile
diff --git a/README.md b/README.md
index f7608c5..210f130 100644
--- a/README.md
+++ b/README.md
@@ -65,11 +65,17 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
* http://aqualink.ip/ <- (Standard WEB UI
* http://aqualink.ip/simple.html <- (Simple opion if you don't like the above)
* http://aqualink.ip/simulator.html <- (RS8 All Button Control Panel simulator)
+* http://aqualink.ip/debug.html <- (Turn on/off debug/serial debug & download logs)
#
-# Update in Release 1.3.9b
-* Small fixes for Jandy protocol.
-* Fixed some debug messages.
-# Update in Release 1.3.9
+# Update in Release 2.0.0a
+* Big update, lots of core changes, please read wiki section https://github.com/sfeakes/AqualinkD/wiki/Version_2
+* Full Variable Speed Pump support.
+* Please consider this ALPHA version, no need to upgrade unless you need VSP support. Use a previous version unless you want VSP.
+* I've noticed there is an issues with colored lights if your light is configured as such in the control panel. For this release suggest you either :-
+ * A) use AqualinkD to control the colors and configure Jandy control panel as normal light
+ * B) Don't use AqualinkD to turn light on/off (or if you do, wait ~10 seconds)
+# Update in Release 1.3.9a
+* Improved Debugging for serial.
* Added panel Timeout mode support to UI and MQTT
* Fixed SWG bug while in Service & Timeout modes
* Cleanded up SWG code and MQTT status messages for SWG and SWG/enabled
diff --git a/a.out b/a.out
new file mode 100755
index 0000000..892e3fe
Binary files /dev/null and b/a.out differ
diff --git a/aq_mqtt.h b/aq_mqtt.h
index b91f4b9..78d1df4 100644
--- a/aq_mqtt.h
+++ b/aq_mqtt.h
@@ -33,7 +33,7 @@
//#define PUMP_TOPIC "Pump_"
#define PUMP_RPM_TOPIC "/RPM"
-#define PUMP_GPH_TOPIC "/GPH"
+#define PUMP_GPM_TOPIC "/GPM"
#define PUMP_WATTS_TOPIC "/Watts"
/*
#define AIR_TEMPERATURE "Air"
diff --git a/aq_programmer.c b/aq_programmer.c
index b75f21f..e848257 100644
--- a/aq_programmer.c
+++ b/aq_programmer.c
@@ -30,6 +30,7 @@
#include "pda_menu.h"
#include "init_buttons.h"
#include "pda_aq_programmer.h"
+#include "onetouch_aq_programmer.h"
#ifdef AQ_DEBUG
#include
@@ -56,6 +57,9 @@ void *set_aqualink_light_colormode( void *ptr );
void *set_aqualink_PDA_init( void *ptr );
void *set_aqualink_SWG( void *ptr );
void *set_aqualink_boost( void *ptr );
+void *set_aqualink_pump_rpm( void *ptr );
+void *set_aqualink_onetouch_macro( void *ptr );
+void *get_aqualink_onetouch_setpoints( void *ptr );
//void *get_aqualink_PDA_device_status( void *ptr );
//void *set_aqualink_PDA_device_on_off( void *ptr );
@@ -67,12 +71,14 @@ bool waitForEitherMessage(struct aqualinkdata *aq_data, char* message1, char* me
bool push_aq_cmd(unsigned char cmd);
void waitfor_queue2empty();
+void longwaitfor_queue2empty();
#define MAX_STACK 20
int _stack_place = 0;
unsigned char _commands[MAX_STACK];
//unsigned char pgm_commands[MAX_STACK];
unsigned char _pgm_command = NUL;
+//unsigned char _ot_pgm_command = NUL;
bool _last_sent_was_cmd = false;
@@ -81,6 +87,23 @@ void aq_send_cmd(unsigned char cmd) {
push_aq_cmd(cmd);
}
+/*
+void ot_send_cmd(unsigned char cmd) {
+ _ot_pgm_command = cmd;
+}
+
+unsigned char pop_ot_cmd(unsigned char receive_type)
+{
+ unsigned char cmd = NUL;
+
+ if (receive_type == CMD_STATUS) {
+ cmd = _ot_pgm_command;
+ _ot_pgm_command = NUL;
+ }
+
+ return cmd;
+}
+*/
bool push_aq_cmd(unsigned char cmd) {
//logMessage(LOG_DEBUG, "push_aq_cmd '0x%02hhx'\n", cmd);
@@ -102,17 +125,47 @@ int get_aq_cmd_length()
}
unsigned char pop_aq_cmd(struct aqualinkdata *aq_data)
+{
+ unsigned char cmd = NUL;
+ // Only send commands on status messages
+ // Are we in programming mode and it's not ONETOUCH programming mode
+ if (aq_data->active_thread.thread_id != 0 && in_ot_programming_mode(aq_data) == false ) {
+ //if (aq_data->active_thread.thread_id != 0) {
+ if ( _pgm_command != NUL && aq_data->last_packet_type == CMD_STATUS) {
+ cmd = _pgm_command;
+ _pgm_command = NUL;
+ logMessage(LOG_DEBUG_SERIAL, "RS SEND cmd '0x%02hhx' (programming)\n", cmd);
+ } else if (_pgm_command != NUL) {
+ logMessage(LOG_DEBUG_SERIAL, "RS Waiting to send cmd '0x%02hhx' (programming)\n", _pgm_command);
+ } else {
+ logMessage(LOG_DEBUG_SERIAL, "RS SEND cmd '0x%02hhx' empty queue (programming)\n", cmd);
+ }
+ } else if (_stack_place > 0 && aq_data->last_packet_type == CMD_STATUS ) {
+ cmd = _commands[0];
+ _stack_place--;
+ logMessage(LOG_DEBUG_SERIAL, "RS SEND cmd '0x%02hhx'\n", cmd);
+ memmove(&_commands[0], &_commands[1], sizeof(unsigned char) * _stack_place ) ;
+ } else {
+ logMessage(LOG_DEBUG_SERIAL, "RS SEND cmd '0x%02hhx'\n", cmd);
+ }
+
+//printf("RSM sending cmd '0x%02hhx' in reply to '0x%02hhx'\n",cmd,aq_data->last_packet_type);
+
+ return cmd;
+}
+
+
+/*
+
+unsigned char pop_aq_cmd_OLD(struct aqualinkdata *aq_data)
{
unsigned char cmd = NUL;
// Only send commands on status messages
// Are we in programming mode
if (aq_data->active_thread.thread_id != 0) {
- /*if ( (_pgm_command == KEY_MENU && aq_data->last_packet_type == CMD_STATUS) ||
+ if ( (_pgm_command == KEY_MENU && aq_data->last_packet_type == CMD_STATUS) ||
// Need to not the key_menu below
- ( _pgm_command != NUL && (aq_data->last_packet_type == CMD_STATUS || aq_data->last_packet_type == CMD_MSG_LONG) )) {*/
- if ( (_pgm_command != NUL && (aq_data->last_packet_type == CMD_STATUS)) ||
- // Boost pool has to send commands to msg long
- (aq_data->active_thread.ptype == AQ_SET_BOOST && (aq_data->last_packet_type == CMD_STATUS || aq_data->last_packet_type == CMD_MSG_LONG)) ) {
+ ( _pgm_command != NUL && (aq_data->last_packet_type == CMD_STATUS || aq_data->last_packet_type == CMD_MSG_LONG) )) {
cmd = _pgm_command;
_pgm_command = NUL;
logMessage(LOG_DEBUG, "RS SEND cmd '0x%02hhx' (programming)\n", cmd);
@@ -134,95 +187,39 @@ unsigned char pop_aq_cmd(struct aqualinkdata *aq_data)
return cmd;
}
-
-
-//unsigned char pop_aq_cmd_old(struct aqualinkdata *aq_data);
-
-unsigned char pop_aq_cmd_XXXXXX(struct aqualinkdata *aq_data)
-{
- unsigned char cmd = NUL;
- static bool last_sent_was_cmd = false;
-
- // USE BELOW IF PDA HAS ISSUES WITH NEW COMMAND LOGIC
-
- //if ( pda_mode() == true ) {
- // return pop_aq_cmd_old(aq_data);
- //}
-
- // Only press menu to a status command
- // Only send commands on status messages when programming date
- // Otherwise send every other command.
-
- // Are we in programming mode
- if (aq_data->active_thread.thread_id != 0) {
- if ( ((_pgm_command == KEY_MENU || aq_data->active_thread.ptype == AQ_SET_TIME) && aq_data->last_packet_type == CMD_STATUS) ||
- (pda_mode() == false && aq_data->active_thread.ptype != AQ_SET_TIME && last_sent_was_cmd == false) ||
- (pda_mode() == true && aq_data->last_packet_type == CMD_STATUS)
- //(pda_mode() == true && last_sent_was_cmd == false)
- ) {
- cmd = _pgm_command;
- _pgm_command = NUL;
- logMessage(LOG_DEBUG, "RS SEND cmd '0x%02hhx' (programming)\n", cmd);
- /*} else if (aq_data->active_thread.ptype != AQ_SET_TIME && last_sent_was_cmd == false) {
- cmd = _pgm_command;
- _pgm_command = NUL;
- logMessage(LOG_DEBUG, "RS SEND cmd '0x%02hhx' (programming)\n", cmd);*/
- } else if (_pgm_command != NUL) {
- logMessage(LOG_DEBUG, "RS Waiting to send cmd '0x%02hhx' (programming)\n", _pgm_command);
- } else {
- logMessage(LOG_DEBUG, "RS SEND cmd '0x%02hhx' empty queue (programming)\n", cmd);
- }
- } else if (_stack_place > 0 && aq_data->last_packet_type == CMD_STATUS ) {
- cmd = _commands[0];
- _stack_place--;
- logMessage(LOG_DEBUG, "RS SEND cmd '0x%02hhx'\n", cmd);
- memmove(&_commands[0], &_commands[1], sizeof(unsigned char) * _stack_place ) ;
- } else {
- logMessage(LOG_DEBUG, "RS SEND cmd '0x%02hhx'\n", cmd);
- }
-
- if (cmd == NUL)
- last_sent_was_cmd= false;
- else
- last_sent_was_cmd= true;
-
- return cmd;
-}
-
-unsigned char pop_aq_cmd_old(struct aqualinkdata *aq_data)
-{
- unsigned char cmd = NUL;
- //logMessage(LOG_DEBUG, "pop_aq_cmd\n");
- // can only send a command every other ack.
-
- if (_last_sent_was_cmd == true) {
- _last_sent_was_cmd= false;
- }
- else if (aq_data->active_thread.thread_id != 0) {
- cmd = _pgm_command;
- _pgm_command = NUL;
- //logMessage(LOG_DEBUG, "pop_aq_cmd '0x%02hhx' (programming)\n", cmd);
- }
- else if (_stack_place > 0) {
- cmd = _commands[0];
- _stack_place--;
- //logMessage(LOG_DEBUG, "pop_aq_cmd '0x%02hhx'\n", cmd);
- //memcpy(&_commands[0], &_commands[1], (sizeof(unsigned char) * MAX_STACK) - 1);
- memmove(&_commands[0], &_commands[1], sizeof(unsigned char) * _stack_place ) ;
- }
-
- if (cmd == NUL)
- _last_sent_was_cmd= false;
- else
- _last_sent_was_cmd= true;
-
- return cmd;
-}
+*/
int roundTo(int num, int denominator) {
return ((num + (denominator/2) ) / denominator )* denominator;
}
+//(Intelliflo VF you set GPM, not RPM)
+int RPM_check(pump_type type, int value, struct aqualinkdata *aqdata)
+{
+ int rtn = value;
+ // RPM 3450 seems to be max
+ // RPM 600 min
+ // GPM 130 max
+ // GPM 15 min
+ if (type == VFPUMP) {
+ if (rtn > 130)
+ rtn = 130;
+ else if (rtn < 15)
+ rtn = 15;
+ else
+ rtn = roundTo(rtn, 5);
+ } else {
+ if (rtn > 3450)
+ rtn = 3450;
+ else if (rtn < 600)
+ rtn = 600;
+ else
+ rtn = roundTo(rtn, 5);
+ }
+
+ return rtn;
+}
+
int setpoint_check(int type, int value, struct aqualinkdata *aqdata)
{
int rtn = value;
@@ -303,6 +300,28 @@ int setpoint_check(int type, int value, struct aqualinkdata *aqdata)
return rtn;
}
+void queueGetExtendedProgramData(emulation_type source_type, struct aqualinkdata *aq_data, bool labels)
+{
+ // Wait for onetouch if enabeled.
+ if ( source_type == ALLBUTTON && ( onetouch_enabled() == false || extended_device_id_programming() == false ) ) {
+ aq_send_cmd(NUL);
+ aq_programmer(AQ_GET_POOL_SPA_HEATER_TEMPS, NULL, aq_data);
+ aq_programmer(AQ_GET_FREEZE_PROTECT_TEMP, NULL, aq_data);
+ if (labels)
+ aq_programmer(AQ_GET_AUX_LABELS, NULL, aq_data);
+ } else if ( source_type == ONETOUCH) {
+ aq_programmer(AQ_GET_ONETOUCH_SETPOINTS, NULL, aq_data);
+ } else if ( source_type == AQUAPDA) {
+ aq_programmer(AQ_PDA_INIT, NULL, aq_data);
+ }
+}
+
+void queueGetProgramData(emulation_type source_type, struct aqualinkdata *aq_data)
+{
+ queueGetExtendedProgramData(source_type, aq_data, false);
+}
+
+/*
void kick_aq_program_thread(struct aqualinkdata *aq_data)
{
if (aq_data->active_thread.thread_id != 0) {
@@ -310,11 +329,78 @@ void kick_aq_program_thread(struct aqualinkdata *aq_data)
pthread_cond_broadcast(&aq_data->active_thread.thread_cond);
}
}
+*/
+bool in_ot_programming_mode(struct aqualinkdata *aq_data)
+{
+ //( type != AQ_SET_PUMP_RPM || type != AQ_SET_OT_MACRO )) {
-void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data)
+ if ( ( aq_data->active_thread.thread_id != 0 ) &&
+ ( aq_data->active_thread.ptype == AQ_SET_ONETOUCH_PUMP_RPM ||
+ aq_data->active_thread.ptype == AQ_SET_ONETOUCH_MACRO ||
+ aq_data->active_thread.ptype == AQ_GET_ONETOUCH_SETPOINTS ||
+ aq_data->active_thread.ptype == AQ_SET_ONETOUCH_TIME ||
+ aq_data->active_thread.ptype == AQ_SET_ONETOUCH_SWG_PERCENT ||
+ aq_data->active_thread.ptype == AQ_SET_ONETOUCH_BOOST ||
+ aq_data->active_thread.ptype == AQ_SET_ONETOUCH_POOL_HEATER_TEMP ||
+ aq_data->active_thread.ptype == AQ_SET_ONETOUCH_SPA_HEATER_TEMP ||
+ aq_data->active_thread.ptype == AQ_SET_ONETOUCH_FREEZEPROTECT)
+ ) {
+ return true;
+ }
+
+ return false;
+}
+
+void kick_aq_program_thread(struct aqualinkdata *aq_data, emulation_type source_type)
+{
+ if ( aq_data->active_thread.thread_id != 0 ) {
+ if ( (source_type == ONETOUCH) && in_ot_programming_mode(aq_data))
+ {
+ logMessage(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 == AQUAPDA && !in_ot_programming_mode(aq_data)) {
+ logMessage(LOG_DEBUG, "Kicking PDA 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)) {
+ logMessage(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);
+ }
+
+ }
+}
+
+void aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_data)
{
struct programmingThreadCtrl *programmingthread = malloc(sizeof(struct programmingThreadCtrl));
-
+
+ program_type type = r_type;
+
+ // reset any types if to onetouch if available and if one touch is quicker
+ // At moment. onetouch is quicker for boost, and slower for heaters
+ if (onetouch_enabled() && extended_device_id_programming()) {
+ switch (r_type){
+ case AQ_GET_POOL_SPA_HEATER_TEMPS:
+ case AQ_GET_FREEZE_PROTECT_TEMP:
+ type = AQ_GET_ONETOUCH_SETPOINTS;
+ break;
+ case AQ_SET_POOL_HEATER_TEMP:
+ type = AQ_SET_ONETOUCH_POOL_HEATER_TEMP;
+ break;
+ case AQ_SET_SPA_HEATER_TEMP:
+ type = AQ_SET_ONETOUCH_SPA_HEATER_TEMP;
+ break;
+ case AQ_SET_BOOST:
+ type = AQ_SET_ONETOUCH_BOOST;
+ break;
+ default:
+ type = r_type;
+ break;
+ }
+ }
+
+ // Check we are doing something valid request
if (pda_mode() == true) {
pda_reset_sleep();
if (type != AQ_PDA_INIT &&
@@ -332,7 +418,11 @@ void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data)
type != AQ_SET_BOOST) {
logMessage(LOG_ERR, "Selected Programming mode '%d' not supported with PDA mode control panel\n",type);
return;
- }
+ } /*else if (onetouch_enabled() == false &&
+ ( type != AQ_SET_ONETOUCH_PUMP_RPM || type != AQ_SET_ONETOUCH_MACRO || type != AQ_GET_ONETOUCH_SETPOINTS)) {
+ logMessage(LOG_ERR, "Selected Programming mode '%d' not supported without OneTouch mode (extra_device_id) enabled\n",type);
+ return;
+ }*/
}
programmingthread->aq_data = aq_data;
@@ -460,6 +550,54 @@ void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data)
return;
}
break;
+ case AQ_SET_ONETOUCH_PUMP_RPM:
+ if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_pump_rpm, (void*)programmingthread) < 0) {
+ logMessage (LOG_ERR, "could not create thread\n");
+ return;
+ }
+ break;
+ case AQ_GET_ONETOUCH_SETPOINTS:
+ if( pthread_create( &programmingthread->thread_id , NULL , get_aqualink_onetouch_setpoints, (void*)programmingthread) < 0) {
+ logMessage (LOG_ERR, "could not create thread\n");
+ return;
+ }
+ break;
+ case AQ_SET_ONETOUCH_TIME:
+ if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_onetouch_time, (void*)programmingthread) < 0) {
+ logMessage (LOG_ERR, "could not create thread\n");
+ return;
+ }
+ break;
+ case AQ_SET_ONETOUCH_BOOST:
+ if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_onetouch_boost, (void*)programmingthread) < 0) {
+ logMessage (LOG_ERR, "could not create thread\n");
+ return;
+ }
+ break;
+ case AQ_SET_ONETOUCH_SWG_PERCENT:
+ if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_onetouch_swg_percent, (void*)programmingthread) < 0) {
+ logMessage (LOG_ERR, "could not create thread\n");
+ return;
+ }
+ break;
+ case AQ_SET_ONETOUCH_POOL_HEATER_TEMP:
+ if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_onetouch_pool_heater_temp, (void*)programmingthread) < 0) {
+ logMessage (LOG_ERR, "could not create thread\n");
+ return;
+ }
+ break;
+ case AQ_SET_ONETOUCH_SPA_HEATER_TEMP:
+ if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_onetouch_spa_heater_temp, (void*)programmingthread) < 0) {
+ logMessage (LOG_ERR, "could not create thread\n");
+ return;
+ }
+ break;
+ case AQ_SET_ONETOUCH_FREEZEPROTECT:
+ if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_onetouch_freezeprotect, (void*)programmingthread) < 0) {
+ logMessage (LOG_ERR, "could not create thread\n");
+ return;
+ }
+ break;
default:
logMessage (LOG_ERR, "Don't understand thread type\n");
break;
@@ -707,19 +845,17 @@ STOP BOOST POOL
if (val==true) {
waitForMessage(threadCtrl->aq_data, "TO START BOOST POOL", 5);
send_cmd(KEY_ENTER);
- waitfor_queue2empty();
+ longwaitfor_queue2empty();
} else {
int wait_messages = 5;
int i=0;
- //waitfor_queue2empty();
- //waitForMessage(aq_data, NULL, 1);
while( i++ < wait_messages)
{
waitForMessage(aq_data, "STOP BOOST POOL", 1);
if (stristr(aq_data->last_message, "STOP BOOST POOL") != NULL) {
// This is a really bad hack, message sequence is out for boost for some reason, so as soon as we see stop message, force enter key.
- _pgm_command = KEY_ENTER;
- //send_cmd(KEY_ENTER);
+ //_pgm_command = KEY_ENTER;
+ send_cmd(KEY_ENTER);
logMessage(LOG_DEBUG, "**** FOUND STOP BOOST POOL ****\n");
//waitfor_queue2empty();
break;
@@ -727,38 +863,29 @@ STOP BOOST POOL
logMessage(LOG_DEBUG, "Find item in Menu: loop %d of %d looking for 'STOP BOOST POOL' received message '%s'\n",i,wait_messages,aq_data->last_message);
delay(200);
if (stristr(aq_data->last_message, "STOP BOOST POOL") != NULL) {
- _pgm_command = KEY_ENTER;
+ //_pgm_command = KEY_ENTER;
+ send_cmd(KEY_ENTER);
logMessage(LOG_DEBUG, "**** FOUND STOP BOOST POOL ****\n");
break;
}
send_cmd(KEY_RIGHT);
//printf("WAIT\n");
- waitfor_queue2empty();
+ longwaitfor_queue2empty();
//printf("FINISHED WAIT\n");
}
//waitfor_queue2empty();
//waitForMessage(aq_data, NULL, 1);
}
-
- waitForMessage(aq_data, "STOP BOOST POOL", 1);
- if (stristr(aq_data->last_message, "STOP BOOST POOL") != NULL) {
- //logMessage(LOG_DEBUG, "**** FOUND STOP BOOST POOL ****\n");
- send_cmd(KEY_ENTER);
- } else {
- logMessage(LOG_DEBUG, "**** GIVING UP ****\n");
+ if (i < wait_messages) {
+ // Takes ages to see bost is off from menu, to set it here.
+ aq_data->boost = false;
+ aq_data->boost_msg[0] = '\0';
+ aq_data->swg_percent = 0;
}
-/*
- if (stristr(aq_data->last_message, "STOP BOOST POOL") == NULL) {
- send_cmd(KEY_RIGHT);
- logMessage(LOG_DEBUG, "**** FOUND STOP BOOST POOL ****\n");
- } else {
- logMessage(LOG_ERR, "**** NOT FOUND STOP BOOST POOL ****\n");
- }
-*/
- // Extra message overcome.
- //send_cmd(KEY_RIGHT);
- //waitfor_queue2empty();
/*
+ // Extra message overcome.
+ send_cmd(KEY_RIGHT);
+ waitfor_queue2empty();
if ( select_sub_menu_item(aq_data, "STOP BOOST POOL") != true ) {
logMessage(LOG_WARNING, "Could not select STOP BOOST POOL menu\n");
cancel_menu();
@@ -767,6 +894,7 @@ STOP BOOST POOL
}*/
//send_cmd(KEY_ENTER);
}
+
waitForMessage(aq_data,NULL, 1);
cleanAndTerminateThread(threadCtrl);
@@ -1403,11 +1531,11 @@ void send_cmd(unsigned char cmd, struct aqualinkdata *aq_data)
}
*/
-void waitfor_queue2empty()
+void _waitfor_queue2empty(bool longwait)
{
int i=0;
- while ( (_pgm_command != NUL) && ( i++ < 20) ) {
+ while ( (_pgm_command != NUL) && ( i++ < (30*(longwait?2:1) ) ) ) {
//sleep(1); // NSF Change to smaller time.
//logMessage(LOG_DEBUG, "******** QUEUE IS FULL ******** delay\n");
delay(50);
@@ -1416,7 +1544,7 @@ void waitfor_queue2empty()
if (_pgm_command != NUL) {
if (pda_mode()) {
// Wait for longer in PDA mode since it's slower.
- while ( (_pgm_command != NUL) && ( i++ < 100) ) {
+ while ( (_pgm_command != NUL) && ( i++ < (130*(longwait?2:1)) ) ) {
delay(100);
}
}
@@ -1425,6 +1553,15 @@ void waitfor_queue2empty()
}
+void waitfor_queue2empty()
+{
+ _waitfor_queue2empty(false);
+}
+void longwaitfor_queue2empty()
+{
+ _waitfor_queue2empty(true);
+}
+
void send_cmd(unsigned char cmd)
{
waitfor_queue2empty();
@@ -1753,6 +1890,33 @@ const char *ptypeName(program_type type)
case AQ_SET_BOOST:
return "SWG Boost";
break;
+ case AQ_SET_ONETOUCH_PUMP_RPM:
+ return "Set Pump RPM";
+ break;
+ case AQ_SET_ONETOUCH_MACRO:
+ return "Set OneTouch Macro";
+ break;
+ case AQ_GET_ONETOUCH_SETPOINTS:
+ return "Get OneTouch setpoints";
+ break;
+ case AQ_SET_ONETOUCH_TIME:
+ return "Set OneTouch time";
+ break;
+ case AQ_SET_ONETOUCH_BOOST:
+ return "Set OneTouch Boost";
+ break;
+ case AQ_SET_ONETOUCH_SWG_PERCENT:
+ return "Set OneTouch SWG Percent";
+ break;
+ case AQ_SET_ONETOUCH_FREEZEPROTECT:
+ return "Set OneTouch Freezeprotect";
+ break;
+ case AQ_SET_ONETOUCH_POOL_HEATER_TEMP:
+ return "Set OneTouch Pool Heater Temp";
+ break;
+ case AQ_SET_ONETOUCH_SPA_HEATER_TEMP:
+ return "Set OneTouch Spa Heater Temp";
+ break;
case AQP_NULL:
default:
return "Unknown";
diff --git a/aq_programmer.h b/aq_programmer.h
index dfe8ed2..7b02f5c 100644
--- a/aq_programmer.h
+++ b/aq_programmer.h
@@ -2,6 +2,8 @@
#ifndef AQ_PROGRAMMER_H_
#define AQ_PROGRAMMER_H_
+#include
+//#include "aqualink.h"
// need to get the C values from aqualink manual and add those just incase
// someone has the controller set to C.
@@ -21,6 +23,12 @@
#define PTHREAD_ARG 25
#define LIGHT_MODE_BUFER PTHREAD_ARG
+typedef enum emulation_type{
+ ALLBUTTON,
+ ONETOUCH,
+ AQUAPDA // AQUAPALM and PDA are taken as specific type.
+} emulation_type;
+
typedef enum {
AQP_NULL = -1,
AQ_GET_POOL_SPA_HEATER_TEMPS,
@@ -39,7 +47,16 @@ typedef enum {
AQ_PDA_DEVICE_ON_OFF,
AQ_GET_AUX_LABELS,
AQ_PDA_WAKE_INIT,
- AQ_SET_BOOST
+ AQ_SET_BOOST,
+ AQ_SET_ONETOUCH_PUMP_RPM,
+ AQ_SET_ONETOUCH_MACRO,
+ AQ_GET_ONETOUCH_SETPOINTS,
+ AQ_SET_ONETOUCH_POOL_HEATER_TEMP,
+ AQ_SET_ONETOUCH_SPA_HEATER_TEMP,
+ AQ_SET_ONETOUCH_FREEZEPROTECT,
+ AQ_SET_ONETOUCH_TIME,
+ AQ_SET_ONETOUCH_BOOST,
+ AQ_SET_ONETOUCH_SWG_PERCENT
} program_type;
struct programmingThreadCtrl {
@@ -49,14 +66,22 @@ struct programmingThreadCtrl {
struct aqualinkdata *aq_data;
};
+typedef enum pump_type {
+ PT_UNKNOWN = -1,
+ EPUMP,
+ VSPUMP,
+ VFPUMP
+} pump_type;
//void aq_programmer(program_type type, void *args, struct aqualinkdata *aq_data);
void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data);
-void kick_aq_program_thread(struct aqualinkdata *aq_data);
-
+//void kick_aq_program_thread(struct aqualinkdata *aq_data);
+void kick_aq_program_thread(struct aqualinkdata *aq_data, emulation_type source_type);
+bool in_ot_programming_mode(struct aqualinkdata *aq_data);
void aq_send_cmd(unsigned char cmd);
-
+void queueGetProgramData(emulation_type source_type, struct aqualinkdata *aq_data);
+void queueGetExtendedProgramData(emulation_type source_type, struct aqualinkdata *aq_data, bool labels);
unsigned char pop_aq_cmd(struct aqualinkdata *aq_data);
//bool push_aq_cmd(unsigned char cmd);
@@ -68,6 +93,8 @@ unsigned char pop_aq_cmd(struct aqualinkdata *aq_data);
int get_aq_cmd_length();
int setpoint_check(int type, int value, struct aqualinkdata *aqdata);
+int RPM_check(pump_type type, int value, struct aqualinkdata *aqdata);
+//int RPM_check(int type, int value, struct aqualinkdata *aqdata);
const char *ptypeName(program_type type);
// These shouldn't be here, but just for the PDA AQ PROGRAMMER
diff --git a/aq_serial.c b/aq_serial.c
index d9cf9ff..6c0be5d 100644
--- a/aq_serial.c
+++ b/aq_serial.c
@@ -40,7 +40,27 @@ static struct termios _oldtio;
void send_packet(int fd, unsigned char *packet, int length);
//unsigned char getProtocolType(unsigned char* packet);
+/*
+#ifdef ONETOUCH
+bool _onetouch_mode = false;
+void set_onetouch_mode(bool mode)
+{
+ if (mode)
+ logMessage(LOG_NOTICE, "AqualinkD is using Onetouch mode\n");
+
+ _onetouch_mode = mode;
+}
+bool onetouch_mode()
+{
+ return _onetouch_mode;
+}
+#endif
+*/
+
bool _pda_mode = false;
+bool _onetouch_enabled = false;
+bool _extended_device_id_programming = false;
+
void set_pda_mode(bool mode)
{
if (mode)
@@ -53,6 +73,30 @@ bool pda_mode()
return _pda_mode;
}
+void set_onetouch_enabled(bool mode)
+{
+ if (mode)
+ logMessage(LOG_NOTICE, "AqualinkD is using use ONETOUCH mode for VSP programming\n");
+ _onetouch_enabled = mode;
+}
+
+bool onetouch_enabled()
+{
+ return _onetouch_enabled;
+}
+
+void set_extended_device_id_programming(bool mode)
+{
+ if (mode)
+ logMessage(LOG_NOTICE, "AqualinkD is using use ONETOUCH mode for programming (where supported)\n");
+ _extended_device_id_programming = mode;
+}
+
+bool extended_device_id_programming()
+{
+ return _extended_device_id_programming;
+}
+
const char* get_packet_type(unsigned char* packet , int length)
{
static char buf[15];
@@ -101,7 +145,7 @@ const char* get_packet_type(unsigned char* packet , int length)
return "PDA Shiftlines";
break;
case CMD_PDA_HIGHLIGHTCHARS:
- return "PDA C_HlightChar";
+ return "PDA HlightChars";
break;
case CMD_IAQ_MSG:
return "iAq Message";
@@ -438,10 +482,8 @@ void send_packet(int fd, unsigned char *packet, int length)
}
if ( getLogLevel() >= LOG_DEBUG_SERIAL) {
- //char buf[30];
- //sprintf(buf, "Sent %8.8s ", get_packet_type(packet+1, length));
- //log_packet(buf, packet, length);
- logMessage(LOG_DEBUG_SERIAL, "Serial send %d bytes\n",length-2);
+ // Packet is padded with 0x00, so discard for logging
+ logMessage(LOG_DEBUG_SERIAL, "Serial write %d bytes\n",length-2);
logPacket(&packet[1], length-2);
}
}
@@ -460,6 +502,8 @@ void _send_ack(int fd, unsigned char ack_type, unsigned char command)
ackPacket[7] = generate_checksum(ackPacket, length-1);
}
+ //printf("***Send ACK (%s) ***\n",(ack_type==ACK_NORMAL?"Normal":(ack_type==ACK_SCREEN_BUSY?"ScreenBusy":"ScreenBusyDisplay")) );
+
send_packet(fd, ackPacket, length);
}
@@ -660,10 +704,8 @@ int _get_packet(int fd, unsigned char* packet, bool rawlog)
return 0;
}
- if ( getLogLevel() >= LOG_DEBUG_SERIAL) {
- logMessage(LOG_DEBUG_SERIAL, "Serial read %d bytes\n",index);
- logPacket(packet, index);
- }
+ logMessage(LOG_DEBUG_SERIAL, "Serial read %d bytes\n",index);
+ logPacket(packet, index);
// Return the packet length.
return index;
}
@@ -673,6 +715,63 @@ int _get_packet(int fd, unsigned char* packet, bool rawlog)
#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#else //USE_AQ_SERIAL_OLD
diff --git a/aq_serial.h b/aq_serial.h
index 71ce0c2..15b8b95 100644
--- a/aq_serial.h
+++ b/aq_serial.h
@@ -65,9 +65,27 @@
/* ACK RETURN COMMANDS */
#define ACK_NORMAL 0x00
-#define ACK_SCREEN_BUSY 0x01 // Seems to be busy but can cache a message,
+#define ACK_SCREEN_BUSY_SCROLL 0x01 // Seems to be busy but can cache a message,
#define ACK_SCREEN_BUSY_BLOCK 0x03 // Seems to be don't send me shit.
+
+// Remove this and fix all compile errors when get time.
+#define ACK_SCREEN_BUSY ACK_SCREEN_BUSY_SCROLL
+
#define ACK_PDA 0x40
+#define ACK_ONETOUCH 0x80
+#define ACK_ALLB_SIM 0x80 // Jandy's Allbutton simulator uses this and not ACK_NORMAL
+#define ACK_ALLB_SIM_BUSY 0x81 // Jandy's Allbutton simulator uses this and not ACK_SCREEN_BUSY_SCROLL
+
+/* ONE TOUCH KEYCODES */
+#define KEY_ONET_UP 0x06
+#define KEY_ONET_DOWN 0x05
+#define KEY_ONET_SELECT 0x04
+#define KEY_ONET_PAGE_UP 0x03 // Top
+#define KEY_ONET_BACK 0x02 // Middle
+#define KEY_ONET_PAGE_DN 0x01 // Bottom
+#define KEY_ONET_SELECT_1 KEY_ONET_PAGE_UP
+#define KEY_ONET_SELECT_2 KEY_ONET_BACK
+#define KEY_ONET_SELECT_3 KEY_ONET_PAGE_DN
/* AquaRite commands */
#define CMD_GETID 0x14 // May be remote control control
@@ -187,7 +205,7 @@ SPILLOVER IS DISABLED WHILE SPA IS ON
#define MSG_PMP_RPM "RPM:"
#define MSG_PMP_WAT "Watts:"
-#define MSG_PMP_GPH "GPH:"
+#define MSG_PMP_GPM "GPM:"
/* AQUAPURE SWG */
@@ -221,11 +239,36 @@ SPILLOVER IS DISABLED WHILE SPA IS ON
#define CMD_PDA_SHIFTLINES 0x0F
#define CMD_PDA_HIGHLIGHTCHARS 0x10
+// One Touch commands
+//#define CMD_PDA_0x04 0x04 // No idea, might be building menu
+
/* iAqualink */
-#define CMD_IAQ_MSG 0x25
+/* None of these are used, just here to gather data for the moment */
+#define CMD_IAQ_MSG 0x25 // Equiptment status message??
#define CMD_IAQ_MENU_MSG 0x24
+#define CMD_IAQ_MSG_LONG 0x2c // Long status message??
+#define CMD_IAQ_MSG_3 0x2d // Equiptment status message??
+#define CMD_IAQ_0x30 0x30
+#define CMD_IAQ_0x23 0x23
+#define CMD_IAQ_0x24 0x24 // Text for labels or maybe buttons (looks like next BIT is placment)
+#define CMD_IAQ_0x25 0x25 // Status for labels
+#define CMD_IAQ_0x31 0x31 // Some pump speed info
+#define IAQ_KEY_PUMP 0x11
+#define IAQ_KEY_SPA 0x12
+#define IAQ_KEY_POOL_HEAT 0x13
+#define IAQ_KEY_SPA_HEAT 0x14
+#define IAQ_KEY_CUST_1 0x15
+#define IAQ_KEY_CUST_2 0x16
+#define IAQ_KEY_CUST_3 0x17
+#define IAQ_KEY_AUX1 0x19 // Depending on page this is 0x15
+#define IAQ_KEY_AUX2 0x1a
+#define IAQ_KEY_AUX3 0x1b
+#define IAQ_KEY_AUX4 0x1c
+#define IAQ_KEY_AUX5 0x1d
+#define IAQ_KEY_AUX6 0x1e
+#define IAQ_KEY_AUX7 0x1f
typedef enum {
ON,
@@ -275,11 +318,22 @@ int get_packet_lograw(int fd, unsigned char* packet);
void process_status(unsigned char* ptr);
const char* get_packet_type(unsigned char* packet , int length);
+void set_onetouch_enabled(bool mode);
+bool onetouch_enabled();
+
+void set_extended_device_id_programming(bool mode);
+bool extended_device_id_programming();
void send_jandy_command(int fd, unsigned char *packet_buffer, int size);
void send_pentair_command(int fd, unsigned char *packet_buffer, int size);
void send_command(int fd, unsigned char *packet_buffer, int size);
+/*
+#ifdef ONETOUCH
+void set_onetouch_mode(bool mode);
+bool onetouch_mode();
+#endif
+*/
//void send_test_cmd(int fd, unsigned char destination, unsigned char b1, unsigned char b2, unsigned char b3);
//void send_command(int fd, unsigned char destination, unsigned char b1, unsigned char b2, unsigned char b3);
//void send_messaged(int fd, unsigned char destination, char *message);
diff --git a/aqualink.h b/aqualink.h
index 8055522..1fc96e7 100644
--- a/aqualink.h
+++ b/aqualink.h
@@ -59,25 +59,40 @@ typedef enum action_type {
SPA_HTR_SETOINT,
FREEZE_SETPOINT,
SWG_SETPOINT,
- SWG_BOOST
+ SWG_BOOST,
+ PUMP_RPM
} action_type;
struct action {
action_type type;
time_t requested;
int value;
+ int id; // Only used for Pumps at the moment.
//char value[10];
};
+// Moved to aq_programmer to stop circular dependancy
+/*
+typedef enum pump_type {
+ PT_UNKNOWN = -1,
+ EPUMP,
+ VSPUMP,
+ VFPUMP
+} pump_type;
+*/
+
typedef struct pumpd
{
int rpm;
- int gph;
+ int gpm;
int watts;
unsigned char pumpID;
+ int pumpIndex;
+ pump_type pumpType;
//int buttonID;
protocolType ptype;
aqkey *button;
+ //bool updated;
} pump_detail;
struct aqualinkdata
@@ -115,6 +130,7 @@ struct aqualinkdata
aqledstate service_mode_state;
aqledstate frz_protect_state;
unsigned char last_packet_type;
+ int num_pumps;
pump_detail pumps[MAX_PUMPS];
int open_websockets;
bool boost;
diff --git a/aqualinkd.c b/aqualinkd.c
index 9c6fedb..141e867 100644
--- a/aqualinkd.c
+++ b/aqualinkd.c
@@ -28,6 +28,7 @@
#include // Need GNU_SOURCE & XOPEN defined for strptime
+#define AQUALINKD_C
#include "mongoose.h"
#include "aqualink.h"
#include "utils.h"
@@ -42,14 +43,15 @@
#include "pda_aq_programmer.h"
#include "packetLogger.h"
#include "aquapure.h"
+#include "onetouch.h"
+#include "onetouch_aq_programmer.h"
#include "version.h"
-//#define PROCESS_INCOMPLETE_MESSAGES
//#define DEFAULT_CONFIG_FILE "./aqualinkd.conf"
static volatile bool _keepRunning = true;
-static struct aqconfig _config_parameters;
+//static struct aqconfig _aqconfig_;
static struct aqualinkdata _aqualink_data;
void main_loop();
@@ -182,26 +184,34 @@ void aqualink_strcpy(char *dest, char *src)
//dest[10] = '\0';
}
*/
+/*
void queueGetProgramData()
{
//aq_programmer(AQ_GET_DIAGNOSTICS_MODEL, NULL, &_aqualink_data);
// Init string good time to get setpoints
//aq_programmer(AQ_SEND_CMD, (char *)KEY_ENTER, &_aqualink_data);
//aq_programmer(AQ_SEND_CMD, (char *)*NUL, &_aqualink_data);
+
+#ifndef DEBUG_NO_INIT_TEST_REMOVE
aq_send_cmd(NUL);
aq_programmer(AQ_GET_POOL_SPA_HEATER_TEMPS, NULL, &_aqualink_data);
aq_programmer(AQ_GET_FREEZE_PROTECT_TEMP, NULL, &_aqualink_data);
+#endif
+
//aq_programmer(AQ_GET_POOL_SPA_HEATER_TEMPS, NULL, &_aqualink_data);
- if (_config_parameters.use_panel_aux_labels == true)
+ if (_aqconfig_.use_panel_aux_labels == true)
{
aq_programmer(AQ_GET_AUX_LABELS, NULL, &_aqualink_data);
}
//aq_programmer(AQ_GET_PROGRAMS, NULL, &_aqualink_data); // only displays to log at present, also seems to confuse getting set_points
}
-
+*/
void setUnits(char *msg)
{
- logMessage(LOG_DEBUG, "Getting temp units from message %s, looking at %c", msg, msg[strlen(msg) - 1]);
+ char buf[AQ_MSGLEN*3];
+
+ ascii(buf, msg);
+ logMessage(LOG_DEBUG, "Getting temp units from message '%s', looking at '%c'\n", buf, buf[strlen(buf) - 1]);
if (msg[strlen(msg) - 1] == 'F')
_aqualink_data.temp_units = FAHRENHEIT;
@@ -210,20 +220,29 @@ void setUnits(char *msg)
else
_aqualink_data.temp_units = UNKNOWN;
- logMessage(LOG_INFO, "Temp Units set to %d (F=0, C=1, Unknown=3)", _aqualink_data.temp_units);
+ logMessage(LOG_INFO, "Temp Units set to %d (F=0, C=1, Unknown=2)\n", _aqualink_data.temp_units);
}
+
+
+#define MSG_FREEZE 1 // 2^0, bit 0
+#define MSG_SERVICE 2 // 2^1, bit 1
+#define MSG_SWG 4 // 2^2, bit 2
+#define MSG_BOOST 8 // 2^3, bit 3
+
void processMessage(char *message)
{
char *msg;
static bool _initWithRS = false;
static bool _gotREV = false;
- static int freeze_msg_count = 0;
- static int service_msg_count = 0;
- static int swg_msg_count = 0;
- static int boost_msg_count = 0;
+ //static int freeze_msg_count = 0;
+ //static int service_msg_count = 0;
+ //static int swg_msg_count = 0;
+ //static int boost_msg_count = 0;
+ static unsigned char msg_loop = '\0';
// NSF replace message with msg
msg = stripwhitespace(message);
+
strcpy(_aqualink_data.last_message, msg);
//_aqualink_data.last_message = _aqualink_data.message;
//_aqualink_data.display_message = NULL;
@@ -233,6 +252,9 @@ void processMessage(char *message)
logMessage(LOG_INFO, "RS Message :- '%s'\n", msg);
//logMessage(LOG_NOTICE, "RS Message :- '%s'\n",msg);
+ // Just set this to off, it will re-set since it'll be the only message we get if on
+ _aqualink_data.service_mode_state = OFF;
+
// Check long messages in this if/elseif block first, as some messages are similar.
// ie "POOL TEMP" and "POOL TEMP IS SET TO" so want correct match first.
//
@@ -240,40 +262,26 @@ void processMessage(char *message)
if (stristr(msg, "JANDY AquaLinkRS") != NULL) {
//_aqualink_data.display_message = NULL;
_aqualink_data.last_display_message[0] = '\0';
- }
- // Don't do any message counts if we are programming
- if (_aqualink_data.active_thread.thread_id == 0) {
- // If we have more than 10 messages without "Service Mode is active" assume it's off.
- if (_aqualink_data.service_mode_state != OFF && service_msg_count++ > 10) {
- _aqualink_data.service_mode_state = OFF;
- service_msg_count = 0;
- }
-
- // If we have more than 40 messages without "SALT or AQUAPURE" assume SWG is off.
- if ( _config_parameters.read_all_devices == false ) {
- if (_aqualink_data.ar_swg_status == SWG_STATUS_ON && swg_msg_count++ > 40) {
- //printf("***************** Manually turned SWG off ************************\n");
- _aqualink_data.ar_swg_status = SWG_STATUS_OFF;
- swg_msg_count = 0;
- }
- }
-
- // If we have more than 10 messages without "FREE PROTECT ACTIVATED" assume it's off.
- if (_aqualink_data.frz_protect_state == ON && freeze_msg_count++ > 10) {
- _aqualink_data.frz_protect_state = ENABLE;
- freeze_msg_count = 0;
- }
+ // Anything that wasn't on during the last set of messages, turn off
+ if ((msg_loop & MSG_FREEZE) != MSG_FREEZE)
+ _aqualink_data.frz_protect_state = OFF;
- if (_aqualink_data.boost == true && boost_msg_count++ > 10) {
+ //if ((msg_loop & MSG_SERVICE) != MSG_SERVICE)
+ // _aqualink_data.service_mode_state = OFF; // IF we get this message then Service / Timeout is off
+
+ if ((msg_loop & MSG_SWG) != MSG_SWG)
+ _aqualink_data.ar_swg_status = SWG_STATUS_OFF;
+
+ if ((msg_loop & MSG_BOOST) != MSG_BOOST) {
_aqualink_data.boost = false;
_aqualink_data.boost_msg[0] = '\0';
- boost_msg_count = 0;
+ if (_aqualink_data.swg_percent >= 101)
+ _aqualink_data.swg_percent = 0;
}
- }
- //else
- //_aqualink_data.display_last_message = false;
+ msg_loop = '\0';
+ }
if (stristr(msg, LNG_MSG_BATTERY_LOW) != NULL)
{
@@ -371,30 +379,35 @@ void processMessage(char *message)
if (_aqualink_data.service_mode_state == OFF)
logMessage(LOG_NOTICE, "AqualinkD set to Service Mode\n");
_aqualink_data.service_mode_state = ON;
- service_msg_count = 0;
+ msg_loop |= MSG_SERVICE;
+ //service_msg_count = 0;
}
else if (stristr(msg, LNG_MSG_TIMEOUT_ACTIVE) != NULL)
{
if (_aqualink_data.service_mode_state == OFF)
logMessage(LOG_NOTICE, "AqualinkD set to Timeout Mode\n");
_aqualink_data.service_mode_state = FLASH;
- service_msg_count = 0;
+ msg_loop |= MSG_SERVICE;
+ //service_msg_count = 0;
}
else if (stristr(msg, LNG_MSG_FREEZE_PROTECTION_ACTIVATED) != NULL)
{
+ msg_loop |= MSG_FREEZE;
_aqualink_data.frz_protect_state = ON;
- freeze_msg_count = 0;
+ //freeze_msg_count = 0;
strcpy(_aqualink_data.last_display_message, msg); // Also display the message on web UI
}
else if (msg[2] == '/' && msg[5] == '/' && msg[8] == ' ')
{ // date in format '08/29/16 MON'
strcpy(_aqualink_data.date, msg);
}
- else if (strncasecmp(msg, MSG_SWG_PCT, MSG_SWG_PCT_LEN) == 0)
+ //else if (strncasecmp(msg, MSG_SWG_PCT, MSG_SWG_PCT_LEN) == 0)
+ else if (strncasecmp(msg, MSG_SWG_PCT, MSG_SWG_PCT_LEN) == 0 && strncasecmp(msg, "AQUAPURE HRS", 12) != 0)
{
_aqualink_data.swg_percent = atoi(msg + MSG_SWG_PCT_LEN);
if (_aqualink_data.ar_swg_status == SWG_STATUS_OFF) {_aqualink_data.ar_swg_status = SWG_STATUS_ON;}
- swg_msg_count = 0;
+ //swg_msg_count = 0;
+ msg_loop |= MSG_SWG;
//logMessage(LOG_DEBUG, "*** '%s' ***\n", msg);
//logMessage(LOG_DEBUG, "SWG set to %d due to message from control panel\n", _aqualink_data.swg_percent);
}
@@ -402,7 +415,8 @@ void processMessage(char *message)
{
_aqualink_data.swg_ppm = atoi(msg + MSG_SWG_PPM_LEN);
if (_aqualink_data.ar_swg_status == SWG_STATUS_OFF) {_aqualink_data.ar_swg_status = SWG_STATUS_ON;}
- swg_msg_count = 0;
+ msg_loop |= MSG_SWG;
+ //swg_msg_count = 0;
//logMessage(LOG_DEBUG, "Stored SWG PPM as %d\n", _aqualink_data.swg_ppm);
}
else if ((msg[1] == ':' || msg[2] == ':') && msg[strlen(msg) - 1] == 'M')
@@ -434,7 +448,8 @@ void processMessage(char *message)
logMessage(LOG_NOTICE, "Control Panel %s\n", msg);
if (_initWithRS == false)
{
- queueGetProgramData();
+ //queueGetProgramData(ALLBUTTON, &_aqualink_data);
+ queueGetExtendedProgramData(ALLBUTTON, &_aqualink_data, _aqconfig_.use_panel_aux_labels);
_initWithRS = true;
}
}
@@ -442,7 +457,7 @@ void processMessage(char *message)
{
logMessage(LOG_NOTICE, "Program data '%s'\n", msg);
}
- else if (_config_parameters.override_freeze_protect == TRUE && strncasecmp(msg, "Press Enter* to override Freeze Protection with", 47) == 0)
+ else if (_aqconfig_.override_freeze_protect == TRUE && strncasecmp(msg, "Press Enter* to override Freeze Protection with", 47) == 0)
{
//send_cmd(KEY_ENTER, aq_data);
//aq_programmer(AQ_SEND_CMD, (char *)KEY_ENTER, &_aqualink_data);
@@ -451,7 +466,7 @@ void processMessage(char *message)
else if ((msg[4] == ':') && (strncasecmp(msg, "AUX", 3) == 0))
{ // AUX label "AUX1:"
int labelid = atoi(msg + 3);
- if (labelid > 0 && _config_parameters.use_panel_aux_labels == true)
+ if (labelid > 0 && _aqconfig_.use_panel_aux_labels == true)
{
// Aux1: on panel = Button 3 in aqualinkd (button 2 in array)
logMessage(LOG_NOTICE, "AUX LABEL %d '%s'\n", labelid + 1, msg);
@@ -460,12 +475,16 @@ void processMessage(char *message)
}
}
// BOOST POOL 23:59 REMAINING
- else if ( (strncasecmp(msg, "BOOST POOL", 10) == 0) && (strstr(msg, "REMAINING") != NULL) ) {
+ else if ( (strncasecmp(msg, "BOOST POOL", 10) == 0) && (strcasestr(msg, "REMAINING") != NULL) ) {
// Ignore messages if in programming mode. We get one of these turning off for some strange reason.
if (_aqualink_data.active_thread.thread_id == 0) {
snprintf(_aqualink_data.boost_msg, 6, &msg[11]);
_aqualink_data.boost = true;
- boost_msg_count = 0;
+ msg_loop |= MSG_BOOST;
+ msg_loop |= MSG_SWG;
+ if (_aqualink_data.ar_swg_status != SWG_STATUS_ON) {_aqualink_data.ar_swg_status = SWG_STATUS_ON;}
+ if (_aqualink_data.swg_percent != 101) {_aqualink_data.swg_percent = 101;}
+ //boost_msg_count = 0;
//if (_aqualink_data.active_thread.thread_id == 0)
strcpy(_aqualink_data.last_display_message, msg); // Also display the message on web UI if not in programming mode
}
@@ -494,59 +513,9 @@ void processMessage(char *message)
// We processed the next message, kick any threads waiting on the message.
//printf ("Message kicking\n");
- kick_aq_program_thread(&_aqualink_data);
+ kick_aq_program_thread(&_aqualink_data, ALLBUTTON);
}
-/*
-bool process_pda_monitor_packet(unsigned char *packet, int length)
-{
- bool rtn = false;
- static bool checkedMenu = false;
- process_pda_menu_packet(packet, length);
-
- //printf("*** PDA Received 0x%02hhx %s ***\n", packet[PKT_CMD], get_packet_type(packet, length));
-
- if (packet[PKT_CMD] == CMD_STATUS && pda_m_type() == PM_EQUIPTMENT_STATUS && checkedMenu == false) {
- // Can't use any of the build in pda_menu find functions.
- //printf("*** PDA Checking equiptment status ***\n");
- logMessage(LOG_INFO, "Checking PDA equiptment status\n");
- int i;
- char *index;
- int pi = 0;
- for (i = 0; i < PDA_LINES; i++) {
- if (strcasestr(pda_m_line(i), "epump") != NULL || strcasestr(pda_m_line(i), "Intelliflo") != NULL )
- { // Pump labels arew ePUMP & Intelliflo with number at end "Jandy ePUMP 1" "Intelliflo VS 1"
- pi = atoi(pda_m_line(i)+14)-1;
- if (pi < 0 || pi >= MAX_PUMPS-1)
- pi = 0;
- }
- else if ((index = strcasestr(pda_m_line(i), MSG_PMP_RPM)) != NULL)
- {
- _aqualink_data.pumps[0].rpm = atoi(index + strlen(MSG_PMP_RPM));
- rtn = true;
- logMessage(LOG_DEBUG, "Pump %d RPM = %d\n", pi+1, _aqualink_data.pumps[0].rpm);
- }
- else if ((index = strcasestr(pda_m_line(i), MSG_PMP_WAT)) != NULL)
- { // Default to pump 0, should check for correct pump
- _aqualink_data.pumps[pi].watts = atoi(index + strlen(MSG_PMP_WAT));
- rtn = true;
- logMessage(LOG_DEBUG, "Pump %d Watts = %d\n", pi+1, _aqualink_data.pumps[pi].watts);
- }
- else if ((index = strcasestr(pda_m_line(i), MSG_PMP_GPH)) != NULL)
- { // Default to pump 0, should check for correct pump
- _aqualink_data.pumps[pi].gph = atoi(index + strlen(MSG_PMP_GPH));
- rtn = true;
- logMessage(LOG_DEBUG, "Pump %d GPH = %d\n", pi+1, _aqualink_data.pumps[pi].watts);
- }
- }
- checkedMenu = true;
- } else if (packet[PKT_CMD] != CMD_STATUS) { // a lot of STATUS messages after menu has been created, so ignore them reset on different message
- checkedMenu = false;
- }
-
- return rtn;
-}
-*/
bool process_packet(unsigned char *packet, int length)
{
bool rtn = false;
@@ -567,12 +536,11 @@ bool process_packet(unsigned char *packet, int length)
rtn = true;
}
- if (_config_parameters.pda_mode == true)
+ if (_aqconfig_.pda_mode == true)
{
return process_pda_packet(packet, length);
}
- // If we are in the middle of processing a message, and get another, we end the message
if (processing_long_msg > 0 && packet[PKT_CMD] != CMD_MSG_LONG)
{
processing_long_msg = 0;
@@ -594,11 +562,11 @@ bool process_packet(unsigned char *packet, int length)
{
_aqualink_data.pool_temp = TEMP_UNKNOWN;
_aqualink_data.spa_temp = TEMP_UNKNOWN;
- //_aqualink_data.spa_temp = _config_parameters.report_zero_spa_temp?-18:TEMP_UNKNOWN;
+ //_aqualink_data.spa_temp = _aqconfig_.report_zero_spa_temp?-18:TEMP_UNKNOWN;
}
else if (_aqualink_data.aqbuttons[SPA_INDEX].led->state == OFF && _aqualink_data.single_device != true)
{
- //_aqualink_data.spa_temp = _config_parameters.report_zero_spa_temp?-18:TEMP_UNKNOWN;
+ //_aqualink_data.spa_temp = _aqconfig_.report_zero_spa_temp?-18:TEMP_UNKNOWN;
_aqualink_data.spa_temp = TEMP_UNKNOWN;
}
else if (_aqualink_data.aqbuttons[SPA_INDEX].led->state == ON && _aqualink_data.single_device != true)
@@ -609,11 +577,11 @@ bool process_packet(unsigned char *packet, int length)
// COLOR MODE programming relies on state changes, so let any threads know
if (_aqualink_data.active_thread.ptype == AQ_SET_COLORMODE) {
//printf ("Light thread kicking\n");
- kick_aq_program_thread(&_aqualink_data);
+ kick_aq_program_thread(&_aqualink_data, ALLBUTTON);
}
break;
- case CMD_MSG:
- case CMD_MSG_LONG:
+ case CMD_MSG:
+ case CMD_MSG_LONG:
{
int index = packet[PKT_DATA]; // Will get 0x00 for complete message, 0x01 for start on long message 0x05 last of long message
//printf("RSM received message at index %d '%.*s'\n",index,AQ_MSGLEN,(char *)packet + PKT_DATA + 1);
@@ -628,7 +596,7 @@ bool process_packet(unsigned char *packet, int length)
//printf("RSM Long message index %d doesn't match buffer %d\n",index,processing_long_msg);
}
#ifdef PROCESS_INCOMPLETE_MESSAGES
- kick_aq_program_thread(&_aqualink_data);
+ kick_aq_program_thread(&_aqualink_data, ALLBUTTON);
#endif
}
@@ -639,37 +607,6 @@ bool process_packet(unsigned char *packet, int length)
}
break;
-/*
- case CMD_MSG:
- memset(message, 0, AQ_MSGLONGLEN + 1);
- strncpy(message, (char *)packet + PKT_DATA + 1, AQ_MSGLEN);
-
- logMessage(LOG_DEBUG_SERIAL, "RS Received message '%s'\n",message);
- //kick_aq_program_thread(&_aqualink_data);
-
- if (packet[PKT_DATA] == 1) // Start of long message, get them all before processing
- {
-//printf ("Start long message thread kicking\n");
-// kick_aq_program_thread(&_aqualink_data);
- break;
- }
- processMessage(message); // This will kick thread
- //processMessage(message);
- break;
- case CMD_MSG_LONG:
- // First in sequence is normal message.
- processing_long_msg++;
- strncpy(&message[processing_long_msg * AQ_MSGLEN], (char *)packet + PKT_DATA + 1, AQ_MSGLEN);
- logMessage(LOG_DEBUG_SERIAL, "RS Received long message '%s'\n",message);
- if (processing_long_msg == 3)
- {
- //logMessage(LOG_DEBUG, "RS Finished receiving of MSG_LONG '%s'\n",message);
- processMessage(message); // This will kick thread
- processing_long_msg = 0;
- } else {
- //kick_aq_program_thread(&_aqualink_data);
- }
- break;*/
case CMD_PROBE:
logMessage(LOG_DEBUG, "RS Received PROBE length %d.\n", length);
//logMessage(LOG_INFO, "Synch'ing with Aqualink master device...\n");
@@ -689,8 +626,9 @@ void action_delayed_request()
char sval[10];
snprintf(sval, 9, "%d", _aqualink_data.unactioned.value);
- // If we don't know the units yet, we can't action, so wait until we do.
- if (_aqualink_data.temp_units == UNKNOWN && _aqualink_data.unactioned.type != SWG_SETPOINT)
+ // If we don't know the units yet, we can't action setpoint, so wait until we do.
+ if (_aqualink_data.temp_units == UNKNOWN &&
+ (_aqualink_data.unactioned.type == POOL_HTR_SETOINT || _aqualink_data.unactioned.type == SPA_HTR_SETOINT || _aqualink_data.unactioned.type == FREEZE_SETPOINT))
return;
if (_aqualink_data.unactioned.type == POOL_HTR_SETOINT)
@@ -768,9 +706,16 @@ void action_delayed_request()
// Let's just tell everyone we set it, before we actually did. Makes homekit happy, and it will re-correct on error.
_aqualink_data.boost = _aqualink_data.unactioned.value;
}
+ else if (_aqualink_data.unactioned.type == PUMP_RPM)
+ {
+ snprintf(sval, 9, "%1d|%d", _aqualink_data.unactioned.id, _aqualink_data.unactioned.value);
+ //printf("**** program string '%s'\n",sval);
+ aq_programmer(AQ_SET_ONETOUCH_PUMP_RPM, sval, &_aqualink_data);
+ }
_aqualink_data.unactioned.type = NO_ACTION;
_aqualink_data.unactioned.value = -1;
+ _aqualink_data.unactioned.id = -1;
_aqualink_data.unactioned.requested = 0;
}
@@ -785,10 +730,10 @@ void printHelp()
printf("\t-rsd (RS485 debug)\n");
printf("\t-rsrd (RS485 raw debug)\n");
}
+
+
int main(int argc, char *argv[])
{
- // main_loop ();
-
int i, j;
//char *cfgFile = DEFAULT_CONFIG_FILE;
char defaultCfg[] = "./aqualinkd.conf";
@@ -796,12 +741,44 @@ int main(int argc, char *argv[])
int cmdln_loglevel = -1;
bool cmdln_debugRS485 = false;
bool cmdln_lograwRS485 = false;
+ _aqualink_data.num_pumps = 0;
+
+/*
+ static unsigned char msg_loop; // = '\0';
+ //msg_loop &= ~MSG_SERVICE;
+ if ((msg_loop & MSG_SERVICE) != MSG_SERVICE)
+ printf("Off\n");
+ else
+ printf("On\n");
+
+ //msg_loop &= ~MSG_SERVICE;
+ msg_loop |= MSG_SERVICE;
+ if ((msg_loop & MSG_SERVICE) != MSG_SERVICE)
+ printf("Off\n");
+ else
+ printf("On\n");
+
+ msg_loop |= MSG_SERVICE;
+ if ((msg_loop & MSG_SERVICE) != MSG_SERVICE)
+ printf("Off\n");
+ else
+ printf("On\n");
+
+ msg_loop |= MSG_SERVICE;
+ if ((msg_loop & MSG_SERVICE) != MSG_SERVICE)
+ printf("Off\n");
+ else
+ printf("On\n");
+
+
+ return 0;
+*/
if (argc > 1 && strcmp(argv[1], "-h") == 0)
- {
- printHelp();
- return 0;
- }
+ {
+ printHelp();
+ return 0;
+ }
// struct lws_context_creation_info info;
// Log only NOTICE messages and above. Debug and info messages
@@ -816,7 +793,8 @@ int main(int argc, char *argv[])
}
// Initialize the daemon's parameters.
- init_parameters(&_config_parameters);
+ //init_parameters(&_aqconfig_);
+ init_config();
cfgFile = defaultCfg;
//sprintf(cfgFile, "%s", DEFAULT_CONFIG_FILE);
@@ -829,7 +807,7 @@ int main(int argc, char *argv[])
}
if (strcmp(argv[i], "-d") == 0)
{
- _config_parameters.deamonize = false;
+ _aqconfig_.deamonize = false;
}
else if (strcmp(argv[i], "-c") == 0)
{
@@ -854,91 +832,95 @@ int main(int argc, char *argv[])
}
initButtons(&_aqualink_data);
-
- readCfg(&_config_parameters, &_aqualink_data, cfgFile);
+
+ read_config(&_aqualink_data, cfgFile);
if (cmdln_loglevel != -1)
- _config_parameters.log_level = cmdln_loglevel;
+ _aqconfig_.log_level = cmdln_loglevel;
if (cmdln_debugRS485)
- _config_parameters.debug_RSProtocol_packets = true;
+ _aqconfig_.debug_RSProtocol_packets = true;
if (cmdln_lograwRS485)
- _config_parameters.log_raw_RS_bytes = true;
+ _aqconfig_.log_raw_RS_bytes = true;
- if (_config_parameters.display_warnings_web == true)
- setLoggingPrms(_config_parameters.log_level, _config_parameters.deamonize, _config_parameters.log_file, _aqualink_data.last_display_message);
+ if (_aqconfig_.display_warnings_web == true)
+ setLoggingPrms(_aqconfig_.log_level, _aqconfig_.deamonize, _aqconfig_.log_file, _aqualink_data.last_display_message);
else
- setLoggingPrms(_config_parameters.log_level, _config_parameters.deamonize, _config_parameters.log_file, NULL);
+ setLoggingPrms(_aqconfig_.log_level, _aqconfig_.deamonize, _aqconfig_.log_file, NULL);
logMessage(LOG_NOTICE, "%s v%s\n", AQUALINKD_NAME, AQUALINKD_VERSION);
- logMessage(LOG_NOTICE, "Config log_level = %d\n", _config_parameters.log_level);
- logMessage(LOG_NOTICE, "Config socket_port = %s\n", _config_parameters.socket_port);
- logMessage(LOG_NOTICE, "Config serial_port = %s\n", _config_parameters.serial_port);
- logMessage(LOG_NOTICE, "Config web_directory = %s\n", _config_parameters.web_directory);
- logMessage(LOG_NOTICE, "Config device_id = 0x%02hhx\n", _config_parameters.device_id);
- logMessage(LOG_NOTICE, "Config read_all_devices = %s\n", bool2text(_config_parameters.read_all_devices));
- logMessage(LOG_NOTICE, "Config use_aux_labels = %s\n", bool2text(_config_parameters.use_panel_aux_labels));
- logMessage(LOG_NOTICE, "Config override frz prot = %s\n", bool2text(_config_parameters.override_freeze_protect));
+ logMessage(LOG_NOTICE, "Config log_level = %d\n", _aqconfig_.log_level);
+ logMessage(LOG_NOTICE, "Config socket_port = %s\n", _aqconfig_.socket_port);
+ logMessage(LOG_NOTICE, "Config serial_port = %s\n", _aqconfig_.serial_port);
+ logMessage(LOG_NOTICE, "Config web_directory = %s\n", _aqconfig_.web_directory);
+ logMessage(LOG_NOTICE, "Config device_id = 0x%02hhx\n", _aqconfig_.device_id);
+ logMessage(LOG_NOTICE, "Config extra_device_id = 0x%02hhx\n", _aqconfig_.onetouch_device_id);
+ logMessage(LOG_NOTICE, "Config extra_device_prog = %s\n", bool2text(_aqconfig_.extended_device_id_programming));
+ logMessage(LOG_NOTICE, "Config read_all_devices = %s\n", bool2text(_aqconfig_.read_all_devices));
+ logMessage(LOG_NOTICE, "Config use_aux_labels = %s\n", bool2text(_aqconfig_.use_panel_aux_labels));
+ logMessage(LOG_NOTICE, "Config override frz prot = %s\n", bool2text(_aqconfig_.override_freeze_protect));
#ifndef MG_DISABLE_MQTT
- logMessage(LOG_NOTICE, "Config mqtt_server = %s\n", _config_parameters.mqtt_server);
- logMessage(LOG_NOTICE, "Config mqtt_dz_sub_topic = %s\n", _config_parameters.mqtt_dz_sub_topic);
- logMessage(LOG_NOTICE, "Config mqtt_dz_pub_topic = %s\n", _config_parameters.mqtt_dz_pub_topic);
- logMessage(LOG_NOTICE, "Config mqtt_aq_topic = %s\n", _config_parameters.mqtt_aq_topic);
- logMessage(LOG_NOTICE, "Config mqtt_user = %s\n", _config_parameters.mqtt_user);
- logMessage(LOG_NOTICE, "Config mqtt_passwd = %s\n", _config_parameters.mqtt_passwd);
- logMessage(LOG_NOTICE, "Config mqtt_ID = %s\n", _config_parameters.mqtt_ID);
- logMessage(LOG_NOTICE, "Config idx water temp = %d\n", _config_parameters.dzidx_air_temp);
- logMessage(LOG_NOTICE, "Config idx pool temp = %d\n", _config_parameters.dzidx_pool_water_temp);
- logMessage(LOG_NOTICE, "Config idx spa temp = %d\n", _config_parameters.dzidx_spa_water_temp);
- logMessage(LOG_NOTICE, "Config idx SWG Percent = %d\n", _config_parameters.dzidx_swg_percent);
- logMessage(LOG_NOTICE, "Config idx SWG PPM = %d\n", _config_parameters.dzidx_swg_ppm);
- logMessage(LOG_NOTICE, "Config PDA Mode = %s\n", bool2text(_config_parameters.pda_mode));
- logMessage(LOG_NOTICE, "Config PDA Sleep Mode = %s\n", bool2text(_config_parameters.pda_sleep_mode));
- logMessage(LOG_NOTICE, "Config force SWG = %s\n", bool2text(_config_parameters.force_swg));
+ logMessage(LOG_NOTICE, "Config mqtt_server = %s\n", _aqconfig_.mqtt_server);
+ logMessage(LOG_NOTICE, "Config mqtt_dz_sub_topic = %s\n", _aqconfig_.mqtt_dz_sub_topic);
+ logMessage(LOG_NOTICE, "Config mqtt_dz_pub_topic = %s\n", _aqconfig_.mqtt_dz_pub_topic);
+ logMessage(LOG_NOTICE, "Config mqtt_aq_topic = %s\n", _aqconfig_.mqtt_aq_topic);
+ logMessage(LOG_NOTICE, "Config mqtt_user = %s\n", _aqconfig_.mqtt_user);
+ logMessage(LOG_NOTICE, "Config mqtt_passwd = %s\n", _aqconfig_.mqtt_passwd);
+ logMessage(LOG_NOTICE, "Config mqtt_ID = %s\n", _aqconfig_.mqtt_ID);
+ logMessage(LOG_NOTICE, "Config idx water temp = %d\n", _aqconfig_.dzidx_air_temp);
+ logMessage(LOG_NOTICE, "Config idx pool temp = %d\n", _aqconfig_.dzidx_pool_water_temp);
+ logMessage(LOG_NOTICE, "Config idx spa temp = %d\n", _aqconfig_.dzidx_spa_water_temp);
+ logMessage(LOG_NOTICE, "Config idx SWG Percent = %d\n", _aqconfig_.dzidx_swg_percent);
+ logMessage(LOG_NOTICE, "Config idx SWG PPM = %d\n", _aqconfig_.dzidx_swg_ppm);
+ logMessage(LOG_NOTICE, "Config PDA Mode = %s\n", bool2text(_aqconfig_.pda_mode));
+ logMessage(LOG_NOTICE, "Config PDA Sleep Mode = %s\n", bool2text(_aqconfig_.pda_sleep_mode));
+ logMessage(LOG_NOTICE, "Config force SWG = %s\n", bool2text(_aqconfig_.force_swg));
/* removed until domoticz has a better virtual thermostat
- logMessage(LOG_NOTICE, "Config idx pool thermostat = %d\n", _config_parameters.dzidx_pool_thermostat);
- logMessage(LOG_NOTICE, "Config idx spa thermostat = %d\n", _config_parameters.dzidx_spa_thermostat);
+ logMessage(LOG_NOTICE, "Config idx pool thermostat = %d\n", _aqconfig_.dzidx_pool_thermostat);
+ logMessage(LOG_NOTICE, "Config idx spa thermostat = %d\n", _aqconfig_.dzidx_spa_thermostat);
*/
#endif // MG_DISABLE_MQTT
- logMessage(LOG_NOTICE, "Config deamonize = %s\n", bool2text(_config_parameters.deamonize));
- logMessage(LOG_NOTICE, "Config log_file = %s\n", _config_parameters.log_file);
- logMessage(LOG_NOTICE, "Config light_pgm_mode = %.2f\n", _config_parameters.light_programming_mode);
- logMessage(LOG_NOTICE, "Debug RS485 protocol = %s\n", bool2text(_config_parameters.debug_RSProtocol_packets));
- //logMessage(LOG_NOTICE, "Use PDA 4 auxiliary info = %s\n", bool2text(_config_parameters.use_PDA_auxiliary));
- logMessage(LOG_NOTICE, "Read Pentair Packets = %s\n", bool2text(_config_parameters.read_pentair_packets));
+ logMessage(LOG_NOTICE, "Config deamonize = %s\n", bool2text(_aqconfig_.deamonize));
+ logMessage(LOG_NOTICE, "Config log_file = %s\n", _aqconfig_.log_file);
+ logMessage(LOG_NOTICE, "Config light_pgm_mode = %.2f\n", _aqconfig_.light_programming_mode);
+ logMessage(LOG_NOTICE, "Debug RS485 protocol = %s\n", bool2text(_aqconfig_.debug_RSProtocol_packets));
+ //logMessage(LOG_NOTICE, "Use PDA 4 auxiliary info = %s\n", bool2text(_aqconfig_.use_PDA_auxiliary));
+ logMessage(LOG_NOTICE, "Read Pentair Packets = %s\n", bool2text(_aqconfig_.read_pentair_packets));
// logMessage (LOG_NOTICE, "Config serial_port = %s\n", config_parameters->serial_port);
- logMessage(LOG_NOTICE, "Display warnings in web = %s\n", bool2text(_config_parameters.display_warnings_web));
+ logMessage(LOG_NOTICE, "Display warnings in web = %s\n", bool2text(_aqconfig_.display_warnings_web));
- if (_config_parameters.swg_zero_ignore > 0)
- logMessage(LOG_NOTICE, "Ignore SWG 0 msg count = %d\n", _config_parameters.swg_zero_ignore);
+ if (_aqconfig_.swg_zero_ignore > 0)
+ logMessage(LOG_NOTICE, "Ignore SWG 0 msg count = %d\n", _aqconfig_.swg_zero_ignore);
for (i = 0; i < TOTAL_BUTONS; i++)
{
char vsp[] = "None";
- for (j = 0; j < MAX_PUMPS; j++) {
+ int alid = 0;
+ for (j = 0; j < _aqualink_data.num_pumps; j++) {
//if (_aqualink_data.pumps[j].buttonID == i) {
if (_aqualink_data.pumps[j].button == &_aqualink_data.aqbuttons[i]) {
sprintf(vsp,"0x%02hhx",_aqualink_data.pumps[j].pumpID);
+ alid = _aqualink_data.pumps[j].pumpIndex;
//printf("Pump %d %d %d\n",_aqualink_data.pumps[j].pumpID, _aqualink_data.pumps[j].buttonID, _aqualink_data.pumps[j].ptype);
}
}
- if (!_config_parameters.pda_mode) {
- logMessage(LOG_NOTICE, "Config BTN %-13s = label %-15s | VSP ID %-4s | dzidx %d | %s\n",
- _aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label, vsp, _aqualink_data.aqbuttons[i].dz_idx,
- (i>0 && (i==_config_parameters.light_programming_button_pool || i==_config_parameters.light_programming_button_spa)?"Programable":"") );
+ if (!_aqconfig_.pda_mode) {
+ logMessage(LOG_NOTICE, "Config BTN %-13s = label %-15s | VSP ID %-4s | AL ID %-1d | dzidx %-3d | %s\n",
+ _aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label, vsp, alid, _aqualink_data.aqbuttons[i].dz_idx,
+ (i>0 && (i==_aqconfig_.light_programming_button_pool || i==_aqconfig_.light_programming_button_spa)?"Programable":"") );
} else {
- logMessage(LOG_NOTICE, "Config BTN %-13s = label %-15s | VSP ID %-4s | PDAlabel %-15s | dzidx %d\n",
- _aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label, vsp,
+ logMessage(LOG_NOTICE, "Config BTN %-13s = label %-15s | VSP ID %-4s | AL ID %-1d | PDAlabel %-15s | dzidx %d\n",
+ _aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label, vsp, alid,
_aqualink_data.aqbuttons[i].pda_label, _aqualink_data.aqbuttons[i].dz_idx );
}
//logMessage(LOG_NOTICE, "Button %d\n", i+1, _aqualink_data.aqbuttons[i].label , _aqualink_data.aqbuttons[i].dz_idx);
}
- if (_config_parameters.deamonize == true)
+ if (_aqconfig_.deamonize == true)
{
char pidfile[256];
// sprintf(pidfile, "%s/%s.pid",PIDLOCATION, basename(argv[0]));
@@ -953,116 +935,6 @@ int main(int argc, char *argv[])
exit(EXIT_SUCCESS);
}
-/*
-void debugPacketPrint(unsigned char ID, unsigned char *packet_buffer, int packet_length)
-{
- char buff[1000];
- int i = 0;
- int cnt = 0;
-
- cnt = sprintf(buff, "%4.4s 0x%02hhx of type %8.8s", (packet_buffer[PKT_DEST] == 0x00 ? "From" : "To"), ID, get_packet_type(packet_buffer, packet_length));
- cnt += sprintf(buff + cnt, " | HEX: ");
- //printHex(packet_buffer, packet_length);
- for (i = 0; i < packet_length; i++)
- cnt += sprintf(buff + cnt, "0x%02hhx|", packet_buffer[i]);
-
- if (packet_buffer[PKT_CMD] == CMD_MSG)
- {
- cnt += sprintf(buff + cnt, " Message : ");
- //fwrite(packet_buffer + 4, 1, packet_length - 4, stdout);
- strncpy(buff + cnt, (char *)packet_buffer + PKT_DATA + 1, AQ_MSGLEN);
- cnt += AQ_MSGLEN;
- }
-
- if (packet_buffer[PKT_DEST] == 0x00)
- cnt += sprintf(buff + cnt, "\n\n");
- else
- cnt += sprintf(buff + cnt, "\n");
-
- //logMessage(LOG_NOTICE, "- AQUA SWG - \n%s", buff);
- if (_config_parameters.debug_RSProtocol_packets)
- writePacketLog(buff);
- else
- logMessage(LOG_NOTICE, "%s", buff);
-}
-
-void debugPacket(unsigned char *packet_buffer, int packet_length)
-{
- static unsigned char lastID;
-
- if (packet_buffer[PKT_DEST] == DEV_MASTER && (lastID == 0x50 || lastID == 0x58))
- {
- debugPacketPrint(lastID, packet_buffer, packet_length);
- }
- else if (packet_buffer[PKT_DEST] == 0x50 || packet_buffer[PKT_DEST] == 0x58)
- {
- debugPacketPrint(packet_buffer[PKT_DEST], packet_buffer, packet_length);
- }
-
- lastID = packet_buffer[PKT_DEST];
-}
-
-void logPacket(unsigned char *packet_buffer, int packet_length)
-{
- static unsigned char last_packet_buffer[AQ_MAXPKTLEN];
- static int last_packet_length;
-
- if (packet_buffer[PKT_DEST] != DEV_MASTER)
- {
- memcpy(last_packet_buffer, packet_buffer, packet_length);
- last_packet_length = packet_length;
- }
- else
- {
- debugPacketPrint(last_packet_buffer[PKT_DEST], last_packet_buffer, last_packet_length);
- debugPacketPrint(last_packet_buffer[PKT_DEST], packet_buffer, packet_length);
- }
-}
-*/
-/*
-void logPacket_new(unsigned char* packet_buffer, int packet_length)
-{
- char buff[1000];
- int i = 0;
- int cnt = 0;
-
- cnt = sprintf(buff, "%8.8s Packet | HEX: ",getProtocolType(packet_buffer)==JANDY?"Jandy":"Pentair");
-
- for (i=0;i 0) {
@@ -1178,40 +1057,48 @@ void main_loop()
for (i=0; i < MAX_PUMPS; i++) {
_aqualink_data.pumps[i].rpm = TEMP_UNKNOWN;
- _aqualink_data.pumps[i].gph = TEMP_UNKNOWN;
+ _aqualink_data.pumps[i].gpm = TEMP_UNKNOWN;
_aqualink_data.pumps[i].watts = TEMP_UNKNOWN;
}
- if (_config_parameters.force_swg == true) {
+ if (_aqconfig_.force_swg == true) {
_aqualink_data.swg_percent = 0;
_aqualink_data.swg_ppm = 0;
}
- if (!start_net_services(&mgr, &_aqualink_data, &_config_parameters))
+ if (!start_net_services(&mgr, &_aqualink_data))
{
- logMessage(LOG_ERR, "Can not start webserver on port %s.\n", _config_parameters.socket_port);
+ logMessage(LOG_ERR, "Can not start webserver on port %s.\n", _aqconfig_.socket_port);
exit(EXIT_FAILURE);
}
- startPacketLogger(_config_parameters.debug_RSProtocol_packets, _config_parameters.read_pentair_packets);
+ startPacketLogger(_aqconfig_.debug_RSProtocol_packets, _aqconfig_.read_pentair_packets);
signal(SIGINT, intHandler);
signal(SIGTERM, intHandler);
int blank_read = 0;
- rs_fd = init_serial_port(_config_parameters.serial_port);
- logMessage(LOG_NOTICE, "Listening to Aqualink RS8 on serial port: %s\n", _config_parameters.serial_port);
+ rs_fd = init_serial_port(_aqconfig_.serial_port);
+ logMessage(LOG_NOTICE, "Listening to Aqualink RS8 on serial port: %s\n", _aqconfig_.serial_port);
- if (_config_parameters.pda_mode == true)
+ if (_aqconfig_.pda_mode == true)
{
#ifdef BETA_PDA_AUTOLABEL
- init_pda(&_aqualink_data, &_config_parameters);
+ init_pda(&_aqualink_data, &_aqconfig_);
#else
init_pda(&_aqualink_data);
#endif
}
+ if (_aqconfig_.onetouch_device_id != 0x00)
+ {
+ set_onetouch_enabled(true);
+ }
+ if (_aqconfig_.extended_device_id_programming == true)
+ {
+ set_extended_device_id_programming(true);
+ }
- if (_config_parameters.device_id == 0x00) {
+ if (_aqconfig_.device_id == 0x00) {
logMessage(LOG_NOTICE, "Searching for valid ID, please configure one for faster startup\n");
}
@@ -1234,11 +1121,11 @@ void main_loop()
logMessage(LOG_ERR, "Aqualink daemon looks like serial error, resetting.\n");
close_serial_port(rs_fd);
}
- rs_fd = init_serial_port(_config_parameters.serial_port);
+ rs_fd = init_serial_port(_aqconfig_.serial_port);
blank_read = 0;
}
- if (_config_parameters.log_raw_RS_bytes)
+ if (_aqconfig_.log_raw_RS_bytes)
packet_length = get_packet_lograw(rs_fd, packet_buffer);
else
packet_length = get_packet(rs_fd, packet_buffer);
@@ -1254,70 +1141,44 @@ void main_loop()
//logMessage(LOG_DEBUG_SERIAL, "Nothing read on serial\n");
blank_read++;
}
- else if (_config_parameters.device_id == 0x00) {
+ else if (_aqconfig_.device_id == 0x00) {
blank_read = 0;
- _config_parameters.device_id = find_unused_address(packet_buffer);
+ _aqconfig_.device_id = find_unused_address(packet_buffer);
continue;
}
else if (packet_length > 0)
{
blank_read = 0;
changed = false;
-
- //if (_config_parameters.debug_RSProtocol_packets || getLogLevel() >= LOG_DEBUG_SERIAL)
- // logPacket(packet_buffer, packet_length);
-
- if (packet_length > 0 && packet_buffer[PKT_DEST] == _config_parameters.device_id)
+/*
+ // This is handeled by aq_serial now
+ if (_aqconfig_.debug_RSProtocol_packets || getLogLevel() >= LOG_DEBUG_SERIAL)
+ logPacket(packet_buffer, packet_length);
+*/
+ if (packet_length > 0 && packet_buffer[PKT_DEST] == _aqconfig_.device_id)
{
-
if (getLogLevel() >= LOG_DEBUG)
logMessage(LOG_DEBUG, "RS received packet of type %s length %d\n", get_packet_type(packet_buffer, packet_length), packet_length);
-
- //logMessage(LOG_DEBUG, "RS received packet of type %s length %d\n", get_packet_type(packet_buffer, packet_length), packet_length);
- //debugPacketPrint(0x00, packet_buffer, packet_length);
- //unsigned char ID, unsigned char *packet_buffer, int packet_length)
-
- // Process the packet. This includes deriving general status, and identifying
- // warnings and errors. If something changed, notify any listeners
- if (process_packet(packet_buffer, packet_length) != false)
- {
- //broadcast_aqualinkstate(mgr.active_connections);
- changed = true;
- }
-
- //_aqualink_data.last_packet_type = packet_buffer[PKT_CMD];
+ changed = process_packet(packet_buffer, packet_length);
// If we are not in PDA or Simulator mode, just sent ACK & any CMD, else caculate the ACK.
- if (!_aqualink_data.simulate_panel && !_config_parameters.pda_mode) {
- send_ack(rs_fd, pop_aq_cmd(&_aqualink_data));
+ if (!_aqualink_data.simulate_panel && !_aqconfig_.pda_mode) {
+ //send_ack(rs_fd, pop_aq_cmd(&_aqualink_data));
+ send_extended_ack(rs_fd, (_aqualink_data.last_packet_type==CMD_MSG_LONG?ACK_SCREEN_BUSY_SCROLL:ACK_NORMAL), pop_aq_cmd(&_aqualink_data));
} else
caculate_ack_packet(rs_fd, packet_buffer);
-/* MOVE PROCESSING TO AFTER ACK, long programming will fail otherwise (like set time) */
- // Process the packet. This includes deriving general status, and identifying
- // warnings and errors. If something changed, notify any listeners
- /*
- if (process_packet(packet_buffer, packet_length) != false)
- {
- //broadcast_aqualinkstate(mgr.active_connections);
- changed = true;
- }
- */
- }/*
- else if (_config_parameters.use_PDA_auxiliary && packet_length > 0 && packet_buffer[PKT_DEST] == 0x60 && _aqualink_data.aqbuttons[PUMP_INDEX].led->state != OFF)
+ }
+ else if (packet_length > 0 && onetouch_enabled() && packet_buffer[PKT_DEST] == _aqconfig_.onetouch_device_id) {
+ //if (getLogLevel() >= LOG_DEBUG)
+ // logMessage(LOG_DEBUG, "RS received ONETOUCH packet of type %s length %d\n", get_packet_type(packet_buffer, packet_length), packet_length);
+ changed = process_onetouch_packet(packet_buffer, packet_length, &_aqualink_data);
+ caculate_ack_packet(rs_fd, packet_buffer);
+ }
+ else if (packet_length > 0 && _aqconfig_.read_all_devices == true)
{
- if (process_pda_monitor_packet(packet_buffer, packet_length))
- broadcast_aqualinkstate(mgr.active_connections);
-
- //send_ack(rs_fd, NUL);
- send_extended_ack(rs_fd, ACK_PDA, NUL);
- }*/
- else if (packet_length > 0 && _config_parameters.read_all_devices == true)
- {
-
//logPacket(packet_buffer, packet_length);
-
if (packet_buffer[PKT_DEST] == DEV_MASTER && interestedInNextAck == true)
{
swg_noreply_cnt = 0;
@@ -1336,35 +1197,27 @@ void main_loop()
else if (packet_buffer[PKT_DEST] == SWG_DEV_ID)
{
interestedInNextAck = true;
- changed = processPacketToSWG(packet_buffer, packet_length, &_aqualink_data, _config_parameters.swg_zero_ignore);
+ changed = processPacketToSWG(packet_buffer, packet_length, &_aqualink_data, _aqconfig_.swg_zero_ignore);
}
else
{
interestedInNextAck = false;
}
- if (_config_parameters.read_pentair_packets && getProtocolType(packet_buffer) == PENTAIR) {
+ if (_aqconfig_.read_pentair_packets && getProtocolType(packet_buffer) == PENTAIR) {
if (processPentairPacket(packet_buffer, packet_length, &_aqualink_data)) {
//broadcast_aqualinkstate(mgr.active_connections);
changed = true;
}
- }
- /* Removed, iAqualink has sleep mode, so no use
- if (packet_buffer[PKT_DEST] == IAQ_DEV_ID && packet_buffer[PKT_CMD] == CMD_IAQ_MSG) {
- if (processiAqualinkMsg(packet_buffer, packet_length, &_aqualink_data) != false)
- broadcast_aqualinkstate(mgr.active_connections);
- }
- */
- //}
-
- // logMessage(LOG_DEBUG_SERIAL, "Received Packet for ID 0x%02hhx of type %s %s\n",packet_buffer[PKT_DEST], get_packet_type(packet_buffer, packet_length),
- // (packet_buffer[PKT_DEST] == _config_parameters.device_id)?" <-- Aqualinkd ID":"");
+ }
}
if (changed)
broadcast_aqualinkstate(mgr.active_connections);
}
- mg_mgr_poll(&mgr, 0);
+
+ mg_mgr_poll(&mgr, 10);
+ tcdrain(rs_fd); // Make sure buffer has been sent.
// Any unactioned commands
if (_aqualink_data.unactioned.type != NO_ACTION)
@@ -1378,15 +1231,12 @@ void main_loop()
}
}
-#ifdef BLOCKING_MODE
-#else
- tcdrain(rs_fd); // Make sure buffer has been sent.
- delay(10);
-#endif
- //}
+
+ //tcdrain(rs_fd); // Make sure buffer has been sent.
+ //delay(10);
}
- //if (_config_parameters.debug_RSProtocol_packets) stopPacketLogger();
+ //if (_aqconfig_.debug_RSProtocol_packets) stopPacketLogger();
stopPacketLogger();
// Reset and close the port.
close_serial_port(rs_fd);
diff --git a/aquapure.c b/aquapure.c
index 56fbf7d..0a33619 100644
--- a/aquapure.c
+++ b/aquapure.c
@@ -17,19 +17,23 @@ bool processPacketToSWG(unsigned char *packet, int packet_length, struct aqualin
// Not really sure what to do with this, just ignore 0xff / 255 for the moment. (if statment above)
// SWG can get ~10 messages to set to 0 then go back again for some reason, so don't go to 0 until 10 messages are received
- if (swg_zero_cnt <= swg_zero_ignore && packet[4] == 0x00 && packet[5] == 0x73) {
+ if (swg_zero_cnt <= swg_zero_ignore && packet[4] == 0x00) {
logMessage(LOG_DEBUG, "Ignoring SWG set to %d due to packet packet count %d <= %d from control panel to SWG 0x%02hhx 0x%02hhx\n", (int)packet[4],
swg_zero_cnt, swg_zero_ignore, packet[4], packet[5]);
swg_zero_cnt++;
- } else if (swg_zero_cnt > swg_zero_ignore && packet[4] == 0x00 && packet[5] == 0x73) {
- aqdata->swg_percent = (int)packet[4];
- changedAnything = true;
+ } else if (swg_zero_cnt > swg_zero_ignore && packet[4] == 0x00) {
+ if (aqdata->swg_percent != (int)packet[4]) {
+ aqdata->swg_percent = (int)packet[4];
+ changedAnything = true;
+ }
// logMessage(LOG_DEBUG, "SWG set to %d due to packet packet count %d <= %d from control panel to SWG 0x%02hhx 0x%02hhx\n",
// (int)packet[4],swg_zero_cnt,SWG_ZERO_IGNORE_COUNT,packet[4],packet[5]); swg_zero_cnt++;
} else {
swg_zero_cnt = 0;
- aqdata->swg_percent = (int)packet[4];
- changedAnything = true;
+ if (aqdata->swg_percent != (int)packet[4]) {
+ aqdata->swg_percent = (int)packet[4];
+ changedAnything = true;
+ }
// logMessage(LOG_DEBUG, "SWG set to %d due to packet from control panel to SWG 0x%02hhx 0x%02hhx\n",
// aqdata.swg_percent,packet[4],packet[5]);
}
@@ -66,7 +70,7 @@ bool processPacketFromSWG(unsigned char *packet, int packet_length, struct aqual
aqledstate get_swg_led_state(struct aqualinkdata *aqdata)
{
switch (aqdata->ar_swg_status) {
- // Level = (0=gray, 1=green, 2=yellow, 3=orange, 4=red)
+
case SWG_STATUS_ON:
return (aqdata->swg_percent > 0?ON:ENABLE);
break;
diff --git a/config.c b/config.c
index 336040b..f6fb53b 100644
--- a/config.c
+++ b/config.c
@@ -33,19 +33,24 @@
#include
#include
+#define CONFIG_C
#include "config.h"
#include "utils.h"
#include "aq_serial.h"
#define MAXCFGLINE 256
+
+
char *generate_mqtt_id(char *buf, int len);
+pump_detail *getpump(struct aqualinkdata *aqdata, int button);
/*
* initialize data to default values
*/
void init_parameters (struct aqconfig * parms)
{
+ //int i;
//char *p;
parms->serial_port = DEFAULT_SERIALPORT;
parms->log_level = DEFAULT_LOG_LEVEL;
@@ -53,6 +58,7 @@ void init_parameters (struct aqconfig * parms)
parms->web_directory = DEFAULT_WEBROOT;
//parms->device_id = strtoul(DEFAULT_DEVICE_ID, &p, 16);
parms->device_id = strtoul(DEFAULT_DEVICE_ID, NULL, 16);
+ parms->onetouch_device_id = 0x00;
//sscanf(DEFAULT_DEVICE_ID, "0x%x", &parms->device_id);
parms->override_freeze_protect = FALSE;
@@ -76,6 +82,7 @@ void init_parameters (struct aqconfig * parms)
parms->deamonize = true;
parms->log_file = '\0';
parms->pda_mode = false;
+ parms->onetouch_mode = false;
parms->pda_sleep_mode = false;
parms->convert_mqtt_temp = true;
parms->convert_dz_temp = true;
@@ -90,6 +97,7 @@ void init_parameters (struct aqconfig * parms)
parms->swg_zero_ignore = DEFAILT_SWG_ZERO_IGNORE_COUNT;
parms->display_warnings_web = false;
parms->log_raw_RS_bytes = false;
+ parms->extended_device_id_programming = false;
generate_mqtt_id(parms->mqtt_ID, MQTT_ID_LEN);
}
@@ -219,69 +227,69 @@ void readCfg_OLD (struct aqconfig *config_parameters, struct aqualinkdata *aqdat
if ( indx != NULL)
{
if (strncasecmp (b_ptr, "socket_port", 11) == 0) {
- //config_parameters->socket_port = cleanint(indx+1);
- config_parameters->socket_port = cleanalloc(indx+1);
+ //_aqconfig_.socket_port = cleanint(indx+1);
+ _aqconfig_.socket_port = cleanalloc(indx+1);
} else if (strncasecmp (b_ptr, "serial_port", 11) == 0) {
- config_parameters->serial_port = cleanalloc(indx+1);
+ _aqconfig_.serial_port = cleanalloc(indx+1);
} else if (strncasecmp (b_ptr, "log_level", 9) == 0) {
- config_parameters->log_level = text2elevel(cleanalloc(indx+1));
+ _aqconfig_.log_level = text2elevel(cleanalloc(indx+1));
// should fee mem here
} else if (strncasecmp (b_ptr, "device_id", 9) == 0) {
- config_parameters->device_id = strtoul(cleanalloc(indx+1), NULL, 16);
+ _aqconfig_.device_id = strtoul(cleanalloc(indx+1), NULL, 16);
// should fee mem here
} else if (strncasecmp (b_ptr, "web_directory", 13) == 0) {
- config_parameters->web_directory = cleanalloc(indx+1);
+ _aqconfig_.web_directory = cleanalloc(indx+1);
} else if (strncasecmp (b_ptr, "log_file", 8) == 0) {
- config_parameters->log_file = cleanalloc(indx+1);
+ _aqconfig_.log_file = cleanalloc(indx+1);
} else if (strncasecmp (b_ptr, "mqtt_address", 12) == 0) {
- config_parameters->mqtt_server = cleanalloc(indx+1);
+ _aqconfig_.mqtt_server = cleanalloc(indx+1);
} else if (strncasecmp (b_ptr, "mqtt_dz_sub_topic", 17) == 0) {
- config_parameters->mqtt_dz_sub_topic = cleanalloc(indx+1);
+ _aqconfig_.mqtt_dz_sub_topic = cleanalloc(indx+1);
} else if (strncasecmp (b_ptr, "mqtt_dz_pub_topic", 17) == 0) {
- config_parameters->mqtt_dz_pub_topic = cleanalloc(indx+1);
+ _aqconfig_.mqtt_dz_pub_topic = cleanalloc(indx+1);
} else if (strncasecmp (b_ptr, "mqtt_aq_topic", 13) == 0) {
- config_parameters->mqtt_aq_topic = cleanalloc(indx+1);
+ _aqconfig_.mqtt_aq_topic = cleanalloc(indx+1);
} else if (strncasecmp (b_ptr, "mqtt_user", 9) == 0) {
- config_parameters->mqtt_user = cleanalloc(indx+1);
+ _aqconfig_.mqtt_user = cleanalloc(indx+1);
} else if (strncasecmp (b_ptr, "mqtt_passwd", 11) == 0) {
- config_parameters->mqtt_passwd = cleanalloc(indx+1);
+ _aqconfig_.mqtt_passwd = cleanalloc(indx+1);
} else if (strncasecmp (b_ptr, "air_temp_dzidx", 14) == 0) {
- config_parameters->dzidx_air_temp = strtoul(indx+1, NULL, 10);
+ _aqconfig_.dzidx_air_temp = strtoul(indx+1, NULL, 10);
} else if (strncasecmp (b_ptr, "pool_water_temp_dzidx", 21) == 0) {
- config_parameters->dzidx_pool_water_temp = strtoul(indx+1, NULL, 10);
+ _aqconfig_.dzidx_pool_water_temp = strtoul(indx+1, NULL, 10);
} else if (strncasecmp (b_ptr, "spa_water_temp_dzidx", 20) == 0) {
- config_parameters->dzidx_spa_water_temp = strtoul(indx+1, NULL, 10);
+ _aqconfig_.dzidx_spa_water_temp = strtoul(indx+1, NULL, 10);
} else if (strncasecmp (b_ptr, "light_programming_mode", 21) == 0) {
- config_parameters->light_programming_mode = atof(cleanalloc(indx+1)); // should free this
+ _aqconfig_.light_programming_mode = atof(cleanalloc(indx+1)); // should free this
} else if (strncasecmp (b_ptr, "light_programming_initial_on", 28) == 0) {
- config_parameters->light_programming_initial_on = strtoul(indx+1, NULL, 10);
+ _aqconfig_.light_programming_initial_on = strtoul(indx+1, NULL, 10);
} else if (strncasecmp (b_ptr, "light_programming_initial_off", 29) == 0) {
- config_parameters->light_programming_initial_off = strtoul(indx+1, NULL, 10);
+ _aqconfig_.light_programming_initial_off = strtoul(indx+1, NULL, 10);
} else if (strncasecmp (b_ptr, "light_programming_button", 21) == 0) {
- config_parameters->light_programming_button = strtoul(indx+1, NULL, 10) - 1;
+ _aqconfig_.light_programming_button = strtoul(indx+1, NULL, 10) - 1;
} else if (strncasecmp (b_ptr, "SWG_percent_dzidx", 17) == 0) {
- config_parameters->dzidx_swg_percent = strtoul(indx+1, NULL, 10);
+ _aqconfig_.dzidx_swg_percent = strtoul(indx+1, NULL, 10);
} else if (strncasecmp (b_ptr, "SWG_PPM_dzidx", 13) == 0) {
- config_parameters->dzidx_swg_ppm = strtoul(indx+1, NULL, 10);
+ _aqconfig_.dzidx_swg_ppm = strtoul(indx+1, NULL, 10);
} else if (strncasecmp (b_ptr, "SWG_Status_dzidx", 14) == 0) {
- config_parameters->dzidx_swg_status = strtoul(indx+1, NULL, 10);
+ _aqconfig_.dzidx_swg_status = strtoul(indx+1, NULL, 10);
} else if (strncasecmp (b_ptr, "override_freeze_protect", 23) == 0) {
- config_parameters->override_freeze_protect = text2bool(indx+1);
+ _aqconfig_.override_freeze_protect = text2bool(indx+1);
} else if (strncasecmp (b_ptr, "pda_mode", 8) == 0) {
- config_parameters->pda_mode = text2bool(indx+1);
- set_pda_mode(config_parameters->pda_mode);
+ _aqconfig_.pda_mode = text2bool(indx+1);
+ set_pda_mode(_aqconfig_.pda_mode);
} else if (strncasecmp (b_ptr, "convert_mqtt_temp_to_c", 22) == 0) {
- config_parameters->convert_mqtt_temp = text2bool(indx+1);
+ _aqconfig_.convert_mqtt_temp = text2bool(indx+1);
} else if (strncasecmp (b_ptr, "convert_dz_temp_to_c", 21) == 0) {
- config_parameters->convert_dz_temp = text2bool(indx+1);
+ _aqconfig_.convert_dz_temp = text2bool(indx+1);
} else if (strncasecmp (b_ptr, "flash_mqtt_buttons", 18) == 0) {
- config_parameters->flash_mqtt_buttons = text2bool(indx+1);
+ _aqconfig_.flash_mqtt_buttons = text2bool(indx+1);
} else if (strncasecmp (b_ptr, "report_zero_pool_temp", 21) == 0) {
- config_parameters->report_zero_pool_temp = text2bool(indx+1);
+ _aqconfig_.report_zero_pool_temp = text2bool(indx+1);
} else if (strncasecmp (b_ptr, "report_zero_spa_temp", 20) == 0) {
- config_parameters->report_zero_spa_temp = text2bool(indx+1);
+ _aqconfig_.report_zero_spa_temp = text2bool(indx+1);
} else if (strncasecmp (b_ptr, "report_zero_pool_temp", 21) == 0) {
- config_parameters->report_zero_pool_temp = text2bool(indx+1);
+ _aqconfig_.report_zero_pool_temp = text2bool(indx+1);
} else if (strncasecmp (b_ptr, "button_", 7) == 0) {
int num = strtoul(b_ptr+7, NULL, 10) - 1;
//logMessage (LOG_DEBUG, "Button %d\n", strtoul(b_ptr+7, NULL, 10));
@@ -310,146 +318,154 @@ void readCfg_OLD (struct aqconfig *config_parameters, struct aqualinkdata *aqdat
}
*/
-bool setConfigValue(struct aqconfig *config_parameters, struct aqualinkdata *aqdata, char *param, char *value) {
+bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
bool rtn = false;
- static int pi=0;
if (strncasecmp(param, "socket_port", 11) == 0) {
- config_parameters->socket_port = cleanalloc(value);
+ _aqconfig_.socket_port = cleanalloc(value);
rtn=true;
} else if (strncasecmp(param, "serial_port", 11) == 0) {
- config_parameters->serial_port = cleanalloc(value);
+ _aqconfig_.serial_port = cleanalloc(value);
rtn=true;
} else if (strncasecmp(param, "log_level", 9) == 0) {
- config_parameters->log_level = text2elevel(cleanalloc(value));
+ _aqconfig_.log_level = text2elevel(cleanalloc(value));
rtn=true;
} else if (strncasecmp(param, "device_id", 9) == 0) {
- config_parameters->device_id = strtoul(cleanalloc(value), NULL, 16);
+ _aqconfig_.device_id = strtoul(cleanalloc(value), NULL, 16);
+ } else if (strncasecmp (param, "extended_device_id_programming", 30) == 0) {
+ // Has to be before the below.
+ _aqconfig_.extended_device_id_programming = text2bool(value);
+ rtn=true;
+ } else if (strncasecmp(param, "extended_device_id", 9) == 0) {
+ _aqconfig_.onetouch_device_id = strtoul(cleanalloc(value), NULL, 16);
+ //_config_parameters.onetouch_device_id != 0x00
rtn=true;
} else if (strncasecmp(param, "web_directory", 13) == 0) {
- config_parameters->web_directory = cleanalloc(value);
+ _aqconfig_.web_directory = cleanalloc(value);
rtn=true;
} else if (strncasecmp(param, "log_file", 8) == 0) {
- config_parameters->log_file = cleanalloc(value);
+ _aqconfig_.log_file = cleanalloc(value);
rtn=true;
} else if (strncasecmp(param, "mqtt_address", 12) == 0) {
- config_parameters->mqtt_server = cleanalloc(value);
+ _aqconfig_.mqtt_server = cleanalloc(value);
rtn=true;
} else if (strncasecmp(param, "mqtt_dz_sub_topic", 17) == 0) {
- config_parameters->mqtt_dz_sub_topic = cleanalloc(value);
+ _aqconfig_.mqtt_dz_sub_topic = cleanalloc(value);
rtn=true;
} else if (strncasecmp(param, "mqtt_dz_pub_topic", 17) == 0) {
- config_parameters->mqtt_dz_pub_topic = cleanalloc(value);
+ _aqconfig_.mqtt_dz_pub_topic = cleanalloc(value);
rtn=true;
} else if (strncasecmp(param, "mqtt_aq_topic", 13) == 0) {
- config_parameters->mqtt_aq_topic = cleanalloc(value);
+ _aqconfig_.mqtt_aq_topic = cleanalloc(value);
rtn=true;
} else if (strncasecmp(param, "mqtt_user", 9) == 0) {
- config_parameters->mqtt_user = cleanalloc(value);
+ _aqconfig_.mqtt_user = cleanalloc(value);
rtn=true;
} else if (strncasecmp(param, "mqtt_passwd", 11) == 0) {
- config_parameters->mqtt_passwd = cleanalloc(value);
+ _aqconfig_.mqtt_passwd = cleanalloc(value);
rtn=true;
} else if (strncasecmp(param, "air_temp_dzidx", 14) == 0) {
- config_parameters->dzidx_air_temp = strtoul(value, NULL, 10);
+ _aqconfig_.dzidx_air_temp = strtoul(value, NULL, 10);
rtn=true;
} else if (strncasecmp(param, "pool_water_temp_dzidx", 21) == 0) {
- config_parameters->dzidx_pool_water_temp = strtoul(value, NULL, 10);
+ _aqconfig_.dzidx_pool_water_temp = strtoul(value, NULL, 10);
rtn=true;
} else if (strncasecmp(param, "spa_water_temp_dzidx", 20) == 0) {
- config_parameters->dzidx_spa_water_temp = strtoul(value, NULL, 10);
+ _aqconfig_.dzidx_spa_water_temp = strtoul(value, NULL, 10);
rtn=true;
} else if (strncasecmp(param, "light_programming_mode", 21) == 0) {
- config_parameters->light_programming_mode = atof(cleanalloc(value)); // should free this
+ _aqconfig_.light_programming_mode = atof(cleanalloc(value)); // should free this
rtn=true;
} else if (strncasecmp(param, "light_programming_initial_on", 28) == 0) {
- config_parameters->light_programming_initial_on = strtoul(value, NULL, 10);
+ _aqconfig_.light_programming_initial_on = strtoul(value, NULL, 10);
rtn=true;
} else if (strncasecmp(param, "light_programming_initial_off", 29) == 0) {
- config_parameters->light_programming_initial_off = strtoul(value, NULL, 10);
+ _aqconfig_.light_programming_initial_off = strtoul(value, NULL, 10);
rtn=true;
} else if (strncasecmp(param, "light_programming_button_spa", 28) == 0) {
- config_parameters->light_programming_button_spa = strtoul(value, NULL, 10) - 1;
+ _aqconfig_.light_programming_button_spa = strtoul(value, NULL, 10) - 1;
rtn=true;
} else if (strncasecmp(param, "light_programming_button", 24) == 0 ||
strncasecmp(param, "light_programming_button_pool", 29) == 0) {
- config_parameters->light_programming_button_pool = strtoul(value, NULL, 10) - 1;
+ _aqconfig_.light_programming_button_pool = strtoul(value, NULL, 10) - 1;
rtn=true;
} else if (strncasecmp(param, "SWG_percent_dzidx", 17) == 0) {
- config_parameters->dzidx_swg_percent = strtoul(value, NULL, 10);
+ _aqconfig_.dzidx_swg_percent = strtoul(value, NULL, 10);
rtn=true;
} else if (strncasecmp(param, "SWG_PPM_dzidx", 13) == 0) {
- config_parameters->dzidx_swg_ppm = strtoul(value, NULL, 10);
+ _aqconfig_.dzidx_swg_ppm = strtoul(value, NULL, 10);
rtn=true;
} else if (strncasecmp(param, "SWG_Status_dzidx", 14) == 0) {
- config_parameters->dzidx_swg_status = strtoul(value, NULL, 10);
+ _aqconfig_.dzidx_swg_status = strtoul(value, NULL, 10);
rtn=true;
} else if (strncasecmp(param, "override_freeze_protect", 23) == 0) {
- config_parameters->override_freeze_protect = text2bool(value);
+ _aqconfig_.override_freeze_protect = text2bool(value);
rtn=true;
} else if (strncasecmp(param, "pda_mode", 8) == 0) {
- config_parameters->pda_mode = text2bool(value);
- set_pda_mode(config_parameters->pda_mode);
- //config_parameters->use_PDA_auxiliary = false;
+ _aqconfig_.pda_mode = text2bool(value);
+ set_pda_mode(_aqconfig_.pda_mode);
+ //_aqconfig_.use_PDA_auxiliary = false;
rtn=true;
} else if (strncasecmp(param, "pda_sleep_mode", 8) == 0) {
- config_parameters->pda_sleep_mode = text2bool(value);
- //set_pda_mode(config_parameters->pda_mode);
+ _aqconfig_.pda_sleep_mode = text2bool(value);
+ //set_pda_mode(_aqconfig_.pda_mode);
rtn=true;
} else if (strncasecmp(param, "convert_mqtt_temp_to_c", 22) == 0) {
- config_parameters->convert_mqtt_temp = text2bool(value);
+ _aqconfig_.convert_mqtt_temp = text2bool(value);
rtn=true;
} else if (strncasecmp(param, "convert_dz_temp_to_c", 20) == 0) {
- config_parameters->convert_dz_temp = text2bool(value);
+ _aqconfig_.convert_dz_temp = text2bool(value);
rtn=true;
/*
} else if (strncasecmp(param, "flash_mqtt_buttons", 18) == 0) {
- config_parameters->flash_mqtt_buttons = text2bool(value);
+ _aqconfig_.flash_mqtt_buttons = text2bool(value);
rtn=true;*/
} else if (strncasecmp(param, "report_zero_spa_temp", 20) == 0) {
- config_parameters->report_zero_spa_temp = text2bool(value);
+ _aqconfig_.report_zero_spa_temp = text2bool(value);
rtn=true;
} else if (strncasecmp (param, "report_zero_pool_temp", 21) == 0) {
- config_parameters->report_zero_pool_temp = text2bool(value);
+ _aqconfig_.report_zero_pool_temp = text2bool(value);
rtn=true;
} else if (strncasecmp (param, "read_all_devices", 16) == 0) {
- config_parameters->read_all_devices = text2bool(value);
+ _aqconfig_.read_all_devices = text2bool(value);
rtn=true;
} else if (strncasecmp (param, "use_panel_aux_labels", 20) == 0) {
- config_parameters->use_panel_aux_labels = text2bool(value);
+ _aqconfig_.use_panel_aux_labels = text2bool(value);
rtn=true;
} else if (strncasecmp (param, "force_SWG", 9) == 0) {
- config_parameters->force_swg = text2bool(value);
+ _aqconfig_.force_swg = text2bool(value);
rtn=true;
} else if (strncasecmp (param, "debug_RSProtocol_packets", 24) == 0) {
- config_parameters->debug_RSProtocol_packets = text2bool(value);
+ _aqconfig_.debug_RSProtocol_packets = text2bool(value);
rtn=true;
} else if (strncasecmp (param, "read_pentair_packets", 17) == 0) {
- config_parameters->read_pentair_packets = text2bool(value);
- config_parameters->read_all_devices = true;
+ _aqconfig_.read_pentair_packets = text2bool(value);
+ if (_aqconfig_.read_pentair_packets)
+ _aqconfig_.read_all_devices = true;
rtn=true;
} else if (strncasecmp (param, "swg_zero_ignore_count", 21) == 0) {
- config_parameters->swg_zero_ignore = strtoul(value, NULL, 10);
+ _aqconfig_.swg_zero_ignore = strtoul(value, NULL, 10);
rtn=true;
} else if (strncasecmp (param, "display_warnings_in_web", 23) == 0) {
- config_parameters->display_warnings_web = text2bool(value);
+ _aqconfig_.display_warnings_web = text2bool(value);
rtn=true;
}
+
/*
else if (strncasecmp (param, "use_PDA_auxiliary", 17) == 0) {
- config_parameters->use_PDA_auxiliary = text2bool(value);
+ _aqconfig_.use_PDA_auxiliary = text2bool(value);
if ( pda_mode() ) {
logMessage(LOG_ERR, "ERROR Can't use `use_PDA_auxiliary` in PDA mode, ignoring'\n");
- config_parameters->use_PDA_auxiliary = false;
+ _aqconfig_.use_PDA_auxiliary = false;
}
rtn=true;
} */
// removed until domoticz has a better virtual thermostat
/*else if (strncasecmp (param, "pool_thermostat_dzidx", 21) == 0) {
- config_parameters->dzidx_pool_thermostat = strtoul(value, NULL, 10);
+ _aqconfig_.dzidx_pool_thermostat = strtoul(value, NULL, 10);
rtn=true;
} else if (strncasecmp (param, "spa_thermostat_dzidx", 20) == 0) {
- config_parameters->dzidx_spa_thermostat = strtoul(value, NULL, 10);
+ _aqconfig_.dzidx_spa_thermostat = strtoul(value, NULL, 10);
rtn=true;
} */
else if (strncasecmp(param, "button_", 7) == 0) {
@@ -463,30 +479,92 @@ bool setConfigValue(struct aqconfig *config_parameters, struct aqualinkdata *aqd
} else if (strncasecmp(param + 9, "_PDA_label", 10) == 0) {
aqdata->aqbuttons[num].pda_label = cleanalloc(value);
rtn=true;
+ } else if (strncasecmp(param + 9, "_pumpID", 7) == 0) {
+ pump_detail *pump = getpump(aqdata, num);
+ if (pump != NULL) {
+ pump->pumpID = strtoul(cleanalloc(value), NULL, 16);
+ if (pump->pumpID < 119) {
+ pump->ptype = PENTAIR;
+ } else {
+ pump->ptype = JANDY;
+ //pump->pumpType = EPUMP; // For testing let the interface set this
+ }
+ } else {
+ logMessage(LOG_ERR, "Config error, VSP Pumps limited to %d, ignoring %s'\n",MAX_PUMPS-1,param);
+ }
+ rtn=true;
+ } else if (strncasecmp(param + 9, "_pumpIndex", 10) == 0) { //button_01_pumpIndex=1
+ pump_detail *pump = getpump(aqdata, num);
+ if (pump != NULL) {
+ pump->pumpIndex = strtoul(value, NULL, 10);
+ } else {
+ logMessage(LOG_ERR, "Config error, VSP Pumps limited to %d, ignoring %s'\n",MAX_PUMPS-1,param);
+ }
+ rtn=true;
+ }
+ /*
} else if (strncasecmp(param + 9, "_pumpID", 7) == 0) {
//aqdata->aqbuttons[num].pda_label = cleanalloc(value);
//96 to 111 = Pentair, 120 to 123 = Jandy
if (pi < MAX_PUMPS) {
aqdata->pumps[pi].button = &aqdata->aqbuttons[num];
aqdata->pumps[pi].pumpID = strtoul(cleanalloc(value), NULL, 16);
+ aqdata->pumps[pi].pumpIndex = pi+1;
//aqdata->pumps[pi].buttonID = num;
if (aqdata->pumps[pi].pumpID < 119)
aqdata->pumps[pi].ptype = PENTAIR;
else
aqdata->pumps[pi].ptype = JANDY;
pi++;
+
} else {
logMessage(LOG_ERR, "Config error, VSP Pumps limited to %d, ignoring %s'\n",MAX_PUMPS,param);
}
rtn=true;
- }
+ } else if (strncasecmp(param + 9, "_pumpIndex", 10) == 0) { //button_01_pumpIndex=1
+ }*/
}
return rtn;
}
+pump_detail *getpump(struct aqualinkdata *aqdata, int button)
+{
+ //static int _pumpindex = 0;
+ //aqdata->num_pumps
+ int pi;
-void readCfg (struct aqconfig *config_parameters, struct aqualinkdata *aqdata, char *cfgFile)
+ // Does it exist
+ for (pi=0; pi < aqdata->num_pumps; pi++) {
+ if (aqdata->pumps[pi].button == &aqdata->aqbuttons[button]) {
+ //printf ("Found pump %d\n",button);
+ return &aqdata->pumps[pi];
+ }
+ }
+
+ // Create new entry
+ if (aqdata->num_pumps < MAX_PUMPS) {
+ //printf ("Creating pump %d\n",button);
+ aqdata->pumps[aqdata->num_pumps].button = &aqdata->aqbuttons[button];
+ aqdata->pumps[aqdata->num_pumps].pumpType = PT_UNKNOWN;
+ aqdata->pumps[aqdata->num_pumps].rpm = TEMP_UNKNOWN;
+ aqdata->pumps[aqdata->num_pumps].watts = TEMP_UNKNOWN;
+ aqdata->pumps[aqdata->num_pumps].gpm = TEMP_UNKNOWN;
+ aqdata->num_pumps++;
+ return &aqdata->pumps[aqdata->num_pumps-1];
+ }
+
+ return NULL;
+}
+
+
+void init_config()
+{
+ init_parameters(&_aqconfig_);
+}
+
+//void readCfg (struct aqconfig *config_parameters, struct aqualinkdata *aqdata, char *cfgFile)
+void read_config (struct aqualinkdata *aqdata, char *cfgFile)
{
FILE * fp ;
char bufr[MAXCFGLINE];
@@ -496,7 +574,7 @@ void readCfg (struct aqconfig *config_parameters, struct aqualinkdata *aqdata, c
//int tokenindex = 0;
char *b_ptr;
- config_parameters->config_file = cleanalloc(cfgFile);
+ _aqconfig_.config_file = cleanalloc(cfgFile);
if( (fp = fopen(cfgFile, "r")) != NULL){
while(! feof(fp)){
@@ -511,7 +589,7 @@ void readCfg (struct aqconfig *config_parameters, struct aqualinkdata *aqdata, c
indx = strchr(b_ptr, '=');
if ( indx != NULL)
{
- if ( ! setConfigValue(config_parameters, aqdata, b_ptr, indx+1))
+ if ( ! setConfigValue(aqdata, b_ptr, indx+1))
logMessage(LOG_ERR, "Unknown config parameter '%.*s'\n",strlen(b_ptr)-1, b_ptr);
}
}
@@ -596,67 +674,67 @@ void writeIntValue (FILE *fp, char *msg, int value)
fprintf(fp, "%s = %d\n", msg, value);
}
-bool writeCfg (struct aqconfig *config_parameters, struct aqualinkdata *aqdata)
+bool writeCfg (struct aqualinkdata *aqdata)
{
FILE *fp;
int i;
bool fs = remount_root_ro(false);
- fp = fopen(config_parameters->config_file, "w");
+ fp = fopen(_aqconfig_.config_file, "w");
if (fp == NULL) {
- logMessage(LOG_ERR, "Open config file failed '%s'\n", config_parameters->config_file);
+ logMessage(LOG_ERR, "Open config file failed '%s'\n", _aqconfig_.config_file);
remount_root_ro(true);
//fprintf(stdout, "Open file failed 'sprinkler.cron'\n");
return false;
}
fprintf(fp, "#***** AqualinkD configuration *****\n");
- fprintf(fp, "socket_port = %s\n", config_parameters->socket_port);
- fprintf(fp, "serial_port = %s\n", config_parameters->serial_port);
- fprintf(fp, "device_id = 0x%02hhx\n", config_parameters->device_id);
- fprintf(fp, "read_all_devices = %s", bool2text(config_parameters->read_all_devices));
- writeCharValue(fp, "log_level", errorlevel2text(config_parameters->log_level));
- writeCharValue(fp, "web_directory", config_parameters->web_directory);
- writeCharValue(fp, "log_file", config_parameters->log_file);
- fprintf(fp, "pda_mode = %s\n", bool2text(config_parameters->pda_mode));
+ fprintf(fp, "socket_port = %s\n", _aqconfig_.socket_port);
+ fprintf(fp, "serial_port = %s\n", _aqconfig_.serial_port);
+ fprintf(fp, "device_id = 0x%02hhx\n", _aqconfig_.device_id);
+ fprintf(fp, "read_all_devices = %s", bool2text(_aqconfig_.read_all_devices));
+ writeCharValue(fp, "log_level", errorlevel2text(_aqconfig_.log_level));
+ writeCharValue(fp, "web_directory", _aqconfig_.web_directory);
+ writeCharValue(fp, "log_file", _aqconfig_.log_file);
+ fprintf(fp, "pda_mode = %s\n", bool2text(_aqconfig_.pda_mode));
fprintf(fp, "\n#** MQTT Configuration **\n");
- writeCharValue(fp, "mqtt_address", config_parameters->mqtt_server);
- writeCharValue(fp, "mqtt_dz_sub_topic", config_parameters->mqtt_dz_sub_topic);
- writeCharValue(fp, "mqtt_dz_pub_topic", config_parameters->mqtt_dz_pub_topic);
- writeCharValue(fp, "mqtt_aq_topic", config_parameters->mqtt_aq_topic);
- writeCharValue(fp, "mqtt_user", config_parameters->mqtt_user);
- writeCharValue(fp, "mqtt_passwd", config_parameters->mqtt_passwd);
+ writeCharValue(fp, "mqtt_address", _aqconfig_.mqtt_server);
+ writeCharValue(fp, "mqtt_dz_sub_topic", _aqconfig_.mqtt_dz_sub_topic);
+ writeCharValue(fp, "mqtt_dz_pub_topic", _aqconfig_.mqtt_dz_pub_topic);
+ writeCharValue(fp, "mqtt_aq_topic", _aqconfig_.mqtt_aq_topic);
+ writeCharValue(fp, "mqtt_user", _aqconfig_.mqtt_user);
+ writeCharValue(fp, "mqtt_passwd", _aqconfig_.mqtt_passwd);
fprintf(fp, "\n#** General **\n");
- fprintf(fp, "convert_mqtt_temp_to_c = %s\n", bool2text(config_parameters->convert_mqtt_temp));
- fprintf(fp, "override_freeze_protect = %s\n", bool2text(config_parameters->override_freeze_protect));
- //fprintf(fp, "flash_mqtt_buttons = %s\n", bool2text(config_parameters->flash_mqtt_buttons));
- fprintf(fp, "report_zero_spa_temp = %s\n", bool2text(config_parameters->report_zero_spa_temp));
- fprintf(fp, "report_zero_pool_temp = %s\n", bool2text(config_parameters->report_zero_pool_temp));
+ fprintf(fp, "convert_mqtt_temp_to_c = %s\n", bool2text(_aqconfig_.convert_mqtt_temp));
+ fprintf(fp, "override_freeze_protect = %s\n", bool2text(_aqconfig_.override_freeze_protect));
+ //fprintf(fp, "flash_mqtt_buttons = %s\n", bool2text(_aqconfig_.flash_mqtt_buttons));
+ fprintf(fp, "report_zero_spa_temp = %s\n", bool2text(_aqconfig_.report_zero_spa_temp));
+ fprintf(fp, "report_zero_pool_temp = %s\n", bool2text(_aqconfig_.report_zero_pool_temp));
fprintf(fp, "\n#** Programmable light **\n");
- //if (config_parameters->light_programming_button_pool <= 0) {
- // fprintf(fp, "#light_programming_button_pool = %d\n", config_parameters->light_programming_button_pool);
- // fprintf(fp, "#light_programming_mode = %f\n", config_parameters->light_programming_mode);
- // fprintf(fp, "#light_programming_initial_on = %d\n", config_parameters->light_programming_initial_on);
- // fprintf(fp, "#light_programming_initial_off = %d\n", config_parameters->light_programming_initial_off);
+ //if (_aqconfig_.light_programming_button_pool <= 0) {
+ // fprintf(fp, "#light_programming_button_pool = %d\n", _aqconfig_.light_programming_button_pool);
+ // fprintf(fp, "#light_programming_mode = %f\n", _aqconfig_.light_programming_mode);
+ // fprintf(fp, "#light_programming_initial_on = %d\n", _aqconfig_.light_programming_initial_on);
+ // fprintf(fp, "#light_programming_initial_off = %d\n", _aqconfig_.light_programming_initial_off);
//} else {
- fprintf(fp, "light_programming_button_pool = %d\n", config_parameters->light_programming_button_pool);
- fprintf(fp, "light_programming_button_spa = %d\n", config_parameters->light_programming_button_spa);
- fprintf(fp, "light_programming_mode = %f\n", config_parameters->light_programming_mode);
- fprintf(fp, "light_programming_initial_on = %d\n", config_parameters->light_programming_initial_on);
- fprintf(fp, "light_programming_initial_off = %d\n", config_parameters->light_programming_initial_off);
+ fprintf(fp, "light_programming_button_pool = %d\n", _aqconfig_.light_programming_button_pool);
+ fprintf(fp, "light_programming_button_spa = %d\n", _aqconfig_.light_programming_button_spa);
+ fprintf(fp, "light_programming_mode = %f\n", _aqconfig_.light_programming_mode);
+ fprintf(fp, "light_programming_initial_on = %d\n", _aqconfig_.light_programming_initial_on);
+ fprintf(fp, "light_programming_initial_off = %d\n", _aqconfig_.light_programming_initial_off);
//}
fprintf(fp, "\n#** Domoticz **\n");
- fprintf(fp, "convert_dz_temp_to_c = %s\n", bool2text(config_parameters->convert_dz_temp));
- writeIntValue(fp, "air_temp_dzidx", config_parameters->dzidx_air_temp);
- writeIntValue(fp, "pool_water_temp_dzidx", config_parameters->dzidx_pool_water_temp);
- writeIntValue(fp, "spa_water_temp_dzidx", config_parameters->dzidx_spa_water_temp);
- writeIntValue(fp, "SWG_percent_dzidx", config_parameters->dzidx_swg_percent);
- writeIntValue(fp, "SWG_PPM_dzidx", config_parameters->dzidx_swg_ppm);
- writeIntValue(fp, "SWG_Status_dzidx", config_parameters->dzidx_swg_status);
+ fprintf(fp, "convert_dz_temp_to_c = %s\n", bool2text(_aqconfig_.convert_dz_temp));
+ writeIntValue(fp, "air_temp_dzidx", _aqconfig_.dzidx_air_temp);
+ writeIntValue(fp, "pool_water_temp_dzidx", _aqconfig_.dzidx_pool_water_temp);
+ writeIntValue(fp, "spa_water_temp_dzidx", _aqconfig_.dzidx_spa_water_temp);
+ writeIntValue(fp, "SWG_percent_dzidx", _aqconfig_.dzidx_swg_percent);
+ writeIntValue(fp, "SWG_PPM_dzidx", _aqconfig_.dzidx_swg_ppm);
+ writeIntValue(fp, "SWG_Status_dzidx", _aqconfig_.dzidx_swg_status);
fprintf(fp, "\n#** Buttons **\n");
for (i=0; i < TOTAL_BUTTONS; i++)
diff --git a/config.h b/config.h
index 80b2896..23116cf 100644
--- a/config.h
+++ b/config.h
@@ -7,7 +7,8 @@
#include "aqualink.h"
-#define DEFAULT_LOG_LEVEL 5
+//#define DEFAULT_LOG_LEVEL 10
+#define DEFAULT_LOG_LEVEL LOG_NOTICE
#define DEFAULT_WEBPORT "6580"
#define DEFAULT_WEBROOT "./"
#define DEFAULT_SERIALPORT "/dev/ttyUSB0"
@@ -18,7 +19,6 @@
#define DEFAULT_MQTT_SERVER NULL
#define DEFAULT_MQTT_USER NULL
#define DEFAULT_MQTT_PASSWD NULL
-// Set this high, as people are confused about SWG bouncing to zero on some panels, just stop the questions
#define DEFAILT_SWG_ZERO_IGNORE_COUNT 20
#define MQTT_ID_LEN 18 // 20 seems to kill mosquitto 1.6
@@ -31,6 +31,8 @@ struct aqconfig
char *socket_port;
char *web_directory;
unsigned char device_id;
+ unsigned char onetouch_device_id;
+ bool extended_device_id_programming;
bool deamonize;
char *log_file;
char *mqtt_dz_sub_topic;
@@ -53,6 +55,7 @@ struct aqconfig
int light_programming_button_spa;
bool override_freeze_protect;
bool pda_mode;
+ bool onetouch_mode;
bool pda_sleep_mode;
bool convert_mqtt_temp;
bool convert_dz_temp;
@@ -75,13 +78,31 @@ struct aqconfig
//char *mqtt_pub_tp_ptr = mqtt_pub_topic[];
};
+#ifndef CONFIG_C
+extern struct aqconfig _aqconfig_;
+#else
+struct aqconfig _aqconfig_;
+#endif
+/*
+#ifndef CONFIG_C
+#ifdef AQUALINKD_C
+extern struct aqconfig _aqconfig_;
+#else
+extern const struct aqconfig _aqconfig_;
+#endif
+#endif
+*/
void init_parameters (struct aqconfig * parms);
//bool parse_config (struct aqconfig * parms, char *cfgfile);
//void readCfg (struct aqconfig *config_parameters, char *cfgFile);
-void readCfg (struct aqconfig *config_parameters, struct aqualinkdata *aqualink_data, char *cfgFile);
-bool writeCfg (struct aqconfig *config_parameters, struct aqualinkdata *aqdata);
-bool setConfigValue(struct aqconfig *config_parameters, struct aqualinkdata *aqdata, char *param, char *value);
+//void readCfg (struct aqconfig *config_parameters, struct aqualinkdata *aqualink_data, char *cfgFile);
+void read_config(struct aqualinkdata *aqdata, char *cfgFile);
+void init_config();
+
+bool writeCfg (struct aqualinkdata *aqdata);
+bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value);
+
char *cleanalloc(char*str);
#endif
diff --git a/epump.h b/epump.h
new file mode 100644
index 0000000..2d2ab2e
--- /dev/null
+++ b/epump.h
@@ -0,0 +1,16 @@
+
+/*
+Nothing seems to change these in simulator, need real pump to test
+0x10|0x02|0x7a|0x44|0x00|0x58|0x1b|0x43|0x10|0x03|
+
+0x10|0x02|0x7a|0x44|0x00|0x58|0x1b|0x43|0x10|0x03|
+
+0x10|0x02|0x7a|0x44|0x00|0x58|0x1b|0x43|0x10|0x03|
+0x10|0x02|0x7a|0x41|0xcd|0x10|0x03|
+
+0x10|0x02|0x7a|0x44|0x00|0x58|0x1b|0x43|0x10|0x03|
+0x10|0x02|0x7a|0x41|0xcd|0x10|0x03|
+
+0x10|0x02|0x7a|0x44|0x00|0x58|0x1b|0x43|0x10|0x03|
+0x10|0x02|0x7a|0x41|0xcd|0x10|0x03|
+*/
\ No newline at end of file
diff --git a/json_messages.c b/json_messages.c
index 3ebe225..3b96c86 100644
--- a/json_messages.c
+++ b/json_messages.c
@@ -171,12 +171,15 @@ char *get_aux_information(aqkey *button, struct aqualinkdata *aqdata, char *buff
int length = 0;
buffer[0] = '\0';
- for (i=0; i < MAX_PUMPS; i++) {
+ for (i=0; i < aqdata->num_pumps; i++) {
if (button == aqdata->pumps[i].button) {
- if (aqdata->pumps[i].rpm != TEMP_UNKNOWN || aqdata->pumps[i].gph != TEMP_UNKNOWN || aqdata->pumps[i].watts != TEMP_UNKNOWN) {
- length += sprintf(buffer, ",\"Pump_RPM\":\"%d\",\"Pump_GPH\":\"%d\",\"Pump_Watts\":\"%d\"", aqdata->pumps[i].rpm,aqdata->pumps[i].gph,aqdata->pumps[i].watts);
+
+ //if (aqdata->pumps[i].rpm != TEMP_UNKNOWN || aqdata->pumps[i].gpm != TEMP_UNKNOWN || aqdata->pumps[i].watts != TEMP_UNKNOWN) {
+ length += sprintf(buffer, ",\"Pump_RPM\":\"%d\",\"Pump_GPM\":\"%d\",\"Pump_Watts\":\"%d\",\"Pump_Type\":\"%s\"",
+ aqdata->pumps[i].rpm,aqdata->pumps[i].gpm,aqdata->pumps[i].watts,
+ (aqdata->pumps[i].pumpType==VFPUMP?"vfPump":(aqdata->pumps[i].pumpType==VSPUMP?"vsPump":"ePump")));
break;
- }
+ //}
}
}
@@ -231,21 +234,38 @@ int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch1, int
LED2int(aqdata->aqbuttons[i].led->state));
} else if ( (programable_switch1 > 0 && programable_switch1 == i) ||
(programable_switch2 > 0 && programable_switch2 == i)) {
+ /*
length += sprintf(buffer+length, "{\"type\": \"switch_program\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"status\": \"%s\", \"int_status\": \"%d\" %s},",
aqdata->aqbuttons[i].name,
aqdata->aqbuttons[i].label,
aqdata->aqbuttons[i].led->state==ON?JSON_ON:JSON_OFF,
LED2text(aqdata->aqbuttons[i].led->state),
LED2int(aqdata->aqbuttons[i].led->state),
- get_aux_information(&aqdata->aqbuttons[i], aqdata, aux_info));
+ get_aux_information(&aqdata->aqbuttons[i], aqdata, aux_info));*/
+ length += sprintf(buffer+length, "{\"type\": \"switch\", \"type_ext\": \"switch_program\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"status\": \"%s\", \"int_status\": \"%d\"},",
+ aqdata->aqbuttons[i].name,
+ aqdata->aqbuttons[i].label,
+ aqdata->aqbuttons[i].led->state==ON?JSON_ON:JSON_OFF,
+ LED2text(aqdata->aqbuttons[i].led->state),
+ LED2int(aqdata->aqbuttons[i].led->state));
} else {
- length += sprintf(buffer+length, "{\"type\": \"switch\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"status\": \"%s\", \"int_status\": \"%d\" %s},",
+ if ( get_aux_information(&aqdata->aqbuttons[i], aqdata, aux_info)[0] == '\0' ) {
+ length += sprintf(buffer+length, "{\"type\": \"switch\", \"type_ext\": \"switch\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"status\": \"%s\", \"int_status\": \"%d\"},",
+ aqdata->aqbuttons[i].name,
+ aqdata->aqbuttons[i].label,
+ aqdata->aqbuttons[i].led->state==ON?JSON_ON:JSON_OFF,
+ LED2text(aqdata->aqbuttons[i].led->state),
+ LED2int(aqdata->aqbuttons[i].led->state));
+ } else {
+ length += sprintf(buffer+length, "{\"type\": \"switch\", \"type_ext\": \"switch_vsp\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"status\": \"%s\", \"int_status\": \"%d\" %s},",
aqdata->aqbuttons[i].name,
aqdata->aqbuttons[i].label,
aqdata->aqbuttons[i].led->state==ON?JSON_ON:JSON_OFF,
LED2text(aqdata->aqbuttons[i].led->state),
LED2int(aqdata->aqbuttons[i].led->state),
- get_aux_information(&aqdata->aqbuttons[i], aqdata, aux_info));
+ aux_info);
+ //get_aux_information(&aqdata->aqbuttons[i], aqdata, aux_info));
+ }
}
}
@@ -455,10 +475,12 @@ int build_aqualink_status_JSON(struct aqualinkdata *aqdata, char* buffer, int si
//length += sprintf(buffer+length, "}, \"extra\":{" );
length += sprintf(buffer+length, "},");
- for (i=0; i < MAX_PUMPS; i++) {
- if (aqdata->pumps[i].rpm != TEMP_UNKNOWN || aqdata->pumps[i].gph != TEMP_UNKNOWN || aqdata->pumps[i].watts != TEMP_UNKNOWN) {
- length += sprintf(buffer+length, "\"Pump_%d\":{\"name\":\"%s\",\"id\":\"%s\",\"RPM\":\"%d\",\"GPH\":\"%d\",\"Watts\":\"%d\"},",
- i+1,aqdata->pumps[i].button->label,aqdata->pumps[i].button->name,aqdata->pumps[i].rpm,aqdata->pumps[i].gph,aqdata->pumps[i].watts);
+ // NSF Check below needs to be for VSP Pump (any state), not just known state
+ for (i=0; i < aqdata->num_pumps; i++) {
+ if (aqdata->pumps[i].pumpType != PT_UNKNOWN && (aqdata->pumps[i].rpm != TEMP_UNKNOWN || aqdata->pumps[i].gpm != TEMP_UNKNOWN || aqdata->pumps[i].watts != TEMP_UNKNOWN)) {
+ length += sprintf(buffer+length, "\"Pump_%d\":{\"name\":\"%s\",\"id\":\"%s\",\"RPM\":\"%d\",\"GPM\":\"%d\",\"Watts\":\"%d\",\"Pump_Type\":\"%s\"},",
+ i+1,aqdata->pumps[i].button->label,aqdata->pumps[i].button->name,aqdata->pumps[i].rpm,aqdata->pumps[i].gpm,aqdata->pumps[i].watts,
+ (aqdata->pumps[i].pumpType==VFPUMP?"vfPump":(aqdata->pumps[i].pumpType==VSPUMP?"vsPump":"ePump")));
}
}
diff --git a/json_messages.h b/json_messages.h
index 256f5de..e442191 100644
--- a/json_messages.h
+++ b/json_messages.h
@@ -4,7 +4,7 @@
//FUNCTION PROTOTYPES
#define JSON_LABEL_SIZE 300
-#define JSON_STATUS_SIZE 800
+#define JSON_STATUS_SIZE 1024
#define JSON_MQTT_MSG_SIZE 100
#define JSON_ON "on"
diff --git a/net_services.c b/net_services.c
index 1e6cd09..d2c6d54 100644
--- a/net_services.c
+++ b/net_services.c
@@ -37,7 +37,7 @@
#include "aquapure.h"
-static struct aqconfig *_aqualink_config;
+//static struct aqconfig *_aqconfig_;
static struct aqualinkdata *_aqualink_data;
static char *_web_root;
@@ -70,7 +70,13 @@ static void signal_handler(int sig_num) {
static int is_websocket(const struct mg_connection *nc) {
- return nc->flags & MG_F_IS_WEBSOCKET;
+ return nc->flags & MG_F_IS_WEBSOCKET && !(nc->flags & MG_F_USER_2);
+}
+static void set_websocket_RSraw(struct mg_connection *nc) {
+ nc->flags |= MG_F_USER_2;
+}
+static int is_websocket_RSraw(const struct mg_connection *nc) {
+ return nc->flags & MG_F_USER_2;
}
static int is_mqtt(const struct mg_connection *nc) {
return nc->flags & MG_F_USER_1;
@@ -153,7 +159,7 @@ void send_domoticz_mqtt_state_msg(struct mg_connection *nc, int idx, int value)
char mqtt_msg[JSON_MQTT_MSG_SIZE];
build_mqtt_status_JSON(mqtt_msg ,JSON_MQTT_MSG_SIZE, idx, value, TEMP_UNKNOWN);
- send_mqtt(nc, _aqualink_config->mqtt_dz_pub_topic, mqtt_msg);
+ send_mqtt(nc, _aqconfig_.mqtt_dz_pub_topic, mqtt_msg);
}
void send_domoticz_mqtt_temp_msg(struct mg_connection *nc, int idx, int value)
@@ -162,8 +168,8 @@ void send_domoticz_mqtt_temp_msg(struct mg_connection *nc, int idx, int value)
return;
char mqtt_msg[JSON_MQTT_MSG_SIZE];
- build_mqtt_status_JSON(mqtt_msg ,JSON_MQTT_MSG_SIZE, idx, 0, (_aqualink_data->temp_units==FAHRENHEIT && _aqualink_config->convert_dz_temp)?roundf(degFtoC(value)):value);
- send_mqtt(nc, _aqualink_config->mqtt_dz_pub_topic, mqtt_msg);
+ build_mqtt_status_JSON(mqtt_msg ,JSON_MQTT_MSG_SIZE, idx, 0, (_aqualink_data->temp_units==FAHRENHEIT && _aqconfig_.convert_dz_temp)?roundf(degFtoC(value)):value);
+ send_mqtt(nc, _aqconfig_.mqtt_dz_pub_topic, mqtt_msg);
}
void send_domoticz_mqtt_numeric_msg(struct mg_connection *nc, int idx, int value)
{
@@ -172,7 +178,7 @@ void send_domoticz_mqtt_numeric_msg(struct mg_connection *nc, int idx, int value
char mqtt_msg[JSON_MQTT_MSG_SIZE];
build_mqtt_status_JSON(mqtt_msg ,JSON_MQTT_MSG_SIZE, idx, 0, value);
- send_mqtt(nc, _aqualink_config->mqtt_dz_pub_topic, mqtt_msg);
+ send_mqtt(nc, _aqconfig_.mqtt_dz_pub_topic, mqtt_msg);
}
void send_domoticz_mqtt_status_message(struct mg_connection *nc, int idx, int value, char *svalue) {
if (idx <= 0)
@@ -181,17 +187,17 @@ void send_domoticz_mqtt_status_message(struct mg_connection *nc, int idx, int va
char mqtt_msg[JSON_MQTT_MSG_SIZE];
build_mqtt_status_message_JSON(mqtt_msg, JSON_MQTT_MSG_SIZE, idx, value, svalue);
- send_mqtt(nc, _aqualink_config->mqtt_dz_pub_topic, mqtt_msg);
+ send_mqtt(nc, _aqconfig_.mqtt_dz_pub_topic, mqtt_msg);
}
void send_mqtt_state_msg(struct mg_connection *nc, char *dev_name, aqledstate state)
{
static char mqtt_pub_topic[250];
- sprintf(mqtt_pub_topic, "%s/%s/delay",_aqualink_config->mqtt_aq_topic, dev_name);
+ sprintf(mqtt_pub_topic, "%s/%s/delay",_aqconfig_.mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, (state==FLASH?MQTT_ON:MQTT_OFF));
- sprintf(mqtt_pub_topic, "%s/%s",_aqualink_config->mqtt_aq_topic, dev_name);
+ sprintf(mqtt_pub_topic, "%s/%s",_aqconfig_.mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, (state==OFF?MQTT_OFF:MQTT_ON));
}
@@ -203,8 +209,8 @@ void send_mqtt_aux_msg(struct mg_connection *nc, char *dev_name, char *dev_topic
sprintf(msg, "%d", value);
- //sprintf(mqtt_pub_topic, "%s/%s%d%s",_aqualink_config->mqtt_aq_topic, root_topic, dev_index, dev_topic);
- sprintf(mqtt_pub_topic, "%s/%s%s",_aqualink_config->mqtt_aq_topic, dev_name, dev_topic);
+ //sprintf(mqtt_pub_topic, "%s/%s%d%s",_aqconfig_.mqtt_aq_topic, root_topic, dev_index, dev_topic);
+ sprintf(mqtt_pub_topic, "%s/%s%s",_aqconfig_.mqtt_aq_topic, dev_name, dev_topic);
send_mqtt(nc, mqtt_pub_topic, msg);
}
@@ -213,15 +219,15 @@ void send_mqtt_heater_state_msg(struct mg_connection *nc, char *dev_name, aqleds
static char mqtt_pub_topic[250];
- sprintf(mqtt_pub_topic, "%s/%s",_aqualink_config->mqtt_aq_topic, dev_name);
+ sprintf(mqtt_pub_topic, "%s/%s",_aqconfig_.mqtt_aq_topic, dev_name);
if (state == ENABLE) {
send_mqtt(nc, mqtt_pub_topic, MQTT_OFF);
- sprintf(mqtt_pub_topic, "%s/%s%s",_aqualink_config->mqtt_aq_topic, dev_name, ENABELED_SUBT);
+ sprintf(mqtt_pub_topic, "%s/%s%s",_aqconfig_.mqtt_aq_topic, dev_name, ENABELED_SUBT);
send_mqtt(nc, mqtt_pub_topic, MQTT_ON);
} else {
send_mqtt(nc, mqtt_pub_topic, (state==OFF?MQTT_OFF:MQTT_ON));
- sprintf(mqtt_pub_topic, "%s/%s%s",_aqualink_config->mqtt_aq_topic, dev_name, ENABELED_SUBT);
+ sprintf(mqtt_pub_topic, "%s/%s%s",_aqconfig_.mqtt_aq_topic, dev_name, ENABELED_SUBT);
send_mqtt(nc, mqtt_pub_topic, (state==OFF?MQTT_OFF:MQTT_ON));
}
}
@@ -231,8 +237,8 @@ void send_mqtt_temp_msg(struct mg_connection *nc, char *dev_name, long value)
{
static char mqtt_pub_topic[250];
static char degC[10];
- sprintf(degC, "%.2f", (_aqualink_data->temp_units==FAHRENHEIT && _aqualink_config->convert_mqtt_temp)?degFtoC(value):value );
- sprintf(mqtt_pub_topic, "%s/%s", _aqualink_config->mqtt_aq_topic, dev_name);
+ sprintf(degC, "%.2f", (_aqualink_data->temp_units==FAHRENHEIT && _aqconfig_.convert_mqtt_temp)?degFtoC(value):value );
+ sprintf(mqtt_pub_topic, "%s/%s", _aqconfig_.mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, degC);
}
/*
@@ -241,9 +247,9 @@ void send_mqtt_temp_msg_new(struct mg_connection *nc, char *dev_name, long value
static char mqtt_pub_topic[250];
static char degC[5];
// NSF remove false below once we have finished.
- sprintf(degC, "%.2f", (false && _aqualink_data->temp_units==FAHRENHEIT && _aqualink_config->convert_mqtt_temp)?degFtoC(value):value );
+ sprintf(degC, "%.2f", (false && _aqualink_data->temp_units==FAHRENHEIT && _aqconfig_.convert_mqtt_temp)?degFtoC(value):value );
//sprintf(degC, "%d", value );
- sprintf(mqtt_pub_topic, "%s/%s", _aqualink_config->mqtt_aq_topic, dev_name);
+ sprintf(mqtt_pub_topic, "%s/%s", _aqconfig_.mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, degC);
}
*/
@@ -252,8 +258,8 @@ void send_mqtt_setpoint_msg(struct mg_connection *nc, char *dev_name, long value
static char mqtt_pub_topic[250];
static char degC[10];
- sprintf(degC, "%.2f", (_aqualink_data->temp_units==FAHRENHEIT && _aqualink_config->convert_mqtt_temp)?degFtoC(value):value );
- sprintf(mqtt_pub_topic, "%s/%s/setpoint", _aqualink_config->mqtt_aq_topic, dev_name);
+ sprintf(degC, "%.2f", (_aqualink_data->temp_units==FAHRENHEIT && _aqconfig_.convert_mqtt_temp)?degFtoC(value):value );
+ sprintf(mqtt_pub_topic, "%s/%s/setpoint", _aqconfig_.mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, degC);
}
void send_mqtt_numeric_msg(struct mg_connection *nc, char *dev_name, int value)
@@ -262,7 +268,7 @@ void send_mqtt_numeric_msg(struct mg_connection *nc, char *dev_name, int value)
static char msg[10];
sprintf(msg, "%d", value);
- sprintf(mqtt_pub_topic, "%s/%s", _aqualink_config->mqtt_aq_topic, dev_name);
+ sprintf(mqtt_pub_topic, "%s/%s", _aqconfig_.mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, msg);
}
void send_mqtt_float_msg(struct mg_connection *nc, char *dev_name, float value) {
@@ -270,7 +276,7 @@ void send_mqtt_float_msg(struct mg_connection *nc, char *dev_name, float value)
static char msg[10];
sprintf(msg, "%.2f", value);
- sprintf(mqtt_pub_topic, "%s/%s", _aqualink_config->mqtt_aq_topic, dev_name);
+ sprintf(mqtt_pub_topic, "%s/%s", _aqconfig_.mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, msg);
}
@@ -281,7 +287,7 @@ void send_mqtt_int_msg(struct mg_connection *nc, char *dev_name, int value) {
static char msg[10];
sprintf(msg, "%d", value);
- sprintf(mqtt_pub_topic, "%s/%s", _aqualink_config->mqtt_aq_topic, dev_name);
+ sprintf(mqtt_pub_topic, "%s/%s", _aqconfig_.mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, msg);
*/
}
@@ -289,7 +295,7 @@ void send_mqtt_int_msg(struct mg_connection *nc, char *dev_name, int value) {
void send_mqtt_string_msg(struct mg_connection *nc, char *dev_name, char *msg) {
static char mqtt_pub_topic[250];
- sprintf(mqtt_pub_topic, "%s/%s", _aqualink_config->mqtt_aq_topic, dev_name);
+ sprintf(mqtt_pub_topic, "%s/%s", _aqconfig_.mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, msg);
}
@@ -321,41 +327,41 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
_last_mqtt_aqualinkdata.air_temp = _aqualink_data->air_temp;
send_mqtt_temp_msg(nc, AIR_TEMP_TOPIC, _aqualink_data->air_temp);
//send_mqtt_temp_msg_new(nc, AIR_TEMPERATURE_TOPIC, _aqualink_data->air_temp);
- send_domoticz_mqtt_temp_msg(nc, _aqualink_config->dzidx_air_temp, _aqualink_data->air_temp);
+ send_domoticz_mqtt_temp_msg(nc, _aqconfig_.dzidx_air_temp, _aqualink_data->air_temp);
}
/*
if (_aqualink_data->pool_temp != TEMP_UNKNOWN && _aqualink_data->pool_temp != _last_mqtt_aqualinkdata.pool_temp) {
_last_mqtt_aqualinkdata.pool_temp = _aqualink_data->pool_temp;
send_mqtt_temp_msg(nc, POOL_TEMP_TOPIC, _aqualink_data->pool_temp);
- send_domoticz_mqtt_temp_msg(nc, _aqualink_config->dzidx_pool_water_temp, _aqualink_data->pool_temp);
+ send_domoticz_mqtt_temp_msg(nc, _aqconfig_.dzidx_pool_water_temp, _aqualink_data->pool_temp);
// IF spa is off, report pool water temp to Domoticz.
if (_aqualink_data->spa_temp == TEMP_UNKNOWN)
- send_domoticz_mqtt_temp_msg(nc, _aqualink_config->dzidx_spa_water_temp, _aqualink_data->pool_temp);
+ send_domoticz_mqtt_temp_msg(nc, _aqconfig_.dzidx_spa_water_temp, _aqualink_data->pool_temp);
}
*/
if (_aqualink_data->pool_temp != _last_mqtt_aqualinkdata.pool_temp) {
- if (_aqualink_data->pool_temp == TEMP_UNKNOWN && _aqualink_config->report_zero_pool_temp) {
+ if (_aqualink_data->pool_temp == TEMP_UNKNOWN && _aqconfig_.report_zero_pool_temp) {
_last_mqtt_aqualinkdata.pool_temp = TEMP_UNKNOWN;
- send_mqtt_temp_msg(nc, POOL_TEMP_TOPIC, (_aqualink_config->convert_mqtt_temp?-18:0));
+ send_mqtt_temp_msg(nc, POOL_TEMP_TOPIC, (_aqconfig_.convert_mqtt_temp?-18:0));
} else if (_aqualink_data->pool_temp != TEMP_UNKNOWN) {
_last_mqtt_aqualinkdata.pool_temp = _aqualink_data->pool_temp;
send_mqtt_temp_msg(nc, POOL_TEMP_TOPIC, _aqualink_data->pool_temp);
- send_domoticz_mqtt_temp_msg(nc, _aqualink_config->dzidx_pool_water_temp, _aqualink_data->pool_temp);
+ send_domoticz_mqtt_temp_msg(nc, _aqconfig_.dzidx_pool_water_temp, _aqualink_data->pool_temp);
// IF spa is off, report pool water temp to Domoticz.
if (_aqualink_data->spa_temp == TEMP_UNKNOWN)
- send_domoticz_mqtt_temp_msg(nc, _aqualink_config->dzidx_spa_water_temp, _aqualink_data->pool_temp);
+ send_domoticz_mqtt_temp_msg(nc, _aqconfig_.dzidx_spa_water_temp, _aqualink_data->pool_temp);
}
}
if (_aqualink_data->spa_temp != _last_mqtt_aqualinkdata.spa_temp) {
- if (_aqualink_data->spa_temp == TEMP_UNKNOWN && _aqualink_config->report_zero_spa_temp) {
+ if (_aqualink_data->spa_temp == TEMP_UNKNOWN && _aqconfig_.report_zero_spa_temp) {
_last_mqtt_aqualinkdata.spa_temp = TEMP_UNKNOWN;
- send_mqtt_temp_msg(nc, SPA_TEMP_TOPIC, (_aqualink_config->convert_mqtt_temp?-18:0));
+ send_mqtt_temp_msg(nc, SPA_TEMP_TOPIC, (_aqconfig_.convert_mqtt_temp?-18:0));
} else if (_aqualink_data->spa_temp != TEMP_UNKNOWN) {
_last_mqtt_aqualinkdata.spa_temp = _aqualink_data->spa_temp;
send_mqtt_temp_msg(nc, SPA_TEMP_TOPIC, _aqualink_data->spa_temp);
- send_domoticz_mqtt_temp_msg(nc, _aqualink_config->dzidx_spa_water_temp, _aqualink_data->spa_temp);
+ send_domoticz_mqtt_temp_msg(nc, _aqconfig_.dzidx_spa_water_temp, _aqualink_data->spa_temp);
}
}
@@ -363,7 +369,7 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
_last_mqtt_aqualinkdata.pool_htr_set_point = _aqualink_data->pool_htr_set_point;
send_mqtt_setpoint_msg(nc, BTN_POOL_HTR, _aqualink_data->pool_htr_set_point);
// removed until domoticz has a better virtuel thermostat
- //send_domoticz_mqtt_temp_msg(nc, _aqualink_config->dzidx_pool_thermostat, _aqualink_data->pool_htr_set_point);
+ //send_domoticz_mqtt_temp_msg(nc, _aqconfig_.dzidx_pool_thermostat, _aqualink_data->pool_htr_set_point);
}
if (_aqualink_data->spa_htr_set_point != TEMP_UNKNOWN && _aqualink_data->spa_htr_set_point != _last_mqtt_aqualinkdata.spa_htr_set_point) {
@@ -384,7 +390,7 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
send_mqtt_string_msg(nc, FREEZE_PROTECT_ENABELED, MQTT_ON);
/*
send_mqtt_string_msg(nc, FREEZE_PROTECT_ENABELED, MQTT_ON);
- //send_domoticz_mqtt_temp_msg(nc, _aqualink_config->dzidx_rfz_protect, _aqualink_data->frz_protect_set_point);
+ //send_domoticz_mqtt_temp_msg(nc, _aqconfig_.dzidx_rfz_protect, _aqualink_data->frz_protect_set_point);
} else if (_aqualink_data->frz_protect_set_point != _last_mqtt_aqualinkdata.frz_protect_set_point) {
_last_mqtt_aqualinkdata.frz_protect_set_point = _aqualink_data->frz_protect_set_point;
send_mqtt_string_msg(nc, FREEZE_PROTECT_ENABELED, MQTT_OFF);*/
@@ -411,7 +417,7 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
if (!_aqualink_data->simulate_panel)
sprintf(_aqualink_data->last_display_message, message);
- send_domoticz_mqtt_status_message(nc, _aqualink_config->dzidx_swg_status, dzalert, &message[9]);
+ send_domoticz_mqtt_status_message(nc, _aqconfig_.dzidx_swg_status, dzalert, &message[9]);
send_mqtt_int_msg(nc, SWG_TOPIC, status);
if (_aqualink_data->ar_swg_status == SWG_STATUS_OFF)
@@ -436,13 +442,13 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
send_mqtt_numeric_msg(nc, SWG_PERCENT_TOPIC, _aqualink_data->swg_percent);
send_mqtt_float_msg(nc, SWG_PERCENT_F_TOPIC, roundf(degFtoC(_aqualink_data->swg_percent)));
send_mqtt_float_msg(nc, SWG_SETPOINT_TOPIC, roundf(degFtoC(_aqualink_data->swg_percent)));
- send_domoticz_mqtt_numeric_msg(nc, _aqualink_config->dzidx_swg_percent, _aqualink_data->swg_percent);
+ send_domoticz_mqtt_numeric_msg(nc, _aqconfig_.dzidx_swg_percent, _aqualink_data->swg_percent);
}
if (_aqualink_data->swg_ppm != TEMP_UNKNOWN && ( force_update || _aqualink_data->swg_ppm != _last_mqtt_aqualinkdata.swg_ppm)) {
_last_mqtt_aqualinkdata.swg_ppm = _aqualink_data->swg_ppm;
send_mqtt_numeric_msg(nc, SWG_PPM_TOPIC, _aqualink_data->swg_ppm);
send_mqtt_float_msg(nc, SWG_PPM_F_TOPIC, roundf(degFtoC(_aqualink_data->swg_ppm)));
- send_domoticz_mqtt_numeric_msg(nc, _aqualink_config->dzidx_swg_ppm, _aqualink_data->swg_ppm);
+ send_domoticz_mqtt_numeric_msg(nc, _aqconfig_.dzidx_swg_ppm, _aqualink_data->swg_ppm);
}
}
@@ -453,7 +459,7 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
// Loop over LED's and send any changes.
for (i=0; i < TOTAL_BUTTONS; i++) {
/*
- if ( _aqualink_data->aqbuttons[i].led->state == FLASH && _aqualink_config->flash_mqtt_buttons == true ) {
+ if ( _aqualink_data->aqbuttons[i].led->state == FLASH && _aqconfig_.flash_mqtt_buttons == true ) {
// Simply send on or off depending on if current second is odd or even.
// will send too many off and on messages as we get hit multiple times a second, but most effecient way to handle this
// considering flash is not very often and not for long.
@@ -475,7 +481,7 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
}
// Loop over Pumps
- 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].gph = TEMP_UNKNOWN;
//_aqualink_data->pumps[i].watts = TEMP_UNKNOWN;
@@ -485,10 +491,10 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
//send_mqtt_aux_msg(nc, PUMP_TOPIC, i+1, PUMP_RPM_TOPIC, _aqualink_data->pumps[i].rpm);
send_mqtt_aux_msg(nc, _aqualink_data->pumps[i].button->name, PUMP_RPM_TOPIC, _aqualink_data->pumps[i].rpm);
}
- if (_aqualink_data->pumps[i].gph != TEMP_UNKNOWN && _aqualink_data->pumps[i].gph != _last_mqtt_aqualinkdata.pumps[i].gph) {
- _last_mqtt_aqualinkdata.pumps[i].gph = _aqualink_data->pumps[i].gph;
+ if (_aqualink_data->pumps[i].gpm != TEMP_UNKNOWN && _aqualink_data->pumps[i].gpm != _last_mqtt_aqualinkdata.pumps[i].gpm) {
+ _last_mqtt_aqualinkdata.pumps[i].gpm = _aqualink_data->pumps[i].gpm;
//send_mqtt_aux_msg(nc, PUMP_TOPIC, i+1, PUMP_GPH_TOPIC, _aqualink_data->pumps[i].gph);
- send_mqtt_aux_msg(nc, _aqualink_data->pumps[i].button->name, PUMP_GPH_TOPIC, _aqualink_data->pumps[i].gph);
+ send_mqtt_aux_msg(nc, _aqualink_data->pumps[i].button->name, PUMP_GPM_TOPIC, _aqualink_data->pumps[i].gpm);
}
if (_aqualink_data->pumps[i].watts != TEMP_UNKNOWN && _aqualink_data->pumps[i].watts != _last_mqtt_aqualinkdata.pumps[i].watts) {
_last_mqtt_aqualinkdata.pumps[i].watts = _aqualink_data->pumps[i].watts;
@@ -507,7 +513,7 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
//if (_aqualink_data->aqbuttons[i].dz_idx != DZ_NULL_IDX) {
if (_aqualink_data->aqbuttons[i].code == KEY_POOL_HTR || _aqualink_data->aqbuttons[i].code == KEY_SPA_HTR) {
send_mqtt_heater_state_msg(nc, _aqualink_data->aqbuttons[i].name, _aqualink_data->aqbuttons[i].led->state);
- } else if (_aqualink_data->aqbuttons[i].led->state == FLASH && _aqualink_config->flash_mqtt_buttons == true) {
+ } else if (_aqualink_data->aqbuttons[i].led->state == FLASH && _aqconfig_.flash_mqtt_buttons == true) {
// This messed up the origional LED state, which means we send the flash to WEB UI as well.
time_t now;
now = time(NULL);
@@ -553,12 +559,12 @@ int getTempforMeteohub(char *buffer)
void set_light_mode(char *value, int button)
{
- if (_aqualink_config->pda_mode == true) {
+ if (_aqconfig_.pda_mode == true) {
logMessage(LOG_ERR, "Light mode control not supported in PDA mode\n");
return;
}
- if (_aqualink_config->light_programming_button_pool != button &&
- _aqualink_config->light_programming_button_spa != button) {
+ if (_aqconfig_.light_programming_button_pool != button &&
+ _aqconfig_.light_programming_button_spa != button) {
logMessage(LOG_ERR, "Light mode control not configured for button %d\n",button);
return;
}
@@ -567,9 +573,9 @@ void set_light_mode(char *value, int button)
// 5 below is light index, need to look this up so it's not hard coded.
sprintf(buf, "%-5s%-5d%-5d%-5d%.2f",value,
button,
- _aqualink_config->light_programming_initial_on,
- _aqualink_config->light_programming_initial_off,
- _aqualink_config->light_programming_mode );
+ _aqconfig_.light_programming_initial_on,
+ _aqconfig_.light_programming_initial_off,
+ _aqconfig_.light_programming_mode );
//logMessage(LOG_NOTICE, "WEB: requset light mode %s\n", buf);
aq_programmer(AQ_SET_COLORMODE, buf, _aqualink_data);
}
@@ -611,24 +617,20 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
char value[20];
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
//aq_programmer(AQ_SET_COLORMODE, value, _aqualink_data);
- set_light_mode(value, _aqualink_config->light_programming_button_pool);
+ set_light_mode(value, _aqconfig_.light_programming_button_pool);
mg_send_head(nc, 200, strlen(GET_RTN_OK), "Content-Type: text/plain");
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
} else if (strcmp(command, "spalightmode") == 0) {
char value[20];
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
//aq_programmer(AQ_SET_COLORMODE, value, _aqualink_data);
- set_light_mode(value, _aqualink_config->light_programming_button_spa);
+ set_light_mode(value, _aqconfig_.light_programming_button_spa);
mg_send_head(nc, 200, strlen(GET_RTN_OK), "Content-Type: text/plain");
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
} else if (strcmp(command, "diag") == 0) {
aq_programmer(AQ_GET_DIAGNOSTICS_MODEL, NULL, _aqualink_data);
mg_send_head(nc, 200, strlen(GET_RTN_OK), "Content-Type: text/plain");
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
- } else if (strcmp(command, "settime") == 0) {
- aq_programmer(AQ_SET_TIME, NULL, _aqualink_data);
- mg_send_head(nc, 200, strlen(GET_RTN_OK), "Content-Type: text/plain");
- mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
} else if (strcmp(command, "swg_percent") == 0) {
char value[20];
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
@@ -659,12 +661,12 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
} else if (strcmp(command, "devices") == 0) {
char message[JSON_LABEL_SIZE*10];
- int size = build_device_JSON(_aqualink_data, _aqualink_config->light_programming_button_pool, _aqualink_config->light_programming_button_spa, message, JSON_LABEL_SIZE*10, false);
+ int size = build_device_JSON(_aqualink_data, _aqconfig_.light_programming_button_pool, _aqconfig_.light_programming_button_spa, message, JSON_LABEL_SIZE*10, false);
mg_send_head(nc, 200, size, "Content-Type: application/json");
mg_send(nc, message, size);
} else if (strcmp(command, "homebridge") == 0) {
char message[JSON_LABEL_SIZE*10];
- int size = build_device_JSON(_aqualink_data, _aqualink_config->light_programming_button_pool, _aqualink_config->light_programming_button_spa, message, JSON_LABEL_SIZE*10, true);
+ int size = build_device_JSON(_aqualink_data, _aqconfig_.light_programming_button_pool, _aqconfig_.light_programming_button_spa, message, JSON_LABEL_SIZE*10, true);
mg_send_head(nc, 200, size, "Content-Type: application/json");
mg_send(nc, message, size);
} else if (strcmp(command, "setconfigprm") == 0) {
@@ -674,7 +676,7 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
mg_get_http_var(&http_msg->query_string, "param", param, sizeof(param));
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
- if (setConfigValue(_aqualink_config, _aqualink_data, param, value)) {
+ if (setConfigValue(_aqualink_data, param, value)) {
webrtn = GET_RTN_OK;
logMessage(LOG_INFO, "Web: request to config %s to %s\n", param, value);
} else {
@@ -684,7 +686,7 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
mg_send_head(nc, 200, strlen(webrtn), "Content-Type: text/plain");
mg_send(nc, webrtn, strlen(webrtn));
} else if (strcmp(command, "writeconfig") == 0) {
- if (writeCfg (_aqualink_config, _aqualink_data)) {
+ if (writeCfg (_aqualink_data)) {
mg_send_head(nc, 200, strlen(GET_RTN_OK), "Content-Type: text/plain");
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
} else {
@@ -704,8 +706,12 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
stopInlineDebug();
rtn = GET_RTN_OK;
} else if (strcmp(value, "serialstart") == 0) {
+ startInlineSerialDebug();
+ logMessage(LOG_DEBUG, "WEB: Started inline debug mode\n");
rtn = GET_RTN_OK;
} else if (strcmp(value, "serialstop") == 0) {
+ logMessage(LOG_DEBUG, "WEB: Stoped inline debug mode\n");
+ stopInlineDebug();
rtn = GET_RTN_OK;
} else if (strcmp(value, "status") == 0) {
snprintf(value,80,"{\"sLevel\":\"%s\", \"iLevel\":%d, \"logReady\":\"%s\"}\n",elevel2text(getLogLevel()),getLogLevel(),islogFileReady()?"true":"false" );
@@ -724,6 +730,28 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
}
mg_send_head(nc, 200, strlen(rtn), "Content-Type: text/plain");
mg_send(nc, rtn, strlen(rtn));
+ } else if (strncmp(command, "Pump_", 5) == 0) {
+ // Set Pump RPM
+ bool found = false;
+ int pumpIndex = atoi(command+5); // Check for 0
+ char value[10];
+ mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
+ int rpm = atoi(value);
+ // Check for pumpIndex = 0 (BAD) and check RPM Value
+ //printf("******** ADD CHECK FOR PUMP & RPM HERE ********\n");
+ int pi;
+ for (pi=0; pi < _aqualink_data->num_pumps; pi++) {
+ if (_aqualink_data->pumps[pi].pumpIndex == pumpIndex) {
+ logMessage(LOG_NOTICE, "WEB: request to change pump %d to %d\n",pumpIndex, round(rpm));
+ _aqualink_data->unactioned.type = PUMP_RPM;
+ _aqualink_data->unactioned.value = round(rpm);
+ _aqualink_data->unactioned.id = pumpIndex;
+ found=true;
+ break;
+ }
+ }
+ if(!found)
+ logMessage(LOG_ERR, "WEB: Didn't find pump %d from command %s\n",pumpIndex,command);
} else {
int i;
for (i = 0; i < TOTAL_BUTTONS; i++) {
@@ -736,7 +764,7 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
// *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
logMessage(LOG_DEBUG, "WEB: Message request '%s' change state to '%s'\n", command, value);
- if (_aqualink_config->pda_mode == true) {
+ if (_aqconfig_.pda_mode == true) {
char msg[PTHREAD_ARG];
sprintf(msg, "%-5d%-5d",i, (strcmp(value, "on") == 0)?ON:OFF);
//printf("******* '%s' ********\n",msg);
@@ -825,8 +853,12 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
//aq_programmer(AQ_SEND_CMD, (char *)&n, NULL);
aq_send_cmd((unsigned char)n);
//char message[JSON_LABEL_SIZE*10];
- //build_device_JSON(_aqualink_data, _aqualink_config->light_programming_button, message, JSON_LABEL_SIZE*10);
+ //build_device_JSON(_aqualink_data, _aqconfig_.light_programming_button, message, JSON_LABEL_SIZE*10);
//ws_send(nc, message);
+ } else if (strcmp(request.first.key, "mode") == 0) {
+ if (strcmp(request.first.value, "onetouchraw") == 0) {
+ set_websocket_RSraw(nc);
+ }
} else if (strcmp(request.first.key, "command") == 0) {
_aqualink_data->simulate_panel = false;
if (strcmp(request.first.value, "GET_AUX_LABELS") == 0) {
@@ -835,7 +867,7 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
ws_send(nc, labels);
} else if (strcmp(request.first.value, "GET_DEVICES") == 0) {
char message[JSON_LABEL_SIZE*10];
- build_device_JSON(_aqualink_data, _aqualink_config->light_programming_button_pool, _aqualink_config->light_programming_button_spa, message, JSON_LABEL_SIZE*10, false);
+ build_device_JSON(_aqualink_data, _aqconfig_.light_programming_button_pool, _aqconfig_.light_programming_button_spa, message, JSON_LABEL_SIZE*10, false);
ws_send(nc, message);
} else if ( strcmp(request.first.value, "simulator") == 0) {
_aqualink_data->simulate_panel = true;
@@ -857,7 +889,7 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
if (strcmp(request.first.value, _aqualink_data->aqbuttons[i].name) == 0) {
logMessage (LOG_INFO, "WS: button '%s' pressed\n",_aqualink_data->aqbuttons[i].name);
// send_command( (unsigned char)_aqualink_data->aqbuttons[i].code);
- if (_aqualink_config->pda_mode == false) {
+ if (_aqconfig_.pda_mode == false) {
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
} else {
@@ -889,7 +921,7 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
_aqualink_data->swg_percent = value; // Set the value as if it's already been set, just incase it's 0 as we won't get that message, or will update next time
}
} else if (strcmp(request.first.value, "POOL_LIGHT_MODE") == 0) {
- set_light_mode(request.second.value, _aqualink_config->light_programming_button_pool);
+ set_light_mode(request.second.value, _aqconfig_.light_programming_button_pool);
} else if (strcmp(request.first.value, "LIGHT_MODE") == 0) {
int i;
for (i = 0; i < TOTAL_BUTTONS; i++) {
@@ -900,7 +932,26 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
}
//set_light_mode(request.second.value, 0);
} else {
- logMessage(LOG_DEBUG, "WS: Unknown parameter %s\n", request.first.value);
+ int i;
+ bool found = false;
+ for (i = 0; i < TOTAL_BUTTONS; i++) {
+ if (strcmp(request.first.value, _aqualink_data->aqbuttons[i].name) == 0) {
+ int pi;
+ logMessage (LOG_INFO, "WS: button parameter request '%s' '%s'\n",_aqualink_data->aqbuttons[i].name, request.second.value);
+ for (pi=0; pi < _aqualink_data->num_pumps; pi++) {
+ if (_aqualink_data->pumps[pi].button == &_aqualink_data->aqbuttons[i]) {
+ logMessage(LOG_NOTICE, "WS: request to change pump %d %s to %s\n",pi, _aqualink_data->aqbuttons[i].name, request.second.value);
+ _aqualink_data->unactioned.type = PUMP_RPM;
+ _aqualink_data->unactioned.value = atoi(request.second.value);
+ _aqualink_data->unactioned.id = _aqualink_data->pumps[pi].pumpIndex;
+ found=true;
+ break;
+ }
+ }
+ }
+ }
+ if (!found)
+ logMessage(LOG_DEBUG, "WS: Unknown parameter %s\n", request.first.value);
}
}
}
@@ -925,12 +976,12 @@ void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg)
//printf("Topic %.*s\n",msg->topic.len, msg->topic.p);
// get the parts from the topic
- char *pt1 = (char *)&msg->topic.p[strlen(_aqualink_config->mqtt_aq_topic)+1];
+ char *pt1 = (char *)&msg->topic.p[strlen(_aqconfig_.mqtt_aq_topic)+1];
char *pt2 = NULL;
char *pt3 = NULL;
//for (i=10; i < msg->topic.len; i++) {
- for (i=strlen(_aqualink_config->mqtt_aq_topic)+1; i < msg->topic.len; i++) {
+ for (i=strlen(_aqconfig_.mqtt_aq_topic)+1; i < msg->topic.len; i++) {
if ( msg->topic.p[i] == '/' ) {
if (pt2 == NULL) {
pt2 = (char *)&msg->topic.p[++i];
@@ -949,8 +1000,11 @@ void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg)
//aqualinkd/Pool_Heater/set
//aqualinkd/SWG/Percent_f/set
+ //aqualinkd/Filter_Pump/RPM/set // Should add this at some point
+ //aqualinkd/Pump_1/RPM/set
+
if (pt3 != NULL && (strncmp(pt2, "setpoint", 8) == 0) && (strncmp(pt3, "set", 3) == 0)) {
- int val = _aqualink_data->unactioned.value = (_aqualink_data->temp_units != CELSIUS && _aqualink_config->convert_mqtt_temp) ? round(degCtoF(value)) : round(value);
+ int val = _aqualink_data->unactioned.value = (_aqualink_data->temp_units != CELSIUS && _aqconfig_.convert_mqtt_temp) ? round(degCtoF(value)) : round(value);
if (strncmp(pt1, BTN_POOL_HTR, strlen(BTN_POOL_HTR)) == 0) {
_aqualink_data->unactioned.value = setpoint_check(POOL_HTR_SETOINT, val, _aqualink_data);
_aqualink_data->unactioned.type = POOL_HTR_SETOINT;
@@ -984,6 +1038,28 @@ void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg)
} else if ((pt3 != NULL && (strncmp(pt1, "SWG", 3) == 0) && (strncmp(pt2, "Boost", 5) == 0) && (strncmp(pt3, "set", 3) == 0))) {
_aqualink_data->unactioned.value = round(value);
_aqualink_data->unactioned.type = SWG_BOOST;
+ } else if ((pt3 != NULL && (strncmp(pt1, "Pump_", 5) == 0) && ((strncmp(pt2, "RPM", 3) == 0) || (strncmp(pt2, "GPM", 3) == 0)) && (strncmp(pt3, "set", 3) == 0))) {
+ // Set Pump RPM
+ bool found = false;
+ int pumpIndex = atoi(pt1+5); // Check for 0
+ // Check for pumpIndex = 0 (BAD) and check RPM Value
+ //printf("******** ADD CHECK FOR PUMP & RPM HERE ********\n");
+ int pi;
+ for (pi=0; pi < _aqualink_data->num_pumps; pi++) {
+ if (_aqualink_data->pumps[pi].pumpIndex == pumpIndex) {
+ //printf("******** Set pump %d RPM to %d ******\n",pumpIndex, round(value));
+ //int val = RPM_check(_aqualink_data->pumps[pi].pumpType, val, _aqualink_data);
+ //RPM_check( val)
+ logMessage(LOG_NOTICE, "MQTT: request to change pump %d %s to %d\n",pumpIndex, (strncmp(pt2, "RPM", 3) == 0)?"RPM":"GPM", round(value));
+ _aqualink_data->unactioned.type = PUMP_RPM;
+ _aqualink_data->unactioned.value = round(value);
+ _aqualink_data->unactioned.id = pumpIndex;
+ found=true;
+ break;
+ }
+ }
+ if(!found)
+ logMessage(LOG_ERR, "MQTT: Didn't find pump %d from message %.*s\n",pumpIndex,msg->topic.len, msg->topic.p);
} else if (pt2 != NULL && (strncmp(pt2, "set", 3) == 0) && (strncmp(pt2, "setpoint", 8) != 0)) {
// Must be a switch on / off
for (i=0; i < TOTAL_BUTTONS; i++) {
@@ -1003,7 +1079,7 @@ void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg)
} else {
logMessage(LOG_INFO, "MQTT: received '%s' for '%s', turning '%s'\n", (value==0?"OFF":"ON"), _aqualink_data->aqbuttons[i].name,(value==0?"OFF":"ON"));
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
- if (_aqualink_config->pda_mode == false) {
+ if (_aqconfig_.pda_mode == false) {
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
} else {
@@ -1048,7 +1124,7 @@ void action_domoticz_mqtt_message(struct mg_connection *nc, struct mg_mqtt_messa
} else {
logMessage(LOG_INFO, "MQTT: DZ: received '%s' for '%s', turning '%s'\n", (nvalue==DZ_OFF?"OFF":"ON"), _aqualink_data->aqbuttons[i].name,(nvalue==DZ_OFF?"OFF":"ON"));
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
- if (_aqualink_config->pda_mode == false) {
+ if (_aqconfig_.pda_mode == false) {
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
} else {
@@ -1062,7 +1138,7 @@ void action_domoticz_mqtt_message(struct mg_connection *nc, struct mg_mqtt_messa
}
}
/* removed until domoticz has a better virtual thermostat
- if (idx == _aqualink_config->dzidx_pool_thermostat) {
+ if (idx == _aqconfig_.dzidx_pool_thermostat) {
float degC = atof(svalue);
int degF = (int)degCtoF(degC);
if (degC > 0.0 && 1 < (degF - _aqualink_data->pool_htr_set_point)) {
@@ -1071,7 +1147,7 @@ void action_domoticz_mqtt_message(struct mg_connection *nc, struct mg_mqtt_messa
} else {
logMessage(LOG_INFO, "MQTT: DZ: received temp setting '%s' for 'pool heater setpoint' matched current setting (or was zero), ignoring!\n", svalue);
}
- } else if (idx == _aqualink_config->dzidx_spa_thermostat) {
+ } else if (idx == _aqconfig_.dzidx_spa_thermostat) {
float degC = atof(svalue);
int degF = (int)degCtoF(degC);
if (degC > 0.0 && 1 < (degF - _aqualink_data->spa_htr_set_point)) {
@@ -1132,18 +1208,18 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
//char *MQTT_id = "AQUALINK_MQTT_TEST_ID";
struct mg_send_mqtt_handshake_opts opts;
memset(&opts, 0, sizeof(opts));
- opts.user_name = _aqualink_config->mqtt_user;
- opts.password = _aqualink_config->mqtt_passwd;
+ opts.user_name = _aqconfig_.mqtt_user;
+ opts.password = _aqconfig_.mqtt_passwd;
opts.keep_alive = 5;
opts.flags |= MG_MQTT_CLEAN_SESSION; // NFS Need to readup on this
- snprintf(aq_topic, 24, "%s/%s", _aqualink_config->mqtt_aq_topic,MQTT_LWM_TOPIC);
+ snprintf(aq_topic, 24, "%s/%s", _aqconfig_.mqtt_aq_topic,MQTT_LWM_TOPIC);
opts.will_topic = aq_topic;
opts.will_message = MQTT_OFF;
mg_set_protocol_mqtt(nc);
- mg_send_mqtt_handshake_opt(nc, _aqualink_config->mqtt_ID, opts);
- logMessage(LOG_INFO, "MQTT: Subscribing mqtt with id of: %s\n", _aqualink_config->mqtt_ID);
+ mg_send_mqtt_handshake_opt(nc, _aqconfig_.mqtt_ID, opts);
+ logMessage(LOG_INFO, "MQTT: Subscribing mqtt with id of: %s\n", _aqconfig_.mqtt_ID);
//last_control_time = mg_time();
} break;
@@ -1160,27 +1236,27 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
_mqtt_exit_flag = true;
}
- snprintf(aq_topic, 29, "%s/#", _aqualink_config->mqtt_aq_topic);
- if (_aqualink_config->mqtt_aq_topic != NULL && _aqualink_config->mqtt_dz_sub_topic != NULL) {
+ snprintf(aq_topic, 29, "%s/#", _aqconfig_.mqtt_aq_topic);
+ if (_aqconfig_.mqtt_aq_topic != NULL && _aqconfig_.mqtt_dz_sub_topic != NULL) {
topics[0].topic = aq_topic;
topics[0].qos = qos;
- topics[1].topic = _aqualink_config->mqtt_dz_sub_topic;
+ topics[1].topic = _aqconfig_.mqtt_dz_sub_topic;
topics[1].qos = qos;
mg_mqtt_subscribe(nc, topics, 2, 42);
logMessage(LOG_INFO, "MQTT: Subscribing to '%s'\n", aq_topic);
- logMessage(LOG_INFO, "MQTT: Subscribing to '%s'\n", _aqualink_config->mqtt_dz_sub_topic);
+ logMessage(LOG_INFO, "MQTT: Subscribing to '%s'\n", _aqconfig_.mqtt_dz_sub_topic);
}
- else if (_aqualink_config->mqtt_aq_topic != NULL) {
+ else if (_aqconfig_.mqtt_aq_topic != NULL) {
topics[0].topic = aq_topic;
topics[0].qos = qos;
mg_mqtt_subscribe(nc, topics, 1, 42);
logMessage(LOG_INFO, "MQTT: Subscribing to '%s'\n", aq_topic);
}
- else if (_aqualink_config->mqtt_dz_sub_topic != NULL) {
- topics[0].topic = _aqualink_config->mqtt_dz_sub_topic;;
+ else if (_aqconfig_.mqtt_dz_sub_topic != NULL) {
+ topics[0].topic = _aqconfig_.mqtt_dz_sub_topic;;
topics[0].qos = qos;
mg_mqtt_subscribe(nc, topics, 1, 42);
- logMessage(LOG_INFO, "MQTT: Subscribing to '%s'\n", _aqualink_config->mqtt_dz_sub_topic);
+ logMessage(LOG_INFO, "MQTT: Subscribing to '%s'\n", _aqconfig_.mqtt_dz_sub_topic);
}
}
break;
@@ -1190,20 +1266,21 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
break;
case MG_EV_MQTT_SUBACK:
logMessage(LOG_INFO, "MQTT: Subscription(s) acknowledged\n");
- snprintf(aq_topic, 24, "%s/%s", _aqualink_config->mqtt_aq_topic,MQTT_LWM_TOPIC);
+ snprintf(aq_topic, 24, "%s/%s", _aqconfig_.mqtt_aq_topic,MQTT_LWM_TOPIC);
send_mqtt(nc, aq_topic ,MQTT_ON);
break;
case MG_EV_MQTT_PUBLISH:
mqtt_msg = (struct mg_mqtt_message *)ev_data;
if (mqtt_msg->message_id != 0) {
- logMessage(LOG_INFO, "MQTT: received (msg_id: %d), looks like my own message, ignoring\n", mqtt_msg->message_id);
+ logMessage(LOG_DEBUG, "MQTT: received (msg_id: %d), looks like my own message, ignoring\n", mqtt_msg->message_id);
}
// NSF Need to change strlen to a global so it's not executed every time we check a topic
- if (_aqualink_config->mqtt_aq_topic != NULL && strncmp(mqtt_msg->topic.p, _aqualink_config->mqtt_aq_topic, strlen(_aqualink_config->mqtt_aq_topic)) == 0) {
+ if (_aqconfig_.mqtt_aq_topic != NULL && strncmp(mqtt_msg->topic.p, _aqconfig_.mqtt_aq_topic, strlen(_aqconfig_.mqtt_aq_topic)) == 0)
+ {
action_mqtt_message(nc, mqtt_msg);
}
- if (_aqualink_config->mqtt_dz_sub_topic != NULL && strncmp(mqtt_msg->topic.p, _aqualink_config->mqtt_dz_sub_topic, strlen(_aqualink_config->mqtt_dz_sub_topic)) == 0) {
+ if (_aqconfig_.mqtt_dz_sub_topic != NULL && strncmp(mqtt_msg->topic.p, _aqconfig_.mqtt_dz_sub_topic, strlen(_aqconfig_.mqtt_dz_sub_topic)) == 0) {
action_domoticz_mqtt_message(nc, mqtt_msg);
}
break;
@@ -1224,13 +1301,13 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
}
void start_mqtt(struct mg_mgr *mgr) {
- logMessage (LOG_NOTICE, "Starting MQTT client to %s\n", _aqualink_config->mqtt_server);
- if ( _aqualink_config->mqtt_server == NULL ||
- ( _aqualink_config->mqtt_aq_topic == NULL && _aqualink_config->mqtt_dz_pub_topic == NULL && _aqualink_config->mqtt_dz_sub_topic == NULL) )
+ logMessage (LOG_NOTICE, "Starting MQTT client to %s\n", _aqconfig_.mqtt_server);
+ if ( _aqconfig_.mqtt_server == NULL ||
+ ( _aqconfig_.mqtt_aq_topic == NULL && _aqconfig_.mqtt_dz_pub_topic == NULL && _aqconfig_.mqtt_dz_sub_topic == NULL) )
return;
- if (mg_connect(mgr, _aqualink_config->mqtt_server, ev_handler) == NULL) {
- logMessage (LOG_ERR, "Failed to create MQTT listener to %s\n", _aqualink_config->mqtt_server);
+ if (mg_connect(mgr, _aqconfig_.mqtt_server, ev_handler) == NULL) {
+ logMessage (LOG_ERR, "Failed to create MQTT listener to %s\n", _aqconfig_.mqtt_server);
} else {
int i;
for (i=0; i < TOTAL_BUTTONS; i++) {
@@ -1246,10 +1323,11 @@ void start_mqtt(struct mg_mgr *mgr) {
}
//bool start_web_server(struct mg_mgr *mgr, struct aqualinkdata *aqdata, char *port, char* web_root) {
-bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata, struct aqconfig *aqconfig) {
+//bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata, struct aqconfig *aqconfig) {
+bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata) {
struct mg_connection *nc;
_aqualink_data = aqdata;
- _aqualink_config = aqconfig;
+ //_aqconfig_ = aqconfig;
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
@@ -1257,8 +1335,8 @@ bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata, struct
setvbuf(stderr, NULL, _IOLBF, 0);
mg_mgr_init(mgr, NULL);
- logMessage (LOG_NOTICE, "Starting web server on port %s\n", _aqualink_config->socket_port);
- nc = mg_bind(mgr, _aqualink_config->socket_port, ev_handler);
+ logMessage (LOG_NOTICE, "Starting web server on port %s\n", _aqconfig_.socket_port);
+ nc = mg_bind(mgr, _aqconfig_.socket_port, ev_handler);
if (nc == NULL) {
logMessage (LOG_ERR, "Failed to create listener\n");
return false;
@@ -1266,7 +1344,7 @@ bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata, struct
// Set up HTTP server parameters
mg_set_protocol_http_websocket(nc);
- s_http_server_opts.document_root = _aqualink_config->web_directory; // Serve current directory
+ s_http_server_opts.document_root = _aqconfig_.web_directory; // Serve current directory
s_http_server_opts.enable_directory_listing = "yes";
#ifndef MG_DISABLE_MQTT
diff --git a/net_services.h b/net_services.h
index ea809df..33e84be 100644
--- a/net_services.h
+++ b/net_services.h
@@ -9,7 +9,8 @@
//void main_server();
//void main_server_TEST(struct aqualinkdata *aqdata, char *s_http_port);
//bool start_web_server(struct mg_mgr *mgr, struct aqualinkdata *aqdata, char *port, char* web_root);
-bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata, struct aqconfig *aqconfig);
+//bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata, struct aqconfig *aqconfig);
+bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata);
void broadcast_aqualinkstate(struct mg_connection *nc);
void broadcast_aqualinkstate_error(struct mg_connection *nc, char *msg);
diff --git a/onetouch.c b/onetouch.c
new file mode 100644
index 0000000..2bde185
--- /dev/null
+++ b/onetouch.c
@@ -0,0 +1,689 @@
+#include
+#include
+#include
+#include
+#include
+
+#include "onetouch.h"
+#include "onetouch_aq_programmer.h"
+#include "aq_serial.h"
+#include "utils.h"
+#include "aq_serial.h"
+#include "packetLogger.h"
+#include "aq_programmer.h"
+#include "aqualink.h"
+//#include "pda_menu.h"
+
+
+int _ot_hlightindex = -1;
+int _ot_hlightcharindexstart = -1;
+int _ot_hlightcharindexstop = -1;
+char _menu[ONETOUCH_LINES][AQ_MSGLEN+1];
+struct ot_macro _macros[3];
+
+void set_macro_status();
+void pump_update(struct aqualinkdata *aq_data, int updated);
+
+void print_onetouch_menu()
+{
+ int i;
+ for (i=0; i < ONETOUCH_LINES; i++) {
+ //printf("PDA Line %d = %s\n",i,_menu[i]);
+ logMessage(LOG_INFO, "OneTouch Menu Line %d = %s\n",i,_menu[i]);
+ }
+
+ if (_ot_hlightcharindexstart > -1) {
+ logMessage(LOG_INFO, "OneTouch Menu highlighted line = %d, '%s' hligh-char(s) '%.*s'\n",
+ _ot_hlightindex,_menu[_ot_hlightindex],
+ (_ot_hlightcharindexstart - _ot_hlightcharindexstop + 1), &_menu[_ot_hlightindex][_ot_hlightcharindexstart]);
+ } else if (_ot_hlightindex > -1) {
+ logMessage(LOG_INFO, "OneTouch Menu highlighted line = %d = %s\n",_ot_hlightindex,_menu[_ot_hlightindex]);
+ }
+}
+
+int onetouch_menu_hlightindex()
+{
+ return _ot_hlightindex;
+}
+
+char *onetouch_menu_hlight()
+{
+ return onetouch_menu_line(_ot_hlightindex);
+}
+
+char *onetouch_menu_hlightchars(int *len)
+{
+ *len = _ot_hlightcharindexstart - _ot_hlightcharindexstop + 1;
+ return &_menu[_ot_hlightindex][_ot_hlightcharindexstart];
+}
+
+char *onetouch_menu_line(int index)
+{
+ if (index >= 0 && index < ONETOUCH_LINES)
+ return _menu[index];
+ else
+ return "-"; // Just return something bad so I can use string comparison with no null check
+ // return NULL;
+}
+
+// Find exact menu item.
+int onetouch_menu_find_index(char *text)
+{
+ int i;
+
+ for (i = 0; i < ONETOUCH_LINES; i++) {
+ if (ot_strcmp(onetouch_menu_line(i), text) == 0)
+ //if (ot_strcmp(onetouch_menu_line(i), text, limit) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+
+bool process_onetouch_menu_packet(unsigned char* packet, int length)
+{
+ bool rtn = true;
+ signed char first_line;
+ signed char last_line;
+ signed char line_shift;
+ signed char i;
+
+ switch (packet[PKT_CMD]) {
+ case CMD_PDA_CLEAR:
+ _ot_hlightindex = -1;
+ _ot_hlightcharindexstart = -1;
+ _ot_hlightcharindexstart = -1;
+ memset(_menu, 0, ONETOUCH_LINES * (AQ_MSGLEN+1));
+ break;
+ case CMD_MSG_LONG:
+ if (packet[PKT_DATA] < ONETOUCH_LINES) {
+ memset(_menu[(int)packet[PKT_DATA]], 0, AQ_MSGLEN);
+ strncpy(_menu[(int)packet[PKT_DATA]], (char*)packet+PKT_DATA+1, AQ_MSGLEN);
+ _menu[packet[PKT_DATA]][AQ_MSGLEN] = '\0';
+ }
+ //if (getLogLevel() >= LOG_DEBUG){print_onetouch_menu();}
+ break;
+ case CMD_PDA_HIGHLIGHT:
+ // when switching from hlight to hlightchars index 255 is sent to turn off hlight
+ if (packet[4] <= ONETOUCH_LINES) {
+ _ot_hlightindex = packet[4];
+ _ot_hlightcharindexstart = -1;
+ _ot_hlightcharindexstart = -1;
+ } else {
+ _ot_hlightindex = -1;
+ _ot_hlightcharindexstart = -1;
+ _ot_hlightcharindexstart = -1;
+ }
+ logMessage(LOG_DEBUG, "OneTouch Menu highlighted line = %d = %s\n",_ot_hlightindex,_menu[_ot_hlightindex]);
+ //if (getLogLevel() >= LOG_DEBUG){print_onetouch_menu();}
+ break;
+ case CMD_PDA_HIGHLIGHTCHARS:
+ if (packet[4] <= ONETOUCH_LINES) {
+ _ot_hlightindex = packet[4];
+ _ot_hlightcharindexstart = packet[5];
+ _ot_hlightcharindexstop = packet[6];
+ } else {
+ _ot_hlightindex = -1;
+ _ot_hlightcharindexstart = -1;
+ _ot_hlightcharindexstart = -1;
+ }
+ logMessage(LOG_DEBUG, "OneTouch Menu highlighted line = %d, '%s' chars '%.*s'\n",
+ _ot_hlightindex,_menu[_ot_hlightindex],
+ (_ot_hlightcharindexstart - _ot_hlightcharindexstop + 1), &_menu[_ot_hlightindex][_ot_hlightcharindexstart]);
+ //if (getLogLevel() >= LOG_DEBUG){print_onetouch_menu();}
+ break;
+ case CMD_PDA_SHIFTLINES:
+ /// press up from top - shift menu down by 1
+ // PDA Shif | HEX: 0x10|0x02|0x62|0x0f|0x01|0x08|0x01|0x8d|0x10|0x03|
+ // press down from bottom - shift menu up by 1
+ // PDA Shif | HEX: 0x10|0x02|0x62|0x0f|0x01|0x08|0xff|0x8b|0x10|0x03|
+ first_line = (signed char)(packet[4]);
+ last_line = (signed char)(packet[5]);
+ line_shift = (signed char)(packet[6]);
+ logMessage(LOG_DEBUG, "\n");
+ if (line_shift < 0) {
+ for (i = first_line-line_shift; i <= last_line; i++) {
+ memcpy(_menu[i+line_shift], _menu[i], AQ_MSGLEN+1);
+ }
+ } else {
+ for (i = last_line; i >= first_line+line_shift; i--) {
+ memcpy(_menu[i], _menu[i-line_shift], AQ_MSGLEN+1);
+ }
+ }
+ //if (getLogLevel() >= LOG_DEBUG){print_onetouch_menu();}
+ break;
+ }
+
+ return rtn;
+}
+
+void setUnits_ot(char *str, struct aqualinkdata *aq_data)
+{
+ // NSF This needs to use setUnits from aqualinkd.c
+ if (aq_data->temp_units == UNKNOWN) {
+ if (str[15] == 'F')
+ aq_data->temp_units = FAHRENHEIT;
+ else if (str[15] == 'C')
+ aq_data->temp_units = CELSIUS;
+ else
+ aq_data->temp_units = UNKNOWN;
+
+ logMessage(LOG_INFO, "Temp Units set to %d (F=0, C=1, Unknown=2)\n", aq_data->temp_units);
+ }
+}
+
+bool log_heater_setpoints(struct aqualinkdata *aq_data)
+{
+ bool rtn = false;
+
+ if (ot_strcmp(_menu[2], "Pool Heat") == 0)
+ aq_data->pool_htr_set_point = ot_atoi(&_menu[2][10]);
+ if (ot_strcmp(_menu[3], "Spa Heat") == 0 )
+ aq_data->spa_htr_set_point = ot_atoi(&_menu[3][9]);
+
+ setUnits_ot(_menu[2], aq_data);
+
+ logMessage(LOG_DEBUG, "POOL HEATER SETPOINT %d\n",aq_data->pool_htr_set_point);
+ logMessage(LOG_DEBUG, "SPA HEATER SETPOINT %d\n",aq_data->spa_htr_set_point);
+
+ return rtn;
+}
+
+bool log_panelversion(struct aqualinkdata *aq_data)
+{
+ char *end;
+
+ // It's already been set
+ if (strlen(aq_data->version) > 0) {
+ return false;
+ }
+
+ strcpy(aq_data->version, trimwhitespace(_menu[4]));
+ // Trim trailing space
+ end = aq_data->version + strlen(aq_data->version) - 1;
+ while(end > aq_data->version && isspace(*end)) end--;
+
+ strcpy(end+2, trimwhitespace(_menu[7]));
+ // Trim trailing space
+ end = aq_data->version + strlen(aq_data->version) - 1;
+ while(end > aq_data->version && isspace(*end)) end--;
+
+ // Write new null terminator
+ *(end+1) = 0;
+
+ logMessage(LOG_DEBUG, "**** '%s' ****\n",aq_data->version);
+
+ return true;
+}
+
+//Info: OneTouch Menu Line 3 = Temp 38`F
+bool log_freeze_setpoints(struct aqualinkdata *aq_data)
+{
+ bool rtn = false;
+
+ if (ot_strcmp(_menu[3], "Temp") == 0)
+ aq_data->frz_protect_set_point = ot_atoi(&_menu[3][11]);
+
+ setUnits_ot(_menu[3], aq_data);
+
+ logMessage(LOG_DEBUG, "FREEZE PROTECT SETPOINT %d\n",aq_data->frz_protect_set_point);
+
+ return rtn;
+}
+
+bool log_qeuiptment_status(struct aqualinkdata *aq_data)
+{
+ bool rtn = false;
+
+ if (ot_strcmp(_menu[2],"Intelliflo VS") == 0 ||
+ ot_strcmp(_menu[2],"Intelliflo VF") == 0 ||
+ ot_strcmp(_menu[2],"Jandy ePUMP") == 0) {
+ rtn = true;
+ int rpm = 0;
+ int watts = 0;
+ int gpm = 0;
+ int pump_index = ot_atoi(&_menu[2][14]);
+ // RPM displays differently depending on 3 or 4 digit rpm.
+ if (ot_strcmp(_menu[3],"RPM:") == 0){
+ rpm = ot_atoi(&_menu[3][10]);
+ if (ot_strcmp(_menu[4],"Watts:") == 0) {
+ watts = ot_atoi(&_menu[4][11]);
+ }
+ if (ot_strcmp(_menu[5],"GPM:") == 0) {
+ gpm = ot_atoi(&_menu[5][11]);
+ }
+ } else if (ot_strcmp(_menu[3],"*** Priming ***") == 0){
+ rpm = PUMP_PRIMING;
+ } else if (ot_strcmp(_menu[3],"(Offline)") == 0){
+ rpm = PUMP_OFFLINE;
+ }
+
+ logMessage(LOG_DEBUG, "OneTouch Pump %s, Index %d, RPM %d, Watts %d, GPM %d\n",_menu[2],pump_index,rpm,watts,gpm);
+
+ int i;
+ for (i=0; i < aq_data->num_pumps; i++) {
+ if (aq_data->pumps[i].pumpIndex == pump_index) {
+ //printf("**** FOUND PUMP %d at index %d *****\n",pump_index,i);
+ //aq_data->pumps[i].updated = true;
+ pump_update(aq_data, i);
+ aq_data->pumps[i].rpm = rpm;
+ aq_data->pumps[i].watts = watts;
+ aq_data->pumps[i].gpm = gpm;
+ if (aq_data->pumps[i].pumpType == PT_UNKNOWN){
+ if (ot_strcmp(_menu[2],"Intelliflo VS") == 0)
+ aq_data->pumps[i].pumpType = VSPUMP;
+ else if (ot_strcmp(_menu[2],"Intelliflo VF") == 0)
+ aq_data->pumps[i].pumpType = VFPUMP;
+ else if (ot_strcmp(_menu[2],"Jandy ePUMP") == 0)
+ aq_data->pumps[i].pumpType = EPUMP;
+ }
+ //printf ("Set Pump Type to %d\n",aq_data->pumps[i].pumpType);
+ }
+ }
+
+ //aqdata->pumps[pumpIndex-1].rpm = atoi((char *) &packet_buffer[13]);
+
+ } else if (true == false) {
+ /*
+ Debug: OneTouch Menu Line 0 = Equipment Status
+ Debug: OneTouch Menu Line 1 =
+ Debug: OneTouch Menu Line 2 = AQUAPURE 30%
+ Debug: OneTouch Menu Line 3 = Salt 3800 PPM
+ Debug: OneTouch Menu Line 4 = Add 2 lbs Salt
+ */
+ }
+ return rtn;
+}
+
+ot_menu_type get_onetouch_memu_type()
+{
+ if (ot_strcmp(_menu[11],"SYSTEM") == 0)
+ return OTM_ONETOUCH;
+ else if (ot_strcmp(_menu[0],"Jandy AquaLinkRS") == 0)
+ return OTM_SYSTEM;
+ else if (ot_strcmp(_menu[0],"EQUIPMENT STATUS") == 0)
+ return OTM_EQUIPTMENT_STATUS;
+ else if (ot_strcmp(_menu[0],"Select Speed") == 0)
+ return OTM_SELECT_SPEED;
+ else if (ot_strcmp(_menu[0],"Menu") == 0)
+ return OTM_MENUHELP;
+ else if (ot_strcmp(_menu[0],"Set Temp") == 0)
+ return OTM_SET_TEMP;
+ else if (ot_strcmp(_menu[0],"Set Time") == 0)
+ return OTM_SET_TIME;
+ else if (ot_strcmp(_menu[0],"System Setup") == 0)
+ return OTM_SYSTEM_SETUP;
+ else if (ot_strcmp(_menu[0],"Freeze Protect") == 0)
+ return OTM_FREEZE_PROTECT;
+ else if (ot_strcmp(_menu[0],"Boost Pool") == 0)
+ return OTM_BOOST;
+ else if (ot_strcmp(_menu[7],"REV ") == 0) // NSF Need a better check.
+ return OTM_VERSION;
+
+ return OTM_UNKNOWN;
+}
+
+void pump_update(struct aqualinkdata *aq_data, int updated) {
+ const int bitmask[MAX_PUMPS] = {1,2,4,8};
+ static unsigned char updates = '\0';
+ int i;
+
+ if (updated == -1) {
+ for(i=0; i < MAX_PUMPS; i++) {
+ if ((updates & bitmask[i]) != bitmask[i]) {
+ aq_data->pumps[i].rpm = TEMP_UNKNOWN;
+ aq_data->pumps[i].gpm = TEMP_UNKNOWN;
+ aq_data->pumps[i].watts = TEMP_UNKNOWN;
+ }
+ }
+ updates = '\0';
+ } else if (updated >=0 && updated < MAX_PUMPS) {
+ updates |= bitmask[updated];
+ }
+}
+
+bool new_menu(struct aqualinkdata *aq_data)
+{
+ static bool initRS = false;
+ bool rtn = false;
+ static ot_menu_type last_menu_type = OTM_UNKNOWN;
+ ot_menu_type menu_type = get_onetouch_memu_type();
+
+ print_onetouch_menu();
+
+ switch (menu_type) {
+ case OTM_ONETOUCH:
+ set_macro_status();
+ break;
+ case OTM_EQUIPTMENT_STATUS:
+ if (initRS == false) {
+ queueGetProgramData(ONETOUCH, aq_data);
+ initRS = true;
+ }
+ rtn = log_qeuiptment_status(aq_data);
+ // Hit select to get to next menu ASAP.
+ if ( in_ot_programming_mode(aq_data) == false )
+ ot_queue_cmd(KEY_ONET_SELECT);
+ break;
+ case OTM_SET_TEMP:
+ rtn = log_heater_setpoints(aq_data);
+ break;
+ case OTM_FREEZE_PROTECT:
+ rtn = log_freeze_setpoints(aq_data);
+ break;
+ case OTM_VERSION:
+ rtn = log_panelversion(aq_data);
+ logMessage(LOG_DEBUG, "**** ONETOUCH INIT ****");
+ queueGetProgramData(ONETOUCH, aq_data);
+ //set_aqualink_onetouch_pool_heater_temp()
+ //aq_programmer(AQ_SET_ONETOUCH_POOL_HEATER_TEMP, "95", aq_data);
+ //aq_programmer(AQ_SET_ONETOUCH_SPA_HEATER_TEMP, "94", aq_data);
+ initRS = true;
+ break;
+ default:
+ break;
+ }
+
+ if (last_menu_type == OTM_EQUIPTMENT_STATUS && menu_type != OTM_EQUIPTMENT_STATUS ) {
+ // End of equiptment status chain of menus, reset any pump that wasn't listed in menus
+ pump_update(aq_data, -1);
+ }
+
+ last_menu_type = menu_type;
+
+ return rtn;
+}
+
+void set_macro_status()
+{
+ // OneTouch Menu Line 2 = SPA MODE OFF
+ // OneTouch Menu Line 5 = CLEAN MODE ON
+ // OneTouch Menu Line 8 = ONETOUCH 3 OFF
+ if (get_onetouch_memu_type() == OTM_ONETOUCH) {
+ strncpy(_macros[0].name, _menu[2], 13);
+ chopwhitespace(_macros[0].name);
+ _macros[0].ison = (_menu[2][15] == 'N'?true:false);
+
+ strncpy(_macros[1].name, _menu[5], 13);
+ chopwhitespace(_macros[1].name);
+ _macros[1].ison = (_menu[5][15] == 'N'?true:false);
+
+ strncpy(_macros[2].name, _menu[8], 13);
+ chopwhitespace(_macros[2].name);
+ _macros[2].ison = (_menu[8][15] == 'N'?true:false);
+
+ logMessage(LOG_DEBUG, "Macro #1 '%s' is %s\n",_macros[0].name,_macros[0].ison?"On":"Off");
+ logMessage(LOG_DEBUG, "Macro #2 '%s' is %s\n",_macros[1].name,_macros[1].ison?"On":"Off");
+ logMessage(LOG_DEBUG, "Macro #3 '%s' is %s\n",_macros[2].name,_macros[2].ison?"On":"Off");
+
+ }
+}
+
+unsigned char _last_msg_type = 0x00;
+unsigned char _last_kick_type = -1;
+
+int thread_kick_type()
+{
+ return _last_kick_type;
+}
+
+unsigned char *last_onetouch_packet()
+{
+ return &_last_msg_type;
+}
+
+bool process_onetouch_packet(unsigned char *packet, int length, struct aqualinkdata *aq_data)
+{
+ static bool filling_menu = false;
+ bool rtn = false;
+ //int i;
+ //char *msg;
+ //static unsigned char last_msg_type = 0x00;
+ //static bool init = false;
+
+ //process_pda_packet(packet, length);
+
+ //logMessage(LOG_DEBUG, "RS Received ONETOUCH 0x%02hhx\n", packet[PKT_CMD]);
+ //debuglogPacket(packet, length);
+
+ process_onetouch_menu_packet(packet, length);
+
+ // Check for new menu.
+ // Usually PDA_CLEAR bunch of CMD_MSG_LONG then a CMD_PDA_HIGHLIGHT or CMD_PDA_HIGHLIGHTCHARS
+ // When we hit page down, just CMD_MSG_LONG then a CMD_PDA_HIGHLIGHT. (not seen CMD_PDA_HIGHLIGHTCHARS yet)
+ if ( (filling_menu == true &&
+ (//packet[PKT_CMD] == CMD_PDA_HIGHLIGHTCHARS ||
+ packet[PKT_CMD] == CMD_PDA_HIGHLIGHT ||
+ packet[PKT_CMD] == CMD_STATUS) )
+ ||
+ ( _last_msg_type == CMD_MSG_LONG && packet[PKT_CMD] == CMD_PDA_HIGHLIGHT )
+ )
+ {
+ filling_menu = false;
+ rtn = new_menu(aq_data);
+ _last_kick_type = KICKT_MENU;
+ } else {
+ _last_kick_type = KICKT_CMD;
+ }
+
+ if (packet[PKT_CMD] == CMD_PDA_CLEAR)
+ filling_menu = true;
+
+/*
+ //if (_last_msg_type == CMD_MSG_LONG && packet[PKT_CMD] != CMD_MSG_LONG) {
+ if (_last_msg_type == CMD_MSG_LONG && ( packet[PKT_CMD] != CMD_MSG_LONG && packet[PKT_CMD] != CMD_PDA_HIGHLIGHTCHARS) ) { // CMD_PDA_SHIFTLINES
+ rtn = new_menu(aq_data);
+ _last_kick_type = KICKT_MENU;
+ } else {
+ _last_kick_type = KICKT_CMD;
+ }
+*/
+ _last_msg_type = packet[PKT_CMD];
+
+ // Receive 0x04 for System menu (before 0x02)
+ // Receive 0x04 for startup menu (before 0x02)
+ // Receive 0x08 for Equiptment menu (before 0x02)
+
+ // Receive 0x04 while building menu
+
+ if ( packet[PKT_CMD] == CMD_MSG_LONG)
+ logMessage(LOG_DEBUG, "RS received ONETOUCH packet of type %s length %d '%.*s'\n", get_packet_type(packet, length), length, AQ_MSGLEN, (char*)packet+PKT_DATA+1);
+ else
+ logMessage(LOG_DEBUG, "RS received ONETOUCH packet of type %s length %d\n", get_packet_type(packet, length), length);
+
+
+ //debuglogPacket(packet, length);
+
+ //if ( in_ot_programming_mode(aq_data) == true )
+ kick_aq_program_thread(aq_data, ONETOUCH);
+/*
+ switch (packet[PKT_CMD])
+ {
+ case CMD_ACK:
+ //logMessage(LOG_DEBUG, "RS Received ACK length %d.\n", length);
+ break;
+
+ //case CMD_PDA_HIGHLIGHT: // This doesn't work for end of menu, if menu is complete then get a change line, highlight isn't sent.
+ //set_macro_status();
+ // break;
+
+ case 0x04:
+ case 0x08:
+ logMessage(LOG_DEBUG, "RS Received MENU complete\n");
+ set_macro_status();
+ break;
+
+
+
+ case CMD_MSG_LONG:
+ msg = (char *)packet + PKT_DATA + 1;
+ logMessage(LOG_DEBUG, "RS Received message data 0x%02hhx string '%s'\n",packet[PKT_DATA],msg);
+ break;
+
+ default:
+ //logMessage(LOG_DEBUG, "RS Received 0x%02hhx\n", packet[PKT_CMD]);
+ break;
+ }
+*/
+ return rtn;
+}
+
+
+// Check s2 exists in s1
+int ot_strcmp(const char *s1, const char *s2)
+{
+ char *sp1 = (char *)s1;
+ char *sp2 = (char *)s2;
+ //int i=0;
+ // Get rid of all padding
+ while(isspace(*sp1)) sp1++;
+ while(isspace(*sp2)) sp2++;
+
+ // Need to write this myself for speed
+ //logMessage(LOG_DEBUG, "OneTouch compare (reset)%d chars of '%s' to '%s'\n",strlen(sp2),sp1,sp2);
+ return strncasecmp(sp1, sp2, strlen(sp2));
+}
+
+
+
+#define INT_MAX +2147483647
+#define INT_MIN -2147483647
+
+// atoi that can have blank start
+int ot_atoi(const char* str)
+{
+ int sign = 1, base = 0, i = 0;
+ // if whitespaces then ignore.
+ while (str[i] == ' ') {
+ i++;
+ }
+
+ // checking for valid input
+ while (str[i] >= '0' && str[i] <= '9') {
+ // handling overflow test case
+ if (base > INT_MAX / 10 || (base == INT_MAX / 10 && str[i] - '0' > 7)) {
+ if (sign == 1)
+ return INT_MAX;
+ else
+ return INT_MIN;
+ }
+ base = 10 * base + (str[i++] - '0');
+ }
+ return base * sign;
+}
+
+/*
+Version something like
+Info: OneTouch Menu Line 0 =
+Info: OneTouch Menu Line 1 =
+Info: OneTouch Menu Line 2 =
+Info: OneTouch Menu Line 3 =
+Info: OneTouch Menu Line 4 = B0029221
+Info: OneTouch Menu Line 5 = RS-8 Combo
+Info: OneTouch Menu Line 6 =
+Info: OneTouch Menu Line 7 = REV T.0.1
+Info: OneTouch Menu Line 8 =
+Info: OneTouch Menu Line 9 =
+Info: OneTouch Menu Line 10 =
+Info: OneTouch Menu Line 11 =
+*/
+/*
+Info: OneTouch Menu Line 0 = Set Temp
+Info: OneTouch Menu Line 1 =
+Info: OneTouch Menu Line 2 = Pool Heat 90`F
+Info: OneTouch Menu Line 3 = Spa Heat 102`F
+Info: OneTouch Menu Line 4 =
+Info: OneTouch Menu Line 5 = Maintain OFF
+Info: OneTouch Menu Line 6 = Hours 12AM-12AM
+Info: OneTouch Menu Line 7 =
+Info: OneTouch Menu Line 8 = Highlight an
+Info: OneTouch Menu Line 9 = item and press
+Info: OneTouch Menu Line 10 = Select
+Info: OneTouch Menu Line 11 =
+*/
+/*
+nfo: OneTouch Menu Line 0 = Freeze Protect
+Info: OneTouch Menu Line 1 =
+Info: OneTouch Menu Line 2 =
+Info: OneTouch Menu Line 3 = Temp 38`F
+Info: OneTouch Menu Line 4 =
+Info: OneTouch Menu Line 5 =
+Info: OneTouch Menu Line 6 = Use Arrow Keys
+Info: OneTouch Menu Line 7 = to set value.
+Info: OneTouch Menu Line 8 = Press SELECT
+Info: OneTouch Menu Line 9 = to continue.
+Info: OneTouch Menu Line 10 =
+Info: OneTouch Menu Line 11 =
+*/
+
+/*
+Pump Stuff Use Intelliflo|Jandy & last number of line.
+(Intelliflo VF you set GPM, not RPM)
+
+Debug: OneTouch Menu Line 0 = Equipment Status
+Debug: OneTouch Menu Line 1 =
+Debug: OneTouch Menu Line 2 = Intelliflo VS 3
+Debug: OneTouch Menu Line 3 = *** Priming ***
+Debug: OneTouch Menu Line 4 = Watts: 100
+Debug: OneTouch Menu Line 5 =
+Debug: OneTouch Menu Line 6 =
+Debug: OneTouch Menu Line 7 =
+Debug: OneTouch Menu Line 8 =
+Debug: OneTouch Menu Line 9 =
+Debug: OneTouch Menu Line 10 =
+Debug: OneTouch Menu Line 11 =
+
+Debug: OneTouch Menu Line 0 = Equipment Status
+Debug: OneTouch Menu Line 1 =
+Debug: OneTouch Menu Line 2 = Intelliflo VS 3
+Debug: OneTouch Menu Line 3 = RPM: 2750
+Debug: OneTouch Menu Line 3 = RPM: 600 // Option for 3 digit RPM
+Debug: OneTouch Menu Line 4 = Watts: 55
+Debug: OneTouch Menu Line 5 =
+Debug: OneTouch Menu Line 6 =
+Debug: OneTouch Menu Line 7 =
+Debug: OneTouch Menu Line 8 =
+Debug: OneTouch Menu Line 9 =
+Debug: OneTouch Menu Line 10 =
+Debug: OneTouch Menu Line 11 =
+
+Debug: OneTouch Menu Line 0 = Equipment Status
+Debug: OneTouch Menu Line 1 =
+Debug: OneTouch Menu Line 2 = Intelliflo VF 2
+Debug: OneTouch Menu Line 3 = (Offline)
+Debug: OneTouch Menu Line 4 =
+Debug: OneTouch Menu Line 5 =
+Debug: OneTouch Menu Line 6 =
+Debug: OneTouch Menu Line 7 =
+Debug: OneTouch Menu Line 8 =
+Debug: OneTouch Menu Line 9 =
+Debug: OneTouch Menu Line 10 =
+Debug: OneTouch Menu Line 11 =
+
+Debug: OneTouch Menu Line 0 = Equipment Status
+Debug: OneTouch Menu Line 1 =
+Debug: OneTouch Menu Line 2 = Intelliflo VF 2
+Debug: OneTouch Menu Line 3 = RPM: 2250
+Debug: OneTouch Menu Line 4 = Watts: 55
+Debug: OneTouch Menu Line 5 = GPM: 80
+Debug: OneTouch Menu Line 6 =
+Debug: OneTouch Menu Line 7 =
+Debug: OneTouch Menu Line 8 =
+Debug: OneTouch Menu Line 9 =
+Debug: OneTouch Menu Line 10 =
+Debug: OneTouch Menu Line 11 =
+
+Debug: OneTouch Menu Line 0 = Equipment Status
+Debug: OneTouch Menu Line 1 =
+Debug: OneTouch Menu Line 2 = Jandy ePUMP 1
+Debug: OneTouch Menu Line 3 = RPM: 1750
+Debug: OneTouch Menu Line 4 = Watts: 43
+Debug: OneTouch Menu Line 5 =
+Debug: OneTouch Menu Line 6 =
+Debug: OneTouch Menu Line 7 =
+Debug: OneTouch Menu Line 8 =
+Debug: OneTouch Menu Line 9 =
+Debug: OneTouch Menu Line 10 =
+Debug: OneTouch Menu Line 11 =
+*/
diff --git a/onetouch.h b/onetouch.h
new file mode 100644
index 0000000..97d0fa8
--- /dev/null
+++ b/onetouch.h
@@ -0,0 +1,80 @@
+
+#ifndef ONETOUCH_H_
+#define ONETOUCH_H_
+
+#include "aq_serial.h"
+#include "aqualink.h"
+
+#define ONETOUCH_LINES 12
+
+#define PUMP_PRIMING -1
+#define PUMP_OFFLINE -2
+
+#define KICKT_CMD 0
+#define KICKT_MENU 1
+
+typedef enum ot_menu_type {
+ OTM_ONETOUCH,
+ OTM_EQUIPTMENT_STATUS,
+ OTM_SYSTEM, // Default screen with date,time & temperature
+ OTM_MAIN,
+ OTM_EQUIPTMENT,
+ OTM_EQUIPTMENT_ONOFF,
+ OTM_SELECT_SPEED,
+ OTM_MENUHELP,
+ OTM_VERSION,
+ OTM_SET_TEMP,
+ OTM_SET_TIME,
+ OTM_SYSTEM_SETUP,
+ OTM_FREEZE_PROTECT,
+ OTM_SET_AQUAPURE,
+ OTM_BOOST,
+ OTM_UNKNOWN
+} ot_menu_type;
+
+struct ot_macro {
+ char name[AQ_MSGLEN];
+ bool ison;
+};
+
+/*
+
+Left Top Button
+Ack | HEX: 0x10|0x02|0x00|0x01|0x80|0x03|0x96|0x10|0x03|
+
+Left Middle Button (Back)
+Ack | HEX: 0x10|0x02|0x00|0x01|0x80|0x02|0x95|0x10|0x03|
+
+Left Botom Button
+Ack | HEX: 0x10|0x02|0x00|0x01|0x80|0x01|0x94|0x10|0x03|
+
+Select Button
+Ack | HEX: 0x10|0x02|0x00|0x01|0x80|0x04|0x97|0x10|0x03|
+
+Up Button
+Ack | HEX: 0x10|0x02|0x00|0x01|0x80|0x06|0x99|0x10|0x03|
+
+Down Button
+Ack | HEX: 0x10|0x02|0x00|0x01|0x80|0x05|0x98|0x10|0x03|
+
+
+*/
+
+bool process_onetouch_packet(unsigned char *packet, int length,struct aqualinkdata *aq_data);
+ot_menu_type get_onetouch_memu_type();
+unsigned char *last_onetouch_packet();
+int thread_kick_type();
+
+int onetouch_menu_hlightindex();
+char *onetouch_menu_hlight();
+char *onetouch_menu_line(int index);
+char *onetouch_menu_hlightchars(int *len);
+int onetouch_menu_find_index(char *text);
+int ot_atoi(const char* str);
+int ot_strcmp(const char *s1, const char *s2);
+
+
+
+
+
+#endif // ONETOUCH_H_
\ No newline at end of file
diff --git a/onetouch_aq_programmer.c b/onetouch_aq_programmer.c
new file mode 100644
index 0000000..36f7cae
--- /dev/null
+++ b/onetouch_aq_programmer.c
@@ -0,0 +1,803 @@
+
+#include
+#include
+#include
+
+#include "utils.h"
+#include "aq_programmer.h"
+#include "onetouch.h"
+#include "aqualink.h"
+
+unsigned char _ot_pgm_command = NUL;
+
+// External command
+bool ot_queue_cmd(unsigned char cmd) {
+
+ if (_ot_pgm_command == NUL) {
+ _ot_pgm_command = cmd;
+ return true;
+ }
+
+ return false;
+}
+
+unsigned char pop_ot_cmd(unsigned char receive_type)
+{
+ unsigned char cmd = NUL;
+
+ if (receive_type == CMD_STATUS) {
+ cmd = _ot_pgm_command;
+ _ot_pgm_command = NUL;
+ }
+
+ logMessage(LOG_DEBUG, "OneTouch Sending '0x%02hhx' to controller\n", cmd);
+ return cmd;
+}
+
+void waitfor_ot_queue2empty()
+{
+ int i=0;
+
+ while ( (_ot_pgm_command != NUL) && ( i++ < 20) ) {
+ delay(50);
+ }
+
+ if (_ot_pgm_command != NUL) {
+ // Wait for longer interval
+ while ( (_ot_pgm_command != NUL) && ( i++ < 100) ) {
+ delay(100);
+ }
+ }
+
+ if (_ot_pgm_command != NUL) {
+ logMessage(LOG_WARNING, "OneTouch Send command Queue did not empty, timeout\n");
+ }
+}
+
+// This is for internal use only.
+// Will only work in programming mode
+void send_ot_cmd(unsigned char cmd)
+{
+ waitfor_ot_queue2empty();
+
+ ot_queue_cmd(cmd);
+
+ logMessage(LOG_INFO, "OneTouch Queue send '0x%02hhx' to controller (programming)\n", _ot_pgm_command);
+}
+
+bool waitForOT_MessageTypes(struct aqualinkdata *aq_data, unsigned char mtype1, unsigned char mtype2, int numMessageReceived)
+{
+ //logMessage(LOG_DEBUG, "waitForOT_MessageType 0x%02hhx || 0x%02hhx\n",mtype1,mtype2);
+
+ int i=0;
+ pthread_mutex_lock(&aq_data->active_thread.thread_mutex);
+
+ while( ++i <= numMessageReceived)
+ {
+ logMessage(LOG_DEBUG, "waitForOT_MessageType 0x%02hhx||0x%02hhx, last message type was 0x%02hhx (%d of %d)\n",mtype1,mtype2,*last_onetouch_packet(),i,numMessageReceived);
+
+ if (*last_onetouch_packet() == mtype1 || *last_onetouch_packet() == mtype2) break;
+
+ pthread_cond_wait(&aq_data->active_thread.thread_cond, &aq_data->active_thread.thread_mutex);
+ }
+
+ pthread_mutex_unlock(&aq_data->active_thread.thread_mutex);
+
+ if (*last_onetouch_packet() != mtype1 && *last_onetouch_packet() != mtype2) {
+ //logMessage(LOG_ERR, "Could not select MENU of Aqualink control panel\n");
+ logMessage(LOG_DEBUG, "waitForOT_MessageType: did not receive 0x%02hhx||0x%02hhx\n",mtype1,mtype2);
+ return false;
+ } else
+ logMessage(LOG_DEBUG, "waitForOT_MessageType: received 0x%02hhx\n",*last_onetouch_packet());
+
+ return true;
+}
+
+bool waitForNextOT_Menu(struct aqualinkdata *aq_data) {
+ //waitForOT_MessageTypes(aq_data,CMD_PDA_CLEAR,CMD_PDA_0x04,10);
+ //return waitForOT_MessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,15);
+
+ int i=0;
+ const int numMessageReceived = 20;
+
+ pthread_mutex_lock(&aq_data->active_thread.thread_mutex);
+
+ while( ++i <= 20)
+ {
+ logMessage(LOG_DEBUG, "waitForNextOT_Menu (%d of %d)\n",i,numMessageReceived);
+
+ //if(thread_kick_type() == KICKT_MENU) break;
+
+ pthread_cond_wait(&aq_data->active_thread.thread_cond, &aq_data->active_thread.thread_mutex);
+ if(thread_kick_type() == KICKT_MENU) break;
+ }
+
+ pthread_mutex_unlock(&aq_data->active_thread.thread_mutex);
+
+ if(thread_kick_type() == KICKT_MENU)
+ return true;
+ else
+ return false;
+}
+
+bool highlight_onetouch_menu_item(struct aqualinkdata *aq_data, char *item)
+{
+ int i;
+ int index;
+ int cnt;
+ // Should probably to an UP as well as DOWN here.
+ // Also need page up and down " ^^ More vv"
+ if ( (index = onetouch_menu_find_index(item)) != -1) {
+ cnt = index - onetouch_menu_hlightindex();
+ logMessage(LOG_DEBUG, "*** OneTouch menu caculator selected=%d, wanted=%d, move=%d times ***\n",onetouch_menu_hlightindex(),index,cnt);
+ for (i=0; i < cnt; i ++) {
+ send_ot_cmd(KEY_ONET_DOWN);
+ waitfor_ot_queue2empty();
+ waitForOT_MessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,3);
+ if (ot_strcmp(onetouch_menu_hlight(), item) == 0) {
+ // We got here early, probably because blank menu item
+ break;
+ }
+ }
+ // check if it's quicker to go up rather than down, if second page can't go up.
+ // This doesn;t work yet, not all versions of control panels have the same amount of items.
+ /*
+ if (cnt <= 5 || ot_strcmp(onetouch_menu_line(10), " ^^ More", 10) == 0 ) {
+ logMessage(LOG_DEBUG, "OneTouch device programmer pressing down %d times\n",cnt);
+ for (i=0; i < cnt; i ++) {
+ send_ot_cmd(KEY_ONET_DOWN);
+ //waitfor_ot_queue2empty();
+ //waitForOT_MessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,15);
+ }
+ } else {
+ cnt = 11 - cnt;
+ logMessage(LOG_DEBUG, "OneTouch device programmer pressing up %d times\n",cnt);
+ for (i=0; i < cnt; i ++) {
+ send_ot_cmd(KEY_ONET_UP);
+ //waitfor_ot_queue2empty();
+ //waitForOT_MessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,15);
+ }
+ }*/
+ // Not much quicker doing it this way that in the for loops above, may have to change back.
+ //waitfor_ot_queue2empty();
+ //waitForOT_MessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,15);
+ } else {
+ // Is their another page to search
+ if (ot_strcmp(onetouch_menu_line(10), "^^ More") == 0) {
+ char first_item[AQ_MSGLEN+1];
+ do {
+ send_ot_cmd(KEY_ONET_PAGE_DN);
+ waitForNextOT_Menu(aq_data);
+ if (onetouch_menu_find_index(item) != -1) {
+ return highlight_onetouch_menu_item(aq_data, item);
+ }
+ } while (strncpy(first_item, onetouch_menu_line(1), AQ_MSGLEN));
+ // Need to get menu item 1.
+ // Hit page down until menu item matches 1.
+ } else
+ logMessage(LOG_ERR, "OneTouch device programmer menu item '%s' does not exist\n",item);
+ //print_onetouch_menu();
+ }
+
+ if ( ot_strcmp(onetouch_menu_hlight(), item) != 0) {
+ logMessage(LOG_ERR, "OneTouch device programmer menu item '%s' not selected\n",item);
+ //print_onetouch_menu();
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool select_onetouch_menu_item(struct aqualinkdata *aq_data, char *item)
+{
+ if (highlight_onetouch_menu_item(aq_data, item)) {
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitForNextOT_Menu(aq_data);
+ return true;
+ }
+ return false;
+}
+
+
+bool goto_onetouch_system_menu(struct aqualinkdata *aq_data)
+{
+ int i=0;
+
+ if (get_onetouch_memu_type() == OTM_SYSTEM)
+ return true;
+
+ // Get back to a known point, the system menu
+ while (get_onetouch_memu_type() != OTM_SYSTEM && get_onetouch_memu_type() != OTM_ONETOUCH && i < 5 ) {
+ send_ot_cmd(KEY_ONET_BACK);
+ waitForNextOT_Menu(aq_data);
+ i++;
+ }
+
+ if (get_onetouch_memu_type() == OTM_SYSTEM) {
+ //printf("*** SYSTEM MENU ***\n");
+ //return false;
+ } else if (get_onetouch_memu_type() == OTM_ONETOUCH) {
+ //printf("*** ONE TOUCH MENU ***\n");
+ // Can only be one of 2 options in this menu, so if it's not the one we want, hit down first
+ if ( ot_strcmp(onetouch_menu_hlight(), "System") != 0) {
+ send_ot_cmd(KEY_ONET_DOWN);
+ waitForOT_MessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,15);
+ }
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitfor_ot_queue2empty();
+ waitForNextOT_Menu(aq_data);
+ //return false;
+ } else {
+ logMessage(LOG_ERR, "OneTouch device programmer couldn't get to System menu\n");
+ return false;
+ }
+
+ if (get_onetouch_memu_type() != OTM_SYSTEM) {
+ logMessage(LOG_ERR, "OneTouch device programmer couldn't get to System menu\n");
+ return false;
+ }
+
+
+
+ return true;
+}
+
+bool goto_onetouch_menu(struct aqualinkdata *aq_data, ot_menu_type menu)
+{
+ char *second_menu = false;
+ char *third_menu = false;
+
+ logMessage(LOG_DEBUG, "OneTouch device programmer request for menu %d\n",menu);
+
+ if ( ! goto_onetouch_system_menu(aq_data) ) {
+ logMessage(LOG_ERR, "OneTouch device programmer failed to get system menu\n");
+ return false;
+ }
+
+ // Now we are at main menu, we should have 3 options
+ /* Debug: OneTouch Menu Line 9 = Equipment ON/OFF
+ Debug: OneTouch Menu Line 10 = OneTouch ON/OFF
+ Debug: OneTouch Menu Line 11 = Menu / Help
+ */
+
+ // First setup any secondary menu's to hit.
+ switch(menu){
+ case OTM_SET_TEMP:
+ second_menu = "Set Temp";
+ break;
+ case OTM_SET_TIME:
+ second_menu = "Set Time";
+ break;
+ case OTM_SET_AQUAPURE:
+ second_menu = "Set AQUAPURE";
+ break;
+ case OTM_FREEZE_PROTECT:
+ second_menu = "System Setup";
+ third_menu = "Freeze Protect";
+ break;
+ case OTM_SYSTEM_SETUP:
+ second_menu = "System Setup";
+ break;
+ case OTM_BOOST:
+ second_menu = "Boost";
+ break;
+ default:
+ break;
+ }
+
+ // Now actually get the menu
+ switch(menu){
+ case OTM_SYSTEM:
+ // We are already here
+ return true;
+ break;
+ case OTM_EQUIPTMENT_ONOFF:
+ //if ( select_onetouch_menu_item(aq_data, "Equipment ON/OFF") == false ) { // NSF Should use this
+ if ( ot_strcmp(onetouch_menu_hlight(), "Equipment ON/OFF") == 0) {
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitfor_ot_queue2empty();
+ waitForNextOT_Menu(aq_data);
+ return true;
+ }
+ return false;
+ break;
+ case OTM_MENUHELP:
+ case OTM_SET_TEMP:
+ case OTM_SET_TIME:
+ case OTM_SET_AQUAPURE:
+ case OTM_FREEZE_PROTECT:
+ case OTM_BOOST:
+ case OTM_SYSTEM_SETUP:
+ if ( select_onetouch_menu_item(aq_data, " Menu / Help") == false ) {
+ logMessage(LOG_ERR, "OneTouch device programmer couldn't select menu %d\n",menu);
+ }
+ if (second_menu)
+ select_onetouch_menu_item(aq_data, second_menu);
+ if (third_menu)
+ select_onetouch_menu_item(aq_data, third_menu);
+ /*
+ if (menu == OTM_SET_HEATER) {
+ select_onetouch_menu_item(aq_data, "Set Temp");
+ } else if (menu == OTM_SET_TIME) {
+ select_onetouch_menu_item(aq_data, "Set Time");
+ } else if (menu == OTM_SET_AQUAPURE) {
+ select_onetouch_menu_item(aq_data, "Set AQUAPURE");
+ }
+ */
+ break;
+ default:
+ logMessage(LOG_ERR, "OneTouch device programmer doesn't know how to access menu %d\n",menu);
+ break;
+ }
+
+ if (get_onetouch_memu_type() != menu)
+ return false;
+
+ return true;
+}
+
+/*
+bool in_ot_programming_mode(struct aqualinkdata *aq_data)
+{
+ //( type != AQ_SET_PUMP_RPM || type != AQ_SET_OT_MACRO )) {
+
+ if ( ( aq_data->active_thread.thread_id != 0 ) &&
+ ( aq_data->active_thread.ptype == AQ_SET_PUMP_RPM ||
+ aq_data->active_thread.ptype == AQ_SET_OT_MACRO ||
+ aq_data->active_thread.ptype == AQ_GET_OT_POOL_SPA_HEATER_TEMPS)
+ ) {
+ return true;
+ }
+
+ return false;
+}
+*/
+
+
+// Return the digit at factor
+// num=12 factor=10 would return 2
+// num=12 factor=100 would return 1
+int digit(int num, int factor)
+{
+ return ( (num % factor) - (num % (factor/10)) ) / (factor/10) ;
+}
+
+// REturn the differance at a particular digit.
+// new=120, old=130, factor=100 return 2-3 = -1
+int digitDiff(int new, int old, int factor)
+{
+ return ( digit(old, factor) - digit(new, factor) );
+}
+
+bool intPress(int diff) {
+ int i;
+ unsigned char key = KEY_ONET_UP;
+
+ if (diff < 0) {
+ diff = 0 - diff;
+ key = KEY_ONET_DOWN;
+ //printf ("**** Pressing down %d times\n",diff);
+ } else {
+ //printf ("**** Pressing UP %d times\n",diff);
+ }
+
+ for (i=0; i < diff; i++) {
+ send_ot_cmd(key);
+ waitfor_ot_queue2empty();
+ }
+
+ return true;
+}
+
+/*
+ PROGRAMMING FUNCTIONS
+*/
+
+void *set_aqualink_pump_rpm( void *ptr )
+{
+ struct programmingThreadCtrl *threadCtrl;
+ threadCtrl = (struct programmingThreadCtrl *) ptr;
+ struct aqualinkdata *aq_data = threadCtrl->aq_data;
+ char *buf = (char*)threadCtrl->thread_args;
+ char VSPstr[20];
+ int i, structIndex;
+
+ //printf("**** program string '%s'\n",buf);
+
+ int pumpIndex = atoi(&buf[0]);
+ int pumpRPM = -1;
+ //int pumpRPM = atoi(&buf[2]);
+ for (structIndex=0; structIndex < aq_data->num_pumps; structIndex++) {
+ if (aq_data->pumps[structIndex].pumpIndex == pumpIndex) {
+ if (aq_data->pumps[structIndex].pumpType == PT_UNKNOWN) {
+ logMessage(LOG_ERR, "Can't set Pump RPM/GPM until type is known\n");
+ cleanAndTerminateThread(threadCtrl);
+ return ptr;
+ }
+ pumpRPM = RPM_check(aq_data->pumps[structIndex].pumpType, atoi(&buf[2]), aq_data);
+ break;
+ }
+ }
+ // NSF Should probably check pumpRPM is not -1 here
+
+ waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_ONETOUCH_PUMP_RPM);
+
+ logMessage(LOG_NOTICE, "OneTouch Set Pump %d to RPM %d, from '%s'\n",pumpIndex,pumpRPM,buf);
+
+ if (! goto_onetouch_menu(aq_data, OTM_EQUIPTMENT_ONOFF) ){
+ logMessage(LOG_ERR, "OneTouch device programmer didn't get Equiptment on/off menu\n");
+ }
+
+ sprintf(VSPstr, "VSP%1d Spd Adj",pumpIndex);
+/*
+ if ( (index = onetouch_menu_find_index(VSPstr)) != -1) {
+ int cnt = index - onetouch_menu_hlightindex();
+ for (i=0; i < cnt; i ++) {
+ send_ot_cmd(KEY_ONET_DOWN);
+ waitfor_ot_queue2empty();
+ }
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitForNextOT_Menu(aq_data);
+*/
+ if ( select_onetouch_menu_item(aq_data, VSPstr) ) {
+ if ( get_onetouch_memu_type() == OTM_SELECT_SPEED) {
+ // Now fine menu item with X as last digit, and select that menu.
+ //Pool X
+ for (i=0; i < 12; i++) {
+ if ( onetouch_menu_hlight()[15] != 'X' ) {
+ send_ot_cmd(KEY_ONET_DOWN);
+ waitfor_ot_queue2empty();
+ waitForOT_MessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,15);
+ } else {
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitfor_ot_queue2empty();
+ waitForNextOT_Menu(aq_data);
+ break;
+ }
+ }
+ //OneTouch Menu Line 3 = set to 50 GPM
+ //OneTouch Menu Line 3 = set to 1750 RPM
+ if ( strstr(onetouch_menu_hlight(), "set to") != NULL ) {
+ //printf("FOUND MENU")
+ if (strstr(onetouch_menu_hlight(), "RPM") != NULL ) {
+ // RPM 3450 & 600 max & min
+ int RPM = ot_atoi(&onetouch_menu_hlight()[7]);
+ intPress(digitDiff(RPM, pumpRPM, 10000));
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitfor_ot_queue2empty();
+ intPress(digitDiff(RPM, pumpRPM, 1000));
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitfor_ot_queue2empty();
+ intPress(digitDiff(RPM, pumpRPM, 100));
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitfor_ot_queue2empty();
+ intPress(digitDiff(RPM, pumpRPM, 10));
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitfor_ot_queue2empty();
+ // Reset the pump RPM
+ aq_data->pumps[structIndex].rpm = RPM;
+ } else if (strstr(onetouch_menu_hlight(), "GPM") != NULL ) {
+ // GPM 130 max, GPM 15 min
+ for (i=0; i < 24 ; i++) { // Max of 23 key presses to get from max to min
+ int GPM = ot_atoi(&onetouch_menu_hlight()[8]);
+ //printf ("*** GPM = %d | Setting to %d\n",GPM,pumpRPM);
+ if ( GPM > pumpRPM ) {
+ send_ot_cmd(KEY_ONET_DOWN);
+ } else if (GPM < pumpRPM) {
+ send_ot_cmd(KEY_ONET_UP);
+ } else {
+ send_ot_cmd(KEY_ONET_SELECT);
+ aq_data->pumps[structIndex].gpm = GPM;
+ waitfor_ot_queue2empty();
+ break;
+ }
+ waitfor_ot_queue2empty();
+ // This really does slow it down, but we hit up.down once too ofter without it, need to fix.
+ waitForOT_MessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,5);
+ // Reset the pump GPM
+ aq_data->pumps[structIndex].rpm = GPM;
+ //waitForOT_MessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_MSG_LONG,5);
+ //waitForNextOT_Menu(aq_data);
+ }
+ } else {
+ logMessage(LOG_ERR, "OneTouch device programmer Not sure how to set '%s'\n",onetouch_menu_hlight());
+ }
+ } else {
+ logMessage(LOG_ERR, "OneTouch device programmer didn't select VSP\n");
+ }
+ } else {
+ logMessage(LOG_ERR, "OneTouch device programmer Couldn't find Select Speed menu\n");
+ }
+ } else {
+ logMessage(LOG_ERR, "OneTouch device programmer Couldn't find VSP in Equiptment on/off menu\n");
+ }
+ //printf( "Menu Index %d\n", onetouch_menu_find_index(VSPstr));
+
+ //printf("**** GOT THIS FAR, NOW LET'S GO BACK ****\n");
+
+ if (! goto_onetouch_menu(aq_data, OTM_SYSTEM) ){
+ logMessage(LOG_ERR, "OneTouch device programmer didn't get back to System menu\n");
+ }
+
+ //printf("**** CLEAN EXIT ****\n");
+
+ cleanAndTerminateThread(threadCtrl);
+
+ // just stop compiler error, ptr is not valid as it's just been freed
+ return ptr;
+}
+
+void *set_aqualink_onetouch_macro( void *ptr )
+{
+ struct programmingThreadCtrl *threadCtrl;
+ threadCtrl = (struct programmingThreadCtrl *) ptr;
+ struct aqualinkdata *aq_data = threadCtrl->aq_data;
+
+ //sprintf(msg, "%-5d%-5d",index, (strcmp(value, "on") == 0)?ON:OFF);
+ // Use above to set
+ char *buf = (char*)threadCtrl->thread_args;
+ unsigned int device = atoi(&buf[0]);
+ unsigned int state = atoi(&buf[5]);
+
+ waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_ONETOUCH_MACRO);
+
+ logMessage(LOG_DEBUG, "OneTouch Marco\n");
+
+ logMessage(LOG_ERR, "OneTouch Macro not implimented (device=%d|state=%d)\n",device,state);
+
+ cleanAndTerminateThread(threadCtrl);
+
+ // just stop compiler error, ptr is not valid as it's just been freed
+ return ptr;
+}
+
+void *get_aqualink_onetouch_setpoints( void *ptr )
+{
+ struct programmingThreadCtrl *threadCtrl;
+ threadCtrl = (struct programmingThreadCtrl *) ptr;
+ struct aqualinkdata *aq_data = threadCtrl->aq_data;
+
+ waitForSingleThreadOrTerminate(threadCtrl, AQ_GET_ONETOUCH_SETPOINTS);
+
+ logMessage(LOG_DEBUG, "OneTouch get heater temps\n");
+
+ if ( !goto_onetouch_menu(aq_data, OTM_SET_TEMP) ){
+ logMessage(LOG_ERR, "OneTouch device programmer failed to get heater temp menu\n");
+ }
+
+ if ( !goto_onetouch_menu(aq_data, OTM_FREEZE_PROTECT) ){
+ logMessage(LOG_ERR, "OneTouch device programmer failed to get freeze protect menu\n");
+ }
+
+ if (! goto_onetouch_menu(aq_data, OTM_SYSTEM) ){
+ logMessage(LOG_ERR, "OneTouch device programmer didn't get back to System menu\n");
+ }
+/*
+ logMessage(LOG_DEBUG, "*** OneTouch device programmer TEST page down ***\n");
+ goto_onetouch_menu(aq_data, OTM_SYSTEM_SETUP);
+ highlight_onetouch_menu_item(aq_data, "About");
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitfor_ot_queue2empty();
+ waitForNextOT_Menu(aq_data);
+ logMessage(LOG_DEBUG, "*** OneTouch device programmer END TEST page down ***\n");
+*/
+ cleanAndTerminateThread(threadCtrl);
+
+ // just stop compiler error, ptr is not valid as it's just been freed
+ return ptr;
+}
+
+void set_aqualink_onetouch_heater_setpoint( struct aqualinkdata *aq_data, bool ispool, int val )
+{
+ int cval;
+ int diff;
+ int i;
+ int len;
+ //char *st;
+ unsigned char direction;
+
+ if ( !goto_onetouch_menu(aq_data, OTM_SET_TEMP) ){
+ logMessage(LOG_ERR, "OneTouch device programmer failed to get heater temp menu\n");
+ }
+
+ if(ispool){
+ if (!highlight_onetouch_menu_item(aq_data, "Pool Heat")) {
+ logMessage(LOG_ERR, "OneTouch device programmer failed to get pool heater temp menu\n");
+ return;
+ }
+ } else {
+ if (!highlight_onetouch_menu_item(aq_data, "Spa Heat")) {
+ logMessage(LOG_ERR, "OneTouch device programmer failed to get spa heater temp menu\n");
+ return;
+ }
+ }
+
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitfor_ot_queue2empty();
+ waitForOT_MessageTypes(aq_data,CMD_PDA_HIGHLIGHTCHARS,0x00,15); // CMD_PDA_0x04 is just a packer.
+
+ {
+ char *st = onetouch_menu_hlightchars(&len);
+ logMessage(LOG_DEBUG, "** OneTouch set heater temp highlighted='%.*s'\n", len, st);
+ }
+
+ cval = atoi(onetouch_menu_hlightchars(&len));
+ diff = val - cval;
+ if (diff > 0) {
+ direction = KEY_ONET_UP;
+ } else if (diff < 0) {
+ direction = KEY_ONET_DOWN;
+ diff=-diff;
+ }
+
+ logMessage(LOG_DEBUG, "** OneTouch set heater temp diff='%d'\n", diff);
+
+ for (i=0; i < diff; i++) {
+ send_ot_cmd(direction);
+ waitfor_ot_queue2empty();
+ }
+
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitfor_ot_queue2empty();
+ send_ot_cmd(KEY_ONET_BACK);
+ waitfor_ot_queue2empty();
+
+/*
+ logMessage(LOG_DEBUG, "** OneTouch set heater temp line='%s'\n", onetouch_menu_line(line));
+ logMessage(LOG_DEBUG, "** OneTouch set heater temp highlight='%d'\n", onetouch_menu_hlightindex());
+ logMessage(LOG_DEBUG, "** OneTouch set heater temp highlightline='%s'\n", onetouch_menu_line(onetouch_menu_hlightindex()));
+ logMessage(LOG_DEBUG, "** OneTouch set heater temp highlightchars='%s'\n", onetouch_menu_hlight());
+*/
+ //onetouch_menu_line(line)
+ //onetouch_menu_hlightindex
+ //onetouch_menu_hlight
+}
+
+void *set_aqualink_onetouch_pool_heater_temp( void *ptr )
+{
+ struct programmingThreadCtrl *threadCtrl;
+ threadCtrl = (struct programmingThreadCtrl *) ptr;
+ struct aqualinkdata *aq_data = threadCtrl->aq_data;
+
+ waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_ONETOUCH_POOL_HEATER_TEMP);
+
+ int val = atoi((char*)threadCtrl->thread_args);
+ val = setpoint_check(POOL_HTR_SETOINT, val, aq_data);
+
+ logMessage(LOG_DEBUG, "OneTouch set pool heater temp to %d\n", val);
+ set_aqualink_onetouch_heater_setpoint(aq_data, true, val);
+
+ cleanAndTerminateThread(threadCtrl);
+
+ // just stop compiler error, ptr is not valid as it's just been freed
+ return ptr;
+}
+
+void *set_aqualink_onetouch_spa_heater_temp( void *ptr )
+{
+ struct programmingThreadCtrl *threadCtrl;
+ threadCtrl = (struct programmingThreadCtrl *) ptr;
+ struct aqualinkdata *aq_data = threadCtrl->aq_data;
+
+ waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_ONETOUCH_SPA_HEATER_TEMP);
+
+ int val = atoi((char*)threadCtrl->thread_args);
+ val = setpoint_check(SPA_HTR_SETOINT, val, aq_data);
+
+ logMessage(LOG_DEBUG, "OneTouch set spa heater temp to %d\n", val);
+ set_aqualink_onetouch_heater_setpoint(aq_data, false, val);
+
+ cleanAndTerminateThread(threadCtrl);
+
+ // just stop compiler error, ptr is not valid as it's just been freed
+ return ptr;
+}
+
+void *set_aqualink_onetouch_boost( void *ptr )
+{
+ struct programmingThreadCtrl *threadCtrl;
+ threadCtrl = (struct programmingThreadCtrl *) ptr;
+ struct aqualinkdata *aq_data = threadCtrl->aq_data;
+
+ waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_ONETOUCH_BOOST);
+
+ int val = atoi((char*)threadCtrl->thread_args);
+
+ logMessage(LOG_DEBUG, "OneTouch request set Boost to '%d'\n",val==true?"On":"Off");
+
+ if ( !goto_onetouch_menu(aq_data, OTM_BOOST) ){
+ logMessage(LOG_ERR, "OneTouch device programmer failed to get BOOST menu\n");
+ } else {
+ if ( ot_strcmp(onetouch_menu_hlight(), "Start") == 0 ) {
+ if (val) {
+ logMessage(LOG_DEBUG, "OneTouch Boost is Off, turning On\n");
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitfor_ot_queue2empty();
+ } else {
+ logMessage(LOG_INFO, "OneTouch Boost is Off, ignore request\n");
+ }
+ } else if ( ot_strcmp(onetouch_menu_hlight(), "Pause") == 0 ) {
+ if (! val) {
+ logMessage(LOG_DEBUG, "OneTouch set Boost is ON, turning Off\n");
+ highlight_onetouch_menu_item(aq_data, "Stop");
+ send_ot_cmd(KEY_ONET_SELECT);
+ waitfor_ot_queue2empty();
+ // Takes ages to see bost is off from menu, to set it here.
+ aq_data->boost = false;
+ aq_data->boost_msg[0] = '\0';
+ aq_data->swg_percent = 0;
+ } else {
+ logMessage(LOG_INFO, "OneTouch Boost is On, ignore request\n");
+ }
+ } else {
+ logMessage(LOG_ERR, "OneTouch Boost unknown menu\n");
+ }
+ }
+
+ if (! goto_onetouch_menu(aq_data, OTM_SYSTEM) ){
+ logMessage(LOG_ERR, "OneTouch device programmer didn't get back to System menu\n");
+ }
+
+ cleanAndTerminateThread(threadCtrl);
+
+ // just stop compiler error, ptr is not valid as it's just been freed
+ return ptr;
+}
+
+void *set_aqualink_onetouch_swg_percent( void *ptr )
+{
+ struct programmingThreadCtrl *threadCtrl;
+ threadCtrl = (struct programmingThreadCtrl *) ptr;
+ struct aqualinkdata *aq_data = threadCtrl->aq_data;
+
+ waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_ONETOUCH_SWG_PERCENT);
+
+ logMessage(LOG_DEBUG, "OneTouch set SWG Percent\n");
+
+ if ( !goto_onetouch_menu(aq_data, OTM_SET_AQUAPURE) ){
+ logMessage(LOG_ERR, "OneTouch device programmer failed to get Aquapure menu\n");
+ } else {
+
+ }
+
+ if (! goto_onetouch_menu(aq_data, OTM_SYSTEM) ){
+ logMessage(LOG_ERR, "OneTouch device programmer didn't get back to System menu\n");
+ }
+
+ cleanAndTerminateThread(threadCtrl);
+
+ // just stop compiler error, ptr is not valid as it's just been freed
+ return ptr;
+}
+
+void *set_aqualink_onetouch_freezeprotect( void *ptr )
+{
+ return ptr;
+}
+
+void *set_aqualink_onetouch_time( void *ptr )
+{
+ struct programmingThreadCtrl *threadCtrl;
+ threadCtrl = (struct programmingThreadCtrl *) ptr;
+ struct aqualinkdata *aq_data = threadCtrl->aq_data;
+
+ waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_ONETOUCH_TIME);
+
+ logMessage(LOG_DEBUG, "OneTouch set time\n");
+
+ if ( !goto_onetouch_menu(aq_data, OTM_SET_TIME) ){
+ logMessage(LOG_ERR, "OneTouch device programmer failed to get time menu\n");
+ } else {
+
+ }
+
+ if (! goto_onetouch_menu(aq_data, OTM_SYSTEM) ){
+ logMessage(LOG_ERR, "OneTouch device programmer didn't get back to System menu\n");
+ }
+
+ cleanAndTerminateThread(threadCtrl);
+
+ // just stop compiler error, ptr is not valid as it's just been freed
+ return ptr;
+}
+
diff --git a/onetouch_aq_programmer.h b/onetouch_aq_programmer.h
new file mode 100644
index 0000000..23dfd09
--- /dev/null
+++ b/onetouch_aq_programmer.h
@@ -0,0 +1,20 @@
+
+#ifndef ONETOUCH_AQ_PROGRAMMER_H_
+#define ONETOUCH_AQ_PROGRAMMER_H_
+
+unsigned char pop_ot_cmd(unsigned char receive_type);
+bool ot_queue_cmd(unsigned char cmd);
+
+//bool in_ot_programming_mode(struct aqualinkdata *aq_data);
+
+void *set_aqualink_pump_rpm( void *ptr );
+void *set_aqualink_onetouch_macro( void *ptr );
+void *get_aqualink_onetouch_setpoints( void *ptr );
+void *set_aqualink_onetouch_spa_heater_temp( void *ptr );
+void *set_aqualink_onetouch_pool_heater_temp( void *ptr );
+void *set_aqualink_onetouch_swg_percent( void *ptr );
+void *set_aqualink_onetouch_boost( void *ptr );
+void *set_aqualink_onetouch_time( void *ptr );
+void *set_aqualink_onetouch_freezeprotect( void *ptr );
+
+#endif // ONETOUCH_AQ_PROGRAMMER_H_
\ No newline at end of file
diff --git a/packetLogger.c b/packetLogger.c
index bb31a7f..9d332f6 100644
--- a/packetLogger.c
+++ b/packetLogger.c
@@ -11,7 +11,7 @@ static FILE *_byteLogFile = NULL;
static bool _log2file = false;
static bool _includePentair = false;
-void _logPacket(unsigned char *packet_buffer, int packet_length, bool error);
+void _logPacket(unsigned char *packet_buffer, int packet_length, bool error, bool force);
void startPacketLogger(bool debug_RSProtocol_packets, bool read_pentair_packets) {
_log2file = debug_RSProtocol_packets;
@@ -37,17 +37,21 @@ void writePacketLog(char *buffer) {
}
void logPacket(unsigned char *packet_buffer, int packet_length) {
- _logPacket(packet_buffer, packet_length, false);
+ _logPacket(packet_buffer, packet_length, false, false);
}
void logPacketError(unsigned char *packet_buffer, int packet_length) {
- _logPacket(packet_buffer, packet_length, true);
+ _logPacket(packet_buffer, packet_length, true, false);
}
-void _logPacket(unsigned char *packet_buffer, int packet_length, bool error)
+void debuglogPacket(unsigned char *packet_buffer, int packet_length) {
+ _logPacket(packet_buffer, packet_length, false, true);
+}
+
+void _logPacket(unsigned char *packet_buffer, int packet_length, bool error, bool force)
{
// No point in continuing if loglevel is < debug_serial and not writing to file
- if ( error == false && getLogLevel() < LOG_DEBUG_SERIAL && _log2file == false)
+ if ( force == false && error == false && getLogLevel() < LOG_DEBUG_SERIAL && _log2file == false)
return;
char buff[1000];
@@ -70,8 +74,12 @@ void _logPacket(unsigned char *packet_buffer, int packet_length, bool error)
if (error == true)
logMessage(LOG_WARNING, "%s", buff);
- else
- logMessage(LOG_DEBUG_SERIAL, "%s", buff);
+ else {
+ if (force)
+ logMessage(LOG_DEBUG, "%s", buff);
+ else
+ logMessage(LOG_DEBUG_SERIAL, "%s", buff);
+ }
}
//#define RAW_BUFFER_SIZE 100
diff --git a/packetLogger.h b/packetLogger.h
index 76751b1..a074ecd 100644
--- a/packetLogger.h
+++ b/packetLogger.h
@@ -13,5 +13,8 @@ void logPacket(unsigned char *packet_buffer, int packet_length);
void logPacketError(unsigned char *packet_buffer, int packet_length);
void logPacketByte(unsigned char *byte);
+// Only use for manual debugging
+void debuglogPacket(unsigned char *packet_buffer, int packet_length);
+
#endif //PACKETLOGGER_H_
\ No newline at end of file
diff --git a/pda.c b/pda.c
index 99e2bf8..9fb3fd9 100644
--- a/pda.c
+++ b/pda.c
@@ -43,11 +43,11 @@ static bool _initWithRS = false;
#ifdef BETA_PDA_AUTOLABEL
-static struct aqconfig *_aqualink_config;
-void init_pda(struct aqualinkdata *aqdata, struct aqconfig *aqconfig)
+//static struct aqconfig *_aqconfig_;
+void init_pda(struct aqualinkdata *aqdata)
{
_aqualink_data = aqdata;
- _aqualink_config = aqconfig;
+ //_aqconfig_ = aqconfig;
set_pda_mode(true);
}
#else
@@ -491,7 +491,7 @@ void process_pda_packet_msg_long_level_aux_device(const char *msg)
int li=-1;
char *str, *label;
- if (! _aqualink_config->use_panel_aux_labels)
+ if (! _aqconfig_->use_panel_aux_labels)
return;
// NSF Need to check config for use_panel_aux_labels value and ignore if not set
@@ -686,10 +686,11 @@ bool process_pda_packet(unsigned char *packet, int length)
{
_initWithRS = true;
logMessage(LOG_DEBUG, "**** PDA INIT ****");
- aq_programmer(AQ_PDA_INIT, NULL, _aqualink_data);
+ //aq_programmer(AQ_PDA_INIT, NULL, _aqualink_data);
+ queueGetProgramData(AQUAPDA, _aqualink_data);
delay(50); // Make sure this one runs first.
#ifdef BETA_PDA_AUTOLABEL
- if (_aqualink_config->use_panel_aux_labels)
+ if (_aqconfig_->use_panel_aux_labels)
aq_programmer(AQ_GET_AUX_LABELS, NULL, _aqualink_data);
#endif
aq_programmer(AQ_PDA_WAKE_INIT, NULL, _aqualink_data);
@@ -707,7 +708,7 @@ bool process_pda_packet(unsigned char *packet, int length)
packet[PKT_CMD] == CMD_PDA_HIGHLIGHTCHARS)
{
// We processed the next message, kick any threads waiting on the message.
- kick_aq_program_thread(_aqualink_data);
+ kick_aq_program_thread(_aqualink_data, AQUAPDA);
}
return rtn;
}
diff --git a/pentair_messages.c b/pentair_messages.c
index a1ec155..8b20811 100644
--- a/pentair_messages.c
+++ b/pentair_messages.c
@@ -105,7 +105,7 @@ bool processiAqualinkMsg(unsigned char *packet_buffer, int packet_length, struct
pumpIndex = atoi((char *) &lastmessage[14]);
- if ( pumpIndex < MAX_PUMPS && pumpIndex < 0) {
+ if ( pumpIndex < aqdata->num_pumps && pumpIndex < 0) {
pumpIndex = 1;
logMessage(LOG_ERR, "Can't find pump index for messsage '%.*s' in string '%.*s' using %d\n",AQ_MSGLEN, packet_buffer+4, AQ_MSGLEN, lastmessage, pumpIndex);
}
diff --git a/release/aqualinkd b/release/aqualinkd
index a85b4e4..c12bdec 100755
Binary files a/release/aqualinkd and b/release/aqualinkd differ
diff --git a/release/aqualinkd.conf b/release/aqualinkd.conf
index 82af0be..864ca05 100755
--- a/release/aqualinkd.conf
+++ b/release/aqualinkd.conf
@@ -64,6 +64,17 @@ report_zero_pool_temp = no
# You can use 0x00 and AqualinkD will find an ID for you, but this makes a slow startup
device_id=0x0a
+# The ID for extended settings, These are ONE TOUCH MACROS & VARIABLE SPEED PUMP RPM
+# Do not enable this if you don't use either, you'll just waste memory and cpu cycles
+# Valid ID's are 0x40, 0x41, 0x42 & 0x43.
+# If you have a one touch remote do not use Ox40
+#extended_device_id=0x41
+
+# If you have extended_device_id set, then you can also use that ID for programming some features.
+# This means that you can turn things on/off while AqualinkD is programming certian features.
+# At the moment only heater setpoints & swg boost is on the extended device programming
+#extended_device_id_programming = yes
+
# Please see forum for this, only set to yes when logging information to support
# new devices. Inflrmation will be written to /tmp/RS485.log
#debug_RSProtocol_packets = no
@@ -127,18 +138,23 @@ use_panel_aux_labels=no
# Simply change these to your setup, comment out ones that ent in _dzidx if you don't use Domoticz.
# If using PDA mode, PDA Labels below are of the utmost importance, the PDA labels MUST match the labels in the "EQUIPTMENT ON/OFF" menu of the PDA device.
#
-# Optional, If you have a Variable Speed Pump, then assign the RS485 ID to the button below so RPM/GPH/WATTS are displayed
+# Optional, ( button_01_pumpID & button_01_pumpIndex )
+# If you have a Variable Speed Pump, then assign the RS485 ID to the button below so RPM/GPH/WATTS are displayed
# Format is button_01_pumpID=0x60. Leave blank if you don't have a VSP.
# Pentair pump ID's
# 0x60 to 0x6F (0x60, 0x61 0x62, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F)
# Jandy pump ID's
# 0x78, 0x79, 0x7A, 0x7B
+#
+# button_01_pumpIndex=1
+# If you have assigned this pump an index number in your Aqualink control panel, (Between 1 & 4), put it here for VSP, RPM, Primp information to be captured.
# Labels for standard butons (shown in web UI), and domoticz idx's
button_01_label=Filter Pump
#button_01_dzidx=37
#button_01_PDA_label=FILTER PUMP
#button_01_pumpID=0x60
+#button_01_pumpIndex=1
button_02_label=Spa Mode
#button_02_dzidx=38
@@ -151,7 +167,8 @@ button_03_label=Cleaner
button_04_label=Waterfall
#button_04_dzidx=40
#button_04_PDA_label=AUX2
-#button_01_pumpID=0x61
+#button_04_pumpID=0x61
+#button_04_pumpIndex=2
button_05_label=Spa Blower
#button_05_dzidx=41
diff --git a/release/install.sh b/release/install.sh
index d020076..c69c821 100755
--- a/release/install.sh
+++ b/release/install.sh
@@ -38,42 +38,19 @@ command -v systemctl >/dev/null 2>&1 || { echo "This script needs systemd's syst
systemctl stop $SERVICE > /dev/null 2>&1
SERVICE_EXISTS=$(echo $?)
-# Clean everything if requested.
-if [ "$1" == "clean" ]; then
- echo "Deleting install"
- systemctl disable $SERVICE > /dev/null 2>&1
- if [ -f $BINLocation/$BIN ]; then
- rm -f $BINLocation/$BIN
- fi
- if [ -f $SRVLocation/$SRV ]; then
- rm -f $SRVLocation/$SRV
- fi
- if [ -f $CFGLocation/$CFG ]; then
- rm -f $CFGLocation/$CFG
- fi
- if [ -f $DEFLocation/$DEF ]; then
- rm -f $DEFLocation/$DEF
- fi
- if [ -d $WEBLocation ]; then
- rm -rf $WEBLocation
- fi
- systemctl daemon-reload
- exit
-fi
-
# copy files to locations, but only copy cfg if it doesn;t already exist
cp $BUILD/$BIN $BINLocation/$BIN
cp $BUILD/$SRV $SRVLocation/$SRV
if [ -f $CFGLocation/$CFG ]; then
- echo "AqualinkD config exists, did not copy new config, you may need to edit existing! $CFGLocation/$CFG"
+ echo "Config exists, did not copy new config, you may need to edit existing! $CFGLocation/$CFG"
else
cp $BUILD/$CFG $CFGLocation/$CFG
fi
if [ -f $DEFLocation/$DEF ]; then
- echo "AqualinkD defaults exists, did not copy new defaults to $DEFLocation/$DEF"
+ echo "Defaults exists, did not copy new defaults to $DEFLocation/$DEF"
else
cp $BUILD/$DEF.defaults $DEFLocation/$DEF
fi
@@ -93,7 +70,7 @@ if [ ! -d "$WEBLocation" ]; then
fi
if [ -f "$WEBLocation/config.js" ]; then
- echo "AqualinkD web config exists, did not copy new config, you may need to edit existing $WEBLocation/config.js "
+ echo "$WEBLocation/config.js exists, did not copy overight, please make sure to update manually"
rsync -avq --exclude='config.js' $BUILD/../web/* $WEBLocation
else
cp -r $BUILD/../web/* $WEBLocation
@@ -106,7 +83,5 @@ systemctl daemon-reload
if [ $SERVICE_EXISTS -eq 0 ]; then
echo "Starting daemon $SERVICE"
systemctl start $SERVICE
-else
- echo "Please edit $CFGLocation/$CFG, then start AqualinkD service"
fi
diff --git a/release/serial_logger b/release/serial_logger
index 3d148ae..c2f1a5f 100755
Binary files a/release/serial_logger and b/release/serial_logger differ
diff --git a/serial_logger.c b/serial_logger.c
index 8f92df9..b1af85c 100644
--- a/serial_logger.c
+++ b/serial_logger.c
@@ -28,11 +28,12 @@
#include "aq_serial.h"
#include "utils.h"
+#include "packetLogger.h"
#define SLOG_MAX 80
#define PACKET_MAX 600
-#define VERSION "serial_logger V1.1"
+#define VERSION "serial_logger V1.2"
/*
typedef enum used {
@@ -51,6 +52,7 @@ bool _keepRunning = true;
unsigned char _goodID[] = {0x0a, 0x0b, 0x08, 0x09};
unsigned char _goodPDAID[] = {0x60, 0x61, 0x62, 0x63};
+unsigned char _goodONETID[] = {0x40, 0x41, 0x42, 0x43};
unsigned char _filter[10];
int _filters=0;
bool _rawlog=false;
@@ -67,7 +69,7 @@ void intHandler(int dummy) {
#define SWG " <-- Salt Water Generator (Aquarite mode)"
#define KEYPAD " <-- RS Keypad"
#define SPA_R " <-- Spa remote"
-#define AQUA " <-- Aqualink (iAqualink?)"
+#define AQUA " <-- Aqualink (iAqualink / Touch)"
#define HEATER " <-- LX Heater"
#define ONE_T " <-- Onetouch device"
#define PC_DOCK " <-- PC Interface (RS485 to RS232)"
@@ -152,6 +154,10 @@ bool canUse(unsigned char ID) {
if (ID == _goodPDAID[i])
return true;
}
+ for (i = 0; i < 4; i++) {
+ if (ID == _goodONETID[i])
+ return true;
+ }
return false;
}
char* canUseExtended(unsigned char ID) {
@@ -164,6 +170,10 @@ char* canUseExtended(unsigned char ID) {
if (ID == _goodPDAID[i])
return " <-- can use for Aqualinkd (PDA mode only)";
}
+ for (i = 0; i < 4; i++) {
+ if (ID == _goodONETID[i])
+ return " <-- can use for Aqualinkd (Extended Device ID)";
+ }
return "";
}
@@ -249,6 +259,7 @@ int main(int argc, char *argv[]) {
int received_packets = 0;
int logPackets = PACKET_MAX;
int logLevel = LOG_NOTICE;
+ bool rsRawDebug = false;
//bool playback_file = false;
//int logLevel;
@@ -264,7 +275,14 @@ int main(int argc, char *argv[]) {
if (argc < 2 || access( argv[1], F_OK ) == -1 ) {
fprintf(stderr, "ERROR, first param must be valid serial port, ie:-\n\t%s /dev/ttyUSB0\n\n", argv[0]);
- fprintf(stderr, "Optional parameters are -d (debug) & -p (log # packets) & -i & -r (raw) ie:=\n\t%s /dev/ttyUSB0 -d -p 1000 -i 0x08\n\n", argv[0]);
+ //fprintf(stderr, "Optional parameters are -d (debug) & -p (log # packets) & -i & -r (raw) ie:=\n\t%s /dev/ttyUSB0 -d -p 1000 -i 0x08\n\n", argv[0]);
+ fprintf(stderr, "Optional parameters are :-\n");
+ fprintf(stderr, "\t-d (debug)\n");
+ fprintf(stderr, "\t-p (log # packets)\n");
+ fprintf(stderr, "\t-i (just log these ID's, can use multiple -i)\n");
+ fprintf(stderr, "\t-r (raw)\n");
+ fprintf(stderr, "\t-rsrd (log raw RS bytes to %s)\n",RS485BYTELOGFILE);
+ fprintf(stderr, "\nie:\t%s /dev/ttyUSB0 -d -p 1000 -i 0x08 -i 0x0a\n\n", argv[0]);
return 1;
}
@@ -286,6 +304,8 @@ int main(int argc, char *argv[]) {
logLevel = LOG_DEBUG;
} else if (strcmp(argv[i], "-f") == 0) {
_playback_file = true;
+ } else if (strcmp(argv[i], "-rsrd") == 0) {
+ rsRawDebug = true;
}
}
@@ -315,7 +335,10 @@ int main(int argc, char *argv[]) {
}
//packet_length = get_packet(rs_fd, packet_buffer);
- packet_length = get_packet(rs_fd, packet_buffer);
+ if (rsRawDebug)
+ packet_length = get_packet_lograw(rs_fd, packet_buffer);
+ else
+ packet_length = get_packet(rs_fd, packet_buffer);
if (packet_length == -1) {
// Unrecoverable read error. Force an attempt to reconnect.
@@ -401,6 +424,7 @@ int main(int argc, char *argv[]) {
if (sindex >= SLOG_MAX)
logMessage(LOG_ERR, "Ran out of storage, some ID's were not captured, please increase SLOG_MAX and recompile\n");
+
logMessage(LOG_NOTICE, "Jandy ID's found\n");
for (i = 0; i < sindex; i++) {
//logMessage(LOG_NOTICE, "ID 0x%02hhx is %s %s\n", slog[i].ID, (slog[i].inuse == true) ? "in use" : "not used",
diff --git a/utils.c b/utils.c
index f9ac7e5..5e526fb 100644
--- a/utils.c
+++ b/utils.c
@@ -87,6 +87,14 @@ void startInlineDebug()
_log_filename = DEFAULT_LOG_FILE;
}
+void startInlineSerialDebug()
+{
+ _log_level = LOG_DEBUG_SERIAL;
+ _log2file = true;
+ if (_log_filename == NULL)
+ _log_filename = DEFAULT_LOG_FILE;
+}
+
void stopInlineDebug()
{
_log_level = _cfg_log_level;
@@ -343,7 +351,7 @@ void logMessage(int msg_level, char *format, ...)
strncpy(buffer, " ", 8);
vsprintf (&buffer[8], format, args);
va_end(args);
-
+
//test(msg_level, buffer);
//fprintf (stderr, buffer);
diff --git a/utils.h b/utils.h
index 2534e8f..d67df0a 100644
--- a/utils.h
+++ b/utils.h
@@ -56,6 +56,7 @@ char *prittyString(char *str);
//void writePacketLog(char *buff);
//void closePacketLog();
void startInlineDebug();
+void startInlineSerialDebug();
void stopInlineDebug();
void cleanInlineDebug();
char *getInlineLogFName();
diff --git a/version.h b/version.h
index b46a25f..ecdb6f6 100644
--- a/version.h
+++ b/version.h
@@ -1,4 +1,4 @@
#define AQUALINKD_NAME "Aqualink Daemon"
-#define AQUALINKD_VERSION "1.3.9c"
+#define AQUALINKD_VERSION "2.0.0a"
diff --git a/web/config.js b/web/config.js
index 8ae7986..d3f38ab 100644
--- a/web/config.js
+++ b/web/config.js
@@ -62,6 +62,10 @@
// 0 means only load once when page loads.
//var background_reload = 10;
+ // By default all Variable Speed Pumps will show RPM.
+ // this will show GPM on VSP's that you can only set GPM (ie Jandy VF pumps)
+ //var show_vsp_gpm=false;
+
var body_background = "#EBEBEA";
var body_text = "#000000";
diff --git a/web/controller.html b/web/controller.html
index 8f8fba5..2ec6ac9 100644
--- a/web/controller.html
+++ b/web/controller.html
@@ -469,6 +469,12 @@
var _aqualink_data;
var _landscape = false;
var _displayNames = [];
+
+ if (typeof show_vsp_gpm !== 'undefined' && show_vsp_gpm == false)
+ var _show_vsp_gpm=false;
+ else
+ var _show_vsp_gpm=true;
+
//init();
function init() {
setSizeSpecifics();
@@ -476,6 +482,7 @@
document.getElementById('thermostat_options').classList.remove("hide");
document.getElementById('swg_options').classList.remove("hide");
document.getElementById('pswitch_options').classList.remove("hide");
+ document.getElementById('vspswitch_options').classList.remove("hide");
setColors();
load_background();
showTileOptions(false);
@@ -714,10 +721,13 @@
subdiv.setAttribute('id', id + '_status');
subdiv.textContent = formatSatus(status);
div.appendChild(subdiv);
- if (type == "switch" && subtype != "switch_program") {
+ if (type == "switch" && (subtype != "switch_program" && subtype != "switch_vsp") ) {
+ //if (type == "switch" && subtype != "switch_program" ) {
div.setAttribute('onclick', "switchTileState('" + id + "')");
+ //console.log("add onclick switchtilestate to "+id);
} else /*if (id != "SWG/Percent")*/ {
add_clickEvent(div, id);
+ //console.log("add click Event to "+id);
}
}
document.getElementById('wrapper').appendChild(div);
@@ -735,9 +745,9 @@
try {
if (state == (document.getElementById(id).getAttribute('status') == 'off')) {
send_command(id);
- console.log("Switch state "+id+" to "+(state)?"on":"off");
+ //console.log("Switch state "+id+" to "+(state)?"on":"off");
} else {
- console.log("state "+id+" to "+(state)?"on":"off")
+ //console.log("state "+id+" to "+(state)?"on":"off")
}
setTileOn(id, ((state) ? "on" : "off"));
} catch(exception) {}
@@ -866,10 +876,10 @@
text = 'Generating';
}
else if (type == 'setpoint_thermo')
- if (status == 'enabled')
+ //if (status == 'enabled')
text = 'Heat to ' + tile.getAttribute('setpoint');
- else
- text = 'Heating to ' + tile.getAttribute('setpoint');
+ //else
+ // text = 'Heating to ' + tile.getAttribute('setpoint'); // too large for phone
else if (type == 'setpoint_freeze')
text = 'Turn on ' + tile.getAttribute('setpoint') + "°";
//else
@@ -921,12 +931,42 @@
if (typeof devices !== 'undefined' && devices.indexOf(object.id) < 0) {
return;
}
- if (object.type == 'switch' || object.type == 'switch_program') {
+ //if (object.type == 'switch' || object.type == 'switch_program') {
+ if (object.type == 'switch') {
var img = object.id.replace('/', '_');
- add_tile(object.id, object.name, object.state, 'switch', object.type, 'hk/' + img + '-off.png', 'hk/' + img + '-on.png');
+ var ext_type;
+ if (typeof object.type_ext !== 'undefined')
+ ext_type = object.type_ext;
+ else
+ ext_type = object.type;
+
+ add_tile(object.id, object.name, object.state, 'switch', ext_type, 'hk/' + img + '-off.png', 'hk/' + img + '-on.png');
setTileOn(object.id, object.status, null);
- if (typeof object.Pump_RPM !== 'undefined' && object.Pump_RPM) {
- setTileOnText(object.id, 'RPM:'+object.Pump_RPM);
+ if (typeof object.type_ext !== 'undefined' && object.type_ext == 'switch_vsp') {
+ if (typeof object.Pump_RPM !== 'undefined' && object.Pump_RPM) {
+ if (object.Pump_RPM == -2) {
+ setTileOnText(object.id, 'Pump Offline'); // Small txt
+ document.getElementById(object.id).setAttribute('setpoint', 0);
+ } else if (object.Pump_RPM == -1) {
+ setTileOnText(object.id, 'Pump Priming'); // Small text
+ document.getElementById(object.id).setAttribute('setpoint', 0);
+ } else {
+ if (object.Pump_Type == "vfPump") {
+ if (_show_vsp_gpm == true)
+ setTileOnText(object.id, 'GPM:'+object.Pump_GPM);
+ else
+ setTileOnText(object.id, 'RPM:'+object.Pump_RPM);
+
+ document.getElementById(object.id).setAttribute('setpoint', object.Pump_GPM);
+ } else {
+ setTileOnText(object.id, 'RPM:'+object.Pump_RPM);
+ document.getElementById(object.id).setAttribute('setpoint', object.Pump_RPM);
+ }
+ }
+ }
+ if (typeof object.Pump_Type !== 'undefined') {
+ document.getElementById(object.id).setAttribute('pumptype', object.Pump_Type);
+ }
}
} else if (object.type == 'value' || object.type == 'temperature') {
add_tile(object.id, object.name, object.state, 'value', object.type);
@@ -942,6 +982,7 @@
}
function showTileOptions(show, id, contex) {
+ console.log("showTileOptions " + show + " "+id+" "+contex);
var active_option;
if (show == true) {
var wrapH = document.getElementById('wrapper').clientHeight + 'px';
@@ -949,14 +990,22 @@
active_option = document.getElementById('thermostat_options');
document.getElementById('swg_options').style.display = 'none';
document.getElementById('pswitch_options').style.display = 'none';
+ document.getElementById('vspswitch_options').style.display = 'none';
} else if (id != null && document.getElementById(id).getAttribute('type') == 'switch_program') {
active_option = document.getElementById('pswitch_options');
document.getElementById('thermostat_options').style.display = 'none';
document.getElementById('swg_options').style.display = 'none';
- } else /*if (id != null && document.getElementById(id).getAttribute('type') == 'setpoint_swg')*/ {
+ document.getElementById('vspswitch_options').style.display = 'none';
+ } else if (id != null && document.getElementById(id).getAttribute('type') == 'setpoint_swg') {
active_option = document.getElementById('swg_options');
document.getElementById('thermostat_options').style.display = 'none';
document.getElementById('pswitch_options').style.display = 'none';
+ document.getElementById('vspswitch_options').style.display = 'none';
+ } else if (id != null && document.getElementById(id).getAttribute('type') == 'switch_vsp') {
+ active_option = document.getElementById('vspswitch_options');
+ document.getElementById('thermostat_options').style.display = 'none';
+ document.getElementById('pswitch_options').style.display = 'none';
+ document.getElementById('swg_options').style.display = 'none';
}
active_option.style.display = 'flex';
var optionH = window.getComputedStyle(active_option, null).getPropertyValue("height");
@@ -974,10 +1023,13 @@
document.getElementById("swg_options_close").click();
else if (document.getElementById('pswitch_options').style.display == 'flex')
document.getElementById("pswitch_options_close").click();
+ else if (document.getElementById('vspswitch_options').style.display == 'flex')
+ document.getElementById("vspswitch_options").click();
}
document.getElementById('thermostat_options').style.display = 'none';
document.getElementById('swg_options').style.display = 'none';
document.getElementById('pswitch_options').style.display = 'none';
+ document.getElementById('vspswitch_options').style.display = 'none';
document.getElementById('wrapper').classList.remove("opaque");
return;
}
@@ -1011,6 +1063,12 @@
title = document.getElementById("pswitch_option_title");
close_button = document.getElementById("pswitch_options_close");
//ext = '°' + _temperature_units;
+ } else if (type == 'switch_vsp') {
+ slider = document.getElementById("vspoption_slider_range");
+ slider_output = document.getElementById("vspoption_slider_text_value");
+ title = document.getElementById("vspswitch_option_title");
+ close_button = document.getElementById("vspswitch_option_close");
+ //ext = '°' + _temperature_units;
} else {
slider = document.getElementById("option_slider_range");
slider_output = document.getElementById("option_slider_text_value");
@@ -1042,6 +1100,18 @@
slider.max = 40;
slider.step = 1;
}
+ } else if (type == 'switch_vsp') {
+ if ( tile.getAttribute('pumptype') == "vfPump" ) { // RPM vs GPM
+ slider.min = 15;
+ slider.max = 130;
+ slider.step = 5;
+ ext = ' GPM';
+ } else {
+ slider.min = 600;
+ slider.max = 3450;
+ slider.step = 5;
+ ext = ' RPM';
+ }
}
title.innerHTML = document.getElementById(id + '_name').innerHTML;
if (type == 'switch_program') {
@@ -1070,6 +1140,21 @@
oswitch_output.innerHTML = ((oswitch.checked) ? "Boost On" : "Boost Off");
//setTileOn(id, ((oswitch.checked)?"on":"off"), null);
}
+ } else if (type == 'switch_vsp') {
+ slider.value = sp_value;
+ oswitch = document.getElementById("vspoption_switch");
+ oswitch.checked = tile_state;
+ var oswitch_output = document.getElementById("vspoption_switch_text_value");
+ slider_output.innerHTML = slider.value + ext;
+ oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
+ slider.oninput = function() {
+ slider_output.innerHTML = this.value + ext;
+ //sp_value = this.value
+ }
+ oswitch.onclick = function() {
+ oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
+ //setTileOn(id, ((oswitch.checked)?"on":"off"), null);
+ }
} else {
slider.value = sp_value;
oswitch = document.getElementById("option_switch");
@@ -1133,6 +1218,12 @@
if (sp_value != slider.value && slider.value != 101) // Don't change setpoint if slider is on boost
setThermostatSetpoint(id, slider.value);
}
+ } else if (type == 'switch_program') {
+ var value = slider.value;
+ if (state == (tile.getAttribute('status') == 'off'))
+ setTileState(id, state);
+ if (sp_value != slider.value)
+ setThermostatSetpoint(id, slider.value)
} else {
var value = slider.value;
if (state == (tile.getAttribute('status') == 'off'))
@@ -1215,7 +1306,24 @@
while (i < 5) {
//console.log(data["Pump_"+i].RPM);
if ((typeof data["Pump_"+i] !== 'undefined') && (typeof data["Pump_"+i].RPM !== 'undefined')) {
- setTileOnText(data["Pump_"+i].id, 'RPM:'+data["Pump_"+i].RPM);
+ if (data["Pump_"+i].RPM == -2) {
+ setTileOnText(data["Pump_"+i].id, 'Pump Offline');
+ } else if (data["Pump_"+i].RPM == -1) {
+ setTileOnText(data["Pump_"+i].id, 'Pump Priming');
+ } else {
+ //setTileOnText(object.id, 'RPM:'+object.Pump_RPM);
+ if (data["Pump_"+i].Pump_Type == "vfPump") {
+ if (_show_vsp_gpm == true)
+ setTileOnText(data["Pump_"+i].id, 'GPM:'+data["Pump_"+i].GPM);
+ else
+ setTileOnText(data["Pump_"+i].id, 'RPM:'+data["Pump_"+i].RPM);
+
+ document.getElementById(data["Pump_"+i].id).setAttribute('setpoint', data["Pump_"+i].GPM);
+ } else {
+ document.getElementById(data["Pump_"+i].id).setAttribute('setpoint', data["Pump_"+i].RPM);
+ setTileOnText(data["Pump_"+i].id, 'RPM:'+data["Pump_"+i].RPM);
+ }
+ }
/*
if (document.getElementById(data["Pump_"+i].id).getAttribute('status') == 'on')
document.getElementById(data["Pump_"+i].id + '_status').innerHTML = 'RPM:'+data["Pump_"+i].RPM;
@@ -1247,8 +1355,12 @@
createTile(data['devices'][obj]);
} else {
//console.log("old type "+document.getElementById(data['devices'][obj].id).getAttribute('type')+" | new "+data['devices'][obj].type);
- if (document.getElementById(data['devices'][obj].id).getAttribute('type') != data['devices'][obj].type) {
- //console.log("Remove and create "+data['devices'][obj].id);
+ var element_type = document.getElementById(data['devices'][obj].id).getAttribute('type');
+
+ if ( (element_type != data['devices'][obj].type) &&
+ (typeof data['devices'][obj].type_ext !== 'undefined' && element_type != data['devices'][obj].type_ext ) ) {
+ console.log("Remove and create "+data['devices'][obj].id);
+ console.log("Old type "+element_type+" | new type "+data['devices'][obj].type+" sub "+data['devices'][obj].type_ext);
var element = document.getElementById(data['devices'][obj].id);
element.parentNode.removeChild(element);
createTile(data['devices'][obj]);
@@ -1335,8 +1447,10 @@
if ((tile = document.getElementById(id)) == null) {
return;
}
+ if (tile.getAttribute('setpoint'))
temperature.parameter = tile.getAttribute('id');
temperature.value = tile.getAttribute('setpoint');
+//console.log("Send value back "+temperature.parameter+" "+temperature.value);
socket_di.send(JSON.stringify(temperature));
}
@@ -1516,6 +1630,42 @@
+
- |
+ |
|
 
|
|
+ |
+
|
|
- |
-
+ |
+
+ |
+
+ |
+
+ |
+
|
- |
-
- |