Erick / Mbed 2 deprecated ICE-F412

Dependencies:   mbed-rtos mbed

Committer:
jmarkel44
Date:
Tue Jan 24 19:05:33 2017 +0000
Revision:
0:61364762ee0e
Port from IAR to Nucleo-F412 board

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jmarkel44 0:61364762ee0e 1 /******************************************************************************
jmarkel44 0:61364762ee0e 2 *
jmarkel44 0:61364762ee0e 3 * File: ManualControl.cpp
jmarkel44 0:61364762ee0e 4 * Desciption: ICE Manual Control Class implementation
jmarkel44 0:61364762ee0e 5 *
jmarkel44 0:61364762ee0e 6 *****************************************************************************/
jmarkel44 0:61364762ee0e 7 #include "ManualControl.h"
jmarkel44 0:61364762ee0e 8 #include "ICELog.h"
jmarkel44 0:61364762ee0e 9 #include "cJSON.h"
jmarkel44 0:61364762ee0e 10 #include "ModbusMasterApi.h"
jmarkel44 0:61364762ee0e 11 #include "global.h"
jmarkel44 0:61364762ee0e 12 #include <string>
jmarkel44 0:61364762ee0e 13 #include <iostream>
jmarkel44 0:61364762ee0e 14 #include <iomanip>
jmarkel44 0:61364762ee0e 15 #include <stdarg.h>
jmarkel44 0:61364762ee0e 16 #include <stdlib.h>
jmarkel44 0:61364762ee0e 17 #include <time.h>
jmarkel44 0:61364762ee0e 18
jmarkel44 0:61364762ee0e 19 using namespace std;
jmarkel44 0:61364762ee0e 20
jmarkel44 0:61364762ee0e 21 // for debugging - this can be set via the console command:
jmarkel44 0:61364762ee0e 22 // "debug-man 1 or debug-man 0
jmarkel44 0:61364762ee0e 23 bool debugManualControl = false;
jmarkel44 0:61364762ee0e 24
jmarkel44 0:61364762ee0e 25 static void debug(const char *fmt, ...)
jmarkel44 0:61364762ee0e 26 {
jmarkel44 0:61364762ee0e 27 if ( debugManualControl ) {
jmarkel44 0:61364762ee0e 28 va_list vargs;
jmarkel44 0:61364762ee0e 29 va_start(vargs, fmt);
jmarkel44 0:61364762ee0e 30 vfprintf(stdout, fmt, vargs);
jmarkel44 0:61364762ee0e 31 va_end(vargs);
jmarkel44 0:61364762ee0e 32 }
jmarkel44 0:61364762ee0e 33 }
jmarkel44 0:61364762ee0e 34
jmarkel44 0:61364762ee0e 35 #ifdef MDOT_ICE
jmarkel44 0:61364762ee0e 36 extern mDot *GLOBAL_mdot;
jmarkel44 0:61364762ee0e 37 #endif
jmarkel44 0:61364762ee0e 38
jmarkel44 0:61364762ee0e 39 //
jmarkel44 0:61364762ee0e 40 // method: load
jmarkel44 0:61364762ee0e 41 // description: open the configuration file and assign data to the
jmarkel44 0:61364762ee0e 42 // setpoint control object
jmarkel44 0:61364762ee0e 43 //
jmarkel44 0:61364762ee0e 44 // @param controlFile -> name of the control file
jmarkel44 0:61364762ee0e 45 // @return true if data is assigned; false on error
jmarkel44 0:61364762ee0e 46 //
jmarkel44 0:61364762ee0e 47 bool ManualControl::load(std::string _controlFile)
jmarkel44 0:61364762ee0e 48 {
jmarkel44 0:61364762ee0e 49 controlFile = _controlFile;
jmarkel44 0:61364762ee0e 50 endTime = 0;
jmarkel44 0:61364762ee0e 51
jmarkel44 0:61364762ee0e 52 char dataBuf[MAX_FILE_SIZE];
jmarkel44 0:61364762ee0e 53
jmarkel44 0:61364762ee0e 54 // read the data into the buffer
jmarkel44 0:61364762ee0e 55 bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf));
jmarkel44 0:61364762ee0e 56 if ( rc != true ) {
jmarkel44 0:61364762ee0e 57 logError("%s: failed to read %s", __func__, controlFile.c_str());
jmarkel44 0:61364762ee0e 58 // caller should destroy the object
jmarkel44 0:61364762ee0e 59 return false;
jmarkel44 0:61364762ee0e 60 }
jmarkel44 0:61364762ee0e 61
jmarkel44 0:61364762ee0e 62 // validate the JSON tags in the control file
jmarkel44 0:61364762ee0e 63 if ( validateControlData(dataBuf) != true ) {
jmarkel44 0:61364762ee0e 64 logError("%s: invalid control data.", __func__);
jmarkel44 0:61364762ee0e 65 return false;
jmarkel44 0:61364762ee0e 66 }
jmarkel44 0:61364762ee0e 67
jmarkel44 0:61364762ee0e 68 // assign object data from control file
jmarkel44 0:61364762ee0e 69 copyControlData(dataBuf);
jmarkel44 0:61364762ee0e 70
jmarkel44 0:61364762ee0e 71 ModbusValue val;
jmarkel44 0:61364762ee0e 72 // validate the output
jmarkel44 0:61364762ee0e 73 if ( ModbusMasterReadRegister(output, &val) == false ) {
jmarkel44 0:61364762ee0e 74 logError("%s failed to find output %s", id.c_str(), output.c_str());
jmarkel44 0:61364762ee0e 75 return false;
jmarkel44 0:61364762ee0e 76 }
jmarkel44 0:61364762ee0e 77
jmarkel44 0:61364762ee0e 78 return true;
jmarkel44 0:61364762ee0e 79 }
jmarkel44 0:61364762ee0e 80
jmarkel44 0:61364762ee0e 81 //
jmarkel44 0:61364762ee0e 82 // method: validateControlData
jmarkel44 0:61364762ee0e 83 // description: validate JSON formatted data
jmarkel44 0:61364762ee0e 84 //
jmarkel44 0:61364762ee0e 85 // @param[in] buf -> JSON formatted string
jmarkel44 0:61364762ee0e 86 // @param[out] none
jmarkel44 0:61364762ee0e 87 // @return true if valid; false otherwise
jmarkel44 0:61364762ee0e 88 //
jmarkel44 0:61364762ee0e 89 bool ManualControl::validateControlData(const char* buf)
jmarkel44 0:61364762ee0e 90 {
jmarkel44 0:61364762ee0e 91 bool rc = true;
jmarkel44 0:61364762ee0e 92 cJSON * root = cJSON_Parse(buf);
jmarkel44 0:61364762ee0e 93
jmarkel44 0:61364762ee0e 94 if ( !cJSON_HasObjectItem(root, "id") ||
jmarkel44 0:61364762ee0e 95 !cJSON_HasObjectItem(root, "output") ||
jmarkel44 0:61364762ee0e 96 !cJSON_HasObjectItem(root, "type") ||
jmarkel44 0:61364762ee0e 97 !cJSON_HasObjectItem(root, "priority") ||
jmarkel44 0:61364762ee0e 98 !cJSON_HasObjectItem(root, "duration") ||
jmarkel44 0:61364762ee0e 99 !cJSON_HasObjectItem(root, "setpoint") ||
jmarkel44 0:61364762ee0e 100 !cJSON_HasObjectItem(root, "state") ||
jmarkel44 0:61364762ee0e 101 !cJSON_HasObjectItem(root, "percent") ) {
jmarkel44 0:61364762ee0e 102 logError("%s: control file is missing expected tags", __func__);
jmarkel44 0:61364762ee0e 103 rc = false;
jmarkel44 0:61364762ee0e 104 }
jmarkel44 0:61364762ee0e 105 cJSON_Delete(root);
jmarkel44 0:61364762ee0e 106 return rc;
jmarkel44 0:61364762ee0e 107 }
jmarkel44 0:61364762ee0e 108
jmarkel44 0:61364762ee0e 109 //
jmarkel44 0:61364762ee0e 110 // method: copyControlData
jmarkel44 0:61364762ee0e 111 // description: copy JSON formatted control data to object
jmarkel44 0:61364762ee0e 112 //
jmarkel44 0:61364762ee0e 113 // @param[in] buf -> JSON formatted string
jmarkel44 0:61364762ee0e 114 // @param[out] none
jmarkel44 0:61364762ee0e 115 // @return none
jmarkel44 0:61364762ee0e 116 //
jmarkel44 0:61364762ee0e 117 void ManualControl::copyControlData(const char *buf)
jmarkel44 0:61364762ee0e 118 {
jmarkel44 0:61364762ee0e 119 cJSON * root = cJSON_Parse(buf);
jmarkel44 0:61364762ee0e 120
jmarkel44 0:61364762ee0e 121 id = cJSON_GetObjectItem(root,"id")->valuestring;
jmarkel44 0:61364762ee0e 122 output = cJSON_GetObjectItem(root,"output")->valuestring;
jmarkel44 0:61364762ee0e 123 type = atoi(cJSON_GetObjectItem(root,"type")->valuestring);
jmarkel44 0:61364762ee0e 124 priority = atoi(cJSON_GetObjectItem(root, "priority")->valuestring);
jmarkel44 0:61364762ee0e 125 duration = atoi(cJSON_GetObjectItem(root, "duration")->valuestring);
jmarkel44 0:61364762ee0e 126 setpoint = atof(cJSON_GetObjectItem(root, "setpoint")->valuestring);
jmarkel44 0:61364762ee0e 127 state = atoi(cJSON_GetObjectItem(root, "state")->valuestring);
jmarkel44 0:61364762ee0e 128 percent = atoi(cJSON_GetObjectItem(root, "percent")->valuestring);
jmarkel44 0:61364762ee0e 129
jmarkel44 0:61364762ee0e 130 cJSON_Delete(root);
jmarkel44 0:61364762ee0e 131 }
jmarkel44 0:61364762ee0e 132
jmarkel44 0:61364762ee0e 133 //
jmarkel44 0:61364762ee0e 134 // method: start
jmarkel44 0:61364762ee0e 135 // description: start the manual control
jmarkel44 0:61364762ee0e 136 //
jmarkel44 0:61364762ee0e 137 // @param none
jmarkel44 0:61364762ee0e 138 // @return none
jmarkel44 0:61364762ee0e 139 //
jmarkel44 0:61364762ee0e 140 void ManualControl::start(void)
jmarkel44 0:61364762ee0e 141 {
jmarkel44 0:61364762ee0e 142 currentState = STATE_STARTUP;
jmarkel44 0:61364762ee0e 143 if ( type == MANUAL_CONTROL_TYPE_TIMED ) {
jmarkel44 0:61364762ee0e 144 debug("\r%s:%s-> manual control is timed\n", __func__, id.c_str());
jmarkel44 0:61364762ee0e 145 endTime = time(NULL) + duration;
jmarkel44 0:61364762ee0e 146 }
jmarkel44 0:61364762ee0e 147 }
jmarkel44 0:61364762ee0e 148
jmarkel44 0:61364762ee0e 149 //
jmarkel44 0:61364762ee0e 150 // method: update
jmarkel44 0:61364762ee0e 151 // description: the manual control's state machine
jmarkel44 0:61364762ee0e 152 //
jmarkel44 0:61364762ee0e 153 // @param none
jmarkel44 0:61364762ee0e 154 // @return none
jmarkel44 0:61364762ee0e 155 //
jmarkel44 0:61364762ee0e 156 ManualControlError_t ManualControl::update(void)
jmarkel44 0:61364762ee0e 157 {
jmarkel44 0:61364762ee0e 158 ManualControlError_t rc = MANUAL_CONTROL_OK;
jmarkel44 0:61364762ee0e 159
jmarkel44 0:61364762ee0e 160 switch ( this->currentState ) {
jmarkel44 0:61364762ee0e 161 case STATE_INIT:
jmarkel44 0:61364762ee0e 162 // do nothing
jmarkel44 0:61364762ee0e 163 break;
jmarkel44 0:61364762ee0e 164 case STATE_STARTUP:
jmarkel44 0:61364762ee0e 165 if ( state & 0x01 ) {
jmarkel44 0:61364762ee0e 166 this->currentState = STATE_CONTROL_ON;
jmarkel44 0:61364762ee0e 167 debug("\r%s: [STARTUP]->manual on->[ON]\n", id.c_str());
jmarkel44 0:61364762ee0e 168 } else {
jmarkel44 0:61364762ee0e 169 this->currentState = STATE_CONTROL_OFF;
jmarkel44 0:61364762ee0e 170 debug("\r%s: [STARTUP]->manual off->[OFF]\n", id.c_str());
jmarkel44 0:61364762ee0e 171
jmarkel44 0:61364762ee0e 172 }
jmarkel44 0:61364762ee0e 173 //this->currentState = (state & 0x01) ? STATE_CONTROL_ON : STATE_CONTROL_OFF;
jmarkel44 0:61364762ee0e 174 this->powerOutput();
jmarkel44 0:61364762ee0e 175 break;
jmarkel44 0:61364762ee0e 176 case STATE_CONTROL_ON:
jmarkel44 0:61364762ee0e 177 if ( !(state & 0x1) ) {
jmarkel44 0:61364762ee0e 178 this->currentState = STATE_CONTROL_OFF;
jmarkel44 0:61364762ee0e 179 // user has changed state, so this is (or becomes) a pure
jmarkel44 0:61364762ee0e 180 // manual control
jmarkel44 0:61364762ee0e 181 endTime = 0;
jmarkel44 0:61364762ee0e 182 this->powerOutput();
jmarkel44 0:61364762ee0e 183 debug("\r%s: [ON]->manual off->[OFF]\n", id.c_str());
jmarkel44 0:61364762ee0e 184 } else if ( endTime != 0 && time(NULL) >= endTime ) {
jmarkel44 0:61364762ee0e 185 // timed interval has elapsed
jmarkel44 0:61364762ee0e 186 currentState = STATE_CONTROL_FINISHED;
jmarkel44 0:61364762ee0e 187 debug("\r%s: [ON]->timer expired->[FINISHED]\n", id.c_str());
jmarkel44 0:61364762ee0e 188 }
jmarkel44 0:61364762ee0e 189 break;
jmarkel44 0:61364762ee0e 190 case STATE_CONTROL_OFF:
jmarkel44 0:61364762ee0e 191 if ( state & 0x1 ) {
jmarkel44 0:61364762ee0e 192 this->currentState = STATE_CONTROL_ON;
jmarkel44 0:61364762ee0e 193 // user has changed the state, so this (or becomes) a pure
jmarkel44 0:61364762ee0e 194 // manual control
jmarkel44 0:61364762ee0e 195 endTime = 0;
jmarkel44 0:61364762ee0e 196 this->powerOutput();
jmarkel44 0:61364762ee0e 197 debug("\r%s: [OFF]->manual on->[ON]\n", id.c_str());
jmarkel44 0:61364762ee0e 198 } else if ( endTime != 0 && time(NULL) >= endTime ) {
jmarkel44 0:61364762ee0e 199 // timed interval has elapsed
jmarkel44 0:61364762ee0e 200 currentState = STATE_CONTROL_FINISHED;
jmarkel44 0:61364762ee0e 201 debug("\r%s: [OFF]->timer expired->[FINISHED]\n", id.c_str());
jmarkel44 0:61364762ee0e 202 }
jmarkel44 0:61364762ee0e 203 break;
jmarkel44 0:61364762ee0e 204 case STATE_CONTROL_FINISHED:
jmarkel44 0:61364762ee0e 205 // mark for deletion (control task will do the cleanup)
jmarkel44 0:61364762ee0e 206 rc = MANUAL_CONTROL_DESTROY;
jmarkel44 0:61364762ee0e 207 break;
jmarkel44 0:61364762ee0e 208 default:
jmarkel44 0:61364762ee0e 209 logError("%s unknown state %d\n", __func__, this->currentState);
jmarkel44 0:61364762ee0e 210 rc = MANUAL_CONTROL_ERROR;
jmarkel44 0:61364762ee0e 211 break;
jmarkel44 0:61364762ee0e 212 }
jmarkel44 0:61364762ee0e 213 return rc;
jmarkel44 0:61364762ee0e 214 }
jmarkel44 0:61364762ee0e 215
jmarkel44 0:61364762ee0e 216 //
jmarkel44 0:61364762ee0e 217 // method: unregisterControl
jmarkel44 0:61364762ee0e 218 // description: unregister this control with the output master
jmarkel44 0:61364762ee0e 219 //
jmarkel44 0:61364762ee0e 220 // @param none
jmarkel44 0:61364762ee0e 221 // @return none
jmarkel44 0:61364762ee0e 222 //
jmarkel44 0:61364762ee0e 223 int ManualControl::unregisterControl(void)
jmarkel44 0:61364762ee0e 224 {
jmarkel44 0:61364762ee0e 225 logInfo("%s: Attempting to unregister %s\n",
jmarkel44 0:61364762ee0e 226 __func__, controlFile.c_str());
jmarkel44 0:61364762ee0e 227
jmarkel44 0:61364762ee0e 228 OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
jmarkel44 0:61364762ee0e 229 memset(output_mail, 0, sizeof(OutputControlMsg_t));
jmarkel44 0:61364762ee0e 230
jmarkel44 0:61364762ee0e 231 output_mail->controlType = CONTROL_MANUAL;
jmarkel44 0:61364762ee0e 232 output_mail->action = ACTION_CONTROL_UNREGISTER;
jmarkel44 0:61364762ee0e 233 output_mail->priority = this->priority;
jmarkel44 0:61364762ee0e 234 strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
jmarkel44 0:61364762ee0e 235 strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
jmarkel44 0:61364762ee0e 236
jmarkel44 0:61364762ee0e 237 OutputMasterMailBox.put(output_mail);
jmarkel44 0:61364762ee0e 238 return 0;
jmarkel44 0:61364762ee0e 239 }
jmarkel44 0:61364762ee0e 240
jmarkel44 0:61364762ee0e 241 //
jmarkel44 0:61364762ee0e 242 // method: powerOutput
jmarkel44 0:61364762ee0e 243 // description: send a message to the output thread to power the relay
jmarkel44 0:61364762ee0e 244 //
jmarkel44 0:61364762ee0e 245 // @param none
jmarkel44 0:61364762ee0e 246 // @return -1 on error; 0 otherwise
jmarkel44 0:61364762ee0e 247 //
jmarkel44 0:61364762ee0e 248 int ManualControl::powerOutput(void)
jmarkel44 0:61364762ee0e 249 {
jmarkel44 0:61364762ee0e 250 printf("\r%s-> id:%s attempting to manually turn %s relay %s\n",
jmarkel44 0:61364762ee0e 251 __func__, id.c_str(), (state & 0x1) ? "ON" : "OFF", output.c_str());
jmarkel44 0:61364762ee0e 252
jmarkel44 0:61364762ee0e 253 OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
jmarkel44 0:61364762ee0e 254 memset(output_mail, 0, sizeof(OutputControlMsg_t));
jmarkel44 0:61364762ee0e 255
jmarkel44 0:61364762ee0e 256 output_mail->controlType = CONTROL_MANUAL;
jmarkel44 0:61364762ee0e 257 output_mail->action = (state & 0x1) ? ACTION_CONTROL_ON : ACTION_CONTROL_OFF;
jmarkel44 0:61364762ee0e 258 output_mail->priority = this->priority;
jmarkel44 0:61364762ee0e 259 strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
jmarkel44 0:61364762ee0e 260 strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
jmarkel44 0:61364762ee0e 261
jmarkel44 0:61364762ee0e 262 OutputMasterMailBox.put(output_mail);
jmarkel44 0:61364762ee0e 263 return 0;
jmarkel44 0:61364762ee0e 264 }
jmarkel44 0:61364762ee0e 265
jmarkel44 0:61364762ee0e 266 //
jmarkel44 0:61364762ee0e 267 // method: display
jmarkel44 0:61364762ee0e 268 // description: display the pertinents
jmarkel44 0:61364762ee0e 269 //
jmarkel44 0:61364762ee0e 270 // @param none
jmarkel44 0:61364762ee0e 271 // @return none
jmarkel44 0:61364762ee0e 272 //
jmarkel44 0:61364762ee0e 273 void ManualControl::display(void)
jmarkel44 0:61364762ee0e 274 {
jmarkel44 0:61364762ee0e 275 string mapper[] = { "INIT",
jmarkel44 0:61364762ee0e 276 "STARTUP",
jmarkel44 0:61364762ee0e 277 "CONTROL_ON",
jmarkel44 0:61364762ee0e 278 "CONTROL_OFF"
jmarkel44 0:61364762ee0e 279 };
jmarkel44 0:61364762ee0e 280
jmarkel44 0:61364762ee0e 281 printf("\r\n");
jmarkel44 0:61364762ee0e 282 std::cout << left << setw(10) << setfill(' ') << "manual: ";
jmarkel44 0:61364762ee0e 283 std::cout << left << setw(40) << setfill(' ') << controlFile;
jmarkel44 0:61364762ee0e 284 std::cout << left << setw(20) << setfill(' ') << id;
jmarkel44 0:61364762ee0e 285 std::cout << left << setw(20) << setfill(' ') << output;
jmarkel44 0:61364762ee0e 286 std::cout << left << setw(6) << setfill(' ') << type;
jmarkel44 0:61364762ee0e 287 std::cout << left << setw(6) << setfill(' ') << priority;
jmarkel44 0:61364762ee0e 288 std::cout << left << setw(8) << setfill(' ') << duration;
jmarkel44 0:61364762ee0e 289 //std::cout << left << setw(8) << setfill(' ') << percent;
jmarkel44 0:61364762ee0e 290 std::cout << left << setw(16) << setfill(' ') << mapper[currentState];
jmarkel44 0:61364762ee0e 291 if ( type == MANUAL_CONTROL_TYPE_TIMED ) {
jmarkel44 0:61364762ee0e 292 std::cout << left << setw(8) << setfill(' ') << "Time Remaining (secs): " << endTime - time(NULL);
jmarkel44 0:61364762ee0e 293 }
jmarkel44 0:61364762ee0e 294 std::cout.flush();
jmarkel44 0:61364762ee0e 295 }