Erick / Mbed 2 deprecated ICE_BLE_TEST

Dependencies:   NaturalTinyShell_ice libmDot-12Sept mbed-rtos mbed

Fork of ICE by Erick

src/ConfigurationHandler/Controls/CompositeControl.cpp

Committer:
jmarkel44
Date:
2016-10-19
Revision:
232:8a86b5bf38f7
Parent:
231:f22901955e0c
Child:
242:3b0086a6d625

File content as of revision 232:8a86b5bf38f7:

/******************************************************************************
 *
 * File:                CompositeControl.cpp
 * Desciption:          ICE Composite Control Class implementation
 *
 *****************************************************************************/
#include "CompositeControl.h"
#include "ConfigurationHandler.h"
#include "mDot.h"
#include "MbedJSONValue.h"
#include "ModbusMasterApi.h"
#include "global.h"
#include <string>
#include <iostream>
#include <iomanip>

extern mDot *GLOBAL_mdot;

//
// method:          load
// description:     load a composite control
//
// @param           none
// @return          none
//
bool CompositeControl::load(std::string _controlFile)
{
    MbedJSONValue json_value;           // JSON parsing element
    controlFile = _controlFile;


    // open and read from the control file
    mDot::mdot_file file = GLOBAL_mdot->openUserFile(controlFile.c_str(), mDot::FM_RDONLY);
    if ( file.fd < 0 ) {
        logError("%s: failed to open %s\n", __func__, controlFile.c_str());
        return false;
    }

    // read the data into a buffer
    char dataBuf[MAX_FILE_SIZE];

    int bytes_read = GLOBAL_mdot->readUserFile(file, (void *)dataBuf, sizeof(dataBuf));
    if ( bytes_read != sizeof(dataBuf) ) {
        logError("%s: failed to read %d bytes from %s", __func__, sizeof(dataBuf), controlFile.c_str());
        // caller should destroy the object
        return false;
    }

    // close the file
    GLOBAL_mdot->closeUserFile(file);

    parse(json_value, dataBuf);

    if ( !json_value.hasMember("id")            ||
            !json_value.hasMember("tag")        ||
            !json_value.hasMember("priority")   ||
            !json_value.hasMember("ca")         ||
            !json_value.hasMember("entries") ) {
        printf("\rComposite control is missing expected tags\n");
        return false;
    }

    id                  = json_value     ["id"].get<string>();
    tag                 = json_value     ["tag"].get<string>();
    priority            = atoi(json_value["priority"].get<string>().c_str());
    ca                  = json_value     ["ca"].get<string>();


    int entries = atoi(json_value["entries"].get<string>().c_str());

    // populate the outputs
    for ( int i = 0; i < entries; ++i ) {
        std::string tag = json_value["outputs"][i]["tag"].get<string>();
        std::string response = json_value["outputs"][i]["responseA"].get<string>();
        if ( !tag.empty() && !response.empty()  ) {
            OutputElement x = { tag, response };
            outputs.push_back(x);
        } else {
            return false;
        }
    }

    return true;
}

//
// method:      start
// description: start the composite control
//
// @param       none
// @return      none
//
void CompositeControl::start(void)
{
    currentState = STATE_START;
}

//
// method:      update
// description: updater for the composite control
//
// @param       none
// @return      none
//
void CompositeControl::update(void)
{
    std::string function;

    switch ( currentState ) {
        case STATE_INIT:
            // do nothing
            break;
        case STATE_START:
            function = executeCommand();
            if ( function == "responseA" ) {
                currentState = STATE_CONTROL_ON;
                triggerOutputs(function);
            } else if ( function == "nothing" ) {
                currentState = STATE_CONTROL_OFF;
            }
            break;
        case STATE_CONTROL_ON:
            function = executeCommand();
            if ( function == "nothing" ) {
                currentState = STATE_CONTROL_OFF;
                unregisterControls();
            } else {
                // do nothing
            }
            break;
        case STATE_CONTROL_OFF:
            function = executeCommand();
            if ( function == "responseA" ) {
                currentState = STATE_CONTROL_ON;
                triggerOutputs(function);
            } else {
                // do nothing
            }
            break;
        default:
            break;
    }
}

//
// method:      executeCommand
// description: execute the command specified in the control algorithm
//
// @param       none
// @return      none
//
std::string CompositeControl::executeCommand(void)
{
    // look up the algorithm
    StringAlgorithmMap::iterator pos;
    pos = algorithmTable.find(this->ca);
    if ( pos != algorithmTable.end() ) {
        // we found the control algorithm
        return this->executeOperation(pos->second);
    }
    return "nothing";
}

