Official reference client implementation for Cumulocity SmartREST on u-blox C027.

Dependencies:   C027_Support C12832 LM75B MMA7660 MbedSmartRest mbed-rtos mbed

Fork of MbedSmartRestMain by Vincent Wochnik

operation/OperationSupport.cpp

Committer:
xinlei
Date:
2015-04-20
Revision:
94:61d44636f020
Parent:
93:0acd11870c6a
Child:
100:47ea098f8a47

File content as of revision 94:61d44636f020:

#include <string.h>
#include "OperationSupport.h"
#include "ComposedRecord.h"
#include "ParsedRecord.h"
#include "IntegerValue.h"
#include "logging.h"

bool OperationSupport::init()
{
    if (_init)
        return false;
    
    // Get pending operations
    // USAGE: 110,<DEVICE/ID>
    if (!_tpl.add("10,110,GET,/devicecontrol/operations?status=PENDING&deviceId=%%&pageSize=100,,application/vnd.com.nsn.cumulocity.operationCollection+json,%%,UNSIGNED,\r\n"))
        return false;

    // Set operation state
    // USAGE: 111,<OPERATION/ID>,<STATE>
    if (!_tpl.add("10,111,PUT,/devicecontrol/operations/%%,application/vnd.com.nsn.cumulocity.operation+json,application/vnd.com.nsn.cumulocity.operation+json,%%,UNSIGNED STRING,\"{\"\"status\"\":\"\"%%\"\"}\"\r\n"))
        return false;

    // Get operations
    // Response: 210,<OPERATION/ID>,<STATUS>
    if (!_tpl.add("11,210,\"$.operations\",,\"$.id\",\"$.status\"\r\n"))
        return false;

    // Get operation
    // Response: 211,<OPERATION/ID>,<STATUS>
    if (!_tpl.add("11,211,,\"$.deviceId\",\"$.id\",\"$.status\"\r\n"))
        return false;
        
    // Get operation by id
    // USAGE: 112,<OPERATION/ID>
    if (!_tpl.add("10,112,GET,/devicecontrol/operations/%%,,application/vnd.com.nsn.cumulocity.operation+json,%%,UNSIGNED,\r\n"))
        return false;

    // Relay operation response
    // Response: 220,<OPERATION/ID>,<STATUS>
    if (!_tpl.add("11,220,,\"$.c8y_Relay\",\"$.id\",\"$.c8y_Relay.relayState\"\r\n"))
        return false;

    // Message operation response
    // Response: 221,<OPERATION/ID>,<MESSAGE>
    if (!_tpl.add("11,221,,\"$.c8y_Message\",\"$.id\",\"$.c8y_Message.text\"\r\n"))
        return false;

    // Configuration operation response
    // Response: 222,<OPERATION/ID>,<CONFIGURATION/STRING>
    if (!_tpl.add("11,222,,\"$.c8y_Configuration\",\"$.id\",\"$.c8y_Configuration.config\"\r\n"))
        return false;

    _init = true;
    return true;
}

bool OperationSupport::run()
{
    if (_firstRun) {
        _firstRun = false;
        bool b = requestPendingOperations();
        return b;
    } else {
        return true;
    }
}

bool OperationSupport::executePendingOperation(Operation& op)
{
    ComposedRecord r;
    if (!r.add(IntegerValue(112)) || !r.add(IntegerValue(op.identifier))) {
        return false;
    } else if (_client.send(r) != SMARTREST_SUCCESS) {
        _client.stop();
        return false;
    }
    ParsedRecord p;
    bool b = true;
    while (_client.receive(p) == SMARTREST_SUCCESS) {
        if (p.values() >= 3 &&
            p.value(0).integerValue() >= 220 &&
            p.value(0).integerValue() <= 222 &&
            p.value(2).valueType() == VALUE_INTEGER) {
            Operation* op1 = opool.alloc();
            op1->identifier = p.value(2).integerValue();
//            bool ret = _executor.executeOperation(p);
            bool ret = true;
            op1->state = ret ? OPERATION_SUCCESSFUL : OPERATION_FAILED;
            opool.put(op1);
        }
    }
    _client.stop();
    return b;
}

bool OperationSupport::requestPendingOperations()
{
    IntegerValue msgId(110);
    IntegerValue deviceId(_deviceId);
    ComposedRecord record;

    if ((!record.add(msgId)) || (!record.add(deviceId)))
        return false;
    else if (_client.send(record) != SMARTREST_SUCCESS) {
        _client.stop();
        return false;
    }

    uint8_t ret;
    ParsedRecord received;
    Operation opl[10];
    size_t c = 0;
    while ((ret=_client.receive(received)) == SMARTREST_SUCCESS) {
        if (c < 10 && operationFromRecord(received, opl[c])) {
            ++c;
        } else {
            aWarning("Ignored pending operation after 10.\n");
            break;
        }
    }
    _client.stop();

    for (size_t i = 0; i < c; ++i) {
        Operation* op = opool.alloc();
        op->identifier = opl[i].identifier;
        op->state = OPERATION_EXECUTING;
        opool.put(op);
        executePendingOperation(opl[i]);
    }
    return (ret == SMARTREST_END_OF_RESPONSE || ret == SMARTREST_CONNECTION_CLOSED);
}

bool OperationSupport::operationFromRecord(ParsedRecord& received, Operation& op)
{
    if ((received.values() < 4) ||
        (received.value(0).valueType() != VALUE_INTEGER) ||
//        (received.value(0).integerValue() != 211) ||
        (received.value(2).valueType() != VALUE_INTEGER) ||
        (received.value(3).valueType() != VALUE_CHARACTER))
        return false;

    op.identifier = received.value(2).integerValue();
    const char *tmp = received.value(3).characterValue();
    if (strcmp(tmp, strExecuting) == 0)
        op.state = OPERATION_EXECUTING;
    else if (strcmp(tmp, strSuccessful) == 0)
        op.state = OPERATION_SUCCESSFUL;
    else if (strcmp(tmp, strFailed) == 0)
        op.state = OPERATION_FAILED;
    else if (strcmp(tmp, strPending) == 0)
        op.state = OPERATION_PENDING;
    else
        return false;
    return true;
}