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
Wiconnect.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 #include <stdio.h> 00030 #include <stdarg.h> 00031 #include <string.h> 00032 00033 #include "api/WiconnectInterface.h" 00034 #include "internal/common.h" 00035 #include "internal/CommandCommon.h" 00036 00037 00038 00039 00040 using namespace wiconnect; 00041 00042 00043 00044 00045 00046 #ifdef WICONNECT_ENABLE_MALLOC 00047 #define MALLOC_ARGS , void* (*mallocPtr)(size_t), void (*freePtr)(void*) 00048 #define MALLOC_CONSTRUCTORS _malloc(mallocPtr), _free(freePtr), 00049 #else 00050 #define MALLOC_ARGS 00051 #define MALLOC_CONSTRUCTORS 00052 #endif 00053 00054 00055 static Wiconnect* instance = NULL; 00056 00057 00058 00059 00060 /*************************************************************************************************/ 00061 void Wiconnect::prepare(void *internalBuffer_, int internalBufferSize_, bool nonBlocking_) 00062 { 00063 instance = this; 00064 internalBufferAlloc = false; 00065 #ifdef WICONNECT_ENABLE_MALLOC 00066 if(internalBufferSize_ > 0 && internalBuffer_ == NULL) 00067 { 00068 wiconnect_assert(this, "Wiconnect(), malloc not defined", _malloc != NULL); 00069 internalBuffer = (char*)_malloc(internalBufferSize_); 00070 internalBufferAlloc = true; 00071 } 00072 else 00073 #endif 00074 { 00075 internalBuffer = (char*)internalBuffer_; 00076 } 00077 00078 internalProcessingState = 0; 00079 currentCommandId = NULL; 00080 internalBufferSize = internalBufferSize_;; 00081 nonBlocking = nonBlocking_; 00082 commandExecuting = false; 00083 initialized = false; 00084 needUpdate = false; 00085 pinToGpioMapper = NULL; 00086 defaultTimeoutMs = WICONNECT_DEFAULT_TIMEOUT; 00087 00088 memset(commandContext, 0, sizeof(commandContext)); 00089 00090 #ifdef WICONNECT_ASYNC_TIMER_ENABLED 00091 commandProcessingPeriod = WICONNECT_DEFAULT_COMMAND_PROCESSING_PERIOD; 00092 currentQueuedCommand = NULL; 00093 #endif 00094 } 00095 00096 00097 /*************************************************************************************************/ 00098 Wiconnect::Wiconnect(const SerialConfig &serialConfig, int internalBufferSize, void *internalBuffer, Pin reset, Pin wake, bool nonBlocking MALLOC_ARGS) : 00099 NetworkInterface(this), SocketInterface(this), FileInterface(this), GhmInterface(this), 00100 MALLOC_CONSTRUCTORS serial(serialConfig, this), resetGpio(reset), wakeGpio(wake) 00101 { 00102 #ifdef WICONNECT_ENABLE_MALLOC 00103 wiconnect_assert(this, "Wiconnect(), bad malloc/free", (mallocPtr == NULL && freePtr == NULL) || (mallocPtr != NULL && freePtr != NULL)); 00104 #endif 00105 prepare(internalBuffer, internalBufferSize, nonBlocking); 00106 } 00107 00108 /*************************************************************************************************/ 00109 Wiconnect::Wiconnect(const SerialConfig &serialConfig, Pin reset, Pin wake, bool nonBlocking MALLOC_ARGS) : 00110 NetworkInterface(this), SocketInterface(this), FileInterface(this), GhmInterface(this), 00111 MALLOC_CONSTRUCTORS serial(serialConfig, this), resetGpio(reset), wakeGpio(wake) 00112 { 00113 #ifdef WICONNECT_ENABLE_MALLOC 00114 wiconnect_assert(this, "Wiconnect(), bad malloc/free", (mallocPtr == NULL && freePtr == NULL) || (mallocPtr != NULL && freePtr != NULL)); 00115 #endif 00116 prepare(NULL, 0, nonBlocking); 00117 } 00118 00119 /*************************************************************************************************/ 00120 Wiconnect::~Wiconnect() 00121 { 00122 #ifdef WICONNECT_ENABLE_MALLOC 00123 if(internalBufferAlloc) 00124 { 00125 _free(internalBuffer); 00126 } 00127 #endif 00128 } 00129 00130 /*************************************************************************************************/ 00131 WiconnectResult Wiconnect::init(bool bringNetworkUp) 00132 { 00133 WiconnectResult result; 00134 int retries; 00135 bool configuredBus = false; 00136 bool savedNonBlocking = nonBlocking; 00137 00138 DEBUG_INFO("Initializing wiconnect"); 00139 00140 serial.initialize(); 00141 00142 if(WICONNECT_FAILED(result, reset())) 00143 { 00144 return result; 00145 } 00146 00147 delayMs(1000); 00148 00149 initialized = true; 00150 nonBlocking = false; 00151 00152 00153 loop: 00154 for(retries = 3; retries > 0; --retries) 00155 { 00156 result = sendCommand(1000, CMD_SET_SYSTEM_COMMAND_MODE, "machine"); 00157 if(result != WICONNECT_SUCCESS) 00158 { 00159 delayMs(100); 00160 } 00161 else 00162 { 00163 break; 00164 } 00165 } 00166 00167 if(result != WICONNECT_SUCCESS && !configuredBus) 00168 { 00169 configuredBus = true; 00170 if(configureModuleDataBus()) 00171 { 00172 goto loop; 00173 } 00174 } 00175 00176 if(result == WICONNECT_SUCCESS) 00177 { 00178 if(WICONNECT_SUCCEEDED(result, getVersion())) 00179 { 00180 const uint32_t version = Wiconnect::wiconnectVersionToInt(this->internalBuffer); 00181 if(version < WICONNECT_MINIMUM_VERSION) 00182 { 00183 needUpdate = true; 00184 result = WICONNECT_FIRMWARE_OUTDATED; 00185 } 00186 } 00187 } 00188 if(result == WICONNECT_SUCCESS) 00189 { 00190 sendCommand("set stream.auto_close 0"); 00191 } 00192 if(result == WICONNECT_SUCCESS && bringNetworkUp) 00193 { 00194 sendCommand(15000, "ping -g"); 00195 } 00196 00197 nonBlocking = savedNonBlocking; 00198 if(result != WICONNECT_SUCCESS && !needUpdate) 00199 { 00200 initialized = false; 00201 } 00202 00203 00204 return result; 00205 } 00206 00207 /*************************************************************************************************/ 00208 void Wiconnect::deinit(void) 00209 { 00210 initialized = false; 00211 } 00212 00213 /*************************************************************************************************/ 00214 Wiconnect* Wiconnect::getInstance() 00215 { 00216 return instance; 00217 } 00218 00219 /*************************************************************************************************/ 00220 bool Wiconnect::isInitialized() 00221 { 00222 return initialized; 00223 } 00224 00225 /*************************************************************************************************/ 00226 bool Wiconnect::updateRequired() 00227 { 00228 return needUpdate; 00229 } 00230 00231 /*************************************************************************************************/ 00232 WiconnectResult Wiconnect::reset() 00233 { 00234 resetGpio = 0; 00235 delayMs(10); 00236 resetGpio = 1; 00237 delayMs(1000); 00238 return WICONNECT_SUCCESS; 00239 } 00240 00241 /*************************************************************************************************/ 00242 WiconnectResult Wiconnect::wakeup() 00243 { 00244 wakeGpio = 1; 00245 delayMs(1); 00246 wakeGpio = 0; 00247 return WICONNECT_SUCCESS; 00248 } 00249 00250 /*************************************************************************************************/ 00251 void Wiconnect::flush(int delayMs) 00252 { 00253 if(delayMs != 0) 00254 { 00255 serial.write("\r\n\r\n", 4, 0); 00256 } 00257 delayMs(delayMs); 00258 serial.flush(); 00259 } 00260 00261 /*************************************************************************************************/ 00262 void Wiconnect::setPinToGpioMapper(PinToGpioMapper mapper) 00263 { 00264 pinToGpioMapper = mapper; 00265 } 00266 00267 /*************************************************************************************************/ 00268 WiconnectResult Wiconnect::getVersion(char *versionBuffer, int versionBufferSize, const Callback &completeCallback) 00269 { 00270 WiconnectResult result; 00271 00272 if(versionBuffer != NULL && versionBufferSize == 0) 00273 { 00274 return WICONNECT_BAD_ARG; 00275 } 00276 00277 _CHECK_OTHER_COMMAND_EXECUTING(); 00278 00279 if(versionBuffer == NULL) 00280 { 00281 result = sendCommand(completeCallback, CMD_GET_VERSION); 00282 } 00283 else 00284 { 00285 result = sendCommand(completeCallback, versionBuffer, versionBufferSize, CMD_GET_VERSION); 00286 } 00287 00288 _CHECK_CLEANUP_COMMAND(); 00289 00290 return result; 00291 } 00292 00293 /*************************************************************************************************/ 00294 WiconnectResult Wiconnect::updateFirmware(bool forced, const char *versionStr, const Callback &completeCallback) 00295 { 00296 WiconnectResult result; 00297 char *cmdBuffer = internalBuffer; 00298 00299 if(_WICONNECT_IS_IDLE()) 00300 { 00301 strcpy(cmdBuffer, "ota "); 00302 if(versionStr != NULL) 00303 { 00304 strcat(cmdBuffer, "-b wiconnect-"); 00305 strcat(cmdBuffer, versionStr); 00306 } 00307 else if(forced) 00308 { 00309 strcat(cmdBuffer, "-f"); 00310 } 00311 } 00312 00313 _CHECK_OTHER_COMMAND_EXECUTING(); 00314 00315 result = sendCommand(completeCallback, WICONNECT_FIRMWARE_UPDATE_TIMEOUT, cmdBuffer); 00316 00317 _CHECK_CLEANUP_COMMAND(); 00318 00319 return result; 00320 } 00321 00322 /*************************************************************************************************/ 00323 const char* Wiconnect::getWiconnectResultStr(WiconnectResult wiconnectResult) 00324 { 00325 static const char* const wiconnectSuccessStrTable[] = { 00326 "Success", // WICONNECT_SUCCESS 00327 "Processing command", // WICONNECT_PROCESSING 00328 "Idle", // WICONNECT_IDLE 00329 "Aborted", // WICONNECT_ABORTED 00330 }; 00331 static const char* const wiconnectErrorStrTable[] = { 00332 "", 00333 "General error", // WICONNECT_ERROR 00334 "WiConnect command code error", // WICONNECT_CMD_RESPONSE_ERROR 00335 "Null buffer", // WICONNECT_NULL_BUFFER 00336 "Not initialized", // WICONNECT_NOT_INITIALIZED 00337 "Overflow", // WICONNECT_OVERFLOW 00338 "Timeout", // WICONNECT_TIMEOUT 00339 "Response handler null", // WICONNECT_RESPONSE_HANDLER_NULL 00340 "Response parse error", // WICONNECT_RESPONSE_PARSE_ERROR 00341 "Another command is executing", // WICONNECT_ANOTHER_CMD_EXECUTING 00342 "Bad argument(s)", // WICONNECT_BAD_ARG 00343 "Unsupported", // WICONNECT_UNSUPPORTED 00344 "Pin name to GPIO mapper null", // WICONNECT_PINNAME_TO_GPIO_MAPPER_NULL 00345 "Duplicate", // WICONNECT_DUPLICATE 00346 "Not found", // WICONNECT_NOT_FOUND 00347 "No mapping for pinname to GPIO", // WICONNECT_PINNAME_TO_GPIO_NO_MAPPING 00348 "Not connected", // WICONNECT_NOT_CONNECTED 00349 "Underflow", // WICONNECT_UNDERFLOW 00350 "A monitor is not available", // WICONNECT_MONITOR_NOT_AVAILABLE 00351 "Not opened for reading", // WICONNECT_NOT_OPENED_FOR_READING 00352 "WiFi firmware update required", // WICONNECT_FIRMWARE_OUTDATED 00353 }; 00354 00355 if((int)wiconnectResult >= (int)WICONNECT_SUCCESS) 00356 { 00357 return wiconnectSuccessStrTable[wiconnectResult]; 00358 } 00359 else 00360 { 00361 wiconnectResult = (WiconnectResult)(-((int)wiconnectResult)); 00362 return wiconnectErrorStrTable[wiconnectResult]; 00363 } 00364 } 00365 00366 /*************************************************************************************************/ 00367 uint32_t Wiconnect::wiconnectVersionToInt(char *versionStr) 00368 { 00369 char *idx = strchr(versionStr, ','); 00370 if(idx == NULL) 00371 { 00372 return UINT_MAX; 00373 } 00374 *idx = 0; 00375 idx = versionStr; 00376 while((idx = strchr(versionStr, '-')) != NULL) 00377 { 00378 versionStr = idx + 1; 00379 } 00380 00381 uint32_t ver; 00382 00383 if(Wiconnect::fileVersionStrToInt(versionStr, &ver)) 00384 { 00385 return ver; 00386 } 00387 00388 return UINT_MAX; 00389 } 00390 00391 /*************************************************************************************************/ 00392 void Wiconnect::setDebugLogger(LogFunc logFunc) 00393 { 00394 #ifdef WICONNECT_ENABLE_DEBUGGING 00395 debugLogger = logFunc; 00396 #endif 00397 } 00398 00399 /*************************************************************************************************/ 00400 void Wiconnect::setAssertLogger(LogFunc assertLogFunc) 00401 { 00402 assertLogger = assertLogFunc; 00403 } 00404 00405 #ifdef WICONNECT_ENABLE_DEBUGGING 00406 /*************************************************************************************************/ 00407 void Wiconnect::debugLog(const char *msg, ...) 00408 { 00409 if(!debugLogger.isValid()) 00410 { 00411 return; 00412 } 00413 00414 static char buffer[96]; 00415 va_list args; 00416 va_start(args, msg); 00417 int len = vsnprintf(buffer, sizeof(buffer)-1, msg, args); 00418 va_end(args); 00419 00420 if(len > (int)(sizeof(buffer)-6)) 00421 { 00422 char *p = &buffer[sizeof(buffer)-6]; 00423 *p++ = '.'; 00424 *p++ = '.'; 00425 *p++ = '.'; 00426 *p++ = '\r'; 00427 *p++ = '\n'; 00428 *p = 0; 00429 } 00430 else 00431 { 00432 if(buffer[len-2] != '\r') 00433 { 00434 char *p = &buffer[len]; 00435 *p++ = '\r'; 00436 *p++ = '\n'; 00437 *p = 0; 00438 } 00439 } 00440 debugLogger.call(buffer); 00441 } 00442 #endif
Generated on Tue Jul 12 2022 17:35:58 by 1.7.2