mirror of https://github.com/sfeakes/AqualinkD.git
Version 1.3.0
parent
d0289b79c3
commit
d884f2e37c
2
Makefile
2
Makefile
|
@ -29,7 +29,7 @@ INCLUDES = -I/nas/data/Development/Raspberry/aqualink/aqualinkd
|
|||
# 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_menu.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
|
||||
PDA_SRC = pda_test.c pda_menu.c aq_serial.c utils.c
|
||||
|
|
19
README.md
19
README.md
|
@ -59,15 +59,26 @@ Designed to mimic AqualinkRS6 All Button keypad, and just like the keypad you ca
|
|||
<img src="extras/HomeAssistant.png?raw=true" width="600"></img>
|
||||
|
||||
## All Web interfaces.
|
||||
* http://aqualink.ip/ <- (New UI)
|
||||
* http://aqualink.ip/old <- (If you prefer the old UI, this is not maintained)
|
||||
* http://aqualink.ip/simple.html <- (Anothr opion if you don't like the above)
|
||||
* 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)
|
||||
#<a name="release"></a>
|
||||
## Update in Release 1.3.0
|
||||
* Large update for PDA only control panels (Majority of this is ballle98 work)
|
||||
* Can distinguish between AquaPalm and PDA supported control panels.
|
||||
* PDA Freeze & Heater setpoints now supported.
|
||||
* Added PDA Sleep mode so AqualinkD can work inconjunction with a real Jandy PDA.
|
||||
* Speeded up many PDA functions.
|
||||
* Fixed many PDA bugs.
|
||||
* Non PDA specific updates :-
|
||||
* Can get button labels from control panel (not in PDA mode)
|
||||
* RS485 Logging so users can submit information on Variable Speed Pumps & other devices for future support.
|
||||
* Force SWG status on startup, rather than wait for pump to turn on.
|
||||
* General bug fixes and improved code in many areas.
|
||||
## Update in Release 1.2.6f
|
||||
* Solution to overcome bug in Mosquitto 1.6.
|
||||
* Fixed Salt Water Generator when % was set to 0.
|
||||
* Added support for different SWG % for pool & spa.
|
||||
* Added support for different SWG % for pool & spa. (SWG reports and sets the mode that's currently active)
|
||||
* Increased speed of SWG messages.
|
||||
* Few other bug fixes (Thanks to ballle98)
|
||||
## Update in Release 1.2.6e (This is a quick update, please only use if you need one of the items below.)
|
||||
|
|
325
aq_programmer.c
325
aq_programmer.c
|
@ -26,12 +26,14 @@
|
|||
#include "utils.h"
|
||||
#include "aq_programmer.h"
|
||||
#include "aq_serial.h"
|
||||
#include "pda.h"
|
||||
#include "pda_menu.h"
|
||||
#include "init_buttons.h"
|
||||
#include "pda_aq_programmer.h"
|
||||
|
||||
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 send_cmd(unsigned char cmd, struct aqualinkdata *aq_data);
|
||||
void cancel_menu(struct aqualinkdata *aq_data);
|
||||
|
||||
|
||||
|
@ -43,17 +45,18 @@ void *get_aqualink_pool_spa_heater_temps( void *ptr );
|
|||
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 *set_aqualink_light_colormode( void *ptr );
|
||||
void *set_aqualink_PDA_init( void *ptr );
|
||||
void *set_aqualink_SWG( void *ptr );
|
||||
|
||||
void *get_aqualink_PDA_device_status( void *ptr );
|
||||
void *set_aqualink_PDA_device_on_off( void *ptr );
|
||||
//void *get_aqualink_PDA_device_status( void *ptr );
|
||||
//void *set_aqualink_PDA_device_on_off( void *ptr );
|
||||
|
||||
bool waitForButtonState(struct aqualinkdata *aq_data, aqkey* button, aqledstate state, int numMessageReceived);
|
||||
|
||||
bool waitForMessage(struct aqualinkdata *aq_data, char* message, int numMessageReceived);
|
||||
//bool waitForMessage(struct aqualinkdata *aq_data, char* message, int numMessageReceived);
|
||||
bool waitForEitherMessage(struct aqualinkdata *aq_data, char* message1, char* message2, int numMessageReceived);
|
||||
|
||||
bool push_aq_cmd(unsigned char cmd);
|
||||
|
@ -204,12 +207,18 @@ void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data)
|
|||
struct programmingThreadCtrl *programmingthread = malloc(sizeof(struct programmingThreadCtrl));
|
||||
|
||||
if (pda_mode() == true) {
|
||||
pda_reset_sleep();
|
||||
if (type != AQ_PDA_INIT &&
|
||||
type != AQ_PDA_WAKE_INIT &&
|
||||
type != AQ_PDA_DEVICE_STATUS &&
|
||||
type != AQ_PDA_DEVICE_ON_OFF) {
|
||||
type != AQ_SET_POOL_HEATER_TEMP &&
|
||||
type != AQ_SET_SPA_HEATER_TEMP &&
|
||||
type != AQ_SET_SWG_PERCENT &&
|
||||
type != AQ_PDA_DEVICE_ON_OFF &&
|
||||
type != AQ_GET_POOL_SPA_HEATER_TEMPS ) {
|
||||
logMessage(LOG_ERR, "Selected Programming mode '%d' not supported with PDA mode control panel\n",type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
programmingthread->aq_data = aq_data;
|
||||
|
@ -289,6 +298,12 @@ void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data)
|
|||
return;
|
||||
}
|
||||
break;
|
||||
case AQ_PDA_WAKE_INIT:
|
||||
if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_PDA_wakeinit, (void*)programmingthread) < 0) {
|
||||
logMessage (LOG_ERR, "could not create thread\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case AQ_SET_SWG_PERCENT:
|
||||
if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_SWG, (void*)programmingthread) < 0) {
|
||||
logMessage (LOG_ERR, "could not create thread\n");
|
||||
|
@ -306,6 +321,12 @@ void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data)
|
|||
logMessage (LOG_ERR, "could not create thread\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case AQ_GET_AUX_LABELS:
|
||||
if( pthread_create( &programmingthread->thread_id , NULL , get_aqualink_aux_labels, (void*)programmingthread) < 0) {
|
||||
logMessage (LOG_ERR, "could not create thread\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logMessage (LOG_ERR, "Don't understand thread type\n");
|
||||
|
@ -478,17 +499,13 @@ void *set_aqualink_SWG( void *ptr )
|
|||
|
||||
int val = atoi((char*)threadCtrl->thread_args);
|
||||
val = setpoint_check(SWG_SETPOINT, val, aq_data);
|
||||
// Just recheck it's in multiple of 5.
|
||||
/*
|
||||
if (0 != (val % 5) )
|
||||
val = ((val + 5) / 10) * 10;
|
||||
|
||||
if (val > SWG_PERCENT_MAX) {
|
||||
val = SWG_PERCENT_MAX;
|
||||
} else if ( val < SWG_PERCENT_MIN) {
|
||||
val = SWG_PERCENT_MIN;
|
||||
if (pda_mode() == true) {
|
||||
set_PDA_aqualink_SWG_setpoint(aq_data, val);
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
*/
|
||||
|
||||
logMessage(LOG_DEBUG, "programming SWG percent to %d\n", val);
|
||||
|
||||
if ( select_menu_item(aq_data, "SET AQUAPURE") != true ) {
|
||||
|
@ -541,258 +558,37 @@ void *set_aqualink_SWG( void *ptr )
|
|||
return ptr;
|
||||
}
|
||||
|
||||
bool select_pda_main_menu(struct aqualinkdata *aq_data)
|
||||
{
|
||||
int i=0;
|
||||
// Check to see if we are at the main menu
|
||||
if (pda_m_type() == PM_MAIN) {
|
||||
return true;
|
||||
}
|
||||
// First send back
|
||||
send_cmd(KEY_PDA_BACK, aq_data);
|
||||
while (_pgm_command != NUL) {
|
||||
delay(500);
|
||||
if (i++ > 6) return false;
|
||||
}
|
||||
//delay(1000);
|
||||
i=0;
|
||||
while (pda_m_type() != PM_MAIN) {
|
||||
delay(500);
|
||||
if (i++ > 6) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wait_pda_selected_item()
|
||||
{
|
||||
int i=0;
|
||||
|
||||
i=0;
|
||||
while (pda_m_hlightindex() == -1){
|
||||
if (i++ > 10)
|
||||
break;
|
||||
delay(100);
|
||||
}
|
||||
|
||||
if (pda_m_hlightindex() == -1)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool select_pda_main_menu_item(struct aqualinkdata *aq_data, pda_menu_type menu_item)
|
||||
{
|
||||
int i=0;
|
||||
char *menu;
|
||||
|
||||
if (! select_pda_main_menu(aq_data))
|
||||
return false;
|
||||
|
||||
logMessage(LOG_DEBUG, "PDA Device programmer at main menu\n");
|
||||
|
||||
if (menu_item == PM_MAIN)
|
||||
return true;
|
||||
else if (menu_item == PM_SETTINGS)
|
||||
menu = "MENU";
|
||||
else if (menu_item == PM_EQUIPTMENT_CONTROL)
|
||||
menu = "EQUIPMENT ON/OFF";
|
||||
else
|
||||
return false;
|
||||
|
||||
if (!wait_pda_selected_item()){
|
||||
logMessage(LOG_ERR, "PDA Device programmer didn't find a selected item\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
while ( strncmp(pda_m_hlight(), menu, strlen(menu)) != 0 ) {
|
||||
if (_pgm_command == NUL) {
|
||||
send_cmd(KEY_PDA_DOWN, aq_data);
|
||||
logMessage(LOG_DEBUG, "PDA Device programmer selected sub menu\n");
|
||||
waitForMessage(aq_data, NULL, 1);
|
||||
}
|
||||
if (i++ > (PDA_LINES * 2))
|
||||
return false;
|
||||
delay(500);
|
||||
}
|
||||
|
||||
send_cmd(KEY_PDA_SELECT, aq_data);
|
||||
while (_pgm_command != NUL) { delay(500); }
|
||||
|
||||
return true;
|
||||
/*
|
||||
send_cmd(KEY_PDA_DOWN, aq_data);
|
||||
while (_pgm_command != NUL) { delay(500); }
|
||||
*/
|
||||
}
|
||||
|
||||
void *set_aqualink_PDA_device_on_off( void *ptr )
|
||||
void *get_aqualink_aux_labels( void *ptr )
|
||||
{
|
||||
struct programmingThreadCtrl *threadCtrl;
|
||||
threadCtrl = (struct programmingThreadCtrl *) ptr;
|
||||
struct aqualinkdata *aq_data = threadCtrl->aq_data;
|
||||
int i=0;
|
||||
int found;
|
||||
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_PDA_DEVICE_STATUS);
|
||||
|
||||
char *buf = (char*)threadCtrl->thread_args;
|
||||
int device = atoi(&buf[0]);
|
||||
int state = atoi(&buf[5]);
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_GET_AUX_LABELS);
|
||||
|
||||
if (device < 0 || device > TOTAL_BUTTONS) {
|
||||
logMessage(LOG_ERR, "PDA Device On/Off :- bad device number '%d'\n",device);
|
||||
if ( select_menu_item(aq_data, "REVIEW") != true ) {
|
||||
logMessage(LOG_WARNING, "Could not select REVIEW menu\n");
|
||||
cancel_menu(aq_data);
|
||||
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);
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
logMessage(LOG_INFO, "PDA Device On/Off, device '%s', state %d\n",aq_data->aqbuttons[device].pda_label,state);
|
||||
|
||||
//printf("DEVICE LABEL = %s\n",aq_data->aqbuttons[device].pda_label);
|
||||
|
||||
if (! select_pda_main_menu_item(aq_data, PM_EQUIPTMENT_CONTROL)) {
|
||||
logMessage(LOG_ERR, "PDA Device On/Off :- can't find main menu\n");
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
/*
|
||||
i=0;
|
||||
while (pda_m_hlightindex() == -1){
|
||||
if (i++ > 10)
|
||||
break;
|
||||
delay(100);
|
||||
}
|
||||
*/
|
||||
delay(500);
|
||||
printf("Wait for select\n");
|
||||
if (!wait_pda_selected_item()){
|
||||
logMessage(LOG_ERR, "PDA Device programmer didn't find a selected item\n");
|
||||
return false;
|
||||
}
|
||||
printf("End wait select\n");
|
||||
i=0;
|
||||
char labelBuff[AQ_MSGLEN];
|
||||
strncpy(labelBuff, pda_m_hlight(), AQ_MSGLEN-4);
|
||||
labelBuff[AQ_MSGLEN-4] = 0;
|
||||
|
||||
while ( (found = strcasecmp(stripwhitespace(labelBuff), aq_data->aqbuttons[device].pda_label)) != 0 ) {
|
||||
if (_pgm_command == NUL) {
|
||||
send_cmd(KEY_PDA_DOWN, aq_data);
|
||||
//printf("*** Send Down for %s ***\n",pda_m_hlight());
|
||||
waitForMessage(aq_data, NULL, 1);
|
||||
}
|
||||
if (i++ > (PDA_LINES * 2)) {
|
||||
break;
|
||||
}
|
||||
delay(500);
|
||||
strncpy(labelBuff, pda_m_hlight(), AQ_MSGLEN-4);
|
||||
labelBuff[AQ_MSGLEN-4] = 0;
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
//printf("*** FOUND ITEM %s ***\n",pda_m_hlight());
|
||||
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);
|
||||
while (_pgm_command != NUL) { 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);
|
||||
}
|
||||
} else {
|
||||
//printf("*** NOT FOUND ITEM ***\n");
|
||||
logMessage(LOG_ERR, "PDA Device On/Off, device '%s' not found\n",aq_data->aqbuttons[device].pda_label);
|
||||
}
|
||||
|
||||
select_pda_main_menu_item(aq_data, PM_MAIN);
|
||||
//while (_pgm_command != NUL) { delay(500); }
|
||||
waitForMessage(aq_data, NULL, 5); // Receive 5 messages
|
||||
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
|
||||
// just stop compiler error, ptr is not valid as it's just been freed
|
||||
return ptr;
|
||||
}
|
||||
void *get_aqualink_PDA_device_status( void *ptr )
|
||||
{
|
||||
struct programmingThreadCtrl *threadCtrl;
|
||||
threadCtrl = (struct programmingThreadCtrl *) ptr;
|
||||
struct aqualinkdata *aq_data = threadCtrl->aq_data;
|
||||
int i;
|
||||
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_PDA_DEVICE_STATUS);
|
||||
|
||||
//int val = atoi((char*)threadCtrl->thread_args);
|
||||
|
||||
logMessage(LOG_DEBUG, "PDA Device Status\n");
|
||||
|
||||
if (! select_pda_main_menu_item(aq_data, PM_EQUIPTMENT_CONTROL)) {
|
||||
logMessage(LOG_ERR, "PDA Device Status :- can't find main menu\n");
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
//select_pda_main_menu_item(aq_data, "EQUIPMENT ON/OFF");
|
||||
|
||||
// Just loop over all the dvices 18 times should do it.
|
||||
for (i=0; i < 18; i++) {
|
||||
send_cmd(KEY_PDA_DOWN, aq_data);
|
||||
while (_pgm_command != NUL) { delay(100); }
|
||||
}
|
||||
|
||||
//printf("*** GET MAIN MENU ***\n");
|
||||
|
||||
select_pda_main_menu_item(aq_data, PM_MAIN);
|
||||
|
||||
//printf("*** FINISHED ***\n");
|
||||
/*
|
||||
send_cmd(KEY_PDA_BACK, aq_data);
|
||||
while (_pgm_command != NUL) { delay(500); }
|
||||
*/
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
|
||||
// just stop compiler error, ptr is not valid as it's just been freed
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *set_aqualink_PDA_init( void *ptr )
|
||||
{
|
||||
struct programmingThreadCtrl *threadCtrl;
|
||||
threadCtrl = (struct programmingThreadCtrl *) ptr;
|
||||
struct aqualinkdata *aq_data = threadCtrl->aq_data;
|
||||
int i=0;
|
||||
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_PDA_INIT);
|
||||
|
||||
//int val = atoi((char*)threadCtrl->thread_args);
|
||||
|
||||
//logMessage(LOG_DEBUG, "PDA Init\n", val);
|
||||
|
||||
logMessage(LOG_DEBUG, "PDA Init\n");
|
||||
|
||||
if (! select_pda_main_menu_item(aq_data, PM_EQUIPTMENT_CONTROL)) {
|
||||
logMessage(LOG_ERR, "PDA Init :- can't find main menu\n");
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
//select_pda_main_menu_item(aq_data, "EQUIPMENT ON/OFF");
|
||||
|
||||
// Just loop over all the dvices 20 times should do it.
|
||||
for (i=0; i < 18; i++) {
|
||||
send_cmd(KEY_PDA_DOWN, aq_data);
|
||||
while (_pgm_command != NUL) { delay(500); }
|
||||
}
|
||||
|
||||
select_pda_main_menu_item(aq_data, PM_MAIN);
|
||||
|
||||
printf("*** PDA Init :- add code to find setpoints ***\n");
|
||||
|
||||
// Run through menu and find freeze setpoints / heater setpoints etc.
|
||||
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
|
||||
// just stop compiler error, ptr is not valid as it's just been freed
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
void *set_aqualink_light_colormode( void *ptr )
|
||||
{
|
||||
|
@ -894,6 +690,13 @@ void *set_aqualink_pool_heater_temps( void *ptr )
|
|||
}
|
||||
*/
|
||||
val = setpoint_check(POOL_HTR_SETOINT, val, aq_data);
|
||||
|
||||
if (pda_mode() == true) {
|
||||
set_PDA_aqualink_heater_setpoint(aq_data, val, true);
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// NSF IF in TEMP1 / TEMP2 mode, we need C range of 1 to 40 is 2 to 40 for TEMP1, 1 to 39 TEMP2
|
||||
if (aq_data->single_device == true ){
|
||||
name = "TEMP1";
|
||||
|
@ -960,6 +763,13 @@ void *set_aqualink_spa_heater_temps( void *ptr )
|
|||
val = MEATER_MIN;
|
||||
}*/
|
||||
val = setpoint_check(SPA_HTR_SETOINT, val, aq_data);
|
||||
|
||||
if (pda_mode() == true) {
|
||||
set_PDA_aqualink_heater_setpoint(aq_data, val, true);
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// NSF IF in TEMP1 / TEMP2 mode, we need C range of 1 to 40 is 2 to 40 for TEMP1, 1 to 39 TEMP2
|
||||
|
||||
if (aq_data->single_device == true ){
|
||||
|
@ -1148,6 +958,14 @@ void *get_aqualink_pool_spa_heater_temps( void *ptr )
|
|||
waitForSingleThreadOrTerminate(threadCtrl, AQ_GET_POOL_SPA_HEATER_TEMPS);
|
||||
logMessage(LOG_NOTICE, "Getting pool & spa heat setpoints from aqualink\n");
|
||||
|
||||
if (pda_mode() == true) {
|
||||
if (!get_PDA_aqualink_pool_spa_heater_temps(aq_data)) {
|
||||
logMessage(LOG_ERR, "Error Getting PDA pool & spa heat protection setpoints\n");
|
||||
}
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
if ( select_menu_item(aq_data, "REVIEW") != true ) {
|
||||
logMessage(LOG_WARNING, "Could not select REVIEW menu\n");
|
||||
cancel_menu(aq_data);
|
||||
|
@ -1182,6 +1000,15 @@ void *get_freeze_protect_temp( void *ptr )
|
|||
waitForSingleThreadOrTerminate(threadCtrl, AQ_GET_FREEZE_PROTECT_TEMP);
|
||||
logMessage(LOG_NOTICE, "Getting freeze protection setpoints\n");
|
||||
|
||||
|
||||
if (pda_mode() == true) {
|
||||
if (! get_PDA_freeze_protect_temp(aq_data)) {
|
||||
logMessage(LOG_ERR, "Error Getting PDA freeze protection setpoints\n");
|
||||
}
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
if ( select_menu_item(aq_data, "REVIEW") != true ) {
|
||||
logMessage(LOG_WARNING, "Could not select REVIEW menu\n");
|
||||
cancel_menu(aq_data);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#define HEATER_MAX_F 104
|
||||
#define HEATER_MIN_F 36
|
||||
#define FREEZE_PT_MAX_F 42
|
||||
#define FREEZE_PT_MIN_F 36
|
||||
#define FREEZE_PT_MIN_F 34
|
||||
|
||||
#define HEATER_MAX_C 40
|
||||
#define HEATER_MIN_C 0
|
||||
|
@ -36,7 +36,9 @@ typedef enum {
|
|||
AQ_PDA_INIT,
|
||||
AQ_SET_SWG_PERCENT,
|
||||
AQ_PDA_DEVICE_STATUS,
|
||||
AQ_PDA_DEVICE_ON_OFF
|
||||
AQ_PDA_DEVICE_ON_OFF,
|
||||
AQ_GET_AUX_LABELS,
|
||||
AQ_PDA_WAKE_INIT
|
||||
} program_type;
|
||||
|
||||
struct programmingThreadCtrl {
|
||||
|
@ -64,4 +66,12 @@ unsigned char pop_aq_cmd(struct aqualinkdata *aq_data);
|
|||
int get_aq_cmd_length();
|
||||
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);
|
||||
bool push_aq_cmd(unsigned char cmd);
|
||||
void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, program_type type);
|
||||
void cleanAndTerminateThread(struct programmingThreadCtrl *threadCtrl);
|
||||
bool waitForMessage(struct aqualinkdata *aq_data, char* message, int numMessageReceived);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -125,6 +125,9 @@ const char* get_packet_type(unsigned char* packet , int length)
|
|||
case CMD_PDA_0x05:
|
||||
return "PDA Unknown";
|
||||
break;
|
||||
case CMD_PDA_0x1B:
|
||||
return "PDA Init (*guess*)";
|
||||
break;
|
||||
case CMD_PDA_HIGHLIGHT:
|
||||
return "PDA Hlight";
|
||||
break;
|
||||
|
|
|
@ -53,8 +53,8 @@
|
|||
#define KEY_PDA_DOWN 0x05
|
||||
#define KEY_PDA_BACK 0x02
|
||||
#define KEY_PDA_SELECT 0x04
|
||||
#define KEY_PDA_PGUP 0x01
|
||||
#define KEY_PDA_PGDN 0x03
|
||||
//#define KEY_PDA_PGUP 0x01 // Think these are hot key #1
|
||||
//#define KEY_PDA_PGDN 0x03 // Think these are hot key #2
|
||||
|
||||
/* KEY/BUTTON CODES */
|
||||
#define KEY_PUMP 0x02
|
||||
|
@ -178,6 +178,7 @@ SPILLOVER IS DISABLED WHILE SPA IS ON
|
|||
#define SWG_STATUS_CHECK_PCB 0x80 // check PCB 0x80
|
||||
|
||||
#define CMD_PDA_0x05 0x05
|
||||
#define CMD_PDA_0x1B 0x1b
|
||||
#define CMD_PDA_HIGHLIGHT 0x08
|
||||
#define CMD_PDA_CLEAR 0x09
|
||||
#define CMD_PDA_SHIFTLINES 0x0F
|
||||
|
|
|
@ -97,6 +97,7 @@ struct aqualinkdata
|
|||
bool simulate_panel;
|
||||
aqledstate service_mode_state;
|
||||
aqledstate frz_protect_state;
|
||||
unsigned char last_packet_type;
|
||||
//bool last_msg_was_status;
|
||||
//bool ar_swg_connected;
|
||||
};
|
||||
|
|
927
aqualinkd.c
927
aqualinkd.c
File diff suppressed because it is too large
Load Diff
18
config.c
18
config.c
|
@ -75,11 +75,15 @@ void init_parameters (struct aqconfig * parms)
|
|||
parms->deamonize = true;
|
||||
parms->log_file = '\0';
|
||||
parms->pda_mode = false;
|
||||
parms->pda_sleep_mode = false;
|
||||
parms->convert_mqtt_temp = true;
|
||||
parms->convert_dz_temp = true;
|
||||
parms->report_zero_pool_temp = false;
|
||||
parms->report_zero_spa_temp = false;
|
||||
parms->read_all_devices = true;
|
||||
parms->use_panel_aux_labels = false;
|
||||
parms->debug_RSProtocol_packets = false;
|
||||
parms->force_swg = false;
|
||||
|
||||
generate_mqtt_id(parms->mqtt_ID, MQTT_ID_LEN);
|
||||
}
|
||||
|
@ -377,6 +381,10 @@ bool setConfigValue(struct aqconfig *config_parameters, struct aqualinkdata *aqd
|
|||
config_parameters->pda_mode = text2bool(value);
|
||||
set_pda_mode(config_parameters->pda_mode);
|
||||
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);
|
||||
rtn=true;
|
||||
} else if (strncasecmp(param, "convert_mqtt_temp_to_c", 22) == 0) {
|
||||
config_parameters->convert_mqtt_temp = text2bool(value);
|
||||
rtn=true;
|
||||
|
@ -396,7 +404,17 @@ bool setConfigValue(struct aqconfig *config_parameters, struct aqualinkdata *aqd
|
|||
} else if (strncasecmp (param, "read_all_devices", 16) == 0) {
|
||||
config_parameters->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);
|
||||
rtn=true;
|
||||
} else if (strncasecmp (param, "force_SWG", 9) == 0) {
|
||||
config_parameters->force_swg = text2bool(value);
|
||||
rtn=true;
|
||||
} else if (strncasecmp (param, "debug_RSProtocol_packets", 24) == 0) {
|
||||
config_parameters->debug_RSProtocol_packets = text2bool(value);
|
||||
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);
|
||||
|
|
5
config.h
5
config.h
|
@ -50,12 +50,16 @@ struct aqconfig
|
|||
int light_programming_button;
|
||||
bool override_freeze_protect;
|
||||
bool pda_mode;
|
||||
bool pda_sleep_mode;
|
||||
bool convert_mqtt_temp;
|
||||
bool convert_dz_temp;
|
||||
//bool flash_mqtt_buttons;
|
||||
bool report_zero_spa_temp;
|
||||
bool report_zero_pool_temp;
|
||||
bool read_all_devices;
|
||||
bool use_panel_aux_labels;
|
||||
bool force_swg;
|
||||
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
|
||||
//char mqtt_pub_topic[250];
|
||||
|
@ -69,5 +73,6 @@ void init_parameters (struct aqconfig * parms);
|
|||
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);
|
||||
char *cleanalloc(char*str);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "json_messages.h"
|
||||
#include "domoticz.h"
|
||||
#include "aq_mqtt.h"
|
||||
#include "pda.h"
|
||||
|
||||
|
||||
static struct aqconfig *_aqualink_config;
|
||||
|
@ -761,7 +762,11 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
|
|||
void action_websocket_request(struct mg_connection *nc, struct websocket_message *wm) {
|
||||
char buffer[50];
|
||||
struct JSONwebrequest request;
|
||||
|
||||
|
||||
// Any websocket request means UI is active, so don't let AqualinkD go to sleep if in PDA mode
|
||||
if (pda_mode())
|
||||
pda_reset_sleep();
|
||||
|
||||
strncpy(buffer, (char *)wm->data, wm->size);
|
||||
buffer[wm->size] = '\0';
|
||||
// logMessage (LOG_DEBUG, "buffer '%s'\n", buffer);
|
||||
|
|
|
@ -0,0 +1,557 @@
|
|||
|
||||
#define _GNU_SOURCE 1 // for strcasestr & strptime
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "aqualink.h"
|
||||
#include "init_buttons.h"
|
||||
#include "pda_menu.h"
|
||||
#include "utils.h"
|
||||
|
||||
// static struct aqualinkdata _aqualink_data;
|
||||
static struct aqualinkdata *_aqualink_data;
|
||||
static unsigned char _last_packet_type;
|
||||
static unsigned long _pda_loop_cnt = 0;
|
||||
static bool _initWithRS = false;
|
||||
|
||||
// Each RS message is around 0.5 seconds apart, so 2 mins = 120 seconds = 240 polls
|
||||
#define PDA_LOOP_COUNT 240 // 2 mins in poll (sleep timer)
|
||||
|
||||
void init_pda(struct aqualinkdata *aqdata)
|
||||
{
|
||||
_aqualink_data = aqdata;
|
||||
set_pda_mode(true);
|
||||
//clock_gettime(CLOCK_REALTIME, &_aqualink_data->last_active_time);
|
||||
//aq_programmer(AQ_PDA_INIT, NULL, _aqualink_data); // NEED TO MOVE THIS. Can't run this here incase serial connection fails / needs to be cleaned up.
|
||||
}
|
||||
|
||||
|
||||
bool pda_shouldSleep() {
|
||||
//logMessage(LOG_DEBUG, "PDA loop count %d, will sleep at %d\n",_pda_loop_cnt,PDA_LOOP_COUNT);
|
||||
if (_pda_loop_cnt++ < PDA_LOOP_COUNT) {
|
||||
return false;
|
||||
} else if (_pda_loop_cnt > PDA_LOOP_COUNT*2) {
|
||||
_pda_loop_cnt = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void pda_wake() {
|
||||
|
||||
}
|
||||
|
||||
void pda_reset_sleep() {
|
||||
_pda_loop_cnt = 0;
|
||||
}
|
||||
|
||||
unsigned char get_last_pda_packet_type()
|
||||
{
|
||||
return _last_packet_type;
|
||||
}
|
||||
|
||||
void set_pda_led(struct aqualinkled *led, char state)
|
||||
{
|
||||
aqledstate old_state = led->state;
|
||||
if (state == 'N')
|
||||
{
|
||||
led->state = ON;
|
||||
}
|
||||
else if (state == 'A')
|
||||
{
|
||||
led->state = ENABLE;
|
||||
}
|
||||
else if (state == '*')
|
||||
{
|
||||
led->state = FLASH;
|
||||
}
|
||||
else
|
||||
{
|
||||
led->state = OFF;
|
||||
}
|
||||
if (old_state != led->state)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "set_pda_led from %d to %d\n", old_state, led->state);
|
||||
}
|
||||
}
|
||||
|
||||
void pass_pda_equiptment_status_item(char *msg)
|
||||
{
|
||||
static char *index;
|
||||
int i;
|
||||
|
||||
// EQUIPMENT STATUS
|
||||
//
|
||||
// AquaPure 100%
|
||||
// SALT 25500 PPM
|
||||
// FILTER PUMP
|
||||
// POOL HEAT
|
||||
// SPA HEAT ENA
|
||||
|
||||
// EQUIPMENT STATUS
|
||||
//
|
||||
// FREEZE PROTECT
|
||||
// AquaPure 100%
|
||||
// SALT 25500 PPM
|
||||
// CHECK AquaPure
|
||||
// GENERAL FAULT
|
||||
// FILTER PUMP
|
||||
// CLEANER
|
||||
//
|
||||
|
||||
// Check message for status of device
|
||||
// Loop through all buttons and match the PDA text.
|
||||
if ((index = strcasestr(msg, "CHECK AquaPure")) != NULL)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "CHECK AquaPure\n");
|
||||
}
|
||||
else if ((index = strcasestr(msg, "FREEZE PROTECT")) != NULL)
|
||||
{
|
||||
_aqualink_data->frz_protect_state = ON;
|
||||
}
|
||||
else if ((index = strcasestr(msg, MSG_SWG_PCT)) != NULL)
|
||||
{
|
||||
_aqualink_data->swg_percent = atoi(index + strlen(MSG_SWG_PCT));
|
||||
logMessage(LOG_DEBUG, "AquaPure = %d\n", _aqualink_data->swg_percent);
|
||||
}
|
||||
else if ((index = strcasestr(msg, MSG_SWG_PPM)) != NULL)
|
||||
{
|
||||
_aqualink_data->swg_ppm = atoi(index + strlen(MSG_SWG_PPM));
|
||||
logMessage(LOG_DEBUG, "SALT = %d\n", _aqualink_data->swg_ppm);
|
||||
}
|
||||
else
|
||||
{
|
||||
char labelBuff[AQ_MSGLEN + 1];
|
||||
strncpy(labelBuff, msg, AQ_MSGLEN + 1);
|
||||
msg = stripwhitespace(labelBuff);
|
||||
|
||||
if (strcasecmp(msg, "POOL HEAT ENA") == 0)
|
||||
{
|
||||
_aqualink_data->aqbuttons[POOL_HEAT_INDEX].led->state = ENABLE;
|
||||
}
|
||||
else if (strcasecmp(msg, "SPA HEAT ENA") == 0)
|
||||
{
|
||||
_aqualink_data->aqbuttons[SPA_HEAT_INDEX].led->state = ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < TOTAL_BUTTONS; i++)
|
||||
{
|
||||
if (strcasecmp(msg, _aqualink_data->aqbuttons[i].pda_label) == 0)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "*** Found Status for %s = '%.*s'\n", _aqualink_data->aqbuttons[i].pda_label, AQ_MSGLEN, msg);
|
||||
// It's on (or delayed) if it's listed here.
|
||||
if (_aqualink_data->aqbuttons[i].led->state != FLASH)
|
||||
{
|
||||
_aqualink_data->aqbuttons[i].led->state = ON;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void process_pda_packet_msg_long_temp(const char *msg)
|
||||
{
|
||||
// 'AIR POOL'
|
||||
// ' 86` 86` '
|
||||
// 'AIR SPA '
|
||||
// ' 86` 86` '
|
||||
// 'AIR '
|
||||
// ' 86` '
|
||||
_aqualink_data->temp_units = FAHRENHEIT; // Force FAHRENHEIT
|
||||
if (stristr(pda_m_line(1), "AIR") != NULL)
|
||||
_aqualink_data->air_temp = atoi(msg);
|
||||
|
||||
if (stristr(pda_m_line(1), "SPA") != NULL)
|
||||
{
|
||||
_aqualink_data->spa_temp = atoi(msg + 4);
|
||||
_aqualink_data->pool_temp = TEMP_UNKNOWN;
|
||||
}
|
||||
else if (stristr(pda_m_line(1), "POOL") != NULL)
|
||||
{
|
||||
_aqualink_data->pool_temp = atoi(msg + 7);
|
||||
_aqualink_data->spa_temp = TEMP_UNKNOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
_aqualink_data->pool_temp = TEMP_UNKNOWN;
|
||||
_aqualink_data->spa_temp = TEMP_UNKNOWN;
|
||||
}
|
||||
// printf("Air Temp = %d | Water Temp = %d\n",atoi(msg),atoi(msg+7));
|
||||
}
|
||||
|
||||
void process_pda_packet_msg_long_time(const char *msg)
|
||||
{
|
||||
// message " SAT 8:46AM "
|
||||
// " SAT 10:29AM"
|
||||
// " SAT 4:23PM "
|
||||
// printf("TIME = '%.*s'\n",AQ_MSGLEN,msg );
|
||||
// printf("TIME = '%c'\n",msg[AQ_MSGLEN-1] );
|
||||
if (msg[AQ_MSGLEN - 1] == ' ')
|
||||
{
|
||||
strncpy(_aqualink_data->time, msg + 9, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(_aqualink_data->time, msg + 9, 7);
|
||||
}
|
||||
strncpy(_aqualink_data->date, msg + 5, 3);
|
||||
// :TODO: NSF Come back and change the above to correctly check date and time in future
|
||||
}
|
||||
|
||||
void process_pda_packet_msg_long_equipment_control(const char *msg)
|
||||
{
|
||||
// These are listed as "FILTER PUMP OFF"
|
||||
int i;
|
||||
char labelBuff[AQ_MSGLEN + 1];
|
||||
strncpy(labelBuff, msg, AQ_MSGLEN - 4);
|
||||
labelBuff[AQ_MSGLEN - 4] = 0;
|
||||
|
||||
logMessage(LOG_DEBUG, "*** Checking Equiptment '%s'\n", labelBuff);
|
||||
|
||||
for (i = 0; i < TOTAL_BUTTONS; i++)
|
||||
{
|
||||
if (strcasecmp(stripwhitespace(labelBuff), _aqualink_data->aqbuttons[i].pda_label) == 0)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "*** Found EQ CTL Status for %s = '%.*s'\n", _aqualink_data->aqbuttons[i].pda_label, AQ_MSGLEN, msg);
|
||||
set_pda_led(_aqualink_data->aqbuttons[i].led, msg[AQ_MSGLEN - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void process_pda_packet_msg_long_home(const char *msg)
|
||||
{
|
||||
if (stristr(msg, "POOL MODE") != NULL)
|
||||
{
|
||||
// If pool mode is on the filter pump is on but if it is off the filter pump might be on if spa mode is on.
|
||||
if (msg[AQ_MSGLEN - 1] == 'N')
|
||||
{
|
||||
_aqualink_data->aqbuttons[PUMP_INDEX].led->state = ON;
|
||||
}
|
||||
else if (msg[AQ_MSGLEN - 1] == '*')
|
||||
{
|
||||
_aqualink_data->aqbuttons[PUMP_INDEX].led->state = FLASH;
|
||||
}
|
||||
}
|
||||
else if (stristr(msg, "POOL HEATER") != NULL)
|
||||
{
|
||||
set_pda_led(_aqualink_data->aqbuttons[POOL_HEAT_INDEX].led, msg[AQ_MSGLEN - 1]);
|
||||
}
|
||||
else if (stristr(msg, "SPA MODE") != NULL)
|
||||
{
|
||||
// when SPA mode is on the filter may be on or pending
|
||||
if (msg[AQ_MSGLEN - 1] == 'N')
|
||||
{
|
||||
_aqualink_data->aqbuttons[PUMP_INDEX].led->state = ON;
|
||||
_aqualink_data->aqbuttons[SPA_INDEX].led->state = ON;
|
||||
}
|
||||
else if (msg[AQ_MSGLEN - 1] == '*')
|
||||
{
|
||||
_aqualink_data->aqbuttons[PUMP_INDEX].led->state = FLASH;
|
||||
_aqualink_data->aqbuttons[SPA_INDEX].led->state = ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
_aqualink_data->aqbuttons[SPA_INDEX].led->state = OFF;
|
||||
}
|
||||
}
|
||||
else if (stristr(msg, "SPA HEATER") != NULL)
|
||||
{
|
||||
set_pda_led(_aqualink_data->aqbuttons[SPA_HEAT_INDEX].led, msg[AQ_MSGLEN - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
void process_pda_packet_msg_long_set_temp(const char *msg)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "process_pda_packet_msg_long_set_temp\n");
|
||||
|
||||
if (stristr(msg, "POOL HEAT") != NULL)
|
||||
{
|
||||
_aqualink_data->pool_htr_set_point = atoi(msg + 10);
|
||||
logMessage(LOG_DEBUG, "pool_htr_set_point = %d\n", _aqualink_data->pool_htr_set_point);
|
||||
}
|
||||
else if (stristr(msg, "SPA HEAT") != NULL)
|
||||
{
|
||||
_aqualink_data->spa_htr_set_point = atoi(msg + 10);
|
||||
logMessage(LOG_DEBUG, "spa_htr_set_point = %d\n", _aqualink_data->spa_htr_set_point);
|
||||
}
|
||||
}
|
||||
|
||||
void process_pda_packet_msg_long_spa_heat(const char *msg)
|
||||
{
|
||||
if (strncmp(msg, " ENABLED ", 16) == 0)
|
||||
{
|
||||
_aqualink_data->aqbuttons[SPA_HEAT_INDEX].led->state = ENABLE;
|
||||
}
|
||||
else if (strncmp(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);
|
||||
}
|
||||
}
|
||||
|
||||
void process_pda_packet_msg_long_pool_heat(const char *msg)
|
||||
{
|
||||
if (strncmp(msg, " ENABLED ", 16) == 0)
|
||||
{
|
||||
_aqualink_data->aqbuttons[POOL_HEAT_INDEX].led->state = ENABLE;
|
||||
}
|
||||
else if (strncmp(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);
|
||||
}
|
||||
}
|
||||
|
||||
void process_pda_packet_msg_long_freeze_protect(const char *msg)
|
||||
{
|
||||
if (strncmp(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);
|
||||
}
|
||||
}
|
||||
|
||||
void process_pda_packet_msg_long_SWG(const char *msg)
|
||||
{
|
||||
//PDA Line 0 = SET AquaPure
|
||||
//PDA Line 1 =
|
||||
//PDA Line 2 =
|
||||
//PDA Line 3 = SET POOL TO: 45%
|
||||
//PDA Line 4 = SET SPA TO: 0%
|
||||
|
||||
// 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)
|
||||
{
|
||||
_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)
|
||||
{
|
||||
_aqualink_data->swg_percent = atoi(msg + 13);
|
||||
logMessage(LOG_DEBUG, "POOL swg_percent = %d\n", _aqualink_data->swg_percent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void process_pda_packet_msg_long_unknown(const char *msg)
|
||||
{
|
||||
int i;
|
||||
// Lets make a guess here and just see if there is an ON/OFF/ENA/*** at the end of the line
|
||||
// When you turn on/off a piece of equiptment, a clear screen followed by single message is sent.
|
||||
// So we are not in any PDA menu, try to catch that message here so we catch new device state ASAP.
|
||||
if (msg[AQ_MSGLEN - 1] == 'N' || msg[AQ_MSGLEN - 1] == 'F' || msg[AQ_MSGLEN - 1] == 'A' || msg[AQ_MSGLEN - 1] == '*')
|
||||
{
|
||||
for (i = 0; i < TOTAL_BUTTONS; i++)
|
||||
{
|
||||
if (stristr(msg, _aqualink_data->aqbuttons[i].pda_label) != NULL)
|
||||
{
|
||||
printf("*** UNKNOWN Found Status for %s = '%.*s'\n", _aqualink_data->aqbuttons[i].pda_label, AQ_MSGLEN, msg);
|
||||
// set_pda_led(_aqualink_data->aqbuttons[i].led, msg[AQ_MSGLEN-1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void process_pda_freeze_protect_devices()
|
||||
{
|
||||
// PDA Line 0 = FREEZE PROTECT
|
||||
// PDA Line 1 = DEVICES
|
||||
// PDA Line 2 =
|
||||
// PDA Line 3 = FILTER PUMP X
|
||||
// PDA Line 4 = SPA
|
||||
// PDA Line 5 = CLEANER X
|
||||
// PDA Line 6 = POOL LIGHT
|
||||
// PDA Line 7 = SPA LIGHT
|
||||
// PDA Line 8 = EXTRA AUX
|
||||
// PDA Line 9 =
|
||||
int i;
|
||||
logMessage(LOG_DEBUG, "process_pda_freeze_protect_devices\n");
|
||||
for (i = 1; i < PDA_LINES; i++)
|
||||
{
|
||||
if (pda_m_line(i)[AQ_MSGLEN - 1] == 'X')
|
||||
{
|
||||
logMessage(LOG_DEBUG, "PDA freeze protect enabled by %s\n", pda_m_line(i));
|
||||
if (_aqualink_data->frz_protect_state == OFF)
|
||||
{
|
||||
_aqualink_data->frz_protect_state = ENABLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool process_pda_packet(unsigned char *packet, int length)
|
||||
{
|
||||
bool rtn = true;
|
||||
int i;
|
||||
char *msg;
|
||||
static bool init = false;
|
||||
static time_t _lastStatus = 0;
|
||||
|
||||
if (_lastStatus == 0)
|
||||
{
|
||||
time(&_lastStatus);
|
||||
}
|
||||
|
||||
process_pda_menu_packet(packet, length);
|
||||
|
||||
// NSF.
|
||||
|
||||
//_aqualink_data->last_msg_was_status = false;
|
||||
|
||||
// debugPacketPrint(0x00, packet, length);
|
||||
|
||||
switch (packet[PKT_CMD])
|
||||
{
|
||||
|
||||
case CMD_ACK:
|
||||
logMessage(LOG_DEBUG, "RS Received ACK length %d.\n", length);
|
||||
if (init == false)
|
||||
{
|
||||
aq_programmer(AQ_PDA_INIT, NULL, _aqualink_data);
|
||||
init = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_STATUS:
|
||||
_aqualink_data->last_display_message[0] = '\0';
|
||||
|
||||
// If we get a status packet, and we are on the status menu, this is a list of what's on
|
||||
// or pending so unless flash turn everything off, and just turn on items that are listed.
|
||||
// This is the only way to update a device that's been turned off by a real PDA / keypad.
|
||||
// Note: if the last line of the status menu is present it may be cut off
|
||||
if (pda_m_type() == PM_EQUIPTMENT_STATUS)
|
||||
{
|
||||
if (_aqualink_data->frz_protect_state == ON)
|
||||
{
|
||||
_aqualink_data->frz_protect_state = ENABLE;
|
||||
}
|
||||
if (pda_m_line(PDA_LINES - 1)[0] == '\0')
|
||||
{
|
||||
for (i = 0; i < TOTAL_BUTTONS; i++)
|
||||
{
|
||||
if (_aqualink_data->aqbuttons[i].led->state != FLASH)
|
||||
{
|
||||
_aqualink_data->aqbuttons[i].led->state = OFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logMessage(LOG_DEBUG, "PDA Equipment status may be truncated.\n");
|
||||
}
|
||||
for (i = 1; i < PDA_LINES; i++)
|
||||
{
|
||||
pass_pda_equiptment_status_item(pda_m_line(i));
|
||||
}
|
||||
time(&_lastStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t now;
|
||||
time(&now);
|
||||
if (init && difftime(now, _lastStatus) > 60)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "OVER 60 SECONDS SINCE LAST STATUS UPDATE, forcing refresh\n");
|
||||
// Reset aquapure to nothing since it must be off at this point
|
||||
_aqualink_data->pool_temp = TEMP_UNKNOWN;
|
||||
_aqualink_data->spa_temp = TEMP_UNKNOWN;
|
||||
time(&_lastStatus);
|
||||
aq_programmer(AQ_PDA_DEVICE_STATUS, NULL, _aqualink_data);
|
||||
}
|
||||
}
|
||||
if (pda_m_type() == PM_FREEZE_PROTECT_DEVICES)
|
||||
{
|
||||
process_pda_freeze_protect_devices();
|
||||
}
|
||||
break;
|
||||
case CMD_MSG_LONG:
|
||||
{
|
||||
//printf ("*******************************************************************************************\n");
|
||||
//printf ("menu type %d\n",pda_m_type());
|
||||
|
||||
msg = (char *)packet + PKT_DATA + 1;
|
||||
|
||||
//strcpy(_aqualink_data->last_message, msg);
|
||||
|
||||
if (packet[PKT_DATA] == 0x82)
|
||||
{ // Air & Water temp is always this ID
|
||||
process_pda_packet_msg_long_temp(msg);
|
||||
}
|
||||
else if (packet[PKT_DATA] == 0x40)
|
||||
{ // Time is always on this ID
|
||||
process_pda_packet_msg_long_time(msg);
|
||||
// If it wasn't a specific msg, (above) then run through and see what kind
|
||||
// of message it is depending on the PDA menu. Note don't process EQUIPTMENT
|
||||
// STATUS menu here, wait until a CMD_STATUS is received.
|
||||
}
|
||||
else {
|
||||
switch (pda_m_type()) {
|
||||
case PM_EQUIPTMENT_CONTROL:
|
||||
process_pda_packet_msg_long_equipment_control(msg);
|
||||
break;
|
||||
case PM_HOME:
|
||||
case PM_BUILDING_HOME:
|
||||
process_pda_packet_msg_long_home(msg);
|
||||
break;
|
||||
case PM_SET_TEMP:
|
||||
process_pda_packet_msg_long_set_temp(msg);
|
||||
break;
|
||||
case PM_SPA_HEAT:
|
||||
process_pda_packet_msg_long_spa_heat(msg);
|
||||
break;
|
||||
case PM_POOL_HEAT:
|
||||
process_pda_packet_msg_long_pool_heat(msg);
|
||||
break;
|
||||
case PM_FREEZE_PROTECT:
|
||||
process_pda_packet_msg_long_freeze_protect(msg);
|
||||
break;
|
||||
case PM_AQUAPURE:
|
||||
process_pda_packet_msg_long_SWG(msg);
|
||||
break;
|
||||
case PM_UNKNOWN:
|
||||
default:
|
||||
process_pda_packet_msg_long_unknown(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// printf("** Line index='%d' Highligh='%s' Message='%.*s'\n",pda_m_hlightindex(), pda_m_hlight(), AQ_MSGLEN, msg);
|
||||
logMessage(LOG_INFO, "PDA Menu '%d' Selectedline '%s', Last line received '%.*s'\n", pda_m_type(), pda_m_hlight(), AQ_MSGLEN, msg);
|
||||
break;
|
||||
}
|
||||
case CMD_PDA_0x1B:
|
||||
{
|
||||
// We get two of these on startup, one with 0x00 another with 0x01 at index 4. Just act on one.
|
||||
// Think this is PDA finishd showing startup screen
|
||||
if (packet[4] == 0x00) {
|
||||
if (_initWithRS == false)
|
||||
{
|
||||
_initWithRS = true;
|
||||
logMessage(LOG_DEBUG, "**** PDA INIT ****");
|
||||
aq_programmer(AQ_PDA_INIT, NULL, _aqualink_data);
|
||||
} else {
|
||||
logMessage(LOG_DEBUG, "**** PDA WAKE INIT ****");
|
||||
aq_programmer(AQ_PDA_WAKE_INIT, NULL, _aqualink_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (packet[PKT_CMD] == CMD_MSG_LONG || packet[PKT_CMD] == CMD_PDA_HIGHLIGHT ||
|
||||
packet[PKT_CMD] == CMD_PDA_SHIFTLINES || packet[PKT_CMD] == CMD_PDA_CLEAR)
|
||||
{
|
||||
// We processed the next message, kick any threads waiting on the message.
|
||||
kick_aq_program_thread(_aqualink_data);
|
||||
}
|
||||
return rtn;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
|
||||
#ifndef PDA_H_
|
||||
#define PDA_H_
|
||||
|
||||
void init_pda(struct aqualinkdata *aqdata);
|
||||
bool process_pda_packet(unsigned char* packet, int length);
|
||||
bool pda_shouldSleep();
|
||||
void pda_wake();
|
||||
void pda_reset_sleep();
|
||||
|
||||
#endif // PDA_MESSAGES_H_
|
|
@ -0,0 +1,770 @@
|
|||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "aqualink.h"
|
||||
#include "utils.h"
|
||||
#include "aq_programmer.h"
|
||||
#include "aq_serial.h"
|
||||
#include "pda.h"
|
||||
#include "pda_menu.h"
|
||||
#include "pda_aq_programmer.h"
|
||||
|
||||
#include "init_buttons.h"
|
||||
|
||||
bool waitForPDAMessageHighlight(struct aqualinkdata *aq_data, int highlighIndex, int numMessageReceived);
|
||||
bool waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, int numMessageReceived);
|
||||
bool goto_pda_menu(struct aqualinkdata *aq_data, pda_menu_type menu);
|
||||
bool wait_pda_selected_item(struct aqualinkdata *aq_data);
|
||||
bool waitForPDAnextMenu(struct aqualinkdata *aq_data);
|
||||
bool loopover_devices(struct aqualinkdata *aq_data);
|
||||
bool find_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, int charlimit);
|
||||
bool select_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, bool waitForNextMenu);
|
||||
|
||||
static pda_type _PDA_Type;
|
||||
|
||||
bool wait_pda_selected_item(struct aqualinkdata *aq_data)
|
||||
{
|
||||
while (pda_m_hlightindex() == -1){
|
||||
waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,10);
|
||||
}
|
||||
|
||||
if (pda_m_hlightindex() == -1)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool waitForPDAnextMenu(struct aqualinkdata *aq_data) {
|
||||
waitForPDAMessageType(aq_data,CMD_PDA_CLEAR,10);
|
||||
return waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,15);
|
||||
}
|
||||
|
||||
bool loopover_devices(struct aqualinkdata *aq_data) {
|
||||
int i;
|
||||
|
||||
if (! goto_pda_menu(aq_data, PM_EQUIPTMENT_CONTROL)) {
|
||||
//logMessage(LOG_ERR, "PDA :- can't find main menu\n");
|
||||
//cleanAndTerminateThread(threadCtrl);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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);
|
||||
//while (get_aq_cmd_length() > 0) { delay(200); }
|
||||
//waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,3);
|
||||
waitForMessage(aq_data, NULL, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
if charlimit is set, use case insensitive match and limit chars.
|
||||
*/
|
||||
bool find_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, int charlimit) {
|
||||
int i=pda_m_hlightindex();
|
||||
int index = (charlimit == 0)?pda_find_m_index(menuText):pda_find_m_index_case(menuText, charlimit);
|
||||
|
||||
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) {
|
||||
int j;
|
||||
for(j=0; j < 20; j++) {
|
||||
send_cmd(KEY_PDA_DOWN, aq_data);
|
||||
//delay(500);
|
||||
//wait_for_empty_cmd_buffer();
|
||||
waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,2);
|
||||
//waitForMessage(aq_data, NULL, 1);
|
||||
index = (charlimit == 0)?pda_find_m_index(menuText):pda_find_m_index_case(menuText, charlimit);
|
||||
if (index >= 0) {
|
||||
i=pda_m_hlightindex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < 0) {
|
||||
logMessage(LOG_ERR, "PDA Device programmer couldn't find menu item on any page '%s'\n",menuText);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
logMessage(LOG_ERR, "PDA Device programmer couldn't find menu item '%s'\n",menuText);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Found the text we want in the menu, now move to that position and select it.
|
||||
//logMessage(LOG_DEBUG, "******************PDA Device programmer menu text '%s' is at index %d\n",menuText, index);
|
||||
|
||||
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);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
return waitForPDAMessageHighlight(aq_data, index, 10);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
logMessage(LOG_DEBUG, "PDA Device programmer selected menu item '%s'\n",menuText);
|
||||
if (waitForNextMenu)
|
||||
waitForPDAnextMenu(aq_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
logMessage(LOG_ERR, "PDA Device programmer couldn't selected menu item '%s' at index %d\n",menuText, index);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool goto_pda_menu(struct aqualinkdata *aq_data, pda_menu_type menu) {
|
||||
//int i = 0;
|
||||
//char *menuText;
|
||||
|
||||
logMessage(LOG_DEBUG, "PDA Device programmer request for menu %d\n",menu);
|
||||
|
||||
// Keep going back, checking each time to get to home.
|
||||
while (pda_m_type() == PM_FW_VERSION || pda_m_type() == PM_BUILDING_HOME) {
|
||||
//logMessage(LOG_DEBUG, "******************PDA Device programmer delay on firmware or building home menu\n");
|
||||
delay(500);
|
||||
}
|
||||
|
||||
while ( pda_m_type() != menu && pda_m_type() != PM_HOME ) {
|
||||
if (pda_m_type() != PM_BUILDING_HOME) {
|
||||
send_cmd(KEY_PDA_BACK, aq_data);
|
||||
//logMessage(LOG_DEBUG, "******************PDA Device programmer selected back button\n",menu);
|
||||
waitForPDAnextMenu(aq_data);
|
||||
} else {
|
||||
waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,15);
|
||||
}
|
||||
//logMessage(LOG_DEBUG, "******************PDA Device programmer menu type %d\n",pda_m_type());
|
||||
//if (!wait_for_empty_cmd_buffer() || i++ > 6)
|
||||
// return false;
|
||||
}
|
||||
|
||||
if (pda_m_type() == menu)
|
||||
return true;
|
||||
|
||||
switch (menu) {
|
||||
//case PM_SYSTEM_SETUP:
|
||||
// select_pda_menu_item(aq_data, "MENU");
|
||||
//break;
|
||||
case PM_EQUIPTMENT_CONTROL:
|
||||
select_pda_menu_item(aq_data, "EQUIPMENT ON/OFF", true);
|
||||
break;
|
||||
case PM_PALM_OPTIONS:
|
||||
select_pda_menu_item(aq_data, "MENU", true);
|
||||
select_pda_menu_item(aq_data, "PALM OPTIONS", true);
|
||||
case PM_AUX_LABEL:
|
||||
if ( _PDA_Type == PDA) {
|
||||
select_pda_menu_item(aq_data, "MENU", true);
|
||||
select_pda_menu_item(aq_data, "SYSTEM SETUP", true); // This is a guess, (I have rev#)
|
||||
select_pda_menu_item(aq_data, "LABEL AUX", true);
|
||||
} else {
|
||||
logMessage(LOG_ERR, "PDA in AquaPlalm mode, there is no SYSTEM SETUP / LABEL AUX menu\n");
|
||||
}
|
||||
break;
|
||||
case PM_SYSTEM_SETUP:
|
||||
if ( _PDA_Type == PDA) {
|
||||
select_pda_menu_item(aq_data, "MENU", true);
|
||||
select_pda_menu_item(aq_data, "SYSTEM SETUP", true); // This is a guess, (I have rev#)
|
||||
} else {
|
||||
logMessage(LOG_ERR, "PDA in AquaPlalm mode, there is no SYSTEM SETUP menu\n");
|
||||
}
|
||||
break;
|
||||
case PM_FREEZE_PROTECT:
|
||||
if ( _PDA_Type == PDA) {
|
||||
select_pda_menu_item(aq_data, "MENU", true);
|
||||
select_pda_menu_item(aq_data, "SYSTEM SETUP", true); // This is a guess, (I have rev#)
|
||||
select_pda_menu_item(aq_data, "FREEZE PROTECT", true); // This is a guess, (I have rev#)
|
||||
} else {
|
||||
logMessage(LOG_ERR, "PDA in AquaPlalm mode, there is no SYSTEM SETUP / FREEZE PROTECT menu\n");
|
||||
}
|
||||
break;
|
||||
case PM_AQUAPURE:
|
||||
select_pda_menu_item(aq_data, "MENU", true);
|
||||
select_pda_menu_item(aq_data, "SET AquaPure", true);
|
||||
//select_pda_menu_item(aq_data, "LABEL AUX");
|
||||
break;
|
||||
case PM_SET_TEMP:
|
||||
select_pda_menu_item(aq_data, "MENU", true);
|
||||
select_pda_menu_item(aq_data, "SET TEMP", true);
|
||||
//select_pda_menu_item(aq_data, "LABEL AUX");
|
||||
break;
|
||||
case PM_SET_TIME:
|
||||
select_pda_menu_item(aq_data, "MENU", true);
|
||||
select_pda_menu_item(aq_data, "SET TIME", true);
|
||||
//select_pda_menu_item(aq_data, "LABEL AUX");
|
||||
break;
|
||||
default:
|
||||
logMessage(LOG_ERR, "PDA Device programmer didn't understand requested menu\n");
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pda_m_type() != menu) {
|
||||
logMessage(LOG_ERR, "PDA Device programmer didn't find a requested menu\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
//logMessage(LOG_DEBUG, "******************PDA Device programmer request for menu %d found\n",menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void *set_aqualink_PDA_device_on_off( void *ptr )
|
||||
{
|
||||
struct programmingThreadCtrl *threadCtrl;
|
||||
threadCtrl = (struct programmingThreadCtrl *) ptr;
|
||||
struct aqualinkdata *aq_data = threadCtrl->aq_data;
|
||||
//int i=0;
|
||||
//int found;
|
||||
char device_name[15];
|
||||
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_PDA_DEVICE_STATUS);
|
||||
|
||||
char *buf = (char*)threadCtrl->thread_args;
|
||||
int device = atoi(&buf[0]);
|
||||
int state = atoi(&buf[5]);
|
||||
|
||||
if (device < 0 || device > TOTAL_BUTTONS) {
|
||||
logMessage(LOG_ERR, "PDA Device On/Off :- bad device number '%d'\n",device);
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
logMessage(LOG_INFO, "PDA Device On/Off, device '%s', state %d\n",aq_data->aqbuttons[device].pda_label,state);
|
||||
|
||||
if (! goto_pda_menu(aq_data, PM_EQUIPTMENT_CONTROL)) {
|
||||
logMessage(LOG_ERR, "PDA Device On/Off :- can't find main menu\n");
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
//Pad name with spaces so something like "SPA" doesn't match "SPA BLOWER"
|
||||
sprintf(device_name,"%-14s\n",aq_data->aqbuttons[device].pda_label);
|
||||
if ( find_pda_menu_item(aq_data, device_name, 13) ) {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
logMessage(LOG_ERR, "PDA Device On/Off, device '%s' not found\n",aq_data->aqbuttons[device].pda_label);
|
||||
}
|
||||
|
||||
goto_pda_menu(aq_data, PM_HOME);
|
||||
//while (_pgm_command != NUL) { delay(500); }
|
||||
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
|
||||
// just stop compiler error, ptr is not valid as it's just been freed
|
||||
return ptr;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void *get_aqualink_PDA_device_status( void *ptr )
|
||||
{
|
||||
struct programmingThreadCtrl *threadCtrl;
|
||||
threadCtrl = (struct programmingThreadCtrl *) ptr;
|
||||
struct aqualinkdata *aq_data = threadCtrl->aq_data;
|
||||
//int i;
|
||||
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_PDA_DEVICE_STATUS);
|
||||
|
||||
if (! loopover_devices(aq_data)) {
|
||||
logMessage(LOG_ERR, "PDA Device Status :- failed\n");
|
||||
}
|
||||
|
||||
goto_pda_menu(aq_data, PM_HOME);
|
||||
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
|
||||
// just stop compiler error, ptr is not valid as it's just been freed
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *set_aqualink_PDA_init( void *ptr )
|
||||
{
|
||||
struct programmingThreadCtrl *threadCtrl;
|
||||
threadCtrl = (struct programmingThreadCtrl *) ptr;
|
||||
struct aqualinkdata *aq_data = threadCtrl->aq_data;
|
||||
//int i=0;
|
||||
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_PDA_INIT);
|
||||
|
||||
//int val = atoi((char*)threadCtrl->thread_args);
|
||||
|
||||
//logMessage(LOG_DEBUG, "PDA Init\n", val);
|
||||
|
||||
logMessage(LOG_DEBUG, "PDA Init\n");
|
||||
|
||||
if (pda_m_type() == PM_FW_VERSION) {
|
||||
// check pda_m_line(1) to "AquaPalm"
|
||||
if (strstr(pda_m_line(1), "AquaPalm") != NULL) {
|
||||
_PDA_Type = AQUAPALM;
|
||||
} else {
|
||||
_PDA_Type = PDA;
|
||||
}
|
||||
char *ptr = pda_m_line(5);
|
||||
ptr[AQ_MSGLEN+1] = '\0';
|
||||
strcpy(aq_data->version, stripwhitespace(ptr));
|
||||
}
|
||||
|
||||
// Get status of all devices
|
||||
if (! loopover_devices(aq_data)) {
|
||||
logMessage(LOG_ERR, "PDA Init :- can't find menu\n");
|
||||
}
|
||||
|
||||
// Get heater setpoints
|
||||
if (! get_PDA_aqualink_pool_spa_heater_temps(aq_data)) {
|
||||
logMessage(LOG_ERR, "PDA Init :- Error getting heater setpoints\n");
|
||||
}
|
||||
|
||||
// Get freeze protect setpoint, AquaPalm doesn't have freeze protect in menu.
|
||||
if (_PDA_Type != AQUAPALM && ! get_PDA_freeze_protect_temp(aq_data)) {
|
||||
logMessage(LOG_ERR, "PDA Init :- Error getting freeze setpoints\n");
|
||||
}
|
||||
|
||||
|
||||
goto_pda_menu(aq_data, PM_HOME);
|
||||
|
||||
pda_reset_sleep();
|
||||
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
|
||||
// just stop compiler error, ptr is not valid as it's just been freed
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
void *set_aqualink_PDA_wakeinit( void *ptr )
|
||||
{
|
||||
struct programmingThreadCtrl *threadCtrl;
|
||||
threadCtrl = (struct programmingThreadCtrl *) ptr;
|
||||
struct aqualinkdata *aq_data = threadCtrl->aq_data;
|
||||
//int i=0;
|
||||
|
||||
// At this point, we should probably just exit if there is a thread already going as
|
||||
// it means the wake was called due to changing a device.
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_PDA_INIT);
|
||||
|
||||
logMessage(LOG_DEBUG, "PDA Wake Init\n");
|
||||
|
||||
// Get status of all devices
|
||||
if (! loopover_devices(aq_data)) {
|
||||
logMessage(LOG_ERR, "PDA Init :- can't find menu\n");
|
||||
}
|
||||
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
|
||||
// just stop compiler error, ptr is not valid as it's just been freed
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
bool get_PDA_freeze_protect_temp(struct aqualinkdata *aq_data) {
|
||||
|
||||
if ( _PDA_Type == PDA) {
|
||||
if (! goto_pda_menu(aq_data, PM_FREEZE_PROTECT)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
logMessage(LOG_INFO, "In PDA AquaPalm mode, freezepoints not supported\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_PDA_aqualink_pool_spa_heater_temps(struct aqualinkdata *aq_data) {
|
||||
|
||||
// Get heater setpoints
|
||||
if (! goto_pda_menu(aq_data, PM_SET_TEMP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool waitForPDAMessageHighlight(struct aqualinkdata *aq_data, int highlighIndex, int numMessageReceived)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "waitForPDAMessageHighlight index %d\n",highlighIndex);
|
||||
|
||||
if(pda_m_hlightindex() == highlighIndex) return true;
|
||||
|
||||
int i=0;
|
||||
pthread_mutex_init(&aq_data->active_thread.thread_mutex, NULL);
|
||||
pthread_mutex_lock(&aq_data->active_thread.thread_mutex);
|
||||
|
||||
while( ++i <= numMessageReceived)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "waitForPDAMessageHighlight last = 0x%02hhx : index %d : (%d of %d)\n",aq_data->last_packet_type,pda_m_hlightindex(),i,numMessageReceived);
|
||||
|
||||
if (aq_data->last_packet_type == CMD_PDA_HIGHLIGHT && pda_m_hlightindex() == highlighIndex) break;
|
||||
|
||||
pthread_cond_init(&aq_data->active_thread.thread_cond, NULL);
|
||||
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 (pda_m_hlightindex() != highlighIndex) {
|
||||
//logMessage(LOG_ERR, "Could not select MENU of Aqualink control panel\n");
|
||||
logMessage(LOG_DEBUG, "waitForPDAMessageHighlight: did not receive index '%d'\n",highlighIndex);
|
||||
return false;
|
||||
} else
|
||||
logMessage(LOG_DEBUG, "waitForPDAMessageHighlight: received index '%d'\n",highlighIndex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, int numMessageReceived)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "waitForPDAMessageType 0x%02hhx\n",mtype);
|
||||
|
||||
int i=0;
|
||||
pthread_mutex_init(&aq_data->active_thread.thread_mutex, NULL);
|
||||
pthread_mutex_lock(&aq_data->active_thread.thread_mutex);
|
||||
|
||||
while( ++i <= numMessageReceived)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "waitForPDAMessageType 0x%02hhx, last message type was 0x%02hhx (%d of %d)\n",mtype,aq_data->last_packet_type,i,numMessageReceived);
|
||||
|
||||
if (aq_data->last_packet_type == mtype) break;
|
||||
|
||||
pthread_cond_init(&aq_data->active_thread.thread_cond, NULL);
|
||||
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 (aq_data->last_packet_type != mtype) {
|
||||
//logMessage(LOG_ERR, "Could not select MENU of Aqualink control panel\n");
|
||||
logMessage(LOG_DEBUG, "waitForPDAMessageType: did not receive 0x%02hhx\n",mtype);
|
||||
return false;
|
||||
} else
|
||||
logMessage(LOG_DEBUG, "waitForPDAMessageType: received 0x%02hhx\n",mtype);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set_PDA_numeric_field_value(struct aqualinkdata *aq_data, int val, int *cur_val, char *select_label, int step) {
|
||||
int i;
|
||||
|
||||
// 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);
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
} else {
|
||||
logMessage(LOG_INFO, "PDA %s value : already at %d\n", select_label, val);
|
||||
send_cmd(KEY_PDA_BACK, aq_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
send_cmd(KEY_PDA_SELECT, aq_data);
|
||||
logMessage(LOG_DEBUG, "PDA %s value : set to %d\n", select_label, *cur_val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set_PDA_aqualink_SWG_setpoint(struct aqualinkdata *aq_data, int val) {
|
||||
|
||||
if (! goto_pda_menu(aq_data, PM_AQUAPURE)) {
|
||||
logMessage(LOG_ERR, "Error getting setpoints menu\n");
|
||||
}
|
||||
|
||||
if (aq_data->aqbuttons[SPA_INDEX].led->state != OFF)
|
||||
set_PDA_numeric_field_value(aq_data, val, &aq_data->swg_percent, "SET SPA", 5);
|
||||
else
|
||||
set_PDA_numeric_field_value(aq_data, val, &aq_data->swg_percent, "SET POOL", 5);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set_PDA_aqualink_heater_setpoint(struct aqualinkdata *aq_data, int val, bool isPool) {
|
||||
char label[10];
|
||||
int *cur_val;
|
||||
|
||||
if (isPool) {
|
||||
sprintf(label, "POOL HEAT");
|
||||
cur_val = &aq_data->pool_htr_set_point;
|
||||
} else {
|
||||
sprintf(label, "SPA HEAT");
|
||||
cur_val = &aq_data->spa_htr_set_point;
|
||||
}
|
||||
|
||||
if (val == *cur_val) {
|
||||
logMessage(LOG_INFO, "PDA %s setpoint : temp already %d\n", label, val);
|
||||
send_cmd(KEY_PDA_BACK, aq_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! goto_pda_menu(aq_data, PM_SET_TEMP)) {
|
||||
logMessage(LOG_ERR, "Error getting setpoints menu\n");
|
||||
}
|
||||
|
||||
set_PDA_numeric_field_value(aq_data, val, cur_val, label, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set_PDA_aqualink_freezeprotect_setpoint(struct aqualinkdata *aq_data, int val) {
|
||||
|
||||
if (! goto_pda_menu(aq_data, PM_FREEZE_PROTECT)) {
|
||||
logMessage(LOG_ERR, "Error getting setpoints menu\n");
|
||||
}
|
||||
|
||||
set_PDA_numeric_field_value(aq_data, val, &aq_data->frz_protect_set_point, "TEMP", 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
bool waitForPDAMessage(struct aqualinkdata *aq_data, int numMessageReceived, unsigned char packettype)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "waitForPDAMessage %s %d\n",message,numMessageReceived);
|
||||
int i=0;
|
||||
pthread_mutex_init(&aq_data->active_thread.thread_mutex, NULL);
|
||||
pthread_mutex_lock(&aq_data->active_thread.thread_mutex);
|
||||
char* msgS;
|
||||
char* ptr;
|
||||
|
||||
if (message != NULL) {
|
||||
if (message[0] == '^')
|
||||
msgS = &message[1];
|
||||
else
|
||||
msgS = message;
|
||||
}
|
||||
|
||||
while( ++i <= numMessageReceived)
|
||||
{
|
||||
if (message != NULL)
|
||||
logMessage(LOG_DEBUG, "Programming mode: loop %d of %d looking for '%s' received message '%s'\n",i,numMessageReceived,message,aq_data->last_message);
|
||||
else
|
||||
logMessage(LOG_DEBUG, "Programming mode: loop %d of %d waiting for next message, received '%s'\n",i,numMessageReceived,aq_data->last_message);
|
||||
|
||||
if (message != NULL) {
|
||||
ptr = stristr(aq_data->last_message, msgS);
|
||||
if (ptr != NULL) { // match
|
||||
logMessage(LOG_DEBUG, "Programming mode: String MATCH\n");
|
||||
if (msgS == message) // match & don't care if first char
|
||||
break;
|
||||
else if (ptr == aq_data->last_message) // match & do care if first char
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//logMessage(LOG_DEBUG, "Programming mode: looking for '%s' received message '%s'\n",message,aq_data->last_message);
|
||||
pthread_cond_init(&aq_data->active_thread.thread_cond, NULL);
|
||||
pthread_cond_wait(&aq_data->active_thread.thread_cond, &aq_data->active_thread.thread_mutex);
|
||||
//logMessage(LOG_DEBUG, "Programming mode: loop %d of %d looking for '%s' received message '%s'\n",i,numMessageReceived,message,aq_data->last_message);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&aq_data->active_thread.thread_mutex);
|
||||
|
||||
if (message != NULL && ptr == NULL) {
|
||||
//logMessage(LOG_ERR, "Could not select MENU of Aqualink control panel\n");
|
||||
logMessage(LOG_DEBUG, "Programming mode: did not find '%s'\n",message);
|
||||
return false;
|
||||
} else if (message != NULL)
|
||||
logMessage(LOG_DEBUG, "Programming mode: found message '%s' in '%s'\n",message,aq_data->last_message);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Link to two different menu's used in PDA
|
||||
http://www.poolequipmentpriceslashers.com.au/wp-content/uploads/2012/11/Jandy-Aqualink-RS-PDA-Wireless-Pool-Controller_manual.pdf
|
||||
https://www.jandy.com/-/media/zodiac/global/downloads/h/h0574200.pdf
|
||||
*/
|
||||
|
||||
/*
|
||||
List of how menu's display
|
||||
|
||||
PDA Line 0 =
|
||||
PDA Line 1 = AquaPalm
|
||||
PDA Line 2 =
|
||||
PDA Line 3 = Firmware Version
|
||||
PDA Line 4 =
|
||||
PDA Line 5 = REV MMM
|
||||
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
|
||||
Line 2 =
|
||||
Line 3 = Firmware Version
|
||||
Line 4 =
|
||||
Line 5 = PPD: PDA 1.2
|
||||
|
||||
PDA Line 0 =
|
||||
PDA Line 1 = AIR POOL
|
||||
PDA Line 2 =
|
||||
PDA Line 3 =
|
||||
PDA Line 4 = POOL MODE ON
|
||||
PDA Line 5 = POOL HEATER OFF
|
||||
PDA Line 6 = SPA MODE OFF
|
||||
PDA Line 7 = SPA HEATER OFF
|
||||
PDA Line 8 = MENU
|
||||
PDA Line 9 = EQUIPMENT ON/OFF
|
||||
|
||||
PDA Line 0 = MAIN MENU
|
||||
PDA Line 1 =
|
||||
PDA Line 2 = SET TEMP >
|
||||
PDA Line 3 = SET TIME >
|
||||
PDA Line 4 = SET AquaPure >
|
||||
PDA Line 5 = PALM OPTIONS >
|
||||
PDA Line 6 =
|
||||
PDA Line 7 = BOOST POOL
|
||||
PDA Line 8 =
|
||||
PDA Line 9 =
|
||||
|
||||
**************** OPTION 2 FOR THIS MENU ********************
|
||||
PDA Line 0 = MAIN MENU
|
||||
PDA Line 1 =
|
||||
PDA Line 2 = HELP >
|
||||
PDA Line 3 = PROGRAM >
|
||||
PDA Line 4 = SET TEMP >
|
||||
PDA Line 5 = SET TIME >
|
||||
PDA Line 6 = PDA OPTIONS >
|
||||
PDA Line 7 = SYSTEM SETUP >
|
||||
PDA Line 8 =
|
||||
PDA Line 9 = BOOST
|
||||
|
||||
********** Guess at SYSTEM SETUP Menu (not on Rev MMM or before)************
|
||||
|
||||
// PDA Line 0 = SYSTEM SETUP
|
||||
// PDA Line 1 = LABEL AUX >
|
||||
// PDA Line 2 = FREEZE PROTECT >
|
||||
// PDA Line 3 = AIR TEMP >
|
||||
// PDA Line 4 = DEGREES C/F >
|
||||
// PDA Line 5 = TEMP CALIBRATE >
|
||||
// PDA Line 6 = SOLAR PRIORITY >
|
||||
// PDA Line 7 = PUMP LOCKOUT >
|
||||
// PDA Line 8 = ASSIGN JVAs >
|
||||
// PDA Line 9 = ^^ MORE __
|
||||
// PDA Line 5 = COLOR LIGHTS >
|
||||
// PDA Line 6 = SPA SWITCH >
|
||||
// PDA Line 7 = SERVICE INFO >
|
||||
// PDA Line 8 = CLEAR MEMORY >
|
||||
|
||||
|
||||
|
||||
PDA Line 0 = PALM OPTIONS
|
||||
PDA Line 1 =
|
||||
PDA Line 2 =
|
||||
PDA Line 3 = SET AUTO-OFF >
|
||||
PDA Line 4 = BACKLIGHT >
|
||||
PDA Line 5 = ASSIGN HOTKEYS >
|
||||
PDA Line 6 =
|
||||
PDA Line 7 = Choose setting
|
||||
PDA Line 8 = and press SELECT
|
||||
PDA Line 9 =
|
||||
|
||||
PDA Line 0 = SET AquaPure
|
||||
PDA Line 1 =
|
||||
PDA Line 2 =
|
||||
PDA Line 3 = SET POOL TO: 45%
|
||||
PDA Line 4 = SET SPA TO: 0%
|
||||
PDA Line 5 =
|
||||
PDA Line 6 =
|
||||
PDA Line 7 = Highlight an
|
||||
PDA Line 8 = item and press
|
||||
PDA Line 9 = SELECT
|
||||
|
||||
PDA Line 0 = SET TIME
|
||||
PDA Line 1 =
|
||||
PDA Line 2 = 05/22/19 WED
|
||||
PDA Line 3 = 10:53 AM
|
||||
PDA Line 4 =
|
||||
PDA Line 5 =
|
||||
PDA Line 6 = Use ARROW KEYS
|
||||
PDA Line 7 = to set value.
|
||||
PDA Line 8 = Press SELECT
|
||||
PDA Line 9 = to continue.
|
||||
|
||||
PDA Line 0 = SET TEMP
|
||||
PDA Line 1 =
|
||||
PDA Line 2 = POOL HEAT 70`F
|
||||
PDA Line 3 = SPA HEAT 98`F
|
||||
PDA Line 4 =
|
||||
PDA Line 5 =
|
||||
PDA Line 6 =
|
||||
PDA Line 7 = Highlight an
|
||||
PDA Line 8 = item and press
|
||||
PDA Line 9 = SELECT
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PDA Line 0 = EQUIPMENT
|
||||
PDA Line 1 = FILTER PUMP ON
|
||||
PDA Line 2 = SPA OFF
|
||||
PDA Line 3 = POOL HEAT OFF
|
||||
PDA Line 4 = SPA HEAT OFF
|
||||
PDA Line 5 = CLEANER ON
|
||||
PDA Line 6 = WATERFALL OFF
|
||||
PDA Line 7 = AIR BLOWER OFF
|
||||
PDA Line 8 = LIGHT OFF
|
||||
PDA Line 9 = ^^ MORE __
|
||||
|
||||
PDA Line 0 = EQUIPMENT
|
||||
PDA Line 1 = WATERFALL OFF
|
||||
PDA Line 2 = AIR BLOWER OFF
|
||||
PDA Line 3 = LIGHT OFF
|
||||
PDA Line 4 = AUX5 OFF
|
||||
PDA Line 5 = EXTRA AUX OFF
|
||||
PDA Line 6 = SPA MODE OFF
|
||||
PDA Line 7 = CLEAN MODE OFF
|
||||
PDA Line 8 = ALL OFF
|
||||
PDA Line 9 =
|
||||
|
||||
*/
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
#ifndef PDA_AQ_PROGRAMMER_H_
|
||||
#define PDA_AQ_PROGRAMMER_H_
|
||||
|
||||
typedef enum pda_type {
|
||||
AQUAPALM,
|
||||
PDA
|
||||
} pda_type;
|
||||
|
||||
void *get_aqualink_PDA_device_status( void *ptr );
|
||||
void *set_aqualink_PDA_device_on_off( void *ptr );
|
||||
void *set_aqualink_PDA_wakeinit( void *ptr );
|
||||
|
||||
bool set_PDA_aqualink_heater_setpoint(struct aqualinkdata *aq_data, int val, bool isPool);
|
||||
bool set_PDA_aqualink_SWG_setpoint(struct aqualinkdata *aq_data, int val);
|
||||
bool set_PDA_aqualink_freezeprotect_setpoint(struct aqualinkdata *aq_data, int val);
|
||||
|
||||
bool get_PDA_aqualink_pool_spa_heater_temps(struct aqualinkdata *aq_data);
|
||||
bool get_PDA_freeze_protect_temp(struct aqualinkdata *aq_data);
|
||||
|
||||
#endif // AQ_PDA_PROGRAMMER_H_
|
164
pda_menu.c
164
pda_menu.c
|
@ -39,23 +39,81 @@ char *pda_m_line(int index)
|
|||
// return NULL;
|
||||
}
|
||||
|
||||
int pda_find_m_index(char *text)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PDA_LINES; i++) {
|
||||
if (strncmp(pda_m_line(i), text, strlen(text)) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pda_find_m_index_case(char *text, int limit)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PDA_LINES; i++) {
|
||||
//printf ("+++ Compare '%s' to '%s' index %d\n",text,pda_m_line(i),i);
|
||||
if (strncasecmp(pda_m_line(i), text, limit) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
pda_menu_type pda_m_type()
|
||||
{
|
||||
|
||||
if (strncmp(_menu[1],"AIR ", 5) == 0)
|
||||
return PM_MAIN;
|
||||
return PM_HOME;
|
||||
else if (strncmp(_menu[0],"EQUIPMENT STATUS", 16) == 0)
|
||||
return PM_EQUIPTMENT_STATUS;
|
||||
else if (strncmp(_menu[0]," EQUIPMENT ", 16) == 0)
|
||||
return PM_EQUIPTMENT_CONTROL;
|
||||
else if (strncmp(_menu[0]," MAIN MENU ", 16) == 0)
|
||||
return PM_SETTINGS;
|
||||
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 )
|
||||
return PM_BUILDING_MAIN;
|
||||
|
||||
else if (strncmp(_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)
|
||||
return PM_SET_TEMP;
|
||||
else if (strncmp(_menu[0]," SET TIME ", 16) == 0)
|
||||
return PM_SET_TIME;
|
||||
else if (strncmp(_menu[0]," SET AquaPure ", 16) == 0)
|
||||
return PM_AQUAPURE;
|
||||
else if (strncmp(_menu[0]," SPA HEAT ", 16) == 0)
|
||||
return PM_SPA_HEAT;
|
||||
else if (strncmp(_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)
|
||||
return PM_FREEZE_PROTECT;
|
||||
else if (strncmp(_menu[1]," DEVICES ", 16) == 0 &&
|
||||
strncmp(_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)
|
||||
return PM_FW_VERSION;
|
||||
|
||||
return PM_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
--- Main Menu ---
|
||||
Line 0 =
|
||||
|
@ -86,15 +144,105 @@ bool process_pda_menu_packet(unsigned char* packet, int length)
|
|||
if (getLogLevel() >= LOG_DEBUG){print_menu();}
|
||||
break;
|
||||
case CMD_PDA_HIGHLIGHT:
|
||||
_hlightindex = packet[4],_menu[packet[4]];
|
||||
// when switching from hlight to hlightchars index 255 is sent to turn off hlight
|
||||
if (packet[4] <= PDA_LINES) {
|
||||
_hlightindex = packet[4];
|
||||
} else {
|
||||
_hlightindex = -1;
|
||||
}
|
||||
if (getLogLevel() >= LOG_DEBUG){print_menu();}
|
||||
break;
|
||||
case CMD_PDA_HIGHLIGHTCHARS:
|
||||
if (packet[4] <= PDA_LINES) {
|
||||
_hlightindex = packet[4];
|
||||
} else {
|
||||
_hlightindex = -1;
|
||||
}
|
||||
if (getLogLevel() >= LOG_DEBUG){print_menu();}
|
||||
break;
|
||||
case CMD_PDA_SHIFTLINES:
|
||||
memcpy(_menu[1], _menu[2], (PDA_LINES-1) * (AQ_MSGLEN+1) );
|
||||
if (getLogLevel() >= LOG_DEBUG){print_menu();}
|
||||
break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
#ifdef SOME_CRAP
|
||||
bool NEW_process_pda_menu_packet_NEW(unsigned char* packet, int length)
|
||||
{
|
||||
bool rtn = true;
|
||||
signed char first_line;
|
||||
signed char last_line;
|
||||
signed char line_shift;
|
||||
signed char i;
|
||||
|
||||
pthread_mutex_lock(&_pda_menu_mutex);
|
||||
switch (packet[PKT_CMD]) {
|
||||
case CMD_STATUS:
|
||||
pthread_cond_signal(&_pda_menu_update_complete_cond);
|
||||
break;
|
||||
case CMD_PDA_CLEAR:
|
||||
rtn = pda_m_clear();
|
||||
break;
|
||||
case CMD_MSG_LONG:
|
||||
if (packet[PKT_DATA] < 10) {
|
||||
memset(_menu[packet[PKT_DATA]], 0, AQ_MSGLEN);
|
||||
strncpy(_menu[packet[PKT_DATA]], (char*)packet+PKT_DATA+1, AQ_MSGLEN);
|
||||
_menu[packet[PKT_DATA]][AQ_MSGLEN] = '\0';
|
||||
}
|
||||
if (packet[PKT_DATA] == _hlightindex) {
|
||||
logMessage(LOG_DEBUG, "process_pda_menu_packet: hlight changed from shift or up/down value\n");
|
||||
pthread_cond_signal(&_pda_menu_hlight_change_cond);
|
||||
}
|
||||
if (getLogLevel() >= LOG_DEBUG){print_menu();}
|
||||
update_pda_menu_type();
|
||||
break;
|
||||
case CMD_PDA_HIGHLIGHT:
|
||||
// when switching from hlight to hlightchars index 255 is sent to turn off hlight
|
||||
if (packet[4] <= PDA_LINES) {
|
||||
_hlightindex = packet[4];
|
||||
} else {
|
||||
_hlightindex = -1;
|
||||
}
|
||||
pthread_cond_signal(&_pda_menu_hlight_change_cond);
|
||||
if (getLogLevel() >= LOG_DEBUG){print_menu();}
|
||||
break;
|
||||
case CMD_PDA_HIGHLIGHTCHARS:
|
||||
if (packet[4] <= PDA_LINES) {
|
||||
_hlightindex = packet[4];
|
||||
} else {
|
||||
_hlightindex = -1;
|
||||
}
|
||||
pthread_cond_signal(&_pda_menu_hlight_change_cond);
|
||||
if (getLogLevel() >= LOG_DEBUG){print_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_menu();}
|
||||
break;
|
||||
|
||||
}
|
||||
pthread_mutex_unlock(&_pda_menu_mutex);
|
||||
|
||||
return rtn;
|
||||
}
|
||||
#endif
|
54
pda_menu.h
54
pda_menu.h
|
@ -5,6 +5,38 @@
|
|||
|
||||
#define PDA_LINES 10 // There is only 9 lines, but add buffer to make shifting easier
|
||||
|
||||
typedef enum pda_menu_type {
|
||||
PM_UNKNOWN,
|
||||
PM_FW_VERSION,
|
||||
PM_HOME,
|
||||
PM_BUILDING_HOME,
|
||||
PM_MAIN,
|
||||
PM_DIAGNOSTICS,
|
||||
PM_PROGRAM,
|
||||
PM_SET_TEMP,
|
||||
PM_SET_TIME,
|
||||
PM_POOL_HEAT,
|
||||
PM_SPA_HEAT,
|
||||
PM_AQUAPURE,
|
||||
PM_SYSTEM_SETUP,
|
||||
PM_AUX_LABEL,
|
||||
PM_FREEZE_PROTECT,
|
||||
PM_FREEZE_PROTECT_DEVICES,
|
||||
PM_VSP,
|
||||
PM_SETTINGS,
|
||||
PM_EQUIPTMENT_CONTROL,
|
||||
PM_EQUIPTMENT_STATUS,
|
||||
PM_PALM_OPTIONS // This seems to be only older revisions
|
||||
} pda_menu_type;
|
||||
|
||||
/*
|
||||
typedef enum pda_home_menu_item {
|
||||
PMI_MAIN,
|
||||
PMI_EQUIPTMENT_CONTROL
|
||||
} pda_home_menu_item;
|
||||
*/
|
||||
|
||||
/*
|
||||
typedef enum pda_menu_type {
|
||||
PM_UNKNOWN,
|
||||
PM_MAIN,
|
||||
|
@ -13,7 +45,25 @@ typedef enum pda_menu_type {
|
|||
PM_EQUIPTMENT_STATUS,
|
||||
PM_BUILDING_MAIN
|
||||
} pda_menu_type;
|
||||
|
||||
*/
|
||||
/*
|
||||
typedef enum pda_menu_type {
|
||||
PM_UNKNOWN,
|
||||
PM_FW_VERSION,
|
||||
PM_HOME,
|
||||
PM_MAIN_MENU,
|
||||
PM_EQUIPTMENT_CONTROL,
|
||||
PM_EQUIPTMENT_STATUS,
|
||||
PM_BUILDING_HOME,
|
||||
PM_SYSTEM_SETUP,
|
||||
PM_SET_TEMP,
|
||||
PM_POOL_HEAT,
|
||||
PM_SPA_HEAT,
|
||||
PM_FREEZE_PROTECT,
|
||||
PM_FREEZE_PROTECT_DEVICES,
|
||||
PM_SET_AQUAPURE
|
||||
} pda_menu_type;
|
||||
*/
|
||||
bool pda_mode();
|
||||
void set_pda_mode(bool val);
|
||||
bool process_pda_menu_packet(unsigned char* packet, int length);
|
||||
|
@ -21,5 +71,7 @@ int pda_m_hlightindex();
|
|||
char *pda_m_hlight();
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
|
Binary file not shown.
|
@ -60,10 +60,27 @@ report_zero_pool_temp = no
|
|||
# Working RS ID's are 0x0a 0x0b 0x09 0x08 <- 0x08 is usually taken
|
||||
device_id=0x0a
|
||||
|
||||
# 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
|
||||
|
||||
#Only for PDA mode
|
||||
# set PDA mode
|
||||
#pda_mode = yes
|
||||
#
|
||||
# Put AqualinkD to sleep when in PDA mode after inactivity.
|
||||
# If you have Jandy PDA then this MUST be set to yes as the controller can only support one PDA.
|
||||
# If you don't have a Jandy PDA leave this at no as AqualinkD will be a lot quicker.
|
||||
# Sleep timer is around 2 mins of inactivity, then wake after 2 mins of sleep.
|
||||
#pda_sleep_mode = yes
|
||||
|
||||
# Read status information from other devices on the RS485 bus.
|
||||
# At the moment just Salt Water Generators are supported.
|
||||
read_all_devices = yes
|
||||
|
||||
# If you have a SWG connected to the control panel, set this to yes.
|
||||
# AqualinkD can only detect a SWG if it's on, so after a restart you will not see/access a SWG until the the next time the pump is on.
|
||||
force_SWG = no
|
||||
|
||||
# Button inxed light probramming button is assigned to. (look at your button labels below)
|
||||
light_programming_button = 0
|
||||
|
@ -91,6 +108,10 @@ spa_water_temp_dzidx=0
|
|||
SWG_percent_dzidx=0
|
||||
SWG_PPM_dzidx=0
|
||||
|
||||
|
||||
# Try to use labels from Control Panel.
|
||||
use_panel_aux_labels=yes
|
||||
|
||||
# Labels for standard butons (shown in web UI), and domoticz idx's
|
||||
button_01_label=Filter Pump
|
||||
#button_01_dzidx=37
|
||||
|
|
|
@ -19,8 +19,8 @@ web_directory=/nas/data/Development/Raspberry/AqualinkD/web
|
|||
# DEBUG would print everything possible
|
||||
|
||||
#log_level=DEBUG_SERIAL
|
||||
log_level=DEBUG
|
||||
#log_level=INFO
|
||||
#log_level=DEBUG
|
||||
log_level=INFO
|
||||
#log_level=NOTICE
|
||||
|
||||
# The socket port that the daemon listens to
|
||||
|
@ -33,13 +33,13 @@ serial_port=/dev/ttyUSB0
|
|||
override_freeze_protect = no
|
||||
|
||||
# mqtt stuff
|
||||
mqtt_address = trident:1883
|
||||
#mqtt_address = trident:1883
|
||||
#mqtt_user = someusername
|
||||
#mqtt_passwd = somepassword
|
||||
|
||||
#mqtt_dz_pub_topic = domoticz/in
|
||||
#mqtt_dz_sub_topic = domoticz/out
|
||||
mqtt_aq_topic = aqualinkd_test
|
||||
#mqtt_aq_topic = aqualinkd
|
||||
|
||||
# The id of the Aqualink terminal device. Devices probed by RS8 master are:
|
||||
# 08-0b, 10-13, 18-1b, 20-23, 28-2b, 30-33, 38-3b, 40-43
|
||||
|
@ -49,6 +49,7 @@ mqtt_aq_topic = aqualinkd_test
|
|||
#device_id=0x09
|
||||
device_id=0x60
|
||||
pda_mode = yes
|
||||
pda_sleep_mode = yes
|
||||
|
||||
convert_mqtt_temp_to_c = yes
|
||||
convert_dz_temp_to_c = yes
|
||||
|
@ -101,15 +102,15 @@ button_03_PDA_label=CLEANER
|
|||
|
||||
button_04_label=Waterfall
|
||||
#button_04_dzidx=40
|
||||
button_04_PDA_label=AUX2
|
||||
button_04_PDA_label=WATERFALL
|
||||
|
||||
button_05_label=Spa Blower
|
||||
#button_05_dzidx=41
|
||||
button_05_PDA_label=AUX3
|
||||
button_05_PDA_label=AIR BLOWER
|
||||
|
||||
button_06_label=Pool Light
|
||||
#button_06_dzidx=42
|
||||
button_06_PDA_label=AUX4
|
||||
button_06_PDA_label=LIGHT
|
||||
|
||||
button_07_label=NONE
|
||||
#button_07_dzidx=43
|
||||
|
|
Binary file not shown.
|
@ -217,7 +217,7 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
if (packet_buffer[PKT_DEST] == DEV_MASTER /*&& packet_buffer[PKT_CMD] == CMD_ACK*/) {
|
||||
//logMessage(LOG_DEBUG_SERIAL, "ID is in use 0x%02hhx %x\n", lastID, lastID);
|
||||
//logMessage(LOG_NOTICE, "ID is in use 0x%02hhx %x\n", lastID, lastID);
|
||||
for (i = 0; i <= sindex; i++) {
|
||||
if (slog[i].ID == lastID) {
|
||||
slog[i].inuse = true;
|
||||
|
@ -257,7 +257,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, "ID's found\n");
|
||||
for (i = 0; i <= sindex; i++) {
|
||||
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",
|
||||
// (slog[i].inuse == false && canUse(slog[i].ID) == true)? " <-- can use for Aqualinkd" : "");
|
||||
|
||||
|
|
46
utils.c
46
utils.c
|
@ -482,4 +482,50 @@ int ascii(char *destination, char *source) {
|
|||
}
|
||||
destination[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
|
||||
char *prittyString(char *str)
|
||||
{
|
||||
char *ptr = str;
|
||||
char *end;
|
||||
bool lastspace=true;
|
||||
|
||||
end = str + strlen(str) - 1;
|
||||
while(end >= ptr){
|
||||
//printf("%d %s ", *ptr, ptr);
|
||||
if (lastspace && *ptr > 96 && *ptr < 123) {
|
||||
*ptr = *ptr - 32;
|
||||
lastspace=false;
|
||||
//printf("to upper\n");
|
||||
} else if (lastspace == false && *ptr > 54 && *ptr < 91) {
|
||||
*ptr = *ptr + 32;
|
||||
lastspace=false;
|
||||
//printf("to lower\n");
|
||||
} else if (*ptr == 32) {
|
||||
lastspace=true;
|
||||
//printf("space\n");
|
||||
} else {
|
||||
lastspace=false;
|
||||
//printf("leave\n");
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
//printf("-- %s --\n", str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static FILE *_packetLogFile = NULL;
|
||||
|
||||
void writePacketLog(char *buffer) {
|
||||
if (_packetLogFile == NULL)
|
||||
_packetLogFile = fopen("/tmp/RS485.log", "a");
|
||||
|
||||
if (_packetLogFile != NULL) {
|
||||
fputs(buffer, _packetLogFile);
|
||||
}
|
||||
}
|
||||
void closePacketLog() {
|
||||
fclose(_packetLogFile);
|
||||
}
|
4
utils.h
4
utils.h
|
@ -49,7 +49,9 @@ float degFtoC(float degF);
|
|||
float degCtoF(float degC);
|
||||
char* stristr(const char* haystack, const char* needle);
|
||||
int ascii(char *destination, char *source);
|
||||
|
||||
char *prittyString(char *str);
|
||||
void writePacketLog(char *buff);
|
||||
void closePacketLog();
|
||||
|
||||
//#ifndef _UTILS_C_
|
||||
extern bool _daemon_;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
|
||||
#define AQUALINKD_NAME "Aqualink Daemon"
|
||||
#define AQUALINKD_VERSION "1.2.6f"
|
||||
#define AQUALINKD_VERSION "1.3.0"
|
||||
|
|
|
@ -1178,7 +1178,8 @@
|
|||
} else if (data.type == 'devices') {
|
||||
check_devices(data);
|
||||
resetBackgroundSize();
|
||||
window.setTimeout(get_devices, (300 * 1000)); // Check for new dvices ever 5 mins.
|
||||
//window.setTimeout(get_devices, (300 * 1000)); // Check for new dvices ever 5 mins.
|
||||
window.setTimeout(get_devices, (60 * 1000)); // Check for new dvices ever 1 mins.
|
||||
}
|
||||
}
|
||||
socket_di.onclose = function() {
|
||||
|
|
Loading…
Reference in New Issue