mbed.org implementation of the abstract SmartREST library for the Cumulocity Platform SmartREST protocol.

Dependents:   MbedSmartRestMain MbedSmartRestMain

SmartRest.cpp

Committer:
Cumulocity
Date:
2014-10-22
Revision:
7:8159a2d12e4e
Parent:
6:cd7ba1ddb664
Child:
11:e1bee9a77652

File content as of revision 7:8159a2d12e4e:

/*
 * SmartRest.cpp
 *
 * Created on: Nov 1, 2013
 * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
 *
 * Copyright (c) 2013 Cumulocity GmbH
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "SmartRest.h"
#include <stdlib.h>
#include <string.h>

SmartRest::SmartRest(AbstractClient& client, const char *identifier) :
    _client(client),
    _identifier(identifier)
{
    _source = NULL;
    _mogid[0] = 0;
}

uint8_t SmartRest::setAuthorization(const char *username, const char *password)
{
    uint8_t res;

    res = _client.setAuthorization(username, password);
    if (res != CLIENT_OK)
        return SMARTREST_INTERNAL_ERROR;
    return SMARTREST_SUCCESS;
}

#ifdef SMARTREST_TRANSACTIONAL
uint8_t SmartRest::request(const DataGenerator& generator, const char *overrideIdentifier)
{
    uint8_t res;

    res = send(generator, overrideIdentifier);
    stop();
    return res;
}

uint8_t SmartRest::request(const DataGenerator& generator, Aggregator& aggregator, const char *overrideIdentifier)
{
    uint8_t res;

    if (!aggregator.managed())
        return SMARTREST_INTERNAL_ERROR;

    res = send(generator, overrideIdentifier);
    if (res != SMARTREST_SUCCESS) {
        stop();
        return res;
    }

    ParsedRecord recvd;
    while ((res = receive(recvd)) == SMARTREST_SUCCESS) {
        if (!aggregator.add(recvd))
            return SMARTREST_INTERNAL_ERROR;
    }

    stop();
    if (res == SMARTREST_END_OF_RESPONSE)
        return SMARTREST_SUCCESS;
    return res;
}
#endif

uint8_t SmartRest::bootstrap(const DataGenerator& generator)
{
    ParsedRecord record;
    int8_t ret;

    ret = beginRequest(NULL);
    if (ret != SMARTREST_SUCCESS)
        return ret;
    ret = awaitResponse();
    if (ret != SMARTREST_SUCCESS)
        return ret;
    ret = receive(record);
    if (ret != SMARTREST_SUCCESS)
        return ret;
    if (!record) {
        return SMARTREST_INTERNAL_ERROR;
    }
    stop();

    if (setMoGid(record))
        return SMARTREST_SUCCESS;

    if (record.value(0).integerValue() != 40)
        return SMARTREST_INTERNAL_ERROR;

    ret = send(generator, NULL);
    if (ret != SMARTREST_SUCCESS)
        return ret;
    ret = receive(record);
    if (ret != SMARTREST_SUCCESS)
        return ret;
    stop();

    if (!setMoGid(record))
        return SMARTREST_INTERNAL_ERROR;

    return SMARTREST_SUCCESS;
}

uint8_t SmartRest::send(const DataGenerator& generator, const char *overrideIdentifier)
{
    uint8_t res;

    res = beginRequest(overrideIdentifier);
    if (res != SMARTREST_SUCCESS)
        return res;

    _client.sendData(generator);
    return awaitResponse();
}

uint8_t SmartRest::receive(ParsedRecord& record)
{
    uint8_t res;
    
    if (_source == NULL)
        return SMARTREST_INTERNAL_ERROR;

    res = _parser.readFrom(*_source, record);

    switch (res) {
    case PARSER_SUCCESS:
        return SMARTREST_SUCCESS;
    case PARSER_END_OF_RESPONSE:
        return SMARTREST_END_OF_RESPONSE;
    case PARSER_TIMEOUT_ERROR:
        return SMARTREST_TIMEOUT_ERROR;
    }
    return SMARTREST_INTERNAL_ERROR;
}

void SmartRest::stop()
{
    _source = NULL;
    _client.stop();
}

const char * SmartRest::getIdentifier()
{
    if (*_mogid)
        return _mogid;
    return _identifier;
}

uint8_t SmartRest::beginRequest(const char *overrideIdentifier)
{
    int res;

    res = _client.beginRequest();
    if (res == CLIENT_CONNECTION_ERROR) {
        return SMARTREST_CONNECTION_FAILED;
    } else if (res != CLIENT_OK) {
        return SMARTREST_INTERNAL_ERROR;
    }
    if (overrideIdentifier != NULL) {
        if (_client.sendIdentifier(overrideIdentifier) != CLIENT_OK)
            return SMARTREST_INTERNAL_ERROR;
    } else {
        if (_client.sendIdentifier(getIdentifier()) != CLIENT_OK)
            return SMARTREST_INTERNAL_ERROR;
    }
    return SMARTREST_SUCCESS;
}

uint8_t SmartRest::awaitResponse()
{
    if ((_client.endRequest() != CLIENT_OK) ||
        (_client.awaitResponse() != CLIENT_OK))
        return SMARTREST_INTERNAL_ERROR;
    _source = &_client.receiveData();
    return SMARTREST_SUCCESS;
}

bool SmartRest::setMoGid(ParsedRecord& record)
{
    const char *mogid;

    *_mogid = 0;
    if ((record.values() < 2) || (record.value(0).integerValue() != 20))
        return false;

    if ((record.value(1).valueType() != VALUE_INTEGER) ||
        (record.value(1).integerValue() <= 0))
        return false;

    mogid = record.rawValue(1);
    if (strlen(mogid)+1 > sizeof(_mogid))
        return false;

    strcpy(_mogid, mogid);

    return true;
}