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/ManualControl.cpp
- Revision:
- 0:61364762ee0e
diff -r 000000000000 -r 61364762ee0e ICE-Application/src/ConfigurationHandler/Controls/ManualControl.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ICE-Application/src/ConfigurationHandler/Controls/ManualControl.cpp Tue Jan 24 19:05:33 2017 +0000
@@ -0,0 +1,295 @@
+/******************************************************************************
+ *
+ * File: ManualControl.cpp
+ * Desciption: ICE Manual Control Class implementation
+ *
+ *****************************************************************************/
+#include "ManualControl.h"
+#include "ICELog.h"
+#include "cJSON.h"
+#include "ModbusMasterApi.h"
+#include "global.h"
+#include <string>
+#include <iostream>
+#include <iomanip>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+
+using namespace std;
+
+// for debugging - this can be set via the console command:
+// "debug-man 1 or debug-man 0
+bool debugManualControl = false;
+
+static void debug(const char *fmt, ...)
+{
+ if ( debugManualControl ) {
+ va_list vargs;
+ va_start(vargs, fmt);
+ vfprintf(stdout, fmt, vargs);
+ va_end(vargs);
+ }
+}
+
+#ifdef MDOT_ICE
+extern mDot *GLOBAL_mdot;
+#endif
+
+//
+// method: load
+// description: open the configuration file and assign data to the
+// setpoint control object
+//
+// @param controlFile -> name of the control file
+// @return true if data is assigned; false on error
+//
+bool ManualControl::load(std::string _controlFile)
+{
+ controlFile = _controlFile;
+ endTime = 0;
+
+ char dataBuf[MAX_FILE_SIZE];
+
+ // read the data into the buffer
+ 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 the JSON tags in the control file
+ if ( validateControlData(dataBuf) != true ) {
+ logError("%s: invalid control data.", __func__);
+ return false;
+ }
+
+ // assign object data from control file
+ copyControlData(dataBuf);
+
+ ModbusValue val;
+ // validate the output
+ if ( ModbusMasterReadRegister(output, &val) == false ) {
+ logError("%s failed to find output %s", id.c_str(), output.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+//
+// method: validateControlData
+// description: validate JSON formatted data
+//
+// @param[in] buf -> JSON formatted string
+// @param[out] none
+// @return true if valid; false otherwise
+//
+bool ManualControl::validateControlData(const char* buf)
+{
+ bool rc = true;
+ cJSON * root = cJSON_Parse(buf);
+
+ if ( !cJSON_HasObjectItem(root, "id") ||
+ !cJSON_HasObjectItem(root, "output") ||
+ !cJSON_HasObjectItem(root, "type") ||
+ !cJSON_HasObjectItem(root, "priority") ||
+ !cJSON_HasObjectItem(root, "duration") ||
+ !cJSON_HasObjectItem(root, "setpoint") ||
+ !cJSON_HasObjectItem(root, "state") ||
+ !cJSON_HasObjectItem(root, "percent") ) {
+ logError("%s: control file is missing expected tags", __func__);
+ rc = false;
+ }
+ cJSON_Delete(root);
+ return rc;
+}
+
+//
+// method: copyControlData
+// description: copy JSON formatted control data to object
+//
+// @param[in] buf -> JSON formatted string
+// @param[out] none
+// @return none
+//
+void ManualControl::copyControlData(const char *buf)
+{
+ cJSON * root = cJSON_Parse(buf);
+
+ id = cJSON_GetObjectItem(root,"id")->valuestring;
+ output = cJSON_GetObjectItem(root,"output")->valuestring;
+ type = atoi(cJSON_GetObjectItem(root,"type")->valuestring);
+ priority = atoi(cJSON_GetObjectItem(root, "priority")->valuestring);
+ duration = atoi(cJSON_GetObjectItem(root, "duration")->valuestring);
+ setpoint = atof(cJSON_GetObjectItem(root, "setpoint")->valuestring);
+ state = atoi(cJSON_GetObjectItem(root, "state")->valuestring);
+ percent = atoi(cJSON_GetObjectItem(root, "percent")->valuestring);
+
+ cJSON_Delete(root);
+}
+
+//
+// method: start
+// description: start the manual control
+//
+// @param none
+// @return none
+//
+void ManualControl::start(void)
+{
+ currentState = STATE_STARTUP;
+ if ( type == MANUAL_CONTROL_TYPE_TIMED ) {
+ debug("\r%s:%s-> manual control is timed\n", __func__, id.c_str());
+ endTime = time(NULL) + duration;
+ }
+}
+
+//
+// method: update
+// description: the manual control's state machine
+//
+// @param none
+// @return none
+//
+ManualControlError_t ManualControl::update(void)
+{
+ ManualControlError_t rc = MANUAL_CONTROL_OK;
+
+ switch ( this->currentState ) {
+ case STATE_INIT:
+ // do nothing
+ break;
+ case STATE_STARTUP:
+ if ( state & 0x01 ) {
+ this->currentState = STATE_CONTROL_ON;
+ debug("\r%s: [STARTUP]->manual on->[ON]\n", id.c_str());
+ } else {
+ this->currentState = STATE_CONTROL_OFF;
+ debug("\r%s: [STARTUP]->manual off->[OFF]\n", id.c_str());
+
+ }
+ //this->currentState = (state & 0x01) ? STATE_CONTROL_ON : STATE_CONTROL_OFF;
+ this->powerOutput();
+ break;
+ case STATE_CONTROL_ON:
+ if ( !(state & 0x1) ) {
+ this->currentState = STATE_CONTROL_OFF;
+ // user has changed state, so this is (or becomes) a pure
+ // manual control
+ endTime = 0;
+ this->powerOutput();
+ debug("\r%s: [ON]->manual off->[OFF]\n", id.c_str());
+ } else if ( endTime != 0 && time(NULL) >= endTime ) {
+ // timed interval has elapsed
+ currentState = STATE_CONTROL_FINISHED;
+ debug("\r%s: [ON]->timer expired->[FINISHED]\n", id.c_str());
+ }
+ break;
+ case STATE_CONTROL_OFF:
+ if ( state & 0x1 ) {
+ this->currentState = STATE_CONTROL_ON;
+ // user has changed the state, so this (or becomes) a pure
+ // manual control
+ endTime = 0;
+ this->powerOutput();
+ debug("\r%s: [OFF]->manual on->[ON]\n", id.c_str());
+ } else if ( endTime != 0 && time(NULL) >= endTime ) {
+ // timed interval has elapsed
+ currentState = STATE_CONTROL_FINISHED;
+ debug("\r%s: [OFF]->timer expired->[FINISHED]\n", id.c_str());
+ }
+ break;
+ case STATE_CONTROL_FINISHED:
+ // mark for deletion (control task will do the cleanup)
+ rc = MANUAL_CONTROL_DESTROY;
+ break;
+ default:
+ logError("%s unknown state %d\n", __func__, this->currentState);
+ rc = MANUAL_CONTROL_ERROR;
+ break;
+ }
+ return rc;
+}
+
+//
+// method: unregisterControl
+// description: unregister this control with the output master
+//
+// @param none
+// @return none
+//
+int ManualControl::unregisterControl(void)
+{
+ logInfo("%s: Attempting to unregister %s\n",
+ __func__, controlFile.c_str());
+
+ OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
+ memset(output_mail, 0, sizeof(OutputControlMsg_t));
+
+ output_mail->controlType = CONTROL_MANUAL;
+ output_mail->action = ACTION_CONTROL_UNREGISTER;
+ output_mail->priority = this->priority;
+ strncpy(output_mail->output_tag, this->output.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);
+ return 0;
+}
+
+//
+// method: powerOutput
+// description: send a message to the output thread to power the relay
+//
+// @param none
+// @return -1 on error; 0 otherwise
+//
+int ManualControl::powerOutput(void)
+{
+ printf("\r%s-> id:%s attempting to manually turn %s relay %s\n",
+ __func__, id.c_str(), (state & 0x1) ? "ON" : "OFF", output.c_str());
+
+ OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
+ memset(output_mail, 0, sizeof(OutputControlMsg_t));
+
+ output_mail->controlType = CONTROL_MANUAL;
+ output_mail->action = (state & 0x1) ? ACTION_CONTROL_ON : ACTION_CONTROL_OFF;
+ output_mail->priority = this->priority;
+ strncpy(output_mail->output_tag, this->output.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);
+ return 0;
+}
+
+//
+// method: display
+// description: display the pertinents
+//
+// @param none
+// @return none
+//
+void ManualControl::display(void)
+{
+ string mapper[] = { "INIT",
+ "STARTUP",
+ "CONTROL_ON",
+ "CONTROL_OFF"
+ };
+
+ printf("\r\n");
+ std::cout << left << setw(10) << setfill(' ') << "manual: ";
+ std::cout << left << setw(40) << setfill(' ') << controlFile;
+ std::cout << left << setw(20) << setfill(' ') << id;
+ std::cout << left << setw(20) << setfill(' ') << output;
+ std::cout << left << setw(6) << setfill(' ') << type;
+ std::cout << left << setw(6) << setfill(' ') << priority;
+ std::cout << left << setw(8) << setfill(' ') << duration;
+ //std::cout << left << setw(8) << setfill(' ') << percent;
+ std::cout << left << setw(16) << setfill(' ') << mapper[currentState];
+ if ( type == MANUAL_CONTROL_TYPE_TIMED ) {
+ std::cout << left << setw(8) << setfill(' ') << "Time Remaining (secs): " << endTime - time(NULL);
+ }
+ std::cout.flush();
+}
\ No newline at end of file