Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: ICE-Application/src/ConfigurationHandler/Controls/CompositeControl.cpp
- 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