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: SequenceControl.cpp
jmarkel44 0:61364762ee0e 4 * Desciption: ICE Sequence Control class implementation
jmarkel44 0:61364762ee0e 5 *
jmarkel44 0:61364762ee0e 6 *****************************************************************************/
jmarkel44 0:61364762ee0e 7
jmarkel44 0:61364762ee0e 8 #include "SequenceControl.h"
jmarkel44 0:61364762ee0e 9 #include "ICELog.h"
jmarkel44 0:61364762ee0e 10 #include "cJSON.h"
jmarkel44 0:61364762ee0e 11 #include "global.h"
jmarkel44 0:61364762ee0e 12
jmarkel44 0:61364762ee0e 13 #include <stdlib.h>
jmarkel44 0:61364762ee0e 14 #include <vector>
jmarkel44 0:61364762ee0e 15 #include <string>
jmarkel44 0:61364762ee0e 16 #include <iostream>
jmarkel44 0:61364762ee0e 17 #include <iomanip>
jmarkel44 0:61364762ee0e 18 #include <stdarg.h>
jmarkel44 0:61364762ee0e 19 #include <assert.h>
jmarkel44 0:61364762ee0e 20 #include "ModbusMasterApi.h"
jmarkel44 0:61364762ee0e 21 #include "ConfigurationHandler.h"
jmarkel44 0:61364762ee0e 22
jmarkel44 0:61364762ee0e 23 // for debugging - this can be set via the console command:
jmarkel44 0:61364762ee0e 24 // "debug-se 1
jmarkel44 0:61364762ee0e 25 bool debugSequenceControl = false;
jmarkel44 0:61364762ee0e 26
jmarkel44 0:61364762ee0e 27 static void debug(const char *fmt, ...)
jmarkel44 0:61364762ee0e 28 {
jmarkel44 0:61364762ee0e 29 if ( debugSequenceControl ) {
jmarkel44 0:61364762ee0e 30 va_list vargs;
jmarkel44 0:61364762ee0e 31 va_start(vargs, fmt);
jmarkel44 0:61364762ee0e 32 vfprintf(stdout, fmt, vargs);
jmarkel44 0:61364762ee0e 33 va_end(vargs);
jmarkel44 0:61364762ee0e 34 }
jmarkel44 0:61364762ee0e 35 }
jmarkel44 0:61364762ee0e 36
jmarkel44 0:61364762ee0e 37 //
jmarkel44 0:61364762ee0e 38 // method: load
jmarkel44 0:61364762ee0e 39 // decsription: load data from the control file
jmarkel44 0:61364762ee0e 40 //
jmarkel44 0:61364762ee0e 41 // @param[in] _controlFile -> the control file
jmarkel44 0:61364762ee0e 42 // @param[out] none
jmarkel44 0:61364762ee0e 43 // @return true on success; false on error
jmarkel44 0:61364762ee0e 44 //
jmarkel44 0:61364762ee0e 45 bool SequenceControl::load(std::string _controlFile)
jmarkel44 0:61364762ee0e 46 {
jmarkel44 0:61364762ee0e 47 controlFile = _controlFile;
jmarkel44 0:61364762ee0e 48
jmarkel44 0:61364762ee0e 49 // read the data into a buffer
jmarkel44 0:61364762ee0e 50 char dataBuf[MAX_FILE_SIZE*3];
jmarkel44 0:61364762ee0e 51 bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf));
jmarkel44 0:61364762ee0e 52 if ( rc != true ) {
jmarkel44 0:61364762ee0e 53 logError("%s: failed to read %d bytes from %s", __func__, sizeof(dataBuf), controlFile.c_str());
jmarkel44 0:61364762ee0e 54 // caller should destroy the object
jmarkel44 0:61364762ee0e 55 return false;
jmarkel44 0:61364762ee0e 56 }
jmarkel44 0:61364762ee0e 57
jmarkel44 0:61364762ee0e 58 // validate the JSON tags in the control file
jmarkel44 0:61364762ee0e 59 if ( validateControlData(dataBuf) != true ) {
jmarkel44 0:61364762ee0e 60 logError("%s: invalid control data.", __func__);
jmarkel44 0:61364762ee0e 61 return false;
jmarkel44 0:61364762ee0e 62 }
jmarkel44 0:61364762ee0e 63
jmarkel44 0:61364762ee0e 64 // assign object data from control file
jmarkel44 0:61364762ee0e 65 copyControlData(dataBuf);
jmarkel44 0:61364762ee0e 66
jmarkel44 0:61364762ee0e 67 // TODO: perform additional validation
jmarkel44 0:61364762ee0e 68
jmarkel44 0:61364762ee0e 69 return true;
jmarkel44 0:61364762ee0e 70 }
jmarkel44 0:61364762ee0e 71
jmarkel44 0:61364762ee0e 72
jmarkel44 0:61364762ee0e 73
jmarkel44 0:61364762ee0e 74 // method: validateControlData
jmarkel44 0:61364762ee0e 75 // description: validates the data in the control file
jmarkel44 0:61364762ee0e 76 //
jmarkel44 0:61364762ee0e 77 // @param[in] dataBuf -> JSON formatted string
jmarkel44 0:61364762ee0e 78 // @param[out] non
jmarkel44 0:61364762ee0e 79 // @return true if valid; false otherwise
jmarkel44 0:61364762ee0e 80 //
jmarkel44 0:61364762ee0e 81 bool SequenceControl::validateControlData(const char *dataBuf)
jmarkel44 0:61364762ee0e 82 {
jmarkel44 0:61364762ee0e 83 // parse the json data
jmarkel44 0:61364762ee0e 84 bool rc = true;
jmarkel44 0:61364762ee0e 85 cJSON * root = cJSON_Parse(dataBuf);
jmarkel44 0:61364762ee0e 86
jmarkel44 0:61364762ee0e 87 // parse the control header
jmarkel44 0:61364762ee0e 88 if ( !cJSON_HasObjectItem(root, "id") ||
jmarkel44 0:61364762ee0e 89 !cJSON_HasObjectItem(root, "startTrigger") ||
jmarkel44 0:61364762ee0e 90 !cJSON_HasObjectItem(root, "sequence") ) {
jmarkel44 0:61364762ee0e 91 logError("Sequence Control is missing expected tags");
jmarkel44 0:61364762ee0e 92 cJSON_Delete(root);
jmarkel44 0:61364762ee0e 93 return false;
jmarkel44 0:61364762ee0e 94 }
jmarkel44 0:61364762ee0e 95
jmarkel44 0:61364762ee0e 96 // validate the sequence table
jmarkel44 0:61364762ee0e 97 cJSON *sequenceTable = cJSON_GetObjectItem(root, "sequence");
jmarkel44 0:61364762ee0e 98 for ( int i = 0; i < cJSON_GetArraySize(sequenceTable); ++i ) {
jmarkel44 0:61364762ee0e 99 cJSON *entry = cJSON_GetArrayItem(sequenceTable, i);
jmarkel44 0:61364762ee0e 100 if ( !cJSON_HasObjectItem(entry, "startTrigger") ) {
jmarkel44 0:61364762ee0e 101 logError("Sequence Table missing startTrigger tag");
jmarkel44 0:61364762ee0e 102 rc = false;
jmarkel44 0:61364762ee0e 103 break;
jmarkel44 0:61364762ee0e 104 }
jmarkel44 0:61364762ee0e 105 if ( !cJSON_HasObjectItem(entry, "actions") ) {
jmarkel44 0:61364762ee0e 106 logError("Sequence table is missing actions tag");
jmarkel44 0:61364762ee0e 107 rc = false;
jmarkel44 0:61364762ee0e 108 // FIXME: finish the internals
jmarkel44 0:61364762ee0e 109 break;
jmarkel44 0:61364762ee0e 110 }
jmarkel44 0:61364762ee0e 111 if ( !cJSON_HasObjectItem(entry, "stopTrigger") ) {
jmarkel44 0:61364762ee0e 112 logError("Sequence table is missing stopTrigger tag");
jmarkel44 0:61364762ee0e 113 rc = false;
jmarkel44 0:61364762ee0e 114 break;
jmarkel44 0:61364762ee0e 115 }
jmarkel44 0:61364762ee0e 116 }
jmarkel44 0:61364762ee0e 117
jmarkel44 0:61364762ee0e 118 cJSON_Delete(root);
jmarkel44 0:61364762ee0e 119 return rc;
jmarkel44 0:61364762ee0e 120 }
jmarkel44 0:61364762ee0e 121
jmarkel44 0:61364762ee0e 122 //
jmarkel44 0:61364762ee0e 123 // method: copyControlData
jmarkel44 0:61364762ee0e 124 // description: copy JSON formatted control data to object
jmarkel44 0:61364762ee0e 125 //
jmarkel44 0:61364762ee0e 126 // @param[in] dataBuf -> JSON formatted data
jmarkel44 0:61364762ee0e 127 // @param[out] none
jmarkel44 0:61364762ee0e 128 // @return none
jmarkel44 0:61364762ee0e 129 //
jmarkel44 0:61364762ee0e 130 void SequenceControl::copyControlData(const char* dataBuf)
jmarkel44 0:61364762ee0e 131 {
jmarkel44 0:61364762ee0e 132 cJSON *root = cJSON_Parse(dataBuf);
jmarkel44 0:61364762ee0e 133
jmarkel44 0:61364762ee0e 134 id = cJSON_GetObjectItem(root, "id")->valuestring;
jmarkel44 0:61364762ee0e 135 startTrigger = cJSON_GetObjectItem(root, "startTrigger")->valuestring;
jmarkel44 0:61364762ee0e 136
jmarkel44 0:61364762ee0e 137 // validate the sequence table
jmarkel44 0:61364762ee0e 138 cJSON *sequenceTable = cJSON_GetObjectItem(root, "sequence");
jmarkel44 0:61364762ee0e 139 for ( int i = 0; i < cJSON_GetArraySize(sequenceTable); ++i ) {
jmarkel44 0:61364762ee0e 140 cJSON *entry = cJSON_GetArrayItem(sequenceTable, i);
jmarkel44 0:61364762ee0e 141
jmarkel44 0:61364762ee0e 142 SequenceEntry n;
jmarkel44 0:61364762ee0e 143
jmarkel44 0:61364762ee0e 144 n.startTrigger = cJSON_GetObjectItem(entry, "startTrigger")->valuestring;
jmarkel44 0:61364762ee0e 145 n.stopTrigger = cJSON_GetObjectItem(entry, "stopTrigger")->valuestring;
jmarkel44 0:61364762ee0e 146
jmarkel44 0:61364762ee0e 147 cJSON *actionList = cJSON_GetObjectItem(entry, "actions");
jmarkel44 0:61364762ee0e 148 for ( int j = 0; j < cJSON_GetArraySize(actionList); ++j ) {
jmarkel44 0:61364762ee0e 149 cJSON *list = cJSON_GetArrayItem(actionList, j);
jmarkel44 0:61364762ee0e 150 Action_t a;
jmarkel44 0:61364762ee0e 151 a.action = cJSON_GetObjectItem(list, "action")->valuestring;
jmarkel44 0:61364762ee0e 152 a.id = cJSON_GetObjectItem(list, "id")->valuestring;
jmarkel44 0:61364762ee0e 153 if ( a.action == "assign" ) {
jmarkel44 0:61364762ee0e 154 a.value = atof(cJSON_GetObjectItem(list, "val")->valuestring);
jmarkel44 0:61364762ee0e 155 } else {
jmarkel44 0:61364762ee0e 156 a.value = 0;
jmarkel44 0:61364762ee0e 157 }
jmarkel44 0:61364762ee0e 158 n.actions.push_back(a);
jmarkel44 0:61364762ee0e 159 }
jmarkel44 0:61364762ee0e 160 // push this entry onto this sequence table
jmarkel44 0:61364762ee0e 161 this->sequenceTable.push_back(n);
jmarkel44 0:61364762ee0e 162 }
jmarkel44 0:61364762ee0e 163
jmarkel44 0:61364762ee0e 164 cJSON_Delete(root);
jmarkel44 0:61364762ee0e 165 }
jmarkel44 0:61364762ee0e 166
jmarkel44 0:61364762ee0e 167 //
jmarkel44 0:61364762ee0e 168 // method: start
jmarkel44 0:61364762ee0e 169 // decsription: start the sequence control
jmarkel44 0:61364762ee0e 170 //
jmarkel44 0:61364762ee0e 171 // @param[in] none
jmarkel44 0:61364762ee0e 172 // @param[out] none
jmarkel44 0:61364762ee0e 173 // @return none
jmarkel44 0:61364762ee0e 174 //
jmarkel44 0:61364762ee0e 175 void SequenceControl::start(void)
jmarkel44 0:61364762ee0e 176 {
jmarkel44 0:61364762ee0e 177 currentState = SEQ_STATE_START;
jmarkel44 0:61364762ee0e 178 }
jmarkel44 0:61364762ee0e 179
jmarkel44 0:61364762ee0e 180 //
jmarkel44 0:61364762ee0e 181 // method: run
jmarkel44 0:61364762ee0e 182 // decsription: run the sequence control (performs the updates)
jmarkel44 0:61364762ee0e 183 //
jmarkel44 0:61364762ee0e 184 // @param[in] none
jmarkel44 0:61364762ee0e 185 // @param[out] none
jmarkel44 0:61364762ee0e 186 // @return OK on success; error otherwise
jmarkel44 0:61364762ee0e 187 //
jmarkel44 0:61364762ee0e 188 SequenceControlError_t SequenceControl::run(void)
jmarkel44 0:61364762ee0e 189 {
jmarkel44 0:61364762ee0e 190 SequenceControlError_t rc = SEQUENCE_CONTROL_OK;
jmarkel44 0:61364762ee0e 191
jmarkel44 0:61364762ee0e 192 switch ( this->currentState ) {
jmarkel44 0:61364762ee0e 193 case SEQ_STATE_INIT:
jmarkel44 0:61364762ee0e 194 // do nothing
jmarkel44 0:61364762ee0e 195 break;
jmarkel44 0:61364762ee0e 196 case SEQ_STATE_START:
jmarkel44 0:61364762ee0e 197 // here we need to wait for the start trigger to happen
jmarkel44 0:61364762ee0e 198 if ( this->isControlStartTriggerOn() ) {
jmarkel44 0:61364762ee0e 199 debug("\r%s: [START]->start trigger->[LOADING]\n", id.c_str());
jmarkel44 0:61364762ee0e 200 ModbusValue val;
jmarkel44 0:61364762ee0e 201 ModbusMasterReadRegister(startTrigger, &val);
jmarkel44 0:61364762ee0e 202 debug("\r%s:%s: val.value = %f\n", id.c_str(), startTrigger.c_str(), val.value);
jmarkel44 0:61364762ee0e 203 currentState = SEQ_STATE_LOADING_NEXT_ENTRY;
jmarkel44 0:61364762ee0e 204 } else {
jmarkel44 0:61364762ee0e 205 // just continue waiting for the start trigger to fire
jmarkel44 0:61364762ee0e 206 }
jmarkel44 0:61364762ee0e 207 break;
jmarkel44 0:61364762ee0e 208 case SEQ_STATE_LOADING_NEXT_ENTRY: {
jmarkel44 0:61364762ee0e 209 // this is a transient state
jmarkel44 0:61364762ee0e 210 bool rc = this->loadNextEntry();
jmarkel44 0:61364762ee0e 211 if ( rc ) {
jmarkel44 0:61364762ee0e 212 debug("\r%s: [LOADING]->next entry->[WAIT-START]\n", id.c_str());
jmarkel44 0:61364762ee0e 213 currentState = SEQ_STATE_WAITING_START;
jmarkel44 0:61364762ee0e 214 } else {
jmarkel44 0:61364762ee0e 215 debug("\r%s: [LOADING]->no entries->[FINISHED]\n", id.c_str());
jmarkel44 0:61364762ee0e 216 currentState = SEQ_STATE_FINISHED;
jmarkel44 0:61364762ee0e 217 }
jmarkel44 0:61364762ee0e 218 break;
jmarkel44 0:61364762ee0e 219 }
jmarkel44 0:61364762ee0e 220 case SEQ_STATE_WAITING_START:
jmarkel44 0:61364762ee0e 221 // wait for the start triggers to evaluate to true
jmarkel44 0:61364762ee0e 222 if ( this->isCurrentEntryStartTriggerOn() ) {
jmarkel44 0:61364762ee0e 223 debug("\r%s: [WAIT-START]->perform actions->[WAIT-STOP]\n", id.c_str());
jmarkel44 0:61364762ee0e 224 performActions();
jmarkel44 0:61364762ee0e 225 currentState = SEQ_STATE_WAITING_STOP;
jmarkel44 0:61364762ee0e 226 } else {
jmarkel44 0:61364762ee0e 227 // wait until the start trigger fires
jmarkel44 0:61364762ee0e 228 }
jmarkel44 0:61364762ee0e 229 break;
jmarkel44 0:61364762ee0e 230 case SEQ_STATE_WAITING_STOP:
jmarkel44 0:61364762ee0e 231 // wait for the stop triggers to evaluate to true
jmarkel44 0:61364762ee0e 232 if ( this->isCurrentEntryStopTriggerOn() ) {
jmarkel44 0:61364762ee0e 233 debug("\r%s: [WAIT-STOP]->stop trigger ON->[LOAD NEXT]\n", id.c_str());
jmarkel44 0:61364762ee0e 234 currentState = SEQ_STATE_LOADING_NEXT_ENTRY;
jmarkel44 0:61364762ee0e 235 } else {
jmarkel44 0:61364762ee0e 236 // continue waiting
jmarkel44 0:61364762ee0e 237 }
jmarkel44 0:61364762ee0e 238 break;
jmarkel44 0:61364762ee0e 239 case SEQ_STATE_FINISHED:
jmarkel44 0:61364762ee0e 240 // do any cleanup work that's needed here.
jmarkel44 0:61364762ee0e 241 debug("\r%s: [FINISHED]->clearing the reg->[START]\n", id.c_str());
jmarkel44 0:61364762ee0e 242 ModbusMasterWriteRegister(this->startTrigger, 0);
jmarkel44 0:61364762ee0e 243 this->currentState = SEQ_STATE_START;
jmarkel44 0:61364762ee0e 244 break;
jmarkel44 0:61364762ee0e 245 case SEQ_STATE_MAX:
jmarkel44 0:61364762ee0e 246 default:
jmarkel44 0:61364762ee0e 247 logError("%s: unknown state %u\n", __func__, this->currentState);
jmarkel44 0:61364762ee0e 248 rc = SEQUENCE_CONTROL_UNK_STATE;
jmarkel44 0:61364762ee0e 249 break;
jmarkel44 0:61364762ee0e 250 }
jmarkel44 0:61364762ee0e 251 return rc;
jmarkel44 0:61364762ee0e 252 }
jmarkel44 0:61364762ee0e 253
jmarkel44 0:61364762ee0e 254 //
jmarkel44 0:61364762ee0e 255 // method: isControlStartTriggerOn
jmarkel44 0:61364762ee0e 256 // description: true if the start trigger evals to true
jmarkel44 0:61364762ee0e 257 //
jmarkel44 0:61364762ee0e 258 // @param[in] none
jmarkel44 0:61364762ee0e 259 // @param[out] none
jmarkel44 0:61364762ee0e 260 // @return true if start trigger > 0; false otherwise
jmarkel44 0:61364762ee0e 261 //
jmarkel44 0:61364762ee0e 262 bool SequenceControl::isControlStartTriggerOn(void)
jmarkel44 0:61364762ee0e 263 {
jmarkel44 0:61364762ee0e 264 ModbusValue value;
jmarkel44 0:61364762ee0e 265 bool rc = ModbusMasterReadRegister(this->startTrigger, &value);
jmarkel44 0:61364762ee0e 266 if ( rc && value.value ) {
jmarkel44 0:61364762ee0e 267 return true;
jmarkel44 0:61364762ee0e 268 }
jmarkel44 0:61364762ee0e 269
jmarkel44 0:61364762ee0e 270 return false;
jmarkel44 0:61364762ee0e 271 }
jmarkel44 0:61364762ee0e 272
jmarkel44 0:61364762ee0e 273 //
jmarkel44 0:61364762ee0e 274 // method: isCurrentEntryStartTriggerOn
jmarkel44 0:61364762ee0e 275 // description; true the current sequence entry start trigger evals to true
jmarkel44 0:61364762ee0e 276 //
jmarkel44 0:61364762ee0e 277 // @param[in] none
jmarkel44 0:61364762ee0e 278 // @param[out] none
jmarkel44 0:61364762ee0e 279 // @return none
jmarkel44 0:61364762ee0e 280 //
jmarkel44 0:61364762ee0e 281 bool SequenceControl::isCurrentEntryStartTriggerOn(void)
jmarkel44 0:61364762ee0e 282 {
jmarkel44 0:61364762ee0e 283 ModbusValue value;
jmarkel44 0:61364762ee0e 284 bool rc = ModbusMasterReadRegister(this->currentEntry.startTrigger, &value);
jmarkel44 0:61364762ee0e 285 if ( rc != true ) {
jmarkel44 0:61364762ee0e 286 logError("%s: failed to read %s from modbus master",
jmarkel44 0:61364762ee0e 287 __func__, this->currentEntry.startTrigger.c_str());
jmarkel44 0:61364762ee0e 288 return rc;
jmarkel44 0:61364762ee0e 289 } else if ( value.value ) {
jmarkel44 0:61364762ee0e 290 debug("\r%s:%s-> returning true\n", __func__, id.c_str());
jmarkel44 0:61364762ee0e 291 return true;
jmarkel44 0:61364762ee0e 292 }
jmarkel44 0:61364762ee0e 293 return false;
jmarkel44 0:61364762ee0e 294 }
jmarkel44 0:61364762ee0e 295
jmarkel44 0:61364762ee0e 296 //
jmarkel44 0:61364762ee0e 297 // method: isCurrentEntryStopTriggerOn
jmarkel44 0:61364762ee0e 298 // description; true the current sequence entry start trigger evals to true
jmarkel44 0:61364762ee0e 299 //
jmarkel44 0:61364762ee0e 300 // @param[in] none
jmarkel44 0:61364762ee0e 301 // @param[out] none
jmarkel44 0:61364762ee0e 302 // @return none
jmarkel44 0:61364762ee0e 303 //
jmarkel44 0:61364762ee0e 304 bool SequenceControl::isCurrentEntryStopTriggerOn(void)
jmarkel44 0:61364762ee0e 305 {
jmarkel44 0:61364762ee0e 306 ModbusValue value;
jmarkel44 0:61364762ee0e 307 bool rc = ModbusMasterReadRegister(this->currentEntry.stopTrigger, &value);
jmarkel44 0:61364762ee0e 308 if ( rc != true ) {
jmarkel44 0:61364762ee0e 309 logError("%s: failed to read %s from modbus master",
jmarkel44 0:61364762ee0e 310 __func__, this->currentEntry.stopTrigger.c_str());
jmarkel44 0:61364762ee0e 311 return rc;
jmarkel44 0:61364762ee0e 312 } else if ( value.value ) {
jmarkel44 0:61364762ee0e 313 debug("\r%s:%s-> returning true\n", __func__, id.c_str());
jmarkel44 0:61364762ee0e 314 return true;
jmarkel44 0:61364762ee0e 315 }
jmarkel44 0:61364762ee0e 316 return false;
jmarkel44 0:61364762ee0e 317 }
jmarkel44 0:61364762ee0e 318
jmarkel44 0:61364762ee0e 319 //
jmarkel44 0:61364762ee0e 320 // method: loadNextEntry
jmarkel44 0:61364762ee0e 321 // description: load the next entry from the sequence table
jmarkel44 0:61364762ee0e 322 //
jmarkel44 0:61364762ee0e 323 // @param[in] none
jmarkel44 0:61364762ee0e 324 // @param[out[ none
jmarkel44 0:61364762ee0e 325 // @return true is loaded; false otherwise
jmarkel44 0:61364762ee0e 326 //
jmarkel44 0:61364762ee0e 327 bool SequenceControl::loadNextEntry(void)
jmarkel44 0:61364762ee0e 328 {
jmarkel44 0:61364762ee0e 329 if ( this->sequenceTable.empty() ) {
jmarkel44 0:61364762ee0e 330 debug("\r%s: sequence table is empty\n", id.c_str());
jmarkel44 0:61364762ee0e 331 return false;
jmarkel44 0:61364762ee0e 332 }
jmarkel44 0:61364762ee0e 333 if ( nextEntryIndex < this->sequenceTable.size() ) {
jmarkel44 0:61364762ee0e 334 currentEntry = sequenceTable.at(nextEntryIndex++);
jmarkel44 0:61364762ee0e 335 printf("\r...successfully loaded new entry\n");
jmarkel44 0:61364762ee0e 336 return true;
jmarkel44 0:61364762ee0e 337 }
jmarkel44 0:61364762ee0e 338 return false;
jmarkel44 0:61364762ee0e 339 }
jmarkel44 0:61364762ee0e 340
jmarkel44 0:61364762ee0e 341 //
jmarkel44 0:61364762ee0e 342 // method: performActions
jmarkel44 0:61364762ee0e 343 // description: perform the actions associated with the current entry
jmarkel44 0:61364762ee0e 344 //
jmarkel44 0:61364762ee0e 345 // @param[in] none
jmarkel44 0:61364762ee0e 346 // @param[out] none
jmarkel44 0:61364762ee0e 347 // @return none
jmarkel44 0:61364762ee0e 348 //
jmarkel44 0:61364762ee0e 349 SequenceControlError_t SequenceControl::performActions(void)
jmarkel44 0:61364762ee0e 350 {
jmarkel44 0:61364762ee0e 351 SequenceControlError_t rc = SEQUENCE_CONTROL_OK;
jmarkel44 0:61364762ee0e 352
jmarkel44 0:61364762ee0e 353 // possible action types:
jmarkel44 0:61364762ee0e 354 // create -> create a control
jmarkel44 0:61364762ee0e 355 // delete -> delete a control
jmarkel44 0:61364762ee0e 356 // modify -> modify a control
jmarkel44 0:61364762ee0e 357 // assign -> assign a value to a modbus register
jmarkel44 0:61364762ee0e 358 // execute -> execute a script
jmarkel44 0:61364762ee0e 359 if ( !currentEntry.actions.empty() ) {
jmarkel44 0:61364762ee0e 360 std::vector<Action_t>::const_iterator pos;
jmarkel44 0:61364762ee0e 361 for ( pos = currentEntry.actions.begin(); pos != currentEntry.actions.end(); ++pos ) {
jmarkel44 0:61364762ee0e 362 debug("\raction->%s on ID->%s\n", pos->action.c_str(), pos->id.c_str());
jmarkel44 0:61364762ee0e 363 // based on the action, we need to determine what to do
jmarkel44 0:61364762ee0e 364 // 1: determine the action
jmarkel44 0:61364762ee0e 365 // 2: see if the file exists (catastrophic)
jmarkel44 0:61364762ee0e 366 // 3: if it's a create or delete action, send a message to the
jmarkel44 0:61364762ee0e 367 // configuration handler
jmarkel44 0:61364762ee0e 368 if ( pos->action == "createsp" ) {
jmarkel44 0:61364762ee0e 369 rc = createSubControl(pos->id, CONTROL_SETPOINT);
jmarkel44 0:61364762ee0e 370 assert(!rc);
jmarkel44 0:61364762ee0e 371 } else if ( pos->action == "createtm" ) {
jmarkel44 0:61364762ee0e 372 rc = createSubControl(pos->id, CONTROL_TIMER);
jmarkel44 0:61364762ee0e 373 assert(!rc);
jmarkel44 0:61364762ee0e 374 } else if ( pos->action == "deletesp" ) {
jmarkel44 0:61364762ee0e 375 rc = destroySubControl(pos->id, CONTROL_SETPOINT);
jmarkel44 0:61364762ee0e 376 assert(!rc);
jmarkel44 0:61364762ee0e 377 } else if ( pos->action == "deletetm" ) {
jmarkel44 0:61364762ee0e 378 rc = destroySubControl(pos->id, CONTROL_TIMER);
jmarkel44 0:61364762ee0e 379 assert(!rc);
jmarkel44 0:61364762ee0e 380 } else if ( pos->action == "execute" ) {
jmarkel44 0:61364762ee0e 381 // not implemented
jmarkel44 0:61364762ee0e 382 } else if ( pos->action == "assign" ) {
jmarkel44 0:61364762ee0e 383 if ( assignRegister(pos->id, pos->value) != true ) {
jmarkel44 0:61364762ee0e 384 assert(0);
jmarkel44 0:61364762ee0e 385 }
jmarkel44 0:61364762ee0e 386 } else {
jmarkel44 0:61364762ee0e 387 logError("%s: unknown action %s (%s)", __func__, pos->action.c_str(), pos->id.c_str());
jmarkel44 0:61364762ee0e 388 rc = SEQUENCE_CONTROL_BAD_ACTION;
jmarkel44 0:61364762ee0e 389 }
jmarkel44 0:61364762ee0e 390 }
jmarkel44 0:61364762ee0e 391 } else {
jmarkel44 0:61364762ee0e 392 logInfo("%s: no entries in the action table", __func__);
jmarkel44 0:61364762ee0e 393 }
jmarkel44 0:61364762ee0e 394 return rc;
jmarkel44 0:61364762ee0e 395 }
jmarkel44 0:61364762ee0e 396
jmarkel44 0:61364762ee0e 397 //
jmarkel44 0:61364762ee0e 398 // method: createSubControl
jmarkel44 0:61364762ee0e 399 // description: create a control that's listed in the sequence table
jmarkel44 0:61364762ee0e 400 //
jmarkel44 0:61364762ee0e 401 // @param[in] action (create, destroy, etc.)
jmarkel44 0:61364762ee0e 402 // @param[in] id -> control identifier
jmarkel44 0:61364762ee0e 403 // @param[out[ none
jmarkel44 0:61364762ee0e 404 // @return OK on success; error otherwise
jmarkel44 0:61364762ee0e 405 //
jmarkel44 0:61364762ee0e 406 SequenceControlError_t SequenceControl::createSubControl(const std::string controlId,
jmarkel44 0:61364762ee0e 407 Control_t type)
jmarkel44 0:61364762ee0e 408 {
jmarkel44 0:61364762ee0e 409 std::string file_prefix;
jmarkel44 0:61364762ee0e 410
jmarkel44 0:61364762ee0e 411 switch (type) {
jmarkel44 0:61364762ee0e 412 case CONTROL_SETPOINT:
jmarkel44 0:61364762ee0e 413 file_prefix = CONTROL_SP_STR;
jmarkel44 0:61364762ee0e 414 break;
jmarkel44 0:61364762ee0e 415 case CONTROL_TIMER:
jmarkel44 0:61364762ee0e 416 file_prefix = CONTROL_TM_STR;
jmarkel44 0:61364762ee0e 417 break;
jmarkel44 0:61364762ee0e 418 default:
jmarkel44 0:61364762ee0e 419 logError("%s %s unsupported type %d", __func__, id.c_str(), type);
jmarkel44 0:61364762ee0e 420 return SEQUENCE_CONTROL_BAD_CONTROL_TYPE;
jmarkel44 0:61364762ee0e 421 }
jmarkel44 0:61364762ee0e 422
jmarkel44 0:61364762ee0e 423 char filename[64];
jmarkel44 0:61364762ee0e 424 snprintf(filename, sizeof(filename), "%s%s_%s%s.json",
jmarkel44 0:61364762ee0e 425 SEQUENCE_CONTROL_FILENAME_PREFIX,
jmarkel44 0:61364762ee0e 426 this->id.c_str(),
jmarkel44 0:61364762ee0e 427 file_prefix.c_str(),
jmarkel44 0:61364762ee0e 428 controlId.c_str());
jmarkel44 0:61364762ee0e 429
jmarkel44 0:61364762ee0e 430 debug("\r%s: searching for %s\n", id.c_str(), filename);
jmarkel44 0:61364762ee0e 431
jmarkel44 0:61364762ee0e 432 // send a message to the configuration handler to create the control
jmarkel44 0:61364762ee0e 433 ConfigMessage_t *msg = ConfigHandlerMailBox.alloc();
jmarkel44 0:61364762ee0e 434 memset(msg, 0, sizeof(ConfigMessage_t));
jmarkel44 0:61364762ee0e 435 msg->action = ACTION_CREATE;
jmarkel44 0:61364762ee0e 436 msg->control = (Control_t)type;
jmarkel44 0:61364762ee0e 437 strncpy(msg->controlFile, filename, sizeof(msg->controlFile)-1);
jmarkel44 0:61364762ee0e 438
jmarkel44 0:61364762ee0e 439 printf("%s: Sending a create request for control %s\r\n",
jmarkel44 0:61364762ee0e 440 __func__, msg->controlFile);
jmarkel44 0:61364762ee0e 441
jmarkel44 0:61364762ee0e 442 ConfigHandlerMailBox.put(msg);
jmarkel44 0:61364762ee0e 443
jmarkel44 0:61364762ee0e 444 return SEQUENCE_CONTROL_OK;
jmarkel44 0:61364762ee0e 445 }
jmarkel44 0:61364762ee0e 446
jmarkel44 0:61364762ee0e 447 //
jmarkel44 0:61364762ee0e 448 // method: destroySubControl
jmarkel44 0:61364762ee0e 449 // description: destroy a control that's listed in the sequence table
jmarkel44 0:61364762ee0e 450 //
jmarkel44 0:61364762ee0e 451 // @param[in] action (create, destroy, etc.)
jmarkel44 0:61364762ee0e 452 // @param[in] id -> control identifier
jmarkel44 0:61364762ee0e 453 // @param[out[ none
jmarkel44 0:61364762ee0e 454 // @return OK on success; error otherwise
jmarkel44 0:61364762ee0e 455 //
jmarkel44 0:61364762ee0e 456 SequenceControlError_t SequenceControl::destroySubControl(const std::string controlId,
jmarkel44 0:61364762ee0e 457 Control_t type)
jmarkel44 0:61364762ee0e 458 {
jmarkel44 0:61364762ee0e 459 std::string file_prefix;
jmarkel44 0:61364762ee0e 460
jmarkel44 0:61364762ee0e 461 switch (type) {
jmarkel44 0:61364762ee0e 462 case CONTROL_SETPOINT:
jmarkel44 0:61364762ee0e 463 file_prefix = CONTROL_SP_STR;
jmarkel44 0:61364762ee0e 464 break;
jmarkel44 0:61364762ee0e 465 case CONTROL_TIMER:
jmarkel44 0:61364762ee0e 466 file_prefix = CONTROL_TM_STR;
jmarkel44 0:61364762ee0e 467 break;
jmarkel44 0:61364762ee0e 468 default:
jmarkel44 0:61364762ee0e 469 logError("%s %s unsupported type %d", __func__, id.c_str(), type);
jmarkel44 0:61364762ee0e 470 return SEQUENCE_CONTROL_BAD_CONTROL_TYPE;
jmarkel44 0:61364762ee0e 471 }
jmarkel44 0:61364762ee0e 472
jmarkel44 0:61364762ee0e 473 char filename[64];
jmarkel44 0:61364762ee0e 474 snprintf(filename, sizeof(filename), "%s%s_%s%s.json",
jmarkel44 0:61364762ee0e 475 SEQUENCE_CONTROL_FILENAME_PREFIX,
jmarkel44 0:61364762ee0e 476 this->id.c_str(),
jmarkel44 0:61364762ee0e 477 file_prefix.c_str(),
jmarkel44 0:61364762ee0e 478 controlId.c_str());
jmarkel44 0:61364762ee0e 479
jmarkel44 0:61364762ee0e 480 debug("\r%s: searching for %s\n", id.c_str(), filename);
jmarkel44 0:61364762ee0e 481
jmarkel44 0:61364762ee0e 482 // send a message to the configuration handler to create the control
jmarkel44 0:61364762ee0e 483 ConfigMessage_t *msg = ConfigHandlerMailBox.alloc();
jmarkel44 0:61364762ee0e 484 memset(msg, 0, sizeof(ConfigMessage_t));
jmarkel44 0:61364762ee0e 485 msg->action = ACTION_DESTROY;
jmarkel44 0:61364762ee0e 486 msg->control = (Control_t)type;
jmarkel44 0:61364762ee0e 487 strncpy(msg->controlFile, filename, sizeof(msg->controlFile)-1);
jmarkel44 0:61364762ee0e 488
jmarkel44 0:61364762ee0e 489 printf("%s: Sending a create request for control %s\r\n",
jmarkel44 0:61364762ee0e 490 __func__, msg->controlFile);
jmarkel44 0:61364762ee0e 491
jmarkel44 0:61364762ee0e 492 ConfigHandlerMailBox.put(msg);
jmarkel44 0:61364762ee0e 493
jmarkel44 0:61364762ee0e 494 return SEQUENCE_CONTROL_OK;
jmarkel44 0:61364762ee0e 495 }
jmarkel44 0:61364762ee0e 496
jmarkel44 0:61364762ee0e 497 bool SequenceControl::assignRegister(const std::string id, float value)
jmarkel44 0:61364762ee0e 498 {
jmarkel44 0:61364762ee0e 499 return (ModbusMasterWriteRegister(id, value));
jmarkel44 0:61364762ee0e 500 }
jmarkel44 0:61364762ee0e 501
jmarkel44 0:61364762ee0e 502 //
jmarkel44 0:61364762ee0e 503 // method: display
jmarkel44 0:61364762ee0e 504 // decsription: display the control data
jmarkel44 0:61364762ee0e 505 //
jmarkel44 0:61364762ee0e 506 // @param[in] none
jmarkel44 0:61364762ee0e 507 // @param[out] none
jmarkel44 0:61364762ee0e 508 // @return none
jmarkel44 0:61364762ee0e 509 //
jmarkel44 0:61364762ee0e 510 void SequenceControl::display(void)
jmarkel44 0:61364762ee0e 511 {
jmarkel44 0:61364762ee0e 512 const char *mapper[] = { "INIT",
jmarkel44 0:61364762ee0e 513 "START",
jmarkel44 0:61364762ee0e 514 "LOADING",
jmarkel44 0:61364762ee0e 515 "WAIT-START",
jmarkel44 0:61364762ee0e 516 "WAIT-STOP",
jmarkel44 0:61364762ee0e 517 "FINISHED",
jmarkel44 0:61364762ee0e 518 "FAILED",
jmarkel44 0:61364762ee0e 519 "NULL"
jmarkel44 0:61364762ee0e 520 };
jmarkel44 0:61364762ee0e 521
jmarkel44 0:61364762ee0e 522 printf("\rid-> %s\n", id.c_str());
jmarkel44 0:61364762ee0e 523 printf("\rstartTrigger-> %s\n", startTrigger.c_str());
jmarkel44 0:61364762ee0e 524 printf("\rSequenceTable: \n");
jmarkel44 0:61364762ee0e 525
jmarkel44 0:61364762ee0e 526 std::vector<SequenceEntry>::const_iterator seqIt;
jmarkel44 0:61364762ee0e 527
jmarkel44 0:61364762ee0e 528 int entry = 0;
jmarkel44 0:61364762ee0e 529
jmarkel44 0:61364762ee0e 530 for ( seqIt = sequenceTable.begin(); seqIt != sequenceTable.end(); ++seqIt ) {
jmarkel44 0:61364762ee0e 531 printf("\rEntry %d: %s\n \r startTrigger: %s\n",
jmarkel44 0:61364762ee0e 532 ++entry,
jmarkel44 0:61364762ee0e 533 (entry == nextEntryIndex-1) ? "<-currently active" : "",
jmarkel44 0:61364762ee0e 534 seqIt->startTrigger.c_str());
jmarkel44 0:61364762ee0e 535 std::vector<Action_t>::const_iterator actIt;
jmarkel44 0:61364762ee0e 536 for ( actIt = seqIt->actions.begin(); actIt != seqIt->actions.end(); ++actIt ) {
jmarkel44 0:61364762ee0e 537 printf("\r\taction-> %s, id-> %s ", actIt->action.c_str(), actIt->id.c_str());
jmarkel44 0:61364762ee0e 538 if ( actIt->action == "assign" ) printf("value -> %f", actIt->value);
jmarkel44 0:61364762ee0e 539 printf("\r\n");
jmarkel44 0:61364762ee0e 540 }
jmarkel44 0:61364762ee0e 541 printf("\r stopTrigger: %s\n", seqIt->stopTrigger.c_str());
jmarkel44 0:61364762ee0e 542 }
jmarkel44 0:61364762ee0e 543
jmarkel44 0:61364762ee0e 544 printf("\r\n\rcurrent state = %s\r\n\r\n", mapper[this->currentState]);
jmarkel44 0:61364762ee0e 545 }
jmarkel44 0:61364762ee0e 546