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
- Committer:
- dan_ackme
- Date:
- 2014-10-27
- Revision:
- 29:b6af04b77a56
- Child:
- 33:9b690d76eedf
- Child:
- 35:15725177aa60
File content as of revision 29:b6af04b77a56:
/** * 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