Host library for controlling a WiConnect enabled Wi-Fi module.
Dependents: wiconnect-ota_example wiconnect-web_setup_example wiconnect-test-console wiconnect-tcp_server_example ... more
ProcessCommand.cpp
00001 /** 00002 * ACKme WiConnect Host Library is licensed under the BSD licence: 00003 * 00004 * Copyright (c)2014 ACKme Networks. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without modification, 00008 * are permitted provided that the following conditions are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright notice, 00011 * this list of conditions and the following disclaimer. 00012 * 2. Redistributions in binary form must reproduce the above copyright notice, 00013 * this list of conditions and the following disclaimer in the documentation 00014 * and/or other materials provided with the distribution. 00015 * 3. The name of the author may not be used to endorse or promote products 00016 * derived from this software without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED 00019 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00020 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00021 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00022 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00023 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00026 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00027 * OF SUCH DAMAGE. 00028 */ 00029 00030 #include "internal/CommandCommon.h" 00031 00032 00033 00034 /*************************************************************************************************/ 00035 WiconnectResult Wiconnect::checkCurrentCommand() 00036 { 00037 WiconnectResult result; 00038 00039 start: 00040 CHECK_INITIALIZED(); 00041 if(!commandExecuting) 00042 { 00043 return WICONNECT_IDLE; 00044 } 00045 CommandContext *context = (CommandContext*)commandContext; 00046 00047 if(context->commandLen > 0) 00048 { 00049 const TimerTimeout timeout = context->nonBlocking ? 0 : timeoutTimer.remainingMs(context->timeoutMs); 00050 const int bytesToWrite = context->commandLen; 00051 const int bytesWritten = serial.write(context->commandPtr, bytesToWrite, timeout); 00052 context->commandPtr += bytesWritten; 00053 context->commandLen -= bytesWritten; 00054 if(bytesToWrite != bytesWritten) 00055 { 00056 if(timeoutTimer.timedOut(context->timeoutMs)) 00057 { 00058 issueCommandCallback(WICONNECT_TIMEOUT); 00059 return WICONNECT_TIMEOUT; 00060 } 00061 else 00062 { 00063 return WICONNECT_PROCESSING; 00064 } 00065 } 00066 } 00067 00068 while(context->reader.isValid()) 00069 { 00070 if(context->bytesToWrite == 0) 00071 { 00072 context->responseBufferPtr = context->responseBuffer; 00073 if(WICONNECT_FAILED(result, context->reader.call(context->user, context->responseBuffer, context->responseBufferLen, &context->bytesToWrite))) 00074 { 00075 issueCommandCallback(result); 00076 return result; 00077 } 00078 else if(context->bytesToWrite == EOF) 00079 { 00080 context->reader.setInvalid(); 00081 context->bytesToWrite = 0; 00082 context->responseBufferPtr = context->responseBuffer; 00083 break; 00084 } 00085 else 00086 { 00087 timeoutTimer.reset(); 00088 } 00089 } 00090 if(context->bytesToWrite > 0) 00091 { 00092 const TimerTimeout timeout = context->nonBlocking ? 0 : timeoutTimer.remainingMs(context->timeoutMs); 00093 const int bytesToWrite = context->bytesToWrite; 00094 const int bytesWritten = serial.write(context->responseBufferPtr, bytesToWrite, timeout); 00095 context->responseBufferPtr += bytesWritten; 00096 context->bytesToWrite -= bytesWritten; 00097 if(bytesToWrite != bytesWritten) 00098 { 00099 if(timeoutTimer.timedOut(context->timeoutMs)) 00100 { 00101 issueCommandCallback(WICONNECT_TIMEOUT); 00102 return WICONNECT_TIMEOUT; 00103 } 00104 else 00105 { 00106 return WICONNECT_PROCESSING; 00107 } 00108 } 00109 } 00110 } 00111 00112 result = receiveResponse(); 00113 if(result == WICONNECT_PROCESSING && !context->nonBlocking) 00114 { 00115 goto start; 00116 } 00117 return result; 00118 } 00119 00120 /*************************************************************************************************/ 00121 WiconnectResult Wiconnect::receiveResponse() 00122 { 00123 loop: 00124 WiconnectResult result = receivePacket(); 00125 00126 if(result == WICONNECT_PROCESSING) 00127 { 00128 } 00129 else if(result == WICONNECT_SUCCESS) 00130 { 00131 CommandHeader *header = (CommandHeader*)commandHeaderBuffer; 00132 CommandContext *context = (CommandContext*)commandContext; 00133 00134 // TODO: need to notify safemode 00135 00136 if(header->response_type == WICONNECT_CMD_TYPE_REPLY || header->response_type == WICONNECT_CMD_TYPE_SAFEMODE) 00137 { 00138 if(header->response_code != WICONNECT_CMD_SUCCESS) 00139 { 00140 DEBUG_CMD_ERROR(header->response_code); 00141 flush(); 00142 issueCommandCallback(WICONNECT_CMD_RESPONSE_ERROR); 00143 return WICONNECT_CMD_RESPONSE_ERROR; 00144 } 00145 else if(header->response_len > 0) 00146 { 00147 DEBUG_CMD_RESPONSE(context->responseBuffer); 00148 00149 if(header->response_len < (uint16_t)context->responseBufferLen) 00150 { 00151 context->responseBuffer[header->response_len] = 0; 00152 } 00153 } 00154 else 00155 { 00156 *context->responseBuffer = 0; 00157 } 00158 00159 issueCommandCallback(WICONNECT_SUCCESS); 00160 00161 return WICONNECT_SUCCESS; 00162 } 00163 else 00164 { 00165 DEBUG_CMD_LOG(context->responseBuffer); 00166 RESET_CMD_HEADER(header); 00167 context->responseBufferPtr = context->responseBuffer; 00168 goto loop; 00169 } 00170 } 00171 else 00172 { 00173 issueCommandCallback(result); 00174 } 00175 00176 return result; 00177 } 00178 00179 /*************************************************************************************************/ 00180 WiconnectResult Wiconnect::receivePacket() 00181 { 00182 CommandHeader *header = (CommandHeader*)commandHeaderBuffer; 00183 CommandContext *context = (CommandContext*)commandContext; 00184 if(header->bytes_remaining > 0) 00185 { 00186 uint16_t bytesReceived; 00187 static uint8_t buffer[WICONNECT_HEADER_LENGTH]; 00188 00189 while(header->bytes_remaining > 0) 00190 { 00191 const TimerTimeout timeout = context->nonBlocking ? 0 : timeoutTimer.remainingMs(context->timeoutMs); 00192 bytesReceived = serial.read((char*)buffer, header->bytes_remaining, timeout); 00193 if(bytesReceived == 0) 00194 { 00195 return timeoutTimer.timedOut(context->timeoutMs) ? WICONNECT_TIMEOUT : WICONNECT_PROCESSING; 00196 } 00197 00198 for(uint8_t *ptr = buffer; bytesReceived > 0; ++ptr) 00199 { 00200 if(header->response_type == WICONNECT_CMD_TYPE_NULL) 00201 { 00202 if( *ptr == WICONNECT_CMD_TYPE_REPLY || 00203 *ptr == WICONNECT_CMD_TYPE_LOG || 00204 *ptr == WICONNECT_CMD_TYPE_SAFEMODE) 00205 { 00206 header->response_type = (ResponseType)*ptr; 00207 -- header->bytes_remaining; 00208 } 00209 --bytesReceived; 00210 } 00211 else if(header->response_code == WICONNECT_CMD_CODE_NULL) 00212 { 00213 if(*ptr >= '0' && *ptr <= '7') 00214 { 00215 header->response_code = (ResponseCode)(*ptr - '0' + 1); 00216 --header->bytes_remaining; 00217 header->len_buffer_ptr = header->len_buffer; 00218 } 00219 else 00220 { 00221 RESET_CMD_HEADER(header); 00222 } 00223 --bytesReceived; 00224 } 00225 else if(header->bytes_remaining > 2) 00226 { 00227 uint8_t len_chars = MIN((int)bytesReceived, (int)(header->bytes_remaining-2)); 00228 header->bytes_remaining -= len_chars; 00229 bytesReceived -= len_chars; 00230 while(len_chars-- > 0) 00231 { 00232 *header->len_buffer_ptr++ = *ptr++; 00233 } 00234 --ptr; // need to decrement since the for loop increments 00235 if(header->bytes_remaining == 2) 00236 { 00237 uint32_t packetLen; 00238 *header->len_buffer_ptr = 0; 00239 if(!StringUtil::strToUint32((const char*)header->len_buffer, &packetLen)) 00240 { 00241 RESET_CMD_HEADER(header); 00242 } 00243 else 00244 { 00245 if(packetLen > 0) 00246 { 00247 if(packetLen <= 2) 00248 { 00249 return WICONNECT_CMD_RESPONSE_ERROR; 00250 } 00251 packetLen -= 2; 00252 } 00253 if((int)packetLen > context->responseBufferLen) 00254 { 00255 DEBUG_ERROR("Packet larger than response buffer: %d > %d", packetLen, context->responseBufferLen); 00256 return WICONNECT_OVERFLOW; 00257 } 00258 header->response_len = (uint16_t)packetLen; 00259 context->bytesToRead = packetLen; 00260 } 00261 } 00262 } 00263 else if(header->bytes_remaining == 2) 00264 { 00265 --bytesReceived; 00266 if(*ptr == '\r') 00267 { 00268 header->bytes_remaining = 1; 00269 } 00270 else 00271 { 00272 RESET_CMD_HEADER(header); 00273 } 00274 } 00275 else 00276 { 00277 --bytesReceived; 00278 if(*ptr == '\n') 00279 { 00280 header->bytes_remaining = 0; 00281 break; 00282 } 00283 else 00284 { 00285 RESET_CMD_HEADER(header); 00286 } 00287 } 00288 } 00289 } 00290 } 00291 00292 while(context->bytesToRead > 0) 00293 { 00294 const TimerTimeout timeout = context->nonBlocking ? 0 : timeoutTimer.remainingMs(context->timeoutMs); 00295 const int bytesToRead = context->bytesToRead; 00296 const int bytesReceived = serial.read(context->responseBufferPtr, bytesToRead, timeout); 00297 context->responseBufferPtr += bytesReceived; 00298 context->bytesToRead -= bytesReceived; 00299 00300 if(bytesReceived != bytesToRead) 00301 { 00302 return timeoutTimer.timedOut(context->timeoutMs) ? WICONNECT_TIMEOUT : WICONNECT_PROCESSING; 00303 } 00304 else if(context->bytesToRead == 0) 00305 { 00306 char buf[2]; 00307 int bytesRemaining = 2; 00308 *context->responseBufferPtr = 0; 00309 00310 // read the trailing \r\n 00311 while(bytesRemaining > 0) 00312 { 00313 const int bytesReceived = serial.read(buf, bytesRemaining, 0); 00314 bytesRemaining -= bytesReceived; 00315 00316 if(bytesRemaining > 0 && timeoutTimer.timedOut(context->timeoutMs)) 00317 { 00318 return WICONNECT_TIMEOUT; 00319 } 00320 } 00321 } 00322 } 00323 00324 return (header->response_code != WICONNECT_CMD_CODE_NULL && 00325 header->response_type != WICONNECT_CMD_TYPE_NULL && 00326 context->bytesToRead == 0) ? WICONNECT_SUCCESS : WICONNECT_PROCESSING; 00327 } 00328 00329 /*************************************************************************************************/ 00330 void Wiconnect::issueCommandCallback(WiconnectResult result) 00331 { 00332 CommandHeader *header = (CommandHeader*)commandHeaderBuffer; 00333 CommandContext *context = (CommandContext*)commandContext; 00334 #ifdef WICONNECT_ASYNC_TIMER_ENABLED 00335 void *returnPtr = (currentQueuedCommand != NULL) ? (void*)currentQueuedCommand : (void*)context->responseBuffer; 00336 currentQueuedCommand = NULL; 00337 commandProcessorTimer.stop(); 00338 #else 00339 void *returnPtr = (void*)context->responseBuffer; 00340 #endif 00341 00342 context->callback.call(result, returnPtr, (void*)(uint32_t)header->response_len); 00343 commandExecuting = false; 00344 00345 #ifdef WICONNECT_ASYNC_TIMER_ENABLED 00346 processNextQueuedCommand(); 00347 #endif 00348 } 00349 00350 /*************************************************************************************************/ 00351 void Wiconnect::stopCurrentCommand() 00352 { 00353 internalProcessingState = 0; 00354 issueCommandCallback(WICONNECT_ABORTED); 00355 } 00356
Generated on Tue Jul 12 2022 17:35:58 by 1.7.2