Version 1.3.3f

pull/76/head
sfeakes 2019-07-14 09:39:15 -05:00
parent c28ef1709c
commit c2fe658d17
13 changed files with 158 additions and 34 deletions

View File

@ -1,4 +1,8 @@
#
# Options
# make DEBUG=true // Turn on timing statments
# make EXFLAGS="-D BETA_PDA_AUTOLABEL" // Add compile flags
#
# define the C compiler to use
CC = gcc
@ -16,7 +20,7 @@ DBG =
# define any compile-time flags
#GCCFLAGS = -Wall -O3 -Wextra
GCCFLAGS = -Wall -O3
GCCFLAGS = -Wall -O3 $(EXFLAGS)
#GCCFLAGS = -Wall
#CFLAGS = -Wall -g $(LIBS)

View File

@ -63,7 +63,7 @@ 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.3d (a,b,c)
## Update in Release 1.3.3d (a,b,c,e,f)
* Some PDA fixes / enhancements.
## Update in Release 1.3.3
* AqualinkD will now automaticaly find a usable ID if not specifically configured.

View File

@ -233,6 +233,9 @@ void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data)
type != AQ_SET_SPA_HEATER_TEMP &&
type != AQ_SET_SWG_PERCENT &&
type != AQ_PDA_DEVICE_ON_OFF &&
#ifdef BETA_PDA_AUTOLABEL
type != AQ_GET_AUX_LABELS &&
#endif
type != AQ_GET_POOL_SPA_HEATER_TEMPS ) {
logMessage(LOG_ERR, "Selected Programming mode '%d' not supported with PDA mode control panel\n",type);
return;
@ -351,7 +354,7 @@ void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data)
logMessage (LOG_ERR, "could not create thread\n");
return;
}
break;
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");
@ -392,9 +395,9 @@ void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, pr
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);
logMessage (LOG_DEBUG, "Thread %d,%p sleeping, waiting for thread %d,%p to finish\n",
type, &threadCtrl->thread_id, threadCtrl->aq_data->active_thread.ptype,
threadCtrl->aq_data->active_thread.thread_id);
logMessage (LOG_DEBUG, "Thread %d,%p (%s) sleeping, waiting for thread %d,%p (%s) to finish\n",
type, &threadCtrl->thread_id, ptypeName(type),
threadCtrl->aq_data->active_thread.ptype, threadCtrl->aq_data->active_thread.thread_id, ptypeName(threadCtrl->aq_data->active_thread.ptype));
sleep(waitTime);
}
@ -415,22 +418,24 @@ void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, pr
#endif
//logMessage (LOG_DEBUG, "Thread %d is active\n", threadCtrl->aq_data->active_thread.thread_id);
logMessage (LOG_DEBUG, "Thread %d,%p is active\n",
logMessage (LOG_DEBUG, "Thread %d,%p is active (%s)\n",
threadCtrl->aq_data->active_thread.ptype,
threadCtrl->aq_data->active_thread.thread_id);
threadCtrl->aq_data->active_thread.thread_id,
ptypeName(threadCtrl->aq_data->active_thread.ptype));
}
void cleanAndTerminateThread(struct programmingThreadCtrl *threadCtrl)
{
#ifndef AQ_DEBUG
logMessage(LOG_DEBUG, "Thread %d,%p finished\n",threadCtrl->aq_data->active_thread.ptype, threadCtrl->thread_id);
logMessage(LOG_DEBUG, "Thread %d,%p (%s) finished\n",threadCtrl->aq_data->active_thread.ptype, threadCtrl->thread_id,ptypeName(threadCtrl->aq_data->active_thread.ptype));
#else
struct timespec elapsed;
clock_gettime(CLOCK_REALTIME, &threadCtrl->aq_data->last_active_time);
timespec_subtract(&elapsed, &threadCtrl->aq_data->last_active_time, &threadCtrl->aq_data->start_active_time);
logMessage(LOG_DEBUG, "Thread %d,%p finished in %d.%03ld sec\n",
logMessage(LOG_DEBUG, "Thread %d,%p (%s) finished in %d.%03ld sec\n",
threadCtrl->aq_data->active_thread.ptype,
threadCtrl->aq_data->active_thread.thread_id,
ptypeName(threadCtrl->aq_data->active_thread.ptype)
elapsed.tv_sec, elapsed.tv_nsec / 1000000L);
#endif
@ -634,6 +639,12 @@ void *get_aqualink_aux_labels( void *ptr )
waitForSingleThreadOrTerminate(threadCtrl, AQ_GET_AUX_LABELS);
if (pda_mode() == true) {
get_PDA_aqualink_aux_labels(aq_data);
cleanAndTerminateThread(threadCtrl);
return ptr;
}
if ( select_menu_item(aq_data, "REVIEW") != true ) {
logMessage(LOG_WARNING, "Could not select REVIEW menu\n");
cancel_menu();
@ -1489,7 +1500,7 @@ const char *ptypeName(program_type type)
return "Switch PDA device on/off";
break;
case AQ_GET_AUX_LABELS:
return "Get labels";
return "Get AUX labels";
break;
case AQ_PDA_WAKE_INIT:
return "PDA init after wake";

View File

@ -208,6 +208,7 @@ void processMessage(char *message)
static bool _gotREV = false;
static int freeze_msg_count = 0;
static int service_msg_count = 0;
static int swg_msg_count = 0;
// NSF replace message with msg
msg = stripwhitespace(message);
strcpy(_aqualink_data.last_message, msg);
@ -234,13 +235,13 @@ void processMessage(char *message)
_aqualink_data.service_mode_state = OFF;
service_msg_count = 0;
}
/*
// If we have more than 10 messages without "Service Mode is active" assume it's off.
if (_aqualink_data.service_mode_state == ON && service_msg_count++ > 10) {
_aqualink_data.service_mode_state = OFF;
service_msg_count = 0;
if (_aqualink_data.ar_swg_status == SWG_STATUS_ON && swg_msg_count++ > 20) {
_aqualink_data.ar_swg_status = SWG_STATUS_OFF;
swg_msg_count = 0;
}
*/
// If we have more than 10 messages without "FREE PROTECT ACTIVATED" assume it's off.
if (_aqualink_data.frz_protect_state == ON && freeze_msg_count++ > 10)
{
@ -362,11 +363,13 @@ void processMessage(char *message)
else if (strncasecmp(msg, MSG_SWG_PCT, MSG_SWG_PCT_LEN) == 0)
{
_aqualink_data.swg_percent = atoi(msg + MSG_SWG_PCT_LEN);
//logMessage(LOG_DEBUG, "Stored SWG Percent as %d\n", _aqualink_data.swg_percent);
if (_aqualink_data.ar_swg_status == SWG_STATUS_OFF) {_aqualink_data.ar_swg_status = SWG_STATUS_ON; swg_msg_count = 0;}
//logMessage(LOG_DEBUG, "*** '%s' ***\n", msg);
}
else if (strncasecmp(msg, MSG_SWG_PPM, MSG_SWG_PPM_LEN) == 0)
{
_aqualink_data.swg_ppm = atoi(msg + MSG_SWG_PPM_LEN);
if (_aqualink_data.ar_swg_status == SWG_STATUS_OFF) {_aqualink_data.ar_swg_status = SWG_STATUS_ON; swg_msg_count = 0;}
//logMessage(LOG_DEBUG, "Stored SWG PPM as %d\n", _aqualink_data.swg_ppm);
}
else if ((msg[1] == ':' || msg[2] == ':') && msg[strlen(msg) - 1] == 'M')
@ -1031,7 +1034,11 @@ void main_loop()
if (_config_parameters.pda_mode == true)
{
init_pda(&_aqualink_data);
#ifdef BETA_PDA_AUTOLABEL
init_pda(&_aqualink_data, &_config_parameters);
#else
init_pda(&_aqualink_data);
#endif
}
if (_config_parameters.device_id == 0x00) {
@ -1139,6 +1146,7 @@ void main_loop()
_aqualink_data.swg_delayed_percent = TEMP_UNKNOWN;
}
_aqualink_data.swg_ppm = packet_buffer[4] * 100;
//logMessage(LOG_DEBUG, "Read SWG PPM %d from ID 0x%02hhx\n", _aqualink_data.swg_ppm, SWG_DEV_ID);
}
interestedInNextAck = false;
}
@ -1154,6 +1162,7 @@ void main_loop()
{
// Only read SWG Percent if we are not programming, as we might be changing this
_aqualink_data.swg_percent = (int)packet_buffer[4];
//logMessage(LOG_DEBUG, "Read SWG Percent %d from ID 0x%02hhx\n", _aqualink_data.swg_percent, SWG_DEV_ID);
}
}
else

66
pda.c
View File

@ -6,11 +6,14 @@
#include <time.h>
#include "aqualink.h"
#include "init_buttons.h"
#include "pda.h"
#include "pda_menu.h"
#include "utils.h"
// static struct aqualinkdata _aqualink_data;
static struct aqualinkdata *_aqualink_data;
static unsigned char _last_packet_type;
@ -22,11 +25,23 @@ static bool _initWithRS = false;
#define PDA_SLEEP_FOR 120 // 30 seconds
#define PDA_WAKE_FOR 6 // ~1 seconds
#ifdef BETA_PDA_AUTOLABEL
static struct aqconfig *_aqualink_config;
void init_pda(struct aqualinkdata *aqdata, struct aqconfig *aqconfig)
{
_aqualink_data = aqdata;
_aqualink_config = aqconfig;
set_pda_mode(true);
}
#else
void init_pda(struct aqualinkdata *aqdata)
{
_aqualink_data = aqdata;
set_pda_mode(true);
}
#endif
bool pda_shouldSleep() {
//logMessage(LOG_DEBUG, "PDA loop count %d, will sleep at %d\n",_pda_loop_cnt,PDA_LOOP_COUNT);
@ -448,6 +463,40 @@ void process_pda_packet_msg_long_unknown(const char *msg)
}
}
void process_pda_packet_msg_long_level_aux_device(const char *msg)
{
#ifdef BETA_PDA_AUTOLABEL
int li=-1;
char *str, *label;
if (! _aqualink_config->use_panel_aux_labels)
return;
// NSF Need to check config for use_panel_aux_labels value and ignore if not set
// Only care once we have the full menu, so check line
// PDA Line 0 = LABEL AUX1
// PDA Line 1 =
// PDA Line 2 = CURRENT LABEL
// PDA Line 3 = AUX1
if ( (strlen(pda_m_line(3)) > 0 ) &&
(strncasecmp(pda_m_line(2)," CURRENT LABEL ", 16) == 0) &&
(strncasecmp(pda_m_line(0)," LABEL AUX", 12) == 0) ) {
str = pda_m_line(0);
li = atoi(&str[12] ); // 12 is a guess, need to check on real system
if (li > 0) {
str = cleanwhitespace(pda_m_line(3));
label = (char*)malloc(strlen(str)+1);
strcpy ( label, str );
_aqualink_data->aqbuttons[li-1].pda_label = label;
} else {
logMessage(LOG_ERR, "PDA couldn't get AUX? number\n", pda_m_line(0));
}
}
#endif
}
void process_pda_freeze_protect_devices()
{
// PDA Line 0 = FREEZE PROTECT
@ -481,7 +530,7 @@ bool process_pda_packet(unsigned char *packet, int length)
bool rtn = true;
int i;
char *msg;
static bool init = false;
//static bool init = false;
process_pda_menu_packet(packet, length);
@ -496,10 +545,12 @@ bool process_pda_packet(unsigned char *packet, int length)
case CMD_ACK:
logMessage(LOG_DEBUG, "RS Received ACK length %d.\n", length);
if (init == false)
//if (init == false)
if (_initWithRS == false)
{
logMessage(LOG_DEBUG, "Running PDA_INIT\n");
aq_programmer(AQ_PDA_INIT, NULL, _aqualink_data);
init = true;
//init = true;
}
break;
@ -585,6 +636,9 @@ bool process_pda_packet(unsigned char *packet, int length)
case PM_AQUAPURE:
process_pda_packet_msg_long_SWG(msg);
break;
case PM_AUX_LABEL_DEVICE:
process_pda_packet_msg_long_level_aux_device(msg);
break;
//case PM_FW_VERSION:
// process_pda_packet_msg_long_FW_version(msg);
//break;
@ -609,6 +663,12 @@ bool process_pda_packet(unsigned char *packet, int length)
_initWithRS = true;
logMessage(LOG_DEBUG, "**** PDA INIT ****");
aq_programmer(AQ_PDA_INIT, NULL, _aqualink_data);
delay(50); // Make sure this one runs first.
#ifdef BETA_PDA_AUTOLABEL
if (_aqualink_config->use_panel_aux_labels)
aq_programmer(AQ_GET_AUX_LABELS, NULL, _aqualink_data);
#endif
aq_programmer(AQ_PDA_WAKE_INIT, NULL, _aqualink_data);
} else {
logMessage(LOG_DEBUG, "**** PDA WAKE INIT ****");
aq_programmer(AQ_PDA_WAKE_INIT, NULL, _aqualink_data);

9
pda.h
View File

@ -3,7 +3,14 @@
#ifndef PDA_H_
#define PDA_H_
void init_pda(struct aqualinkdata *aqdata);
#ifdef BETA_PDA_AUTOLABEL
#include "aqualink.h"
#include "config.h"
void init_pda(struct aqualinkdata *aqdata, struct aqconfig *aqconfig);
#else
void init_pda(struct aqualinkdata *aqdata);
#endif
bool process_pda_packet(unsigned char* packet, int length);
bool pda_shouldSleep();
void pda_wake();

View File

@ -421,12 +421,12 @@ void *set_aqualink_PDA_init( void *ptr )
//printf("****** Version '%s' ********\n",aq_data->version);
}
/*
// 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");
@ -437,7 +437,6 @@ void *set_aqualink_PDA_init( void *ptr )
logMessage(LOG_ERR, "PDA Init :- Error getting freeze setpoints\n");
}
goto_pda_menu(aq_data, PM_HOME);
pda_reset_sleep();
@ -709,6 +708,30 @@ bool set_PDA_aqualink_freezeprotect_setpoint(struct aqualinkdata *aq_data, int v
//return true;
}
// Test ine this.
bool get_PDA_aqualink_aux_labels(struct aqualinkdata *aq_data) {
#ifdef BETA_PDA_AUTOLABEL
int i=0;
char label[10];
logMessage(LOG_INFO, "Finding PDA labels, (BETA ONLY)\n");
if (! goto_pda_menu(aq_data, PM_AUX_LABEL)) {
logMessage(LOG_ERR, "Error finding aux label menu\n");
return false;
}
for (i=1;i<8;i++) {
sprintf(label, "AUX%d",i);
select_pda_menu_item(aq_data, label, true);
send_cmd(KEY_PDA_BACK);
waitForPDAnextMenu(aq_data);
}
// Read first page of devices and make some assumptions.
#endif
return true;
}
/*
bool waitForPDAMessage(struct aqualinkdata *aq_data, int numMessageReceived, unsigned char packettype)

View File

@ -18,6 +18,8 @@ bool set_PDA_aqualink_freezeprotect_setpoint(struct aqualinkdata *aq_data, int v
bool get_PDA_aqualink_pool_spa_heater_temps(struct aqualinkdata *aq_data);
bool get_PDA_freeze_protect_temp(struct aqualinkdata *aq_data);
bool get_PDA_aqualink_aux_labels(struct aqualinkdata *aq_data);
//void pda_programming_thread_check(struct aqualinkdata *aq_data);
#endif // AQ_PDA_PROGRAMMER_H_

View File

@ -123,6 +123,11 @@ pda_menu_type pda_m_type()
strncasecmp(_menu[1]," AquaPalm", 12) == 0 ||
strncasecmp(_menu[1]," PDA-P", 6) == 0) // PDA-P4 Only -or- PDA-PS4 Combo
return PM_FW_VERSION;
else if (strncasecmp(_menu[0]," LABEL AUX ", 16) == 0) // Catch AUX and not AUX4
return PM_AUX_LABEL;
else if (strncasecmp(_menu[0]," LABEL AUX", 12) == 0 && // Will have number ie AUX4
strncasecmp(_menu[2]," CURRENT LABEL ", 16) == 0)
return PM_AUX_LABEL_DEVICE;
return PM_UNKNOWN;
}

View File

@ -20,6 +20,7 @@ typedef enum pda_menu_type {
PM_AQUAPURE,
PM_SYSTEM_SETUP,
PM_AUX_LABEL,
PM_AUX_LABEL_DEVICE, // label a specific device
PM_FREEZE_PROTECT,
PM_FREEZE_PROTECT_DEVICES,
PM_VSP,

Binary file not shown.

View File

@ -105,14 +105,15 @@ light_programming_initial_off=12
# Everything below here, if it ends with dzidx, then that's the ID for domoticz,
# so not needed if you are not suing dooticz.
# Domoticz ID's for temps.
air_temp_dzidx=0
pool_water_temp_dzidx=0
spa_water_temp_dzidx=0
SWG_percent_dzidx=0
SWG_PPM_dzidx=0
#air_temp_dzidx=0
#pool_water_temp_dzidx=0
#spa_water_temp_dzidx=0
#SWG_percent_dzidx=0
#SWG_PPM_dzidx=0
# Try to use labels from Control Panel.
# Use/find labels from Control Panel, these will overwrite the button_xx_label below,
# it dows NOT work in PDA mode.
use_panel_aux_labels=no
# These are all the button labels you want to use for the web interface and Domoticz virtual sensors.
@ -122,7 +123,7 @@ use_panel_aux_labels=no
# Optional, If you have a Variable Speed Pump, then assign the RS485 ID to the button below so RPM/GPH/WATTS are displayed
# Format is button_01_pumpID=0x60. Leave blank if you don't have a VSP.
# Pentair pump ID's
# 0x60 to 0x6F (0x60, 0x61 0x61, 0x62, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F)
# 0x60 to 0x6F (0x60, 0x61 0x62, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F)
# Jandy pump ID's
# 0x78, 0x79, 0x7A, 0x7B
@ -143,6 +144,7 @@ button_03_label=Cleaner
button_04_label=Waterfall
#button_04_dzidx=40
#button_04_PDA_label=AUX2
#button_01_pumpID=0x61
button_05_label=Spa Blower
#button_05_dzidx=41

View File

@ -1,4 +1,4 @@
#define AQUALINKD_NAME "Aqualink Daemon"
#define AQUALINKD_VERSION "1.3.3d"
#define AQUALINKD_VERSION "1.3.3f"