Erick / Mbed 2 deprecated ICE-F412

Dependencies:   mbed-rtos mbed

Revision:
0:61364762ee0e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ICE-Application/src/ConfigurationHandler/Controls/CompositeControl.cpp	Tue Jan 24 19:05:33 2017 +0000
@@ -0,0 +1,372 @@
+/******************************************************************************
+ *
+ * File:                CompositeControl.cpp
+ * Desciption:          ICE Composite Control Class implementation
+ *
+ *****************************************************************************/
+#include "CompositeControl.h"
+#include "ConfigurationHandler.h"
+#include "cJSON.h"
+#include "ModbusMasterApi.h"
+#include "global.h"
+#include "ICELog.h"
+#include <string>
+#include <iostream>
+#include <iomanip>
+
+#ifdef MDOT_ICE
+extern mDot *GLOBAL_mdot;
+#endif 
+
+using namespace std;
+
+
+//
+// method:          load
+// description:     load a composite control
+//
+// @param[in]       _controlFile -> the file containing the JSON data
+// @return          false if an error occurs; true otherwise
+//
+
+bool CompositeControl::load(std::string _controlFile)
+{
+    controlFile = _controlFile;
+
+
+    char dataBuf[MAX_FILE_SIZE];
+
+    // read the control data
+    bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf));
+    if ( rc != true ) {
+        logError("%s: failed to read %s", __func__, controlFile.c_str());
+        // caller should destroy the object
+        return false;
+    }
+
+    // validate control data
+    if ( !validateControlData(dataBuf) ) {
+        logError("%s: failed to validate control data", __func__);
+        return false;
+    }
+
+    // copy  control data
+    copyControlData(dataBuf);
+    
+    // TODO: validate the list fo outputs
+    
+    return true;
+}
+
+//
+// method:              validateControlData
+// description:         validate JSON formatted control data
+//
+// @param[in]           buf -> JSON formatted string
+// @param[out]          none
+// @return              true if valid; false otherwise
+//
+
+bool CompositeControl::validateControlData(const char *buf)
+{
+    bool rc = true;
+    cJSON * root    = cJSON_Parse(buf);
+
+    if ( !cJSON_HasObjectItem(root, "id") ||
+            !cJSON_HasObjectItem(root, "tag") ||
+            !cJSON_HasObjectItem(root, "priority") ||
+            !cJSON_HasObjectItem(root, "ca") ||
+            !cJSON_HasObjectItem(root, "outputs") ) {
+        logError("%s: control file missing expected tags", __func__);
+        cJSON_Delete(root);
+        return false;
+    }
+
+    cJSON_Delete(root);
+    return rc;
+}
+
+//
+// method:              copyControlData
+// description:         copy the JSON formatted data
+//
+// @param[in]           buf -> JSON formatted string
+// @param[out]          none
+// @return              none
+//
+void CompositeControl::copyControlData(const char *buf)
+{
+    cJSON * root    = cJSON_Parse(buf);
+
+    id              = cJSON_GetObjectItem(root,"id")->valuestring;
+    tag             = cJSON_GetObjectItem(root, "tag")->valuestring;
+    priority        = atoi(cJSON_GetObjectItem(root, "priority")->valuestring);
+    ca              = cJSON_GetObjectItem(root, "ca")->valuestring;
+    cJSON *array    = cJSON_GetObjectItem(root, "outputs");
+    for ( int i = 0; i < cJSON_GetArraySize(array); ++i ) {
+        cJSON *subitem = cJSON_GetArrayItem(array, i);
+        std::string tag      = cJSON_GetObjectItem(subitem, "tag")->valuestring;
+        std::string response = cJSON_GetObjectItem(subitem, "responseA")->valuestring;
+        OutputElement x = { tag, response };
+        outputs.push_back(x);
+    }
+    cJSON_Delete(root);
+}
+
+//
+// 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
+//
+CompositeControlError_t CompositeControl::update(void)
+{
+    CompositeControlError_t rc = COMPOSITE_CONTROL_OK;
+    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:
+            logError("%s: unknown state %d", __func__, this->currentState);
+            rc = COMPOSITE_CONTROL_UNK_STATE;
+            break;
+    }
+    return rc;
+}
+
+//
+// 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::const_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[in]       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();
+        }
+    }
+
+    if ( ca->getOp() == "&" ) {
+        if ( (int)value.value & (int)atoi(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[in]       result -> the result of the operation
+// @return          none
+//
+void CompositeControl::triggerOutputs(std::string result)
+{
+
+    // loop through the list
+    StringAlgorithmMap::const_iterator pos;
+    pos = algorithmTable.find(this->ca);
+    if ( pos != algorithmTable.end() ) {
+        std::vector<OutputElement>::const_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[in]       io_tag  -> input/output tag
+// @param[in]       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::const_iterator pos;
+    pos = algorithmTable.find(this->ca);
+    if ( pos != algorithmTable.end() ) {
+        std::vector<OutputElement>::const_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(40) << 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>::const_iterator it;
+    for ( it = outputs.begin(); it != outputs.end(); ++it ) {
+        std::cout << left << (*it).tag << ":" << (*it).response << "  ";
+    }
+
+    std::cout.flush();
+
+}
\ No newline at end of file