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/ControlParser.cpp

Committer:
xinlei
Date:
2015-08-10
Revision:
135:c4009ecaf5c0
Parent:
113:3872569be2af

File content as of revision 135:c4009ecaf5c0:

#include <stdio.h>
#include <string.h>
#include "ControlParser.h"
#include "Peripheral.h"
#include "LCDDisplay.h"
#include "ConfigSync.h"
#include "logging.h"


void ControlParser::parse(const char *buf)
{
        if (buf == NULL) return;
        const char *p = skipHTTPHeader(buf);
        if (p == NULL) return;
        Token tok;
        ptrPF = &ControlParser::parseGetOp;
        do {
                p = lex(p, tok);
                (this->*ptrPF)(tok);
        } while (*p);
}


void ControlParser::parseGetOp(Token& tok)
{
        if (tok.type == Token::INT && strncmp("211", tok.p, tok.len)==0) {
                opType = 211;
                ptrPF = &ControlParser::parseRowNumber;
        } else {
                parseError(tok);
        }
}


void ControlParser::parseRowNumber(Token& tok)
{
        if (tok.type == Token::INT) {
                if (opType == 86)
                        ptrPF = &ControlParser::parseAdviceTimeout;
                else
                        ptrPF = &ControlParser::parseOpId;
        } else if (tok.type == Token::NONE) {
                ptrPF = &ControlParser::parseAdviceTimeout;
        } else {
                parseError(tok);
        }
}


void ControlParser::parseOpId(Token& tok)
{
        if (tok.type == Token::INT) {
                if (opType == 211) {
                        sscanf(tok.p, "%ld", &op.identifier);
                        ptrPF = &ControlParser::parseOpState;
                        return;
                } else if (opType >= 220 && opType <= 222) {
                        ptrPF = &ControlParser::parseOpData;
                        return;
                }
        }
        parseError(tok);
}


void ControlParser::parseOpState(Token& tok)
{
        if (tok.type == Token::STRING) {
                if (strncmp(strPending, tok.p, tok.len)==0) {
                        Operation *p = opool.alloc();
                        if (p) {
                                p->identifier = op.identifier;
                                p->state = OPERATION_EXECUTING;
                                opool.put(p);
                        }
                        ptrPF = &ControlParser::parseOpType;
                        return;
                }
        }
        parseError(tok);
}


void ControlParser::parseOpType(Token& tok)
{
        if (tok.type == Token::INT) {
                sscanf(tok.p, "%hu", &opType);
                if (opType >= 220 && opType <= 222) {
                        ptrPF = &ControlParser::parseRowNumber;
                        return;
                }
        }
        parseError(tok);
}


void ControlParser::parseOpData(Token& tok)
{
        bool ret = true;
        if (opType == 220) {
                if (strncmp("CLOSED", tok.p, tok.len) == 0) {
                        closeRelay();
                } else if (strncmp("OPEN", tok.p, tok.len) == 0) {
                        openRelay();
                } else {
                        aError("Relay op (%.*s)\n", (int)tok.len, tok.p);
                        ret = false;
                }
        } else if (opType == 221) {
                char line[30] = {0};
                size_t num = tok.len < 30 ? tok.len : 30;
                if (tok.type == Token::STRING)
                        strncpyEscape(line, tok.p, num);
                else if (tok.type != Token::NONE)
                        strncpy(line, tok.p, num);
                LCDDisplay::inst().setFirstLine(line);
        } else if (opType == 222) {
                char config[128] = {0};
                size_t num = tok.len < 127 ? tok.len : 127;
                strncpy(config, tok.p, num);
                ret = ConfigSync::inst().updateConfiguration(config);
        } else {
                parseError(tok);
                return;
        }
        Operation *p = opool.alloc();
        if (p) {
                p->identifier = op.identifier;
                p->state = ret ? OPERATION_SUCCESSFUL : OPERATION_FAILED;
                opool.put(p);
        }
        ptrPF = &ControlParser::parseGetOpOrBayeuxAdvice;
}


void ControlParser::parseGetOpOrBayeuxAdvice(Token& tok)
{
        if (strncmp("211", tok.p, tok.len) == 0) {
                parseGetOp(tok);
        } else if (strncmp("86", tok.p, tok.len) == 0) {
                parseBayeuxAdvice(tok);
        } else {
                parseError(tok);
        }
}


void ControlParser::parseBayeuxAdvice(Token& tok)
{
        if (strncmp("86", tok.p, tok.len) == 0) {
                opType = 86;
                ptrPF = &ControlParser::parseRowNumber;
        } else {
                parseError(tok);
        }
}


void ControlParser::parseAdviceTimeout(Token& tok)
{
        if (tok.type == Token::NONE) {
                bayeuxTimeout = -1;
                ptrPF = &ControlParser::parseAdviceInterval;
        } else if (tok.type == Token::INT) {
                sscanf(tok.p, "%d", &bayeuxTimeout);
                ptrPF = &ControlParser::parseAdviceInterval;
        } else {
                parseError(tok);
        }
}


void ControlParser::parseAdviceInterval(Token& tok)
{
        if (tok.type == Token::NONE) {
                bayeuxInterval = 0;
                ptrPF = &ControlParser::parseAdvicePolicy;
        } else if (tok.type == Token::INT) {
                sscanf(tok.p, "%d", &bayeuxInterval);
                ptrPF = &ControlParser::parseAdvicePolicy;
        } else {
                parseError(tok);
        }
}


void ControlParser::parseAdvicePolicy(Token& tok)
{
        if (tok.type == Token::STRING) {
                if (strncmp("retry", tok.p, tok.len) == 0) {
                        bayeuxAdvice = BA_RETRY;
                } else if (strncmp("handshake", tok.p, tok.len) == 0) {
                        bayeuxAdvice = BA_HANDSHAKE;
                } else if (strncmp("none", tok.p, tok.len) == 0) {
                        bayeuxAdvice = BA_NONE;
                } else {
                        parseError(tok);
                }
        } else {
                parseError(tok);
        }
}


void ControlParser::parseError(Token& tok)
{
        aError("CtrlParse: %.*s[%d]\n", (int)tok.len, tok.p, tok.type);
        parseRecover(tok);
}


void ControlParser::parseRecover(Token& tok)
{
        if (tok.type == Token::INT) {
                int i = 0;
                sscanf(tok.p, "%d", &i);
                if (i == 211) {
                        parseGetOp(tok);
                } else if (i >= 220 && i <= 222) {
                        parseOpType(tok);
                } else if (i == 86) {
                        parseBayeuxAdvice(tok);
                } else {
                        ptrPF = &ControlParser::parseRecover;
                }
        } else {
                ptrPF = &ControlParser::parseRecover;
        }
}