//
// method:      executeOperation
// description: execute an operations from the control equation
//
// @param       ca -> composite control algorithm
// @return      string to the result
//
std::string CompositeControl::executeOperation(const CompositeAlgorithm *ca)
{
    // (this->tag) <op> <opr> = <result>
    //
    // example:
    // this->tag = "i_flowswitch"
    // opr = "1"
    // op = "=="
    // if true return "responseA" else return "nothing"

    ModbusValue value;
    bool rc = ModbusMasterReadRegister(tag,&value);
    if ( rc != true ) {
        logError("%s cannot find tag", __func__);
        return "nothing";
    }

    // equal to operator
    if ( ca->getOp() == "==" ) {
        // perform the equality operation
        if ( value.value == atof(ca->getOpr().c_str()) ) {
            return ca->getResultTrue();
        } else {
            return ca->getResultFalse();
        }
    }
    if ( ca->getOp() == ">=" ) {
        if ( value.value >= atof(ca->getOpr().c_str()) ) {
            return ca->getResultTrue();
        } else {
            return ca->getResultFalse();
        }
    }
    // addition operator
    if ( ca->getOp() == "+" ) {
        // TODO
    }
    // multiply operator
    if ( ca->getOp() == "*" ) {
        // TODO:
    }
    // subtraction operator
    if ( ca->getOp() == "-" ) {
        // TODO:
    }

    return "nothing";
}

//
// method:          triggerOutputs
// description:     trigger the output(s) to do something
//
// @param           result -> the result of the operation
// @return          none
//
void CompositeControl::triggerOutputs(std::string result)
{

    // loop through the list
    StringAlgorithmMap::iterator pos;
    pos = algorithmTable.find(this->ca);
    if ( pos != algorithmTable.end() ) {
        std::vector<OutputElement>::iterator it;
        for ( it = outputs.begin(); it != outputs.end(); ++it ) {
            if ( it->response == "fixed off" ) {
                printf("\rSending an OFF control for %s\n", it->tag.c_str());
                sendMail(it->tag, ACTION_CONTROL_OFF);
            } else if ( it->response == "fixed on" ) {
                printf("\rSending an ON request for %s\n", it->tag.c_str());
                sendMail(it->tag, ACTION_CONTROL_ON);
            }
        }
    } else {
        logError("%s: failed to find the control algorithm %s\n", __func__, this->ca.c_str());
    }
}

//
// method:      sendMail
// description: send mail to the output task
//
// @param       io_tag  -> input/output tag
// @param       action  -> ON, OFF, UNREGISTER
// @return      none
//
void CompositeControl::sendMail(const std::string io_tag, OutputAction action)
{
    logInfo("%s: composite control attempting to send action %d\n",
            __func__, action);

    OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
    memset(output_mail, 0, sizeof(OutputControlMsg_t));

    output_mail->action         = action;
    output_mail->controlType    = CONTROL_COMPOSITE;
    output_mail->priority       = this->priority;

    strncpy(output_mail->input_tag,  this->tag.c_str(),  sizeof(output_mail->input_tag)-1);
    strncpy(output_mail->output_tag, io_tag.c_str(), sizeof(output_mail->output_tag)-1);
    strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);

    OutputMasterMailBox.put(output_mail);
}

//
// method:      unregisterControls
// description: unregister the control with the output task
//
// @param       none
// @return      none
//
void CompositeControl::unregisterControls(void)
{
    // loop through the list
    StringAlgorithmMap::iterator pos;
    pos = algorithmTable.find(this->ca);
    if ( pos != algorithmTable.end() ) {
        std::vector<OutputElement>::iterator it;
        for ( it = outputs.begin(); it != outputs.end(); ++it ) {
            sendMail(it->tag, ACTION_CONTROL_UNREGISTER);
        }
    } else {
        logError("%s: failed to find the control algorithm %s\n", __func__, this->ca.c_str());
    }
}

//
// method:          display
// description:     display the pertinents
//
// @param           none
// @return          none
//
void CompositeControl::display(void)
{
    const char *mapper[] = { "INIT",
                             "START",
                             "CONTROL_OFF",
                             "CONTROL_ON" };

    printf("\r\n");                           
    std::cout << left << setw(10) << setfill(' ') << "composite: ";
    std::cout << left << setw(32) << setfill(' ') << controlFile;
    std::cout << left << setw(20) << setfill(' ') << id;
    std::cout << left << setw(20) << setfill(' ') << tag;
    std::cout << left << setw(6)  << setfill(' ') << priority;
    std::cout << left << setw(20) << setfill(' ') << ca;
    std::cout << left << setw(16) << setfill(' ') << mapper[currentState];

    vector<OutputElement>::iterator it;
    for ( it = outputs.begin(); it != outputs.end(); ++it ) {
        std::cout << left << (*it).tag << ":" << (*it).response << "  ";
    }

    std::cout.flush();

}