From 7144d35e33e0f868957ad77f98ec1b6084b9162c Mon Sep 17 00:00:00 2001 From: Lee Ballard Date: Wed, 25 Sep 2019 12:31:53 -0500 Subject: [PATCH] ballle98/AqualinkD#13: add time sync --- aq_programmer.c | 10 ++++-- aqualink.h | 2 ++ pda.c | 80 ++++++++++++++++++++++++++++++++++++++------- pda_aq_programmer.c | 72 ++++++++++++++++++++++++++++------------ pda_aq_programmer.h | 5 ++- pda_menu.c | 10 +++--- 6 files changed, 139 insertions(+), 40 deletions(-) diff --git a/aq_programmer.c b/aq_programmer.c index 6cf9f347..de3912f7 100644 --- a/aq_programmer.c +++ b/aq_programmer.c @@ -50,7 +50,6 @@ 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 ); bool waitForButtonState(struct aqualinkdata *aq_data, aqkey* button, aqledstate state, int numMessageReceived); @@ -238,7 +237,8 @@ void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data) type != AQ_GET_AUX_LABELS && #endif type != AQ_GET_POOL_SPA_HEATER_TEMPS && - type != AQ_SET_FRZ_PROTECTION_TEMP) { + type != AQ_SET_FRZ_PROTECTION_TEMP && + type != AQ_SET_TIME) { logMessage(LOG_ERR, "Selected Programming mode '%d' not supported with PDA mode control panel\n",type); return; } @@ -975,6 +975,12 @@ void *set_aqualink_time( void *ptr ) waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_TIME); logMessage(LOG_NOTICE, "Setting time on aqualink\n"); + if (pda_mode() == true) { + set_PDA_aqualink_time(aq_data); + cleanAndTerminateThread(threadCtrl); + return ptr; + } + time_t now = time(0); // get time now struct tm *result = localtime(&now); char hour[11]; diff --git a/aqualink.h b/aqualink.h index bc2500cf..c894b04a 100644 --- a/aqualink.h +++ b/aqualink.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "aq_serial.h" #include "aq_programmer.h" @@ -122,6 +123,7 @@ struct aqualinkdata struct timespec start_active_time; pthread_mutex_t mutex; pthread_cond_t thread_finished_cond; + struct tm tm; }; diff --git a/pda.c b/pda.c index b74eeee7..6d38a624 100644 --- a/pda.c +++ b/pda.c @@ -263,7 +263,31 @@ void process_pda_packet_msg_long_time(const char *msg) 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 + + time_t now; + + time(&now); + localtime_r(&now, &_aqualink_data->tm); + int real_wday = _aqualink_data->tm.tm_wday; + + char result[30]; + + if (strptime(msg, "%t%A%t%I:%M%p", &_aqualink_data->tm) == NULL) { + logMessage(LOG_DEBUG, "process_pda_packet_msg_long_time strptime failed\n"); + } else { + logMessage(LOG_DEBUG, "process_pda_packet_msg_long_time strptime %s\n", + asctime_r(&_aqualink_data->tm,result)); + if (real_wday != _aqualink_data->tm.tm_wday) { + logMessage(LOG_INFO, "Day of the week incorrect - request time set\n"); + aq_programmer(AQ_SET_TIME, NULL, _aqualink_data); + } else { + time_t display_time = mktime(&_aqualink_data->tm); + if (abs(difftime(display_time, now)) > 120) { + logMessage(LOG_INFO, "Time incorrect - request time set\n"); + aq_programmer(AQ_SET_TIME, NULL, _aqualink_data); + } + } + } } void process_pda_packet_msg_long_equipment_control(const char *msg) @@ -491,18 +515,46 @@ void process_pda_packet_msg_long_level_aux_device(const char *msg) #endif } +void process_pda_packet_msg_long_set_time(int index, const char *msg) +{ + // Line 0 = SET TIME + // Line 1 = + // Line 2 = 08/16/05 TUE + // Line 3 = 8:29 PM + // Line 4 = + // Line 5 = + // Line 6 = Use ARROW KEYS + // Line 7 = to set value. + // Line 8 = Press SELECT + // Line 9 = to continue. + if (index == 2) { + if (strptime(msg, "%t%D %a", &_aqualink_data->tm) == NULL) { + logMessage(LOG_ERR, "process_pda_packet_msg_long_set_time(%d,%.*s) failed\n", + index, AQ_MSGLEN, msg); + } + } else if (index == 3) { + if (strptime(msg, "%t%I:%M %p", &_aqualink_data->tm) == NULL) { + logMessage(LOG_ERR, "process_pda_packet_msg_long_set_time(%d,%.*s) failed\n", + index, AQ_MSGLEN, msg); + } + char result[30]; + logMessage(LOG_DEBUG, "process_pda_packet_msg_long_set_time %s\n", + asctime_r(&_aqualink_data->tm,result)); + } +} + 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 = + // Line 0 = FREEZE PROTECT + // Line 1 = DEVICES + // Line 2 = + // Line 3 = FILTER PUMP X + // Line 4 = SPA + // Line 5 = CLEANER X + // Line 6 = POOL LIGHT + // Line 7 = SPA LIGHT + // Line 8 = EXTRA AUX + // Line 9 = int i; logMessage(LOG_DEBUG, "process_pda_freeze_protect_devices\n"); for (i = 1; i < PDA_LINES; i++) @@ -524,6 +576,7 @@ bool process_pda_packet(unsigned char *packet, int length) bool rtn = true; int i; char *msg; + int index = -1; //static bool init = false; process_pda_menu_packet(packet, length); @@ -597,7 +650,7 @@ bool process_pda_packet(unsigned char *packet, int length) //printf ("menu type %d\n",pda_m_type()); msg = (char *)packet + PKT_DATA + 1; - + index = packet[PKT_DATA] & 0xF; //strcpy(_aqualink_data->last_message, msg); if (packet[PKT_DATA] == 0x82) @@ -638,6 +691,9 @@ bool process_pda_packet(unsigned char *packet, int length) case PM_AUX_LABEL_DEVICE: process_pda_packet_msg_long_level_aux_device(msg); break; + case PM_SET_TIME: + process_pda_packet_msg_long_set_time(index, msg); + break; //case PM_FW_VERSION: // process_pda_packet_msg_long_FW_version(msg); //break; diff --git a/pda_aq_programmer.c b/pda_aq_programmer.c index 144ab8d1..336fa001 100644 --- a/pda_aq_programmer.c +++ b/pda_aq_programmer.c @@ -795,13 +795,9 @@ bool waitForPDAMessageTypes(struct aqualinkdata *aq_data, unsigned char mtype1, return waitForPDAMessageTypesOrMenu(aq_data, mtype1, mtype2, 0xFF, sec, msec, NULL, 0); } -bool set_PDA_numeric_field_value(struct aqualinkdata *aq_data, int val, int *cur_val, char *select_label, int step) { +bool set_PDA_numeric_field_value(struct aqualinkdata *aq_data, int val, int cur_val, char *select_label, int step) { int i=0; - if (val == *cur_val) { - logMessage(LOG_INFO, "PDA %s value : already at %d\n", select_label, val); - return true; - } if (select_label != NULL) { // :TODO: 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 @@ -818,20 +814,22 @@ bool set_PDA_numeric_field_value(struct aqualinkdata *aq_data, int val, int *cur send_cmd(KEY_PDA_SELECT); } - if (val < *cur_val) { - logMessage(LOG_DEBUG, "PDA %s value : lower from %d to %d\n", select_label, *cur_val, val); - for (i = *cur_val; i > val; i=i-step) { + if (val == cur_val) { + logMessage(LOG_INFO, "PDA %s value : already at %d\n", select_label, val); + } else 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); } - } 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) { + } 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); } } send_cmd(KEY_PDA_SELECT); - logMessage(LOG_DEBUG, "PDA %s value : set to %d\n", select_label, *cur_val); + logMessage(LOG_DEBUG, "PDA %s value : set to %d\n", select_label, val); return true; } @@ -843,36 +841,36 @@ bool set_PDA_aqualink_SWG_setpoint(struct aqualinkdata *aq_data, int val) { } if (aq_data->aqbuttons[SPA_INDEX].led->state != OFF) - return set_PDA_numeric_field_value(aq_data, val, &aq_data->swg_percent, "SET SPA", 5); + return set_PDA_numeric_field_value(aq_data, val, aq_data->swg_percent, "SET SPA", 5); else - return set_PDA_numeric_field_value(aq_data, val, &aq_data->swg_percent, "SET POOL", 5); + return 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; + int cur_val; if ( aq_data->single_device != true ) { if (isPool) { sprintf(label, "POOL HEAT"); - cur_val = &aq_data->pool_htr_set_point; + cur_val = aq_data->pool_htr_set_point; } else { sprintf(label, "SPA HEAT"); - cur_val = &aq_data->spa_htr_set_point; + cur_val = aq_data->spa_htr_set_point; } } else { if (isPool) { sprintf(label, "TEMP1"); - cur_val = &aq_data->pool_htr_set_point; + cur_val = aq_data->pool_htr_set_point; } else { sprintf(label, "TEMP2"); - cur_val = &aq_data->spa_htr_set_point; + cur_val = aq_data->spa_htr_set_point; } } - if (val == *cur_val) { + if (val == cur_val) { logMessage(LOG_INFO, "PDA %s setpoint : temp already %d\n", label, val); send_cmd(KEY_PDA_BACK); return true; @@ -896,7 +894,7 @@ bool set_PDA_aqualink_freezeprotect_setpoint(struct aqualinkdata *aq_data, int v } else if (! goto_pda_menu(aq_data, PM_FREEZE_PROTECT)) { logMessage(LOG_ERR, "Error finding freeze protect setpoints menu\n"); return false; - } else if (! set_PDA_numeric_field_value(aq_data, val, &aq_data->frz_protect_set_point, NULL, 1)) { + } else if (! set_PDA_numeric_field_value(aq_data, val, aq_data->frz_protect_set_point, NULL, 1)) { logMessage(LOG_ERR, "Error failed to set freeze protect temp value\n"); return false; } else { @@ -904,6 +902,38 @@ bool set_PDA_aqualink_freezeprotect_setpoint(struct aqualinkdata *aq_data, int v } } +bool set_PDA_aqualink_time(struct aqualinkdata *aq_data) { + if (! goto_pda_menu(aq_data, PM_SET_TIME)) { + logMessage(LOG_ERR, "Error finding freeze protect setpoints menu\n"); + return false; + } + struct tm tm; + time_t now; + static char result[30]; + + time(&now); // get time now + localtime_r(&now, &tm); + logMessage(LOG_DEBUG, "set_PDA_aqualink_time %s\n", + asctime_r(&tm,result)); + if (! set_PDA_numeric_field_value(aq_data, tm.tm_mon, aq_data->tm.tm_mon, NULL, 1)) { + logMessage(LOG_ERR, "Error failed to set month\n"); + } else if (! set_PDA_numeric_field_value(aq_data, tm.tm_mday, aq_data->tm.tm_mday, NULL, 1)) { + logMessage(LOG_ERR, "Error failed to set day\n"); + } else if (! set_PDA_numeric_field_value(aq_data, tm.tm_year, aq_data->tm.tm_year, NULL, 1)) { + logMessage(LOG_ERR, "Error failed to set year\n"); + } else if (! set_PDA_numeric_field_value(aq_data, tm.tm_hour, aq_data->tm.tm_hour, NULL, 1)) { + logMessage(LOG_ERR, "Error failed to set hour\n"); + } else { + time(&now); // update time + localtime_r(&now, &tm); + if (! set_PDA_numeric_field_value(aq_data, tm.tm_min, aq_data->tm.tm_min, NULL, 1)) { + logMessage(LOG_ERR, "Error failed to set min\n"); + } + waitForPDAnextMenu(aq_data); + } + return true; +} + // Test ine this. bool get_PDA_aqualink_aux_labels(struct aqualinkdata *aq_data) { #ifdef BETA_PDA_AUTOLABEL diff --git a/pda_aq_programmer.h b/pda_aq_programmer.h index 60034b08..0ce34562 100644 --- a/pda_aq_programmer.h +++ b/pda_aq_programmer.h @@ -7,6 +7,7 @@ typedef enum pda_type { PDA } pda_type; +void *set_aqualink_PDA_init( void *ptr ); void *get_aqualink_PDA_device_status( void *ptr ); void *set_aqualink_PDA_device_on_off( void *ptr ); void *set_aqualink_PDA_wakeinit( void *ptr ); @@ -20,6 +21,8 @@ bool get_PDA_freeze_protect_temp(struct aqualinkdata *aq_data); bool get_PDA_aqualink_aux_labels(struct aqualinkdata *aq_data); +bool set_PDA_aqualink_time(struct aqualinkdata *aq_data); + //void pda_programming_thread_check(struct aqualinkdata *aq_data); -#endif // AQ_PDA_PROGRAMMER_H_ \ No newline at end of file +#endif // AQ_PDA_PROGRAMMER_H_ diff --git a/pda_menu.c b/pda_menu.c index 5acd6763..1e7cefe2 100644 --- a/pda_menu.c +++ b/pda_menu.c @@ -188,16 +188,18 @@ bool process_pda_menu_packet(unsigned char* packet, int length) signed char last_line; signed char line_shift; signed char i; + int index = 0; switch (packet[PKT_CMD]) { 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'; + index = packet[PKT_DATA] & 0xF; + if (index < 10) { + memset(_menu[index], 0, AQ_MSGLEN); + strncpy(_menu[index], (char*)packet+PKT_DATA+1, AQ_MSGLEN); + _menu[index][AQ_MSGLEN] = '\0'; } if (getLogLevel() >= LOG_DEBUG){print_menu();} break;