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
Diff: Wiconnect.cpp
- Revision:
- 29:b6af04b77a56
- Child:
- 33:9b690d76eedf
- Child:
- 35:15725177aa60
diff -r 3c52f578708a -r b6af04b77a56 Wiconnect.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Wiconnect.cpp Mon Oct 27 13:42:26 2014 -0700 @@ -0,0 +1,398 @@ +/** + * ACKme WiConnect Host Library is licensed under the BSD licence: + * + * Copyright (c)2014 ACKme Networks. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +#include "api/WiconnectInterface.h" +#include "internal/common.h" +#include "internal/CommandCommon.h" + + + + +using namespace wiconnect; + + + + + +#ifdef WICONNECT_ENABLE_MALLOC +#define MALLOC_ARGS , void* (*mallocPtr)(size_t), void (*freePtr)(void*) +#define MALLOC_CONSTRUCTORS _malloc(mallocPtr), _free(freePtr), +#else +#define MALLOC_ARGS +#define MALLOC_CONSTRUCTORS +#endif + + +static Wiconnect* instance = NULL; + + + + +/*************************************************************************************************/ +void Wiconnect::prepare(void *internalBuffer_, int internalBufferSize_, bool nonBlocking_) +{ + instance = this; + internalBufferAlloc = false; +#ifdef WICONNECT_ENABLE_MALLOC + if(internalBufferSize_ > 0 && internalBuffer_ == NULL) + { + wiconnect_assert(this, "Wiconnect(), malloc not defined", _malloc != NULL); + internalBuffer = (char*)_malloc(internalBufferSize_); + internalBufferAlloc = true; + } + else +#endif + { + internalBuffer = (char*)internalBuffer_; + } + + internalProcessingState = 0; + currentCommandId = NULL; + internalBufferSize = internalBufferSize_;; + nonBlocking = nonBlocking_; + commandExecuting = false; + initialized = false; + pinToGpioMapper = NULL; + defaultTimeoutMs = WICONNECT_DEFAULT_TIMEOUT; + + memset(commandContext, 0, sizeof(commandContext)); + +#ifdef WICONNECT_ASYNC_TIMER_ENABLED + commandProcessingPeriod = WICONNECT_DEFAULT_COMMAND_PROCESSING_PERIOD; + currentQueuedCommand = NULL; +#endif +} + + +/*************************************************************************************************/ +Wiconnect::Wiconnect(const SerialConfig &serialConfig, int internalBufferSize, void *internalBuffer, Pin reset, Pin wake, bool nonBlocking MALLOC_ARGS) : + NetworkInterface(this), SocketInterface(this), FileInterface(this), GhmInterface(this), + MALLOC_CONSTRUCTORS serial(serialConfig, this), resetGpio(reset), wakeGpio(wake) +{ +#ifdef WICONNECT_ENABLE_MALLOC + wiconnect_assert(this, "Wiconnect(), bad malloc/free", (mallocPtr == NULL && freePtr == NULL) || (mallocPtr != NULL && freePtr != NULL)); +#endif + prepare(internalBuffer, internalBufferSize, nonBlocking); +} + +/*************************************************************************************************/ +Wiconnect::Wiconnect(const SerialConfig &serialConfig, Pin reset, Pin wake, bool nonBlocking MALLOC_ARGS) : + NetworkInterface(this), SocketInterface(this), FileInterface(this), GhmInterface(this), + MALLOC_CONSTRUCTORS serial(serialConfig, this), resetGpio(reset), wakeGpio(wake) +{ +#ifdef WICONNECT_ENABLE_MALLOC + wiconnect_assert(this, "Wiconnect(), bad malloc/free", (mallocPtr == NULL && freePtr == NULL) || (mallocPtr != NULL && freePtr != NULL)); +#endif + prepare(NULL, 0, nonBlocking); +} + +/*************************************************************************************************/ +Wiconnect::~Wiconnect() +{ +#ifdef WICONNECT_ENABLE_MALLOC + if(internalBufferAlloc) + { + _free(internalBuffer); + } +#endif +} + +/*************************************************************************************************/ +WiconnectResult Wiconnect::init(bool bringNetworkUp) +{ + WiconnectResult result; + int retries; + bool configuredBus = false; + bool savedNonBlocking = nonBlocking; + + DEBUG_INFO("Initializing wiconnect"); + + serial.initialize(); + + if(WICONNECT_FAILED(result, reset())) + { + return result; + } + + delayMs(1000); + + initialized = true; + nonBlocking = false; + + + loop: + for(retries = 3; retries > 0; --retries) + { + result = sendCommand(1000, CMD_SET_SYSTEM_COMMAND_MODE, "machine"); + if(result != WICONNECT_SUCCESS) + { + delayMs(100); + } + else + { + break; + } + } + + if(result != WICONNECT_SUCCESS && !configuredBus) + { + configuredBus = true; + if(configureModuleDataBus()) + { + goto loop; + } + } + + if(result == WICONNECT_SUCCESS) + { + sendCommand("set stream.auto_close 0"); + } + if(result == WICONNECT_SUCCESS && bringNetworkUp) + { + sendCommand(15000, "ping -g"); + } + + nonBlocking = savedNonBlocking; + if(result != WICONNECT_SUCCESS) + { + initialized = false; + } + + + return result; +} + +/*************************************************************************************************/ +void Wiconnect::deinit(void) +{ + initialized = false; +} + +/*************************************************************************************************/ +Wiconnect* Wiconnect::getInstance() +{ + return instance; +} + +/*************************************************************************************************/ +bool Wiconnect::isInitialized() +{ + return initialized; +} + +/*************************************************************************************************/ +WiconnectResult Wiconnect::reset() +{ + resetGpio = 0; + delayMs(10); + resetGpio = 1; + delayMs(1000); + return WICONNECT_SUCCESS; +} + +/*************************************************************************************************/ +WiconnectResult Wiconnect::wakeup() +{ + wakeGpio = 1; + delayMs(1); + wakeGpio = 0; + return WICONNECT_SUCCESS; +} + +/*************************************************************************************************/ +void Wiconnect::flush(int delayMs) +{ +// if(delayMs != 0) +// { +// serial.write("\r\n\r\n", 4, 0); +// } +// delayMs(delayMs); +// serial.flush(); +} + +/*************************************************************************************************/ +void Wiconnect::setPinToGpioMapper(PinToGpioMapper mapper) +{ + pinToGpioMapper = mapper; +} + +/*************************************************************************************************/ +WiconnectResult Wiconnect::getVersion(char *versionBuffer, int versionBufferSize, const Callback &completeCallback) +{ + WiconnectResult result; + + if(versionBuffer != NULL && versionBufferSize == 0) + { + return WICONNECT_BAD_ARG; + } + + _CHECK_OTHER_COMMAND_EXECUTING(); + + if(versionBuffer == NULL) + { + result = sendCommand(completeCallback, CMD_GET_VERSION); + } + else + { + result = sendCommand(completeCallback, versionBuffer, versionBufferSize, CMD_GET_VERSION); + } + + _CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +WiconnectResult Wiconnect::updateFirmware(bool forced, const char *versionStr, const Callback &completeCallback) +{ + WiconnectResult result; + char *cmdBuffer = internalBuffer; + + if(_WICONNECT_IS_IDLE()) + { + strcpy(cmdBuffer, "ota "); + if(versionStr != NULL) + { + strcat(cmdBuffer, "-b wiconnect-"); + strcat(cmdBuffer, versionStr); + } + else if(forced) + { + strcat(cmdBuffer, "-f"); + } + } + + _CHECK_OTHER_COMMAND_EXECUTING(); + + result = sendCommand(completeCallback, WICONNECT_FIRMWARE_UPDATE_TIMEOUT, cmdBuffer); + + _CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +const char* Wiconnect::getWiconnectResultStr(WiconnectResult wiconnectResult) +{ + static const char* const wiconnectSuccessStrTable[] = { + "Success", // WICONNECT_SUCCESS + "Processing command", // WICONNECT_PROCESSING + "Idle", // WICONNECT_IDLE + "Aborted", // WICONNECT_ABORTED + }; + static const char* const wiconnectErrorStrTable[] = { + "", + "General error", // WICONNECT_ERROR + "WiConnect command code error", // WICONNECT_CMD_RESPONSE_ERROR + "Null buffer", // WICONNECT_NULL_BUFFER + "Not initialized", // WICONNECT_NOT_INITIALIZED + "Overflow", // WICONNECT_OVERFLOW + "Timeout", // WICONNECT_TIMEOUT + "Response handler null", // WICONNECT_RESPONSE_HANDLER_NULL + "Response parse error", // WICONNECT_RESPONSE_PARSE_ERROR + "Another command is executing", // WICONNECT_ANOTHER_CMD_EXECUTING + "Bad argument(s)", // WICONNECT_BAD_ARG + "Unsupported", // WICONNECT_UNSUPPORTED + "Pin name to GPIO mapper null", // WICONNECT_PINNAME_TO_GPIO_MAPPER_NULL + "Duplicate", // WICONNECT_DUPLICATE + "Not found", // WICONNECT_NOT_FOUND + "No mapping for pinname to GPIO", // WICONNECT_PINNAME_TO_GPIO_NO_MAPPING + "Not connected", // WICONNECT_NOT_CONNECTED + "Underflow", // WICONNECT_UNDERFLOW + "A monitor is not available", // WICONNECT_MONITOR_NOT_AVAILABLE + "Not opened for reading", // WICONNECT_NOT_OPENED_FOR_READING + }; + + if((int)wiconnectResult >= (int)WICONNECT_SUCCESS) + { + return wiconnectSuccessStrTable[wiconnectResult]; + } + else + { + wiconnectResult = (WiconnectResult)(-((int)wiconnectResult)); + return wiconnectErrorStrTable[wiconnectResult]; + } +} + + +/*************************************************************************************************/ +void Wiconnect::setDebugLogger(LogFunc logFunc) +{ +#ifdef WICONNECT_ENABLE_DEBUGGING + debugLogger = logFunc; +#endif +} + +/*************************************************************************************************/ +void Wiconnect::setAssertLogger(LogFunc assertLogFunc) +{ + assertLogger = assertLogFunc; +} + +#ifdef WICONNECT_ENABLE_DEBUGGING +/*************************************************************************************************/ +void Wiconnect::debugLog(const char *msg, ...) +{ + if(!debugLogger.isValid()) + { + return; + } + + static char buffer[96]; + va_list args; + va_start(args, msg); + int len = vsnprintf(buffer, sizeof(buffer)-1, msg, args); + va_end(args); + + if(len > (int)(sizeof(buffer)-6)) + { + char *p = &buffer[sizeof(buffer)-6]; + *p++ = '.'; + *p++ = '.'; + *p++ = '.'; + *p++ = '\r'; + *p++ = '\n'; + *p = 0; + } + else + { + if(buffer[len-2] != '\r') + { + char *p = &buffer[len]; + *p++ = '\r'; + *p++ = '\n'; + *p = 0; + } + } + debugLogger.call(buffer); +} +#endif