pull/66/head
sfeakes 2019-06-05 11:41:38 -05:00
parent c5b1869e77
commit d0e5db5d73
24 changed files with 409 additions and 152 deletions

View File

@ -15,6 +15,7 @@ DBG =
#GCCFLAGS = -Wall -ffunction-sections -fdata-sections
# define any compile-time flags
#GCCFLAGS = -Wall -O3 -Wextra
GCCFLAGS = -Wall -O3
#GCCFLAGS = -Wall
@ -26,7 +27,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 iAqualink_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 mongoose.c
SL_SRC = serial_logger.c aq_serial.c utils.c
LR_SRC = log_reader.c aq_serial.c utils.c

View File

@ -63,9 +63,12 @@ Designed to mimic AqualinkRS6 All Button keypad, and just like the keypad you ca
* 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)
#<a name="release"></a>
## Update in Release 1.3.2
* Miscellaneous bug fixes and buffer overrun (could cause core dump).
* VSP update.
## Update in Release 1.3.1
* Changed the way PDA mode will sleep.
* Added preliminary support for Variable Speed Pumps. (Limited to only reading status and post to MQTT/WebSocket/API if iAqualink is active on the RS485 bus)
* Added preliminary support for Variable Speed Pumps. (many limitations on support)
* Added int status to Web API
## Update in Release 1.3.0
* Large update for PDA only control panels (Majority of this is ballle98 work)

View File

@ -34,7 +34,7 @@
bool select_sub_menu_item(struct aqualinkdata *aq_data, char* item_string);
bool select_menu_item(struct aqualinkdata *aq_data, char* item_string);
//void send_cmd(unsigned char cmd, struct aqualinkdata *aq_data);
void cancel_menu(struct aqualinkdata *aq_data);
void cancel_menu();
void *set_aqualink_pool_heater_temps( void *ptr );
@ -46,7 +46,7 @@ void *get_aqualink_programs( void *ptr );
void *get_freeze_protect_temp( void *ptr );
void *get_aqualink_diag_model( void *ptr );
void *get_aqualink_aux_labels( void *ptr );
void *threadded_send_cmd( void *ptr );
//void *threadded_send_cmd( void *ptr );
void *set_aqualink_light_colormode( void *ptr );
void *set_aqualink_PDA_init( void *ptr );
void *set_aqualink_SWG( void *ptr );
@ -69,8 +69,15 @@ unsigned char _pgm_command = NUL;
bool _last_sent_was_cmd = false;
// External view of adding to queue
void aq_send_cmd(unsigned char cmd) {
push_aq_cmd(cmd);
}
bool push_aq_cmd(unsigned char cmd) {
//logMessage(LOG_DEBUG, "push_aq_cmd\n");
//logMessage(LOG_DEBUG, "push_aq_cmd '0x%02hhx'\n", cmd);
if (_stack_place < MAX_STACK) {
_commands[_stack_place] = cmd;
_stack_place++;
@ -92,17 +99,21 @@ unsigned char pop_aq_cmd(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--;
memcpy(&_commands[0], &_commands[1], sizeof(unsigned char) * MAX_STACK);
//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)
@ -113,6 +124,8 @@ unsigned char pop_aq_cmd(struct aqualinkdata *aq_data)
return cmd;
}
int setpoint_check(int type, int value, struct aqualinkdata *aqdata)
{
int rtn = value;
@ -222,13 +235,25 @@ void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data)
}
programmingthread->aq_data = aq_data;
programmingthread->thread_id = 0;
//programmingthread->thread_args = args;
if (args != NULL && type != AQ_SEND_CMD)
if (args != NULL /*&& type != AQ_SEND_CMD*/)
strncpy(programmingthread->thread_args, args, sizeof(programmingthread->thread_args)-1);
switch(type) {
/*
case AQ_SEND_CMD:
push_aq_cmd((unsigned char)*args);
logMessage(LOG_INFO, "Queue send '0x%02hhx' to controller\n", (unsigned char)*args);
logMessage(LOG_INFO, "Queue send '0x%02hhx' to controller\n", &args[0]);
unsigned char cmd = (unsigned char) &args[0];
if (cmd == NUL) {
logMessage(LOG_INFO, "Queue send '0x%02hhx' to controller (NEW)\n", cmd);
push_aq_cmd( cmd );
} else {
logMessage(LOG_INFO, "Queue send '0x%02hhx' to controller (OLD)\n", cmd);
push_aq_cmd((unsigned char)*args);
}*/
//logMessage(LOG_INFO, "Queue send '0x%02hhx' to controller\n", (unsigned char)*args);
/*
if(aq_data->active_thread.thread_id == 0) { // No need to thread a plane send if no active threads
send_cmd( (unsigned char)*args, aq_data);
@ -237,7 +262,7 @@ void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data)
return;
}
*/
break;
//break;
case AQ_GET_POOL_SPA_HEATER_TEMPS:
if( pthread_create( &programmingthread->thread_id , NULL , get_aqualink_pool_spa_heater_temps, (void*)programmingthread) < 0) {
logMessage (LOG_ERR, "could not create thread\n");
@ -349,6 +374,17 @@ void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, pr
static int waitTime = 1;
int i=0;
i = 0;
while (get_aq_cmd_length() > 0 && ( i++ <= tries) ) {
logMessage (LOG_DEBUG, "Thread %d sleeping, waiting for queue to empty\n", threadCtrl->thread_id, threadCtrl->aq_data->active_thread.thread_id);
sleep(waitTime);
}
if (i >= tries) {
logMessage (LOG_ERR, "Thread %d timeout waiting, ending\n",threadCtrl->thread_id);
free(threadCtrl);
pthread_exit(0);
}
while ( (threadCtrl->aq_data->active_thread.thread_id != 0) && ( i++ <= tries) ) {
logMessage (LOG_DEBUG, "Thread %d sleeping, waiting for thread %d to finish\n", threadCtrl->thread_id, threadCtrl->aq_data->active_thread.thread_id);
sleep(waitTime);
@ -359,7 +395,7 @@ void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, pr
free(threadCtrl);
pthread_exit(0);
}
threadCtrl->aq_data->active_thread.thread_id = &threadCtrl->thread_id;
threadCtrl->aq_data->active_thread.ptype = type;
logMessage (LOG_DEBUG, "Thread %d is active\n", threadCtrl->aq_data->active_thread.thread_id);
@ -397,7 +433,7 @@ bool setAqualinkNumericField_new(struct aqualinkdata *aq_data, char *value_label
{
if (waitForMessage(aq_data, searchBuf, 3) != true) {
logMessage(LOG_WARNING, "AQ_Programmer Could not set numeric input '%s', not found\n",value_label);
cancel_menu(aq_data);
cancel_menu();
return false;
}
//logMessage(LOG_DEBUG,"WAITING for kick value=%d\n",current_val);
@ -409,17 +445,17 @@ bool setAqualinkNumericField_new(struct aqualinkdata *aq_data, char *value_label
if(value > current_val) {
// Increment the field.
sprintf(searchBuf, "%s %d", value_label, current_val+increment);
send_cmd(KEY_RIGHT, aq_data);
send_cmd(KEY_RIGHT);
}
else if(value < current_val) {
// Decrement the field.
sprintf(searchBuf, "%s %d", value_label, current_val-increment);
send_cmd(KEY_LEFT, aq_data);
send_cmd(KEY_LEFT);
}
else {
// Just send ENTER. We are at the right value.
sprintf(searchBuf, "%s %d", value_label, current_val);
send_cmd(KEY_ENTER, aq_data);
send_cmd(KEY_ENTER);
}
if (i++ >= 100) {
@ -445,7 +481,7 @@ bool OLD_setAqualinkNumericField_OLD(struct aqualinkdata *aq_data, char *value_l
{
if (waitForMessage(aq_data, searchBuf, 3) != true) {
logMessage(LOG_WARNING, "AQ_Programmer Could not set numeric input '%s', not found\n",value_label);
cancel_menu(aq_data);
cancel_menu();
return false;
}
//logMessage(LOG_DEBUG,"WAITING for kick value=%d\n",current_val);
@ -455,17 +491,17 @@ bool OLD_setAqualinkNumericField_OLD(struct aqualinkdata *aq_data, char *value_l
if(value > current_val) {
// Increment the field.
sprintf(searchBuf, "%s %d", value_label, current_val+1);
send_cmd(KEY_RIGHT, aq_data);
send_cmd(KEY_RIGHT);
}
else if(value < current_val) {
// Decrement the field.
sprintf(searchBuf, "%s %d", value_label, current_val-1);
send_cmd(KEY_LEFT, aq_data);
send_cmd(KEY_LEFT);
}
else {
// Just send ENTER. We are at the right value.
sprintf(searchBuf, "%s %d", value_label, current_val);
send_cmd(KEY_ENTER, aq_data);
send_cmd(KEY_ENTER);
}
} while(value != current_val);
@ -510,7 +546,7 @@ void *set_aqualink_SWG( void *ptr )
if ( select_menu_item(aq_data, "SET AQUAPURE") != true ) {
logMessage(LOG_WARNING, "Could not select SET AQUAPURE menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -519,7 +555,7 @@ void *set_aqualink_SWG( void *ptr )
if (aq_data->aqbuttons[SPA_INDEX].led->state != OFF) {
if (select_sub_menu_item(aq_data, "SET SPA SP") != true) {
logMessage(LOG_WARNING, "Could not select SWG setpoint menu for SPA\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -527,7 +563,7 @@ void *set_aqualink_SWG( void *ptr )
} else {
if (select_sub_menu_item(aq_data, "SET POOL SP") != true) {
logMessage(LOG_WARNING, "Could not select SWG setpoint menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -570,14 +606,14 @@ void *get_aqualink_aux_labels( void *ptr )
if ( select_menu_item(aq_data, "REVIEW") != true ) {
logMessage(LOG_WARNING, "Could not select REVIEW menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
if (select_sub_menu_item(aq_data, "AUX LABELS") != true) {
logMessage(LOG_WARNING, "Could not select AUX LABELS menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -620,7 +656,7 @@ void *set_aqualink_light_colormode( void *ptr )
// Simply turn the light off if value is 0
if (val <= 0) {
if ( button->led->state == ON ) {
send_cmd(code, aq_data);
send_cmd(code);
}
cleanAndTerminateThread(threadCtrl);
return ptr;
@ -631,14 +667,14 @@ void *set_aqualink_light_colormode( void *ptr )
// before we can send the next off.
if ( button->led->state != ON ) {
logMessage(LOG_INFO, "Pool Light Initial state off, turning on for 15 seconds\n");
send_cmd(code, aq_data);
send_cmd(code);
//delay(15 * seconds);
delay(iOn * seconds);
}
logMessage(LOG_INFO, "Pool Light turn off for 12 seconds\n");
// Now need to turn off for between 11 and 14 seconds to reset light.
send_cmd(code, aq_data);
send_cmd(code);
//delay(12 * seconds);
delay(iOff * seconds);
@ -649,21 +685,21 @@ void *set_aqualink_light_colormode( void *ptr )
if (pmode > 0) {
for (i = 1; i < (val * 2); i++) {
logMessage(LOG_INFO, "Pool Light button press number %d - %s of %d\n", i, i % 2 == 0 ? "Off" : "On", val);
send_cmd(code, aq_data);
send_cmd(code);
delay(pmode * seconds); // 0.3 works, but using 0.4 to be safe
}
} else {
for (i = 1; i < val; i++) {
logMessage(LOG_INFO, "Pool Light button press number %d - %s of %d\n", i, "ON", val);
send_cmd(code, aq_data);
send_cmd(code);
waitForButtonState(aq_data, button, ON, 2);
logMessage(LOG_INFO, "Pool Light button press number %d - %s of %d\n", i, "OFF", val);
send_cmd(code, aq_data);
send_cmd(code);
waitForButtonState(aq_data, button, OFF, 2);
}
logMessage(LOG_INFO, "Finished - Pool Light button press number %d - %s of %d\n", i, "ON", val);
send_cmd(code, aq_data);
send_cmd(code);
}
//waitForButtonState(aq_data, &aq_data->aqbuttons[btn], ON, 2);
@ -711,7 +747,7 @@ void *set_aqualink_pool_heater_temps( void *ptr )
if ( select_menu_item(aq_data, "SET TEMP") != true ) {
logMessage(LOG_WARNING, "Could not select SET TEMP menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -719,7 +755,7 @@ void *set_aqualink_pool_heater_temps( void *ptr )
//if (select_sub_menu_item(aq_data, "SET POOL TEMP") != true) {
if (select_sub_menu_item(aq_data, menu_name) != true) {
logMessage(LOG_WARNING, "Could not select SET POOL TEMP menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -729,7 +765,7 @@ void *set_aqualink_pool_heater_temps( void *ptr )
// and get this message 'TEMP1 20<32>C ~*'
// Before going to numeric field.
waitForMessage(threadCtrl->aq_data, "MUST BE SET", 5);
send_cmd(KEY_LEFT, aq_data);
send_cmd(KEY_LEFT);
while (stristr(aq_data->last_message, "MUST BE SET") != NULL) {
delay(500);
}
@ -785,7 +821,7 @@ void *set_aqualink_spa_heater_temps( void *ptr )
//setAqualinkTemp(aq_data, "SET TEMP", "SET SPA TEMP", NULL, "SPA", val);
if ( select_menu_item(aq_data, "SET TEMP") != true ) {
logMessage(LOG_WARNING, "Could not select SET TEMP menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -793,7 +829,7 @@ void *set_aqualink_spa_heater_temps( void *ptr )
//if (select_sub_menu_item(aq_data, "SET SPA TEMP") != true) {
if (select_sub_menu_item(aq_data, menu_name) != true) {
logMessage(LOG_WARNING, "Could not select SET SPA TEMP menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -803,7 +839,7 @@ void *set_aqualink_spa_heater_temps( void *ptr )
// and get this message 'TEMP2 20<32>C ~*'
// Before going to numeric field.
waitForMessage(threadCtrl->aq_data, "MUST BE SET", 5);
send_cmd(KEY_LEFT, aq_data);
send_cmd(KEY_LEFT);
while (stristr(aq_data->last_message, "MUST BE SET") != NULL) {
delay(500);
}
@ -843,21 +879,21 @@ void *set_aqualink_freeze_heater_temps( void *ptr )
//setAqualinkTemp(aq_data, "SYSTEM SETUP", "FRZ PROTECT", "TEMP SETTING", "FRZ", val);
if ( select_menu_item(aq_data, "SYSTEM SETUP") != true ) {
logMessage(LOG_WARNING, "Could not select SYSTEM SETUP menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
if (select_sub_menu_item(aq_data, "FRZ PROTECT") != true) {
logMessage(LOG_WARNING, "Could not select FRZ PROTECT menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
if (select_sub_menu_item(aq_data, "TEMP SETTING") != true) {
logMessage(LOG_WARNING, "Could not select TEMP SETTING menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -898,7 +934,7 @@ void *set_aqualink_time( void *ptr )
if ( select_menu_item(aq_data, "SET TIME") != true ) {
logMessage(LOG_WARNING, "Could not select SET TIME menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -910,7 +946,7 @@ void *set_aqualink_time( void *ptr )
select_sub_menu_item(aq_data, hour);
setAqualinkNumericField(aq_data, "MINUTE", result->tm_min);
send_cmd(KEY_ENTER, aq_data);
send_cmd(KEY_ENTER);
cleanAndTerminateThread(threadCtrl);
@ -928,14 +964,14 @@ void *get_aqualink_diag_model( void *ptr )
if ( select_menu_item(aq_data, "SYSTEM SETUP") != true ) {
logMessage(LOG_WARNING, "Could not select HELP menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
if (select_sub_menu_item(aq_data, "DIAGNOSTICS") != true) {
logMessage(LOG_WARNING, "Could not select DIAGNOSTICS menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -968,14 +1004,14 @@ void *get_aqualink_pool_spa_heater_temps( void *ptr )
if ( select_menu_item(aq_data, "REVIEW") != true ) {
logMessage(LOG_WARNING, "Could not select REVIEW menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
if (select_sub_menu_item(aq_data, "TEMP SET") != true) {
logMessage(LOG_WARNING, "Could not select TEMP SET menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -1011,14 +1047,14 @@ void *get_freeze_protect_temp( void *ptr )
if ( select_menu_item(aq_data, "REVIEW") != true ) {
logMessage(LOG_WARNING, "Could not select REVIEW menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
if (select_sub_menu_item(aq_data, "FRZ PROTECT") != true) {
logMessage(LOG_WARNING, "Could not select FRZ PROTECT menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
@ -1039,7 +1075,7 @@ bool get_aqualink_program_for_button(struct aqualinkdata *aq_data, unsigned char
return false;
logMessage(LOG_DEBUG, "Send key '%d'\n",cmd);
send_cmd(cmd, aq_data);
send_cmd(cmd);
return waitForEitherMessage(aq_data, "NOT SET", "TURNS ON", rtnStringsWait);
}
@ -1054,19 +1090,19 @@ void *get_aqualink_programs( void *ptr )
if ( select_menu_item(aq_data, "REVIEW") != true ) {
//logMessage(LOG_WARNING, "Could not select REVIEW menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
if (select_sub_menu_item(aq_data, "PROGRAMS") != true) {
//logMessage(LOG_WARNING, "Could not select PROGRAMS menu\n");
cancel_menu(aq_data);
cancel_menu();
cleanAndTerminateThread(threadCtrl);
return ptr;
}
int i;
unsigned int i;
for (i=0; i < strlen(keys); i++) {
//logMessage(LOG_DEBUG, "**** START program for key in loop %d\n",i);
@ -1082,10 +1118,10 @@ void *get_aqualink_programs( void *ptr )
if (waitForMessage(aq_data, "SELECT DEVICE TO REVIEW or PRESS ENTER TO END", 6)) {
//logMessage(LOG_DEBUG, "Send key ENTER\n");
send_cmd(KEY_ENTER, aq_data);
send_cmd(KEY_ENTER);
} else {
//logMessage(LOG_DEBUG, "Send CANCEL\n");
cancel_menu(aq_data);
cancel_menu();
}
//cancel_menu(aq_data);
@ -1103,7 +1139,7 @@ void send_cmd(unsigned char cmd, struct aqualinkdata *aq_data)
}
*/
void send_cmd(unsigned char cmd, struct aqualinkdata *aq_data)
void send_cmd(unsigned char cmd)
{
int i=0;
// If there is an unsent command, wait.
@ -1116,7 +1152,7 @@ void send_cmd(unsigned char cmd, struct aqualinkdata *aq_data)
_pgm_command = cmd;
//delay(200);
logMessage(LOG_INFO, "Queue send '0x%02hhx' to controller\n", _pgm_command);
logMessage(LOG_INFO, "Queue send '0x%02hhx' to controller (programming)\n", _pgm_command);
}
/*
@ -1136,9 +1172,9 @@ void send_cmd(unsigned char cmd, struct aqualinkdata *aq_data)
}
*/
void cancel_menu(struct aqualinkdata *aq_data)
void cancel_menu()
{
send_cmd(KEY_CANCEL, aq_data);
send_cmd(KEY_CANCEL);
}
/*
@ -1269,13 +1305,13 @@ bool waitForMessage(struct aqualinkdata *aq_data, char* message, int numMessageR
bool select_menu_item(struct aqualinkdata *aq_data, char* item_string)
{
char* expectedMsg = "PRESS ENTER* TO SELECT";
int wait_messages = 3;
int wait_messages = 5;
bool found = false;
int tries = 0;
// Select the MENU and wait to get the RS8 respond.
while (found == false && tries <= 3) {
send_cmd(KEY_MENU, aq_data);
send_cmd(KEY_MENU);
found = waitForMessage(aq_data, expectedMsg, wait_messages);
tries++;
}
@ -1322,7 +1358,7 @@ bool select_sub_menu_item(struct aqualinkdata *aq_data, char* item_string)
while( (stristr(aq_data->last_message, item_string) == NULL) && ( i++ < wait_messages) )
{
send_cmd(KEY_RIGHT, aq_data);
send_cmd(KEY_RIGHT);
waitForMessage(aq_data, NULL, 1);
logMessage(LOG_DEBUG, "Find item in Menu: loop %d of %d looking for '%s' received message '%s'\n",i,wait_messages,item_string,aq_data->last_message);
}
@ -1336,7 +1372,7 @@ bool select_sub_menu_item(struct aqualinkdata *aq_data, char* item_string)
// Enter the mode specified by the argument.
send_cmd(KEY_ENTER, aq_data);
send_cmd(KEY_ENTER);
waitForMessage(aq_data, NULL, 1);
//sendCmdWaitForReturn(aq_data, KEY_ENTER);

View File

@ -30,7 +30,7 @@ typedef enum {
AQ_SET_SPA_HEATER_TEMP,
AQ_SET_FRZ_PROTECTION_TEMP,
AQ_GET_DIAGNOSTICS_MODEL,
AQ_SEND_CMD,
//AQ_SEND_CMD,
AQ_GET_PROGRAMS,
AQ_SET_COLORMODE,
AQ_PDA_INIT,
@ -54,6 +54,8 @@ struct programmingThreadCtrl {
void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data);
void kick_aq_program_thread(struct aqualinkdata *aq_data);
void aq_send_cmd(unsigned char cmd);
unsigned char pop_aq_cmd(struct aqualinkdata *aq_data);
//bool push_aq_cmd(unsigned char cmd);
@ -68,7 +70,7 @@ int setpoint_check(int type, int value, struct aqualinkdata *aqdata);
// These shouldn't be here, but just for the PDA AQ PROGRAMMER
void send_cmd(unsigned char cmd, struct aqualinkdata *aq_data);
void send_cmd(unsigned char cmd);
bool push_aq_cmd(unsigned char cmd);
void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, program_type type);
void cleanAndTerminateThread(struct programmingThreadCtrl *threadCtrl);

View File

@ -365,8 +365,8 @@ void send_command(int fd, unsigned char destination, unsigned char b1, unsigned
void send_messaged(int fd, unsigned char destination, char *message)
{
const int length = 24;
int i;
const unsigned int length = 24;
unsigned int i;
//unsigned char ackPacket[] = { NUL, DLE, STX, DEV_MASTER, CMD_ACK, NUL, NUL, 0x13, DLE, ETX, NUL };
unsigned char msgPacket[] = { DLE,STX,DEV_MASTER,CMD_MSG,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,NUL,DLE,ETX };
//unsigned char ackPacket[] = { NUL, DLE, STX, DEV_MASTER, NUL, NUL, NUL, 0x13, DLE, ETX, NUL };
@ -454,6 +454,7 @@ void _send_ack(int fd, unsigned char ack_type, unsigned char command)
//tcdrain(fd);
#endif
//logMessage(LOG_DEBUG, "Sent '0x%02hhx' to controller\n", command);
log_packet(LOG_DEBUG_SERIAL, "Sent ", ackPacket, length);
}

View File

@ -155,10 +155,14 @@ SPILLOVER IS DISABLED WHILE SPA IS ON
*/
#define MSG_SWG_PCT "AQUAPURE" // AquaPure 55%
#define MSG_SWG_PPM "SALT" // Salt 3000 PPM
#define MSG_SWG_PPM "SALT" // Salt 3000 PPM
#define MSG_SWG_PCT_LEN 8
#define MSG_SWG_PPM_LEN 4
#define MSG_PMP_RPM "RPM:"
#define MSG_PMP_WAT "Watts:"
#define MSG_PMP_GPH "GPH:"
/* AQUAPURE SWG */
// These are madeup.

View File

@ -41,7 +41,7 @@
#include "iAqualink_messages.h"
#include "version.h"
#define DEFAULT_CONFIG_FILE "./aqualinkd.conf"
//#define DEFAULT_CONFIG_FILE "./aqualinkd.conf"
static volatile bool _keepRunning = true;
static struct aqconfig _config_parameters;
@ -53,6 +53,7 @@ void intHandler(int dummy)
{
_keepRunning = false;
logMessage(LOG_NOTICE, "Stopping!");
if (dummy){}// stop compile warnings
}
void processLEDstate()
@ -165,14 +166,18 @@ void aqualink_strcpy(char *dest, char *src)
dest[i] = '\0';
//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);
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);
//aq_programmer(AQ_GET_POOL_SPA_HEATER_TEMPS, NULL, &_aqualink_data);
if (_config_parameters.use_panel_aux_labels == true)
{
aq_programmer(AQ_GET_AUX_LABELS, NULL, &_aqualink_data);
@ -402,7 +407,8 @@ void processMessage(char *message)
else if (_config_parameters.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);
//aq_programmer(AQ_SEND_CMD, (char *)KEY_ENTER, &_aqualink_data);
aq_send_cmd(KEY_ENTER);
}
else if ((msg[4] == ':') && (strncasecmp(msg, "AUX", 3) == 0))
{ // AUX label "AUX1:"
@ -440,6 +446,55 @@ void processMessage(char *message)
kick_aq_program_thread(&_aqualink_data);
}
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)
{
@ -619,7 +674,9 @@ int main(int argc, char *argv[])
// main_loop ();
int i;
char *cfgFile = DEFAULT_CONFIG_FILE;
//char *cfgFile = DEFAULT_CONFIG_FILE;
char defaultCfg[] = "./aqualinkd.conf";
char *cfgFile;
int cmdln_loglevel = -1;
bool cmdln_debugRS485 = false;
@ -637,6 +694,8 @@ int main(int argc, char *argv[])
// Initialize the daemon's parameters.
init_parameters(&_config_parameters);
cfgFile = defaultCfg;
//sprintf(cfgFile, "%s", DEFAULT_CONFIG_FILE);
for (i = 1; i < argc; i++)
{
@ -705,6 +764,7 @@ int main(int argc, char *argv[])
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, "Config serial_port = %s\n", config_parameters->serial_port);
for (i = 0; i < TOTAL_BUTONS; i++)
@ -982,6 +1042,14 @@ void main_loop()
else
caculate_ack_packet(rs_fd, packet_buffer);
}
else if (_config_parameters.use_PDA_auxiliary && packet_length > 0 && packet_buffer[PKT_DEST] == 0x60 && _aqualink_data.aqbuttons[PUMP_INDEX].led->state != OFF)
{
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)
{
@ -1022,12 +1090,12 @@ void main_loop()
{
interestedInNextAck = false;
}
/* 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),

View File

@ -84,6 +84,7 @@ void init_parameters (struct aqconfig * parms)
parms->use_panel_aux_labels = false;
parms->debug_RSProtocol_packets = false;
parms->force_swg = false;
parms->use_PDA_auxiliary = false;
generate_mqtt_id(parms->mqtt_ID, MQTT_ID_LEN);
}
@ -380,6 +381,7 @@ bool setConfigValue(struct aqconfig *config_parameters, struct aqualinkdata *aqd
} 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;
rtn=true;
} else if (strncasecmp(param, "pda_sleep_mode", 8) == 0) {
config_parameters->pda_sleep_mode = text2bool(value);
@ -413,8 +415,14 @@ bool setConfigValue(struct aqconfig *config_parameters, struct aqualinkdata *aqd
} else if (strncasecmp (param, "debug_RSProtocol_packets", 24) == 0) {
config_parameters->debug_RSProtocol_packets = text2bool(value);
rtn=true;
} else if (strncasecmp (param, "use_PDA_auxiliary", 17) == 0) {
config_parameters->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;
}
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);
@ -475,6 +483,7 @@ void readCfg (struct aqconfig *config_parameters, struct aqualinkdata *aqdata, c
fclose(fp);
} else {
/* error processing, couldn't open file */
logMessage(LOG_ERR, "Error reading config file '%s'\n",cfgFile);
displayLastSystemError(cfgFile);
exit (EXIT_FAILURE);
}
@ -515,6 +524,7 @@ char *errorlevel2text(int level)
bool remount_root_ro(bool readonly) {
// NSF Check if config is RO_ROOT set
if (readonly) {} // Dummy to stop compile warnings.
/*
if (readonly) {
logMessage(LOG_INFO, "reMounting root RO\n");
@ -530,7 +540,7 @@ bool remount_root_ro(bool readonly) {
mount (NULL, "/", NULL, MS_REMOUNT, NULL);
return true;
}
*/
*/
return true;
}

View File

@ -59,6 +59,7 @@ struct aqconfig
bool read_all_devices;
bool use_panel_aux_labels;
bool force_swg;
bool use_PDA_auxiliary;
bool debug_RSProtocol_packets;
//int dzidx_pool_thermostat; // Domoticz virtual thermostats are crap removed until better
//int dzidx_spa_thermostat; // Domoticz virtual thermostats are crap removed until better

View File

@ -1,4 +1,10 @@
/*
Removed as iAqualink has a sleep mode, Keeping code to use as stub for other devices.
*/
#include <stdio.h>
#include <stdlib.h>
@ -16,7 +22,13 @@ bool processiAqualinkMsg(unsigned char *packet_buffer, int packet_length, struct
//static char message[AQ_MSGLONGLEN + 1];
static int pumpIndex = 1;
/*
/*
Jandy ePumpTM DC,
Jandy ePumpTM AC,
IntelliFlo 1 VF,
IntelliFlo VS
Pump type are like // Not sure how to read this accuratly.
"Jandy ePUMP 1"
"Intelliflo VS 1"

View File

@ -515,7 +515,7 @@ bool parseJSONwebrequest(char *buffer, struct JSONwebrequest *request)
}
bool parseJSONmqttrequest(const char *str, size_t len, int *idx, int *nvalue, char *svalue) {
int i = 0;
unsigned int i = 0;
int found = 0;
svalue[0] = '\0';

View File

@ -266,7 +266,7 @@ void send_mqtt_float_msg(struct mg_connection *nc, char *dev_name, float value)
static char mqtt_pub_topic[250];
static char msg[10];
sprintf(msg, "%f", value);
sprintf(msg, "%.2f", value);
sprintf(mqtt_pub_topic, "%s/%s", _aqualink_config->mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, msg);
}
@ -744,7 +744,8 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
}
else if (strcmp(value, "on") == 0) {
if (_aqualink_data->aqbuttons[i].led->state == OFF || _aqualink_data->aqbuttons[i].led->state == FLASH) {
aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
rtn = GET_RTN_OK;
logMessage(LOG_INFO, "WEB: turn ON '%s' changed state to '%s'\n", command, value);
} else {
@ -755,7 +756,8 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
if (_aqualink_data->aqbuttons[i].led->state == ON ||
_aqualink_data->aqbuttons[i].led->state == ENABLE ||
_aqualink_data->aqbuttons[i].led->state == FLASH) {
aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
rtn = GET_RTN_OK;
logMessage(LOG_INFO, "WEB: turn Off '%s' changed state to '%s'\n", command, value);
} else {
@ -763,7 +765,8 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
logMessage(LOG_INFO, "WEB: '%s' is already off '%s', current state %d\n", command, value, _aqualink_data->aqbuttons[i].led->state);
}
} else { // Blind switch
aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
rtn = GET_RTN_OK;
logMessage(LOG_INFO, "WEB: '%s' blindly changed state\n", command, value);
}
@ -818,7 +821,8 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
logMessage (LOG_WARNING, "WS: Send raw command to controller %s\n",request.first.value);
unsigned int n;
sscanf(request.first.value, "0x%2x", &n);
aq_programmer(AQ_SEND_CMD, (char *)&n, NULL);
//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);
//ws_send(nc, message);
@ -845,7 +849,8 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
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) {
aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
} else {
char msg[PTHREAD_ARG];
sprintf(msg, "%-5d%-5d",i, (_aqualink_data->aqbuttons[i].led->state!=OFF)?OFF:ON);
@ -884,7 +889,7 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
}
void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg) {
int i;
unsigned int i;
//logMessage(LOG_DEBUG, "MQTT: topic %.*s %.2f\n",msg->topic.len, msg->topic.p, atof(msg->payload.p));
// If message doesn't end in set we don't care about it.
if (strncmp(&msg->topic.p[msg->topic.len -4], "/set", 4) != 0) {
@ -979,7 +984,8 @@ void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg)
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) {
aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
} else {
char msg[PTHREAD_ARG];
sprintf(msg, "%-5d%-5d",i, (value==0?OFF:ON) );
@ -1023,7 +1029,8 @@ void action_domoticz_mqtt_message(struct mg_connection *nc, struct mg_mqtt_messa
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) {
aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
} else {
char msg[PTHREAD_ARG];
sprintf(msg, "%-5d%-5d",i, (nvalue == DZ_OFF?OFF:ON) );

34
pda.c
View File

@ -130,6 +130,16 @@ void pass_pda_equiptment_status_item(char *msg)
// FILTER PUMP
// CLEANER
//
// Equipment Status
//
// Intelliflo VS 1
// RPM: 1700
// Watts: 367
//
//
//
//
//
// Check message for status of device
// Loop through all buttons and match the PDA text.
@ -151,6 +161,16 @@ void pass_pda_equiptment_status_item(char *msg)
_aqualink_data->swg_ppm = atoi(index + strlen(MSG_SWG_PPM));
logMessage(LOG_DEBUG, "SALT = %d\n", _aqualink_data->swg_ppm);
}
else if ((index = strcasestr(msg, MSG_PMP_RPM)) != NULL)
{ // Default to pump 0, should check for correct pump
_aqualink_data->pumps[0].rpm = atoi(index + strlen(MSG_PMP_RPM));
logMessage(LOG_DEBUG, "RPM = %d\n", _aqualink_data->pumps[0].rpm);
}
else if ((index = strcasestr(msg, MSG_PMP_WAT)) != NULL)
{ // Default to pump 0, should check for correct pump
_aqualink_data->pumps[0].watts = atoi(index + strlen(MSG_PMP_WAT));
logMessage(LOG_DEBUG, "Watts = %d\n", _aqualink_data->pumps[0].watts);
}
else
{
char labelBuff[AQ_MSGLEN + 1];
@ -313,11 +333,11 @@ void process_pda_packet_msg_long_set_temp(const char *msg)
void process_pda_packet_msg_long_spa_heat(const char *msg)
{
if (strncmp(msg, " ENABLED ", 16) == 0)
if (strncasecmp(msg, " ENABLED ", 16) == 0)
{
_aqualink_data->aqbuttons[SPA_HEAT_INDEX].led->state = ENABLE;
}
else if (strncmp(msg, " SET TO", 8) == 0)
else if (strncasecmp(msg, " SET TO", 8) == 0)
{
_aqualink_data->spa_htr_set_point = atoi(msg + 8);
logMessage(LOG_DEBUG, "spa_htr_set_point = %d\n", _aqualink_data->spa_htr_set_point);
@ -326,11 +346,11 @@ void process_pda_packet_msg_long_spa_heat(const char *msg)
void process_pda_packet_msg_long_pool_heat(const char *msg)
{
if (strncmp(msg, " ENABLED ", 16) == 0)
if (strncasecmp(msg, " ENABLED ", 16) == 0)
{
_aqualink_data->aqbuttons[POOL_HEAT_INDEX].led->state = ENABLE;
}
else if (strncmp(msg, " SET TO", 8) == 0)
else if (strncasecmp(msg, " SET TO", 8) == 0)
{
_aqualink_data->pool_htr_set_point = atoi(msg + 8);
logMessage(LOG_DEBUG, "pool_htr_set_point = %d\n", _aqualink_data->pool_htr_set_point);
@ -339,7 +359,7 @@ void process_pda_packet_msg_long_pool_heat(const char *msg)
void process_pda_packet_msg_long_freeze_protect(const char *msg)
{
if (strncmp(msg, "TEMP ", 10) == 0)
if (strncasecmp(msg, "TEMP ", 10) == 0)
{
_aqualink_data->frz_protect_set_point = atoi(msg + 10);
logMessage(LOG_DEBUG, "frz_protect_set_point = %d\n", _aqualink_data->frz_protect_set_point);
@ -356,13 +376,13 @@ void process_pda_packet_msg_long_SWG(const char *msg)
// If spa is on, read SWG for spa, if not set SWG for pool
if (_aqualink_data->aqbuttons[SPA_INDEX].led->state != OFF) {
if (strncmp(msg, "SET SPA TO:", 11) == 0)
if (strncasecmp(msg, "SET SPA TO:", 11) == 0)
{
_aqualink_data->swg_percent = atoi(msg + 13);
logMessage(LOG_DEBUG, "SPA swg_percent = %d\n", _aqualink_data->swg_percent);
}
} else {
if (strncmp(msg, "SET POOL TO:", 12) == 0)
if (strncasecmp(msg, "SET POOL TO:", 12) == 0)
{
_aqualink_data->swg_percent = atoi(msg + 13);
logMessage(LOG_DEBUG, "POOL swg_percent = %d\n", _aqualink_data->swg_percent);

View File

@ -55,7 +55,7 @@ bool loopover_devices(struct aqualinkdata *aq_data) {
// Should look for message "ALL OFF", that's end of device list.
for (i=0; i < 18 && pda_find_m_index("ALL OFF") == -1 ; i++) {
send_cmd(KEY_PDA_DOWN, aq_data);
send_cmd(KEY_PDA_DOWN);
//while (get_aq_cmd_length() > 0) { delay(200); }
//waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,3);
waitForMessage(aq_data, NULL, 1);
@ -74,10 +74,10 @@ bool find_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, int charli
logMessage(LOG_DEBUG, "PDA Device programmer menu text '%s'\n",menuText);
if (index < 0) { // No menu, is there a page down. "PDA Line 9 = ^^ MORE __"
if (strncmp(pda_m_line(9)," ^^ MORE", 10) == 0) {
if (strncasecmp(pda_m_line(9)," ^^ MORE", 10) == 0) {
int j;
for(j=0; j < 20; j++) {
send_cmd(KEY_PDA_DOWN, aq_data);
send_cmd(KEY_PDA_DOWN);
//delay(500);
//wait_for_empty_cmd_buffer();
waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,2);
@ -104,12 +104,12 @@ bool find_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, int charli
if (i < index) {
for (i=pda_m_hlightindex(); i < index; i++) {
//logMessage(LOG_DEBUG, "******************PDA queue down index %d\n",i);
send_cmd(KEY_PDA_DOWN, aq_data);
send_cmd(KEY_PDA_DOWN);
}
} else if (i > index) {
for (i=pda_m_hlightindex(); i > index; i--) {
//logMessage(LOG_DEBUG, "******************PDA queue down index %d\n",i);
send_cmd(KEY_PDA_UP, aq_data);
send_cmd(KEY_PDA_UP);
}
}
@ -119,7 +119,7 @@ bool find_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, int charli
bool select_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, bool waitForNextMenu) {
if ( find_pda_menu_item(aq_data, menuText, 0) ) {
send_cmd(KEY_PDA_SELECT, aq_data);
send_cmd(KEY_PDA_SELECT);
logMessage(LOG_DEBUG, "PDA Device programmer selected menu item '%s'\n",menuText);
if (waitForNextMenu)
@ -146,7 +146,7 @@ bool goto_pda_menu(struct aqualinkdata *aq_data, pda_menu_type menu) {
while ( pda_m_type() != menu && pda_m_type() != PM_HOME ) {
if (pda_m_type() != PM_BUILDING_HOME) {
send_cmd(KEY_PDA_BACK, aq_data);
send_cmd(KEY_PDA_BACK);
//logMessage(LOG_DEBUG, "******************PDA Device programmer selected back button\n",menu);
waitForPDAnextMenu(aq_data);
} else {
@ -235,10 +235,10 @@ void *set_aqualink_PDA_device_on_off( void *ptr )
waitForSingleThreadOrTerminate(threadCtrl, AQ_PDA_DEVICE_STATUS);
char *buf = (char*)threadCtrl->thread_args;
int device = atoi(&buf[0]);
int state = atoi(&buf[5]);
unsigned int device = atoi(&buf[0]);
unsigned int state = atoi(&buf[5]);
if (device < 0 || device > TOTAL_BUTTONS) {
if (device > TOTAL_BUTTONS) {
logMessage(LOG_ERR, "PDA Device On/Off :- bad device number '%d'\n",device);
cleanAndTerminateThread(threadCtrl);
return ptr;
@ -258,7 +258,7 @@ void *set_aqualink_PDA_device_on_off( void *ptr )
if (aq_data->aqbuttons[device].led->state != state) {
//printf("*** Select State ***\n");
logMessage(LOG_INFO, "PDA Device On/Off, found device '%s', changing state\n",aq_data->aqbuttons[device].pda_label,state);
send_cmd(KEY_PDA_SELECT, aq_data);
send_cmd(KEY_PDA_SELECT);
while (get_aq_cmd_length() > 0) { delay(500); }
} else {
logMessage(LOG_INFO, "PDA Device On/Off, found device '%s', not changing state, is same\n",aq_data->aqbuttons[device].pda_label,state);
@ -471,31 +471,31 @@ bool set_PDA_numeric_field_value(struct aqualinkdata *aq_data, int val, int *cur
// Should probably change below to call find_pda_menu_item(), rather than doing it here
// If we lease this, need to limit on the number of loops
while ( strncmp(pda_m_hlight(), select_label, 8) != 0 ) {
send_cmd(KEY_PDA_DOWN, aq_data);
while ( strncasecmp(pda_m_hlight(), select_label, 8) != 0 ) {
send_cmd(KEY_PDA_DOWN);
delay(500); // Last message probably was CMD_PDA_HIGHLIGHT, so wait before checking.
waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,2);
}
send_cmd(KEY_PDA_SELECT, aq_data);
send_cmd(KEY_PDA_SELECT);
if (val < *cur_val) {
logMessage(LOG_DEBUG, "PDA %s value : lower from %d to %d\n", select_label, *cur_val, val);
for (i = *cur_val; i > val; i=i-step) {
send_cmd(KEY_PDA_DOWN, aq_data);
send_cmd(KEY_PDA_DOWN);
}
} else if (val > *cur_val) {
logMessage(LOG_DEBUG, "PDA %s value : raise from %d to %d\n", select_label, *cur_val, val);
for (i = *cur_val; i < val; i=i+step) {
send_cmd(KEY_PDA_UP, aq_data);
send_cmd(KEY_PDA_UP);
}
} else {
logMessage(LOG_INFO, "PDA %s value : already at %d\n", select_label, val);
send_cmd(KEY_PDA_BACK, aq_data);
send_cmd(KEY_PDA_BACK);
return true;
}
send_cmd(KEY_PDA_SELECT, aq_data);
send_cmd(KEY_PDA_SELECT);
logMessage(LOG_DEBUG, "PDA %s value : set to %d\n", select_label, *cur_val);
return true;
@ -529,7 +529,7 @@ bool set_PDA_aqualink_heater_setpoint(struct aqualinkdata *aq_data, int val, boo
if (val == *cur_val) {
logMessage(LOG_INFO, "PDA %s setpoint : temp already %d\n", label, val);
send_cmd(KEY_PDA_BACK, aq_data);
send_cmd(KEY_PDA_BACK);
return true;
}
@ -630,6 +630,17 @@ PDA Line 7 =
PDA Line 8 =
PDA Line 9 =
PDA Line 0 =
PDA Line 1 = AquaPalm
PDA Line 2 =
PDA Line 3 = Firmware Version
PDA Line 4 =
PDA Line 5 = REV T
PDA Line 6 =
PDA Line 7 =
PDA Line 8 =
PDA Line 9 =
***************** Think this is startup different rev *************
Line 0 =
Line 1 = PDA-PS4 Combo
@ -761,4 +772,26 @@ PDA Line 7 = CLEAN MODE OFF
PDA Line 8 = ALL OFF
PDA Line 9 =
PDA Line 0 = Equipment Status
PDA Line 1 =
PDA Line 2 = Intelliflo VS 1
PDA Line 3 = RPM: 1700
PDA Line 4 = Watts: 367
PDA Line 5 =
PDA Line 6 =
PDA Line 7 =
PDA Line 8 =
PDA Line 9 =
PDA Line 0 = Equipment Status
PDA Line 1 =
PDA Line 2 = AquaPure 20%
PDA Line 3 = Salt 4000 PPM
PDA Line 4 =
PDA Line 5 =
PDA Line 6 =
PDA Line 7 =
PDA Line 8 =
PDA Line 9 =
*/

View File

@ -13,11 +13,15 @@ char _menu[PDA_LINES][AQ_MSGLEN+1];
void print_menu()
{
int i;
for (i=0; i < PDA_LINES; i++)
printf("PDA Line %d = %s\n",i,_menu[i]);
for (i=0; i < PDA_LINES; i++) {
//printf("PDA Line %d = %s\n",i,_menu[i]);
logMessage(LOG_DEBUG, "PDA Menu Line %d = %s\n",i,_menu[i]);
}
if (_hlightindex > -1)
printf("PDA highlighted line = %d = %s\n",_hlightindex,_menu[_hlightindex]);
if (_hlightindex > -1) {
//printf("PDA highlighted line = %d = %s\n",_hlightindex,_menu[_hlightindex]);
logMessage(LOG_DEBUG, "PDA Menu highlighted line = %d = %s\n",_hlightindex,_menu[_hlightindex]);
}
}
int pda_m_hlightindex()
@ -63,44 +67,60 @@ int pda_find_m_index_case(char *text, int limit)
return -1;
}
/*
// Same as above but strip whitespace from menu item (NOT text parameter)
int pda_find_m_index_swcase(char *text, int limit)
{
int i;
char *mi;
for (i = 0; i < PDA_LINES; i++) {
//printf ("+++ Compare '%s' to '%s' index %d\n",text,pda_m_line(i),i);
mi = trimwhitespace(pda_m_line(i));
if (strncasecmp(mi, text, limit) == 0)
return i;
}
return -1;
}
*/
pda_menu_type pda_m_type()
{
if (strncmp(_menu[1],"AIR ", 5) == 0)
if (strncasecmp(_menu[1],"AIR ", 5) == 0)
return PM_HOME;
else if (strncmp(_menu[0],"EQUIPMENT STATUS", 16) == 0)
else if (strncasecmp(_menu[0],"EQUIPMENT STATUS", 16) == 0)
return PM_EQUIPTMENT_STATUS;
else if (strncmp(_menu[0]," EQUIPMENT ", 16) == 0)
else if (strncasecmp(_menu[0]," EQUIPMENT ", 16) == 0)
return PM_EQUIPTMENT_CONTROL;
else if (strncmp(_menu[0]," MAIN MENU ", 16) == 0)
else if (strncasecmp(_menu[0]," MAIN MENU ", 16) == 0)
return PM_MAIN;
//else if ((_menu[0] == '\0' && _hlightindex == -1) || strncmp(_menu[4], "POOL MODE", 9) == 0 )// IF we are building the main menu this may be valid
else if (strncmp(_menu[4], "POOL MODE", 9) == 0 ) {
else if (strncasecmp(_menu[4], "POOL MODE", 9) == 0 ) {
if (pda_m_hlightindex() == -1)
return PM_BUILDING_HOME;
else
return PM_HOME;
}
else if (strncmp(_menu[0]," SET TEMP ", 16) == 0)
else if (strncasecmp(_menu[0]," SET TEMP ", 16) == 0)
return PM_SET_TEMP;
else if (strncmp(_menu[0]," SET TIME ", 16) == 0)
else if (strncasecmp(_menu[0]," SET TIME ", 16) == 0)
return PM_SET_TIME;
else if (strncmp(_menu[0]," SET AquaPure ", 16) == 0)
else if (strncasecmp(_menu[0]," SET AquaPure ", 16) == 0)
return PM_AQUAPURE;
else if (strncmp(_menu[0]," SPA HEAT ", 16) == 0)
else if (strncasecmp(_menu[0]," SPA HEAT ", 16) == 0)
return PM_SPA_HEAT;
else if (strncmp(_menu[0]," POOL HEAT ", 16) == 0)
else if (strncasecmp(_menu[0]," POOL HEAT ", 16) == 0)
return PM_POOL_HEAT;
else if (strncmp(_menu[6],"Use ARROW KEYS ", 16) == 0 &&
strncmp(_menu[0]," FREEZE PROTECT ", 16) == 0)
else if (strncasecmp(_menu[6],"Use ARROW KEYS ", 16) == 0 &&
strncasecmp(_menu[0]," FREEZE PROTECT ", 16) == 0)
return PM_FREEZE_PROTECT;
else if (strncmp(_menu[1]," DEVICES ", 16) == 0 &&
strncmp(_menu[0]," FREEZE PROTECT ", 16) == 0)
else if (strncasecmp(_menu[1]," DEVICES ", 16) == 0 &&
strncasecmp(_menu[0]," FREEZE PROTECT ", 16) == 0)
return PM_FREEZE_PROTECT_DEVICES;
else if (strncmp(_menu[3],"Firmware Version", 16) == 0 ||
strncmp(_menu[1]," AquaPalm", 12) == 0 ||
strncmp(_menu[1]," PDA-PS4 Combo", 14) == 0)
else if (strncasecmp(_menu[3],"Firmware Version", 16) == 0 ||
strncasecmp(_menu[1]," AquaPalm", 12) == 0 ||
strncasecmp(_menu[1]," PDA-PS4 Combo", 14) == 0)
return PM_FW_VERSION;
return PM_UNKNOWN;

View File

@ -73,5 +73,6 @@ char *pda_m_line(int index);
pda_menu_type pda_m_type();
int pda_find_m_index(char *text);
int pda_find_m_index_case(char *text, int limit);
//int pda_find_m_index_swcase(char *text, int limit);
#endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -7,6 +7,9 @@
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "aq_serial.h"
#include "utils.h"
@ -33,10 +36,13 @@ unsigned char _goodPDAID[] = {0x60, 0x61, 0x62, 0x63};
unsigned char _filter[10];
int _filters=0;
bool _rawlog=false;
bool _playback_file = false;
void intHandler(int dummy) {
_keepRunning = false;
logMessage(LOG_NOTICE, "Stopping!");
if (_playback_file) // If we are reading file, loop is irevelent
exit(0);
}
void advance_cursor() {
@ -145,6 +151,7 @@ int main(int argc, char *argv[]) {
int received_packets = 0;
int logPackets = PACKET_MAX;
int logLevel = LOG_NOTICE;
//bool playback_file = false;
//int logLevel;
//char buffer[256];
@ -178,12 +185,23 @@ int main(int argc, char *argv[]) {
} else if (strcmp(argv[i], "-r") == 0) {
_rawlog = true;
logLevel = LOG_DEBUG;
} else if (strcmp(argv[i], "-f") == 0) {
_playback_file = true;
}
}
setLoggingPrms(logLevel, false, false);
rs_fd = init_serial_port(argv[1]);
if (_playback_file) {
rs_fd = open(argv[1], O_RDONLY | O_NOCTTY | O_NONBLOCK | O_NDELAY);
if (rs_fd < 0) {
logMessage(LOG_ERR, "Unable to open file: %s\n", argv[1]);
displayLastSystemError(argv[1]);
return -1;
}
} else {
rs_fd = init_serial_port(argv[1]);
}
signal(SIGINT, intHandler);
signal(SIGTERM, intHandler);

43
utils.c
View File

@ -152,15 +152,6 @@ void timestamp(char* time_string)
strftime(time_string, TIMESTAMP_LENGTH, "%b-%d-%y %H:%M:%S %p ", tmptr);
}
void trimwhitespace(char *str)
{
char *end;
end = str + strlen(str) - 1;
while(end > str && isspace(*end)) end--;
*(end+1) = 0;
}
//Move existing pointer
char *cleanwhitespace(char *str)
{
@ -185,6 +176,7 @@ char *cleanwhitespace(char *str)
// Return new pointer
char *stripwhitespace(char *str)
{
// Should probably just call Trim and Chop functions.
char *end;
char *start = str;
@ -204,6 +196,33 @@ char *stripwhitespace(char *str)
return start;
}
// Trim whispace (return new pointer) leave trailing whitespace
char *trimwhitespace(char *str)
{
char *start = str;
// Trim leading space
while(isspace(*start)) start++;
if(*start == 0) // All spaces?
return start;
return start;
}
char *chopwhitespace(char *str)
{
char *end;
end = str + strlen(str) - 1;
while(end > str && isspace(*end)) end--;
// Write new null terminator
*(end+1) = 0;
return str;
}
/*
char *cleanquotes(char *str)
@ -345,8 +364,8 @@ void daemonise (char *pidFile, void (*main_function) (void))
int rc = flock (pid_file, LOCK_EX | LOCK_NB);
if (rc)
{
if (EWOULDBLOCK == errno)
; // another instance is running
//if (EWOULDBLOCK == errno)
//; // another instance is running
//fputs ("\nAnother instance is already running\n", stderr);
logMessage(LOG_ERR,"\nAnother instance is already running\n");
exit (EXIT_FAILURE);
@ -467,7 +486,7 @@ char* stristr(const char* haystack, const char* needle) {
}
int ascii(char *destination, char *source) {
int i;
unsigned int i;
for(i = 0; i < strlen(source); i++) {
if ( source[i] >= 0 && source[i] < 128 )
destination[i] = source[i];

View File

@ -39,7 +39,8 @@ int text2elevel(char* level);
char *elevel2text(int level);
char *cleanwhitespace(char *str);
//char *cleanquotes(char *str);
void trimwhitespace(char *str);
char *chopwhitespace(char *str);
char *trimwhitespace(char *str);
char *stripwhitespace(char *str);
int cleanint(char*str);
bool text2bool(char *str);

View File

@ -1,4 +1,4 @@
#define AQUALINKD_NAME "Aqualink Daemon"
#define AQUALINKD_VERSION "1.3.1"
#define AQUALINKD_VERSION "1.3.2"

View File

@ -761,7 +761,7 @@
ext = '%';
}
} catch (e) {
console.log('ERROR id=' + id + ' Line 764 | element = '+document.getElementById(id));
//console.log('ERROR id=' + id + ' Line 764 | element = '+document.getElementById(id));
}
}
//document.getElementById(id + '_tile_icon_value').textContent = value;
@ -974,7 +974,7 @@
slider.step = 5;
} else if (type == 'setpoint_freeze') {
if (_temperature_units != 'c') { // Change to DegF
slider.min = 36;
slider.min = 34;
slider.max = 42;
slider.step = 1;
} else { // Change to DegF
@ -1108,7 +1108,7 @@
}
// NSF Really quick hack to show RPM on filter pump. Need to come back and do this correctly.
if (typeof data.extra["Pump_1"].RPM !== 'undefined') {
if ((typeof data.extra["Pump_1"] !== 'undefined') && (typeof data.extra["Pump_1"].RPM !== 'undefined')) {
console.log(data.extra["Pump_1"].RPM);
if (document.getElementById('Filter_Pump').getAttribute('status') == 'on') {
document.getElementById('Filter_Pump_status').innerHTML = 'RPM:'+data.extra["Pump_1"].RPM;