From f5af49b5a898efc1ab9fb994ee044a155435e051 Mon Sep 17 00:00:00 2001 From: Lee Ballard Date: Fri, 14 Jun 2019 14:47:20 -0500 Subject: [PATCH] ballle98/AqualinkD#21: unpredictable waitForPDAMessageType added 45 second delay --- pda_aq_programmer.c | 152 +++++++++++++++++++++++++------------------- 1 file changed, 86 insertions(+), 66 deletions(-) diff --git a/pda_aq_programmer.c b/pda_aq_programmer.c index 20c66a64..66a6e2a6 100644 --- a/pda_aq_programmer.c +++ b/pda_aq_programmer.c @@ -41,9 +41,16 @@ #endif bool waitForPDAMessageHighlight(struct aqualinkdata *aq_data, int highlighIndex, int numMessageReceived); -bool waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, int numMessageReceived); -bool waitForPDAMessageTypes(struct aqualinkdata *aq_data, unsigned char mtype1, unsigned char mtype2, int numMessageReceived); -bool waitForPDAMessageTypesOrMenu(struct aqualinkdata *aq_data, unsigned char mtype1, unsigned char mtype2, int numMessageReceived, char *text, int line); +static bool waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, + unsigned long sec, unsigned long msec); +static bool _waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, + unsigned long sec, unsigned long msec, bool forceNext); +bool waitForPDAMessageTypes(struct aqualinkdata *aq_data, unsigned char mtype1, unsigned char mtype2, unsigned long sec, unsigned long msec); +bool waitForPDAMessageTypesOrMenu(struct aqualinkdata *aq_data, unsigned char mtype1, unsigned char mtype2, unsigned long sec, unsigned long msec, char *text, int line); +static bool _waitForPDAMessageTypesOrMenu(struct aqualinkdata *aq_data, + unsigned char mtype1, unsigned char mtype2, + unsigned long sec, unsigned long msec, + char *text, int line, bool forceNext); 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); @@ -112,8 +119,8 @@ bool wait_pda_selected_item(struct aqualinkdata *aq_data) { int i=0; - while (pda_m_hlightindex() == -1 && i < 5){ - waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,10); + while ((pda_m_hlightindex() == -1) && (i < 5)){ + waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,2,0); i++; } @@ -124,9 +131,10 @@ bool wait_pda_selected_item(struct aqualinkdata *aq_data) } bool waitForPDAnextMenu(struct aqualinkdata *aq_data) { - if (!waitForPDAMessageType(aq_data,CMD_PDA_CLEAR,10)) + if (!waitForPDAMessageType(aq_data,CMD_PDA_CLEAR,2,0)) { return false; - return waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,15); + } + return waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,3,0); } bool loopover_devices(struct aqualinkdata *aq_data) { @@ -143,7 +151,7 @@ bool loopover_devices(struct aqualinkdata *aq_data) { for (i=0; i < 18 && (index = pda_find_m_index("ALL OFF")) == -1 ; i++) { send_cmd(KEY_PDA_DOWN); //waitForMessage(aq_data, NULL, 1); - waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_MSG_LONG,8); + waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_MSG_LONG,2,0); } if (index == -1) { LOG(PDA_LOG,LOG_ERR, "loopover_devices :- can't find ALL OFF\n"); @@ -184,7 +192,7 @@ bool find_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, int charli //delay(500); //wait_for_empty_cmd_buffer(); //waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,2); - waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_MSG_LONG,8); + waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_MSG_LONG,2,0); //waitForMessage(aq_data, NULL, 1); index = (charlimit == 0)?pda_find_m_index(menuText):pda_find_m_index_case(menuText, charlimit); if (index >= 0) { @@ -359,7 +367,7 @@ bool goto_pda_menu(struct aqualinkdata *aq_data, pda_menu_type menu) { } } else if (pda_m_type() == PM_BUILDING_HOME) { LOG(PDA_LOG,LOG_DEBUG, "goto_pda_menu building home menu\n"); - waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,15); + waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,3,0); } @@ -466,7 +474,7 @@ bool goto_pda_menu(struct aqualinkdata *aq_data, pda_menu_type menu) { LOG(PDA_LOG,LOG_DEBUG, "PDA in single device mode, \n"); ret = select_pda_menu_item(aq_data, "SET TEMP", false); // We could press enter here, but I can't test it, so just wait for message to dissapear. - ret = waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,25); + ret = waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,5,0); //waitForPDAMessageType(aq_data,CMD_PDA_CLEAR,10); //waitForPDAMessageTypesOrMenu(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,20,"press ANY key",8); } @@ -558,14 +566,14 @@ void *set_aqualink_PDA_device_on_off( void *ptr ) } else { send_cmd(KEY_PDA_SELECT); while (get_aq_cmd_length() > 0) { delay(500); } - if (!waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,20)) { + if (!waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,5,0)) { LOG(PDA_LOG,LOG_ERR, "PDA Device On/Off: %s on - wait for CMD_PDA_HIGHLIGHT\n", aq_data->aqbuttons[device].label); } } } else { // not turning on heater wait for line update // worst case spa when pool is running - if (!waitForPDAMessageType(aq_data,CMD_MSG_LONG,2)) { + if (!waitForPDAMessageType(aq_data,CMD_MSG_LONG,0,500)) { LOG(PDA_LOG,LOG_ERR, "PDA Device On/Off: %s on - wait for CMD_MSG_LONG\n", aq_data->aqbuttons[device].label); } @@ -642,8 +650,8 @@ void *set_aqualink_PDA_init( void *ptr ) // don't wait for version menu to time out press back to get to home menu faster //send_cmd(KEY_PDA_BACK); //if (! waitForPDAnextMenu(aq_data)) { // waitForPDAnextMenu waits for highlight chars, which we don't get on normal menu - - if (! waitForPDAMessageType(aq_data,CMD_PDA_CLEAR,10)) { + // :TODO: perhaps get rid of this and restore KEY_PDA_BACK + if (! waitForPDAMessageType(aq_data,CMD_PDA_CLEAR, 2, 0)) { LOG(PDA_LOG,LOG_ERR, "PDA Init :- wait for next menu failed\n"); } } @@ -763,88 +771,100 @@ bool waitForPDAMessageHighlight(struct aqualinkdata *aq_data, int highlighIndex, } -bool _waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, int numMessageReceived, bool forceNext) +static bool _waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, + unsigned long sec, unsigned long msec, bool forceNext) { - LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageType 0x%02hhx\n",mtype); - - int i=0; - pthread_mutex_lock(&aq_data->active_thread.thread_mutex); - - if (forceNext) { // Ignore current message type, and wait for next - pthread_cond_wait(&aq_data->active_thread.thread_cond, &aq_data->active_thread.thread_mutex); - } - - while( ++i <= numMessageReceived) - { - LOG(PDA_LOG,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_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) { - //LOG(PDA_LOG,LOG_ERR, "Could not select MENU of Aqualink control panel\n"); - LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageType: did not receive 0x%02hhx\n",mtype); - return false; - } else - LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageType: received 0x%02hhx\n",mtype); - - return true; + return _waitForPDAMessageTypesOrMenu(aq_data, mtype, 0xFF, sec, msec, NULL, 0, forceNext); } -bool waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, int numMessageReceived){ - return _waitForPDAMessageType(aq_data, mtype, numMessageReceived, false); +static bool waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, + unsigned long sec, unsigned long msec) { + return _waitForPDAMessageType(aq_data, mtype, sec, msec, false); } -bool waitForPDANextMessageType(struct aqualinkdata *aq_data, unsigned char mtype, int numMessageReceived){ - return _waitForPDAMessageType(aq_data, mtype, numMessageReceived, true); +bool waitForPDANextMessageType(struct aqualinkdata *aq_data, unsigned char mtype, + unsigned long sec, unsigned long msec) { + return _waitForPDAMessageType(aq_data, mtype, sec, msec, true); } // Wait for Message, hit return on particular menu. -bool waitForPDAMessageTypesOrMenu(struct aqualinkdata *aq_data, unsigned char mtype1, unsigned char mtype2, int numMessageReceived, char *text, int line) +bool waitForPDAMessageTypesOrMenu(struct aqualinkdata *aq_data, unsigned char mtype1, unsigned char mtype2, unsigned long sec, unsigned long msec, char *text, int line) { - LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageTypes 0x%02hhx or 0x%02hhx\n",mtype1,mtype2); + return _waitForPDAMessageTypesOrMenu(aq_data, mtype1, mtype2, sec, msec, text, line, false); +} + +static bool _waitForPDAMessageTypesOrMenu(struct aqualinkdata *aq_data, unsigned char mtype1, unsigned char mtype2, unsigned long sec, unsigned long msec, char *text, int line, bool forceNext) +{ + LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageTypesOrMenu 0x%02hhx,0x%02hhx,%s,%d,%lu.%03lu sec\n", + mtype1,mtype2,text,line,sec, msec); int i=0; bool gotmenu = false; + struct timespec max_wait; + int ret = 0; + + if (msec > 999) + { + LOG(PDA_LOG,LOG_ERR, "waitForPDAMessageTypesOrMenu INVALID msec value %lu\n", msec); + } + clock_gettime(CLOCK_REALTIME, &max_wait); + max_wait.tv_sec += sec; + max_wait.tv_nsec += msec*1000000; + if (max_wait.tv_nsec > 999999999L) { + max_wait.tv_nsec -= 1000000000L; + max_wait.tv_sec++; + } pthread_mutex_lock(&aq_data->active_thread.thread_mutex); - while( ++i <= numMessageReceived) - { + if (forceNext) { // Ignore current message type, and wait for next + + if ((ret = pthread_cond_timedwait(&aq_data->active_thread.thread_cond, + &aq_data->active_thread.thread_mutex, &max_wait))) { + LOG(PDA_LOG,LOG_ERR, "waitForPDAMessageTypesOrMenu 0x%02hhx,0x%02hhx,%s,%d - %s\n", + mtype1, mtype2, text,line, strerror(ret)); + } + } + + while (true) { + i++; if (gotmenu == false && line > 0 && text != NULL) { if (stristr(pda_m_line(line), text) != NULL) { send_cmd(KEY_PDA_SELECT); gotmenu = true; - LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageTypesOrMenu saw '%s' and line %d\n",text,line); + LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageTypesOrMenu saw '%s' in line %d\n",text,line); } } - LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageTypes 0x%02hhx | 0x%02hhx, last message type was 0x%02hhx (%d of %d)\n",mtype1,mtype2,aq_data->last_packet_type,i,numMessageReceived); - - if (aq_data->last_packet_type == mtype1 || aq_data->last_packet_type == mtype2) break; - - pthread_cond_wait(&aq_data->active_thread.thread_cond, &aq_data->active_thread.thread_mutex); + if (aq_data->last_packet_type == mtype1 || aq_data->last_packet_type == mtype2) { + break; + } + LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageTypesOrMenu last message type 0x%02hhx (%d)\n", aq_data->last_packet_type, i); + if ((ret = pthread_cond_timedwait(&aq_data->active_thread.thread_cond, + &aq_data->active_thread.thread_mutex, &max_wait))) { + LOG(PDA_LOG,LOG_ERR, "waitForPDAMessageTypesOrMenu 0x%02hhx,0x%02hhx,%s,%d - %s\n", + mtype1, mtype2, text,line, strerror(ret)); + break; + } } pthread_mutex_unlock(&aq_data->active_thread.thread_mutex); if (aq_data->last_packet_type != mtype1 && aq_data->last_packet_type != mtype2) { //LOG(PDA_LOG,LOG_ERR, "Could not select MENU of Aqualink control panel\n"); - LOG(PDA_LOG,LOG_ERR, "waitForPDAMessageTypes: did not receive 0x%02hhx or 0x%02hhx\n",mtype1,mtype2); + LOG(PDA_LOG,LOG_ERR, "waitForPDAMessageTypesOrMenu: did not receive 0x%02hhx or 0x%02hhx\n",mtype1,mtype2); return false; - } else - LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageTypes: received 0x%02hhx\n",aq_data->last_packet_type); - + } else { + LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageTypesOrMenu: received 0x%02hhx\n",aq_data->last_packet_type); + } return true; } -bool waitForPDAMessageTypes(struct aqualinkdata *aq_data, unsigned char mtype1, unsigned char mtype2, int numMessageReceived) +bool waitForPDAMessageTypes(struct aqualinkdata *aq_data, unsigned char mtype1, + unsigned char mtype2, unsigned long sec, + unsigned long msec) { - return waitForPDAMessageTypesOrMenu(aq_data, mtype1, mtype2, numMessageReceived, NULL, 0); + return waitForPDAMessageTypesOrMenu(aq_data, mtype1, mtype2, sec, msec, NULL, 0); } /* @@ -868,7 +888,7 @@ bool set_PDA_numeric_field_value(struct aqualinkdata *aq_data, int val, int cur_ hghlight_chars = pda_m_hlightchars(&hlight_length); // NSF May need to take this out and there for the LOG entry after while while (hlight_length >= 15 || hlight_length <= 0) { delay(500); - waitForPDANextMessageType(aq_data,CMD_PDA_HIGHLIGHTCHARS,5); + waitForPDANextMessageType(aq_data,CMD_PDA_HIGHLIGHTCHARS, 1, 0); hghlight_chars = pda_m_hlightchars(&hlight_length); LOG(PDA_LOG,LOG_DEBUG, "Numeric selector, highlight chars '%.*s'\n",hlight_length , hghlight_chars); if (++i >= 20) { @@ -908,7 +928,7 @@ bool set_PDA_aqualink_SWG_setpoint(struct aqualinkdata *aq_data, int val) { return false; } // wait for menu to display to capture current value with process_pda_packet_msg_long_SWG - waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS, 10); + waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS, 2, 0); if (pda_find_m_index("SET POOL") < 0) { // Single Setpoint Screen