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: OutputTask.cpp
jmarkel44 0:61364762ee0e 4 * Desciption: source for the ICE Output task
jmarkel44 0:61364762ee0e 5 *
jmarkel44 0:61364762ee0e 6 *****************************************************************************/
jmarkel44 0:61364762ee0e 7 #include <vector>
jmarkel44 0:61364762ee0e 8 #include <string>
jmarkel44 0:61364762ee0e 9 #include <algorithm>
jmarkel44 0:61364762ee0e 10 #include <assert.h>
jmarkel44 0:61364762ee0e 11 #include <time.h>
jmarkel44 0:61364762ee0e 12 #include "OutputTask.h"
jmarkel44 0:61364762ee0e 13 #include "global.h"
jmarkel44 0:61364762ee0e 14 #include "cJSON.h"
jmarkel44 0:61364762ee0e 15 #include "ModbusMasterApi.h"
jmarkel44 0:61364762ee0e 16 #include "LoggerApi.h"
jmarkel44 0:61364762ee0e 17 #include "Control.h"
jmarkel44 0:61364762ee0e 18 #include "rtc.h"
jmarkel44 0:61364762ee0e 19 #include "ICELog.h"
jmarkel44 0:61364762ee0e 20
jmarkel44 0:61364762ee0e 21 //#include "../add-ons/MTSLog/MTSLog.h"
jmarkel44 0:61364762ee0e 22
jmarkel44 0:61364762ee0e 23
jmarkel44 0:61364762ee0e 24 // local functions
jmarkel44 0:61364762ee0e 25 static int createOutput(const char *controlFile);
jmarkel44 0:61364762ee0e 26 static int loadPersistentOutputs(void);
jmarkel44 0:61364762ee0e 27 static void writeOutputs(const std::string, const std::string);
jmarkel44 0:61364762ee0e 28 static int enableOutputReqHandler(OutputControlMsg_t *msg);
jmarkel44 0:61364762ee0e 29 static int disableOutputReqHandler(OutputControlMsg_t *msg);
jmarkel44 0:61364762ee0e 30 static int unregisterControl(const char *id, unsigned int pri, const char *output);
jmarkel44 0:61364762ee0e 31 static void dumpEventRecord(EventReasonStruct_t &ev);
jmarkel44 0:61364762ee0e 32
jmarkel44 0:61364762ee0e 33 //
jmarkel44 0:61364762ee0e 34 // The Output Map
jmarkel44 0:61364762ee0e 35 //
jmarkel44 0:61364762ee0e 36 // this is the main data structure used to distinguish which control has
jmarkel44 0:61364762ee0e 37 // priority of an output. the layout is as-follows:
jmarkel44 0:61364762ee0e 38 //
jmarkel44 0:61364762ee0e 39 // outputMap["o_rly1"]-> Control<"ManControl_rly1", 100, ON > <-- highest pri control manipulates relay
jmarkel44 0:61364762ee0e 40 // Control<"Flowswitch", 700 OFF> <-- lower pri (queued up)
jmarkel44 0:61364762ee0e 41 // Control<"SetpointControl_rly1", 800, OFF> <-- lowest pri (queued up)
jmarkel44 0:61364762ee0e 42 //
jmarkel44 0:61364762ee0e 43 // outputMap["o_rly2"]-> Control<"Flowswitch", 700, OFF>
jmarkel44 0:61364762ee0e 44 // -> Control<"SetpointControl_rly2", 800, OFF>
jmarkel44 0:61364762ee0e 45 //
jmarkel44 0:61364762ee0e 46 // outputMap["o_rly3"]-> Control<"ManControl_rly3", 100, ON >
jmarkel44 0:61364762ee0e 47 // Control<"Flowswitch", 700, ON >
jmarkel44 0:61364762ee0e 48 // Control<"TimerControl_rly3", 750, ON >
jmarkel44 0:61364762ee0e 49 //
jmarkel44 0:61364762ee0e 50 //
jmarkel44 0:61364762ee0e 51 // The Control Vector (per relay) is always sorted by priority, whereas
jmarkel44 0:61364762ee0e 52 // the highest priority control (lower priority number) is at the front
jmarkel44 0:61364762ee0e 53 // (v.front()) of the list.
jmarkel44 0:61364762ee0e 54 //
jmarkel44 0:61364762ee0e 55
jmarkel44 0:61364762ee0e 56 typedef std::map<std::string, std::vector<Control> > StringOutputVector_t;
jmarkel44 0:61364762ee0e 57 static StringOutputVector_t outputMap;
jmarkel44 0:61364762ee0e 58
jmarkel44 0:61364762ee0e 59 // operator for sorting the outputs vectors
jmarkel44 0:61364762ee0e 60 bool operator<(const Control &control1, const Control &control2)
jmarkel44 0:61364762ee0e 61 {
jmarkel44 0:61364762ee0e 62 return control1.getPriority() < control2.getPriority();
jmarkel44 0:61364762ee0e 63 }
jmarkel44 0:61364762ee0e 64
jmarkel44 0:61364762ee0e 65 /*****************************************************************************
jmarkel44 0:61364762ee0e 66 * Function: OutputTask
jmarkel44 0:61364762ee0e 67 * Description: Main entry point for the Output Task
jmarkel44 0:61364762ee0e 68 *
jmarkel44 0:61364762ee0e 69 * @param args -> not used
jmarkel44 0:61364762ee0e 70 * @return none
jmarkel44 0:61364762ee0e 71 *****************************************************************************/
jmarkel44 0:61364762ee0e 72 void OutputTask(void const *args)
jmarkel44 0:61364762ee0e 73 {
jmarkel44 0:61364762ee0e 74 int rc;
jmarkel44 0:61364762ee0e 75 (void)args;
jmarkel44 0:61364762ee0e 76
jmarkel44 0:61364762ee0e 77 printf("\r%s has started...\n", __func__);
jmarkel44 0:61364762ee0e 78
jmarkel44 0:61364762ee0e 79 #ifdef LOAD_PERSISTENT_CONFIGURATIONS
jmarkel44 0:61364762ee0e 80 if ( loadPersistentOutputs() != 0 ) {
jmarkel44 0:61364762ee0e 81 logError("Failed to load persistent outputs");
jmarkel44 0:61364762ee0e 82 }
jmarkel44 0:61364762ee0e 83 #endif
jmarkel44 0:61364762ee0e 84
jmarkel44 0:61364762ee0e 85 // signal the main thread to continue
jmarkel44 0:61364762ee0e 86 osSignalSet(mainThreadId, sig_config_continue);
jmarkel44 0:61364762ee0e 87
jmarkel44 0:61364762ee0e 88 while (true) {
jmarkel44 0:61364762ee0e 89 // wait for a message
jmarkel44 0:61364762ee0e 90 osEvent evt = OutputMasterMailBox.get();
jmarkel44 0:61364762ee0e 91 if (evt.status == osEventMail) {
jmarkel44 0:61364762ee0e 92
jmarkel44 0:61364762ee0e 93 OutputControlMsg_t *msg = (OutputControlMsg_t*) evt.value.p;
jmarkel44 0:61364762ee0e 94
jmarkel44 0:61364762ee0e 95 switch ( msg->action ) {
jmarkel44 0:61364762ee0e 96 case ACTION_NEW:
jmarkel44 0:61364762ee0e 97 // read the file and and create an output entry
jmarkel44 0:61364762ee0e 98 rc = createOutput(msg->controlFile);
jmarkel44 0:61364762ee0e 99 if ( rc != 0 ) {
jmarkel44 0:61364762ee0e 100 logError("%s: failed to create output %s\n",
jmarkel44 0:61364762ee0e 101 __func__, msg->controlFile);
jmarkel44 0:61364762ee0e 102 }
jmarkel44 0:61364762ee0e 103 break;
jmarkel44 0:61364762ee0e 104 case ACTION_CONTROL_ON:
jmarkel44 0:61364762ee0e 105 logInfo("%s is requesting ON control of %s", msg->id, msg->output_tag);
jmarkel44 0:61364762ee0e 106 rc = enableOutputReqHandler(msg);
jmarkel44 0:61364762ee0e 107 if ( rc != 0 ) {
jmarkel44 0:61364762ee0e 108 logError("%s: failed to enable output for %s",
jmarkel44 0:61364762ee0e 109 __func__, msg->id);
jmarkel44 0:61364762ee0e 110 }
jmarkel44 0:61364762ee0e 111 break;
jmarkel44 0:61364762ee0e 112 case ACTION_CONTROL_OFF:
jmarkel44 0:61364762ee0e 113 logInfo("%s is requesting OFF control of %s", msg->id, msg->output_tag);
jmarkel44 0:61364762ee0e 114 rc = disableOutputReqHandler(msg);
jmarkel44 0:61364762ee0e 115 if ( rc != 0 ) {
jmarkel44 0:61364762ee0e 116 logError("%s: failed to disable output for %s",
jmarkel44 0:61364762ee0e 117 __func__, msg->id);
jmarkel44 0:61364762ee0e 118 }
jmarkel44 0:61364762ee0e 119 break;
jmarkel44 0:61364762ee0e 120 case ACTION_CONTROL_UNREGISTER:
jmarkel44 0:61364762ee0e 121 logInfo("%s is requesting its deletion from %s", msg->id, msg->output_tag);
jmarkel44 0:61364762ee0e 122 rc = unregisterControl(msg->id, msg->priority, msg->output_tag);
jmarkel44 0:61364762ee0e 123 if ( rc != 0 ) {
jmarkel44 0:61364762ee0e 124 logError("%s: failed to unregister control %s",
jmarkel44 0:61364762ee0e 125 __func__, msg->id);
jmarkel44 0:61364762ee0e 126 }
jmarkel44 0:61364762ee0e 127 break;
jmarkel44 0:61364762ee0e 128 default:
jmarkel44 0:61364762ee0e 129 logError("%s unknown action %u", __func__, msg->action);
jmarkel44 0:61364762ee0e 130 break;
jmarkel44 0:61364762ee0e 131 }
jmarkel44 0:61364762ee0e 132
jmarkel44 0:61364762ee0e 133 // free the message
jmarkel44 0:61364762ee0e 134 OutputMasterMailBox.free(msg);
jmarkel44 0:61364762ee0e 135
jmarkel44 0:61364762ee0e 136 // refresh the outputs
jmarkel44 0:61364762ee0e 137 writeOutputs(msg->id, msg->output_tag);
jmarkel44 0:61364762ee0e 138 }
jmarkel44 0:61364762ee0e 139 }
jmarkel44 0:61364762ee0e 140 }
jmarkel44 0:61364762ee0e 141
jmarkel44 0:61364762ee0e 142 /*****************************************************************************
jmarkel44 0:61364762ee0e 143 * Function: publishEvent
jmarkel44 0:61364762ee0e 144 * Description: publish an event to the logger
jmarkel44 0:61364762ee0e 145 *
jmarkel44 0:61364762ee0e 146 * @param output -> the output channel
jmarkel44 0:61364762ee0e 147 * @param control -> the control, this can be null
jmarkel44 0:61364762ee0e 148 * @return none
jmarkel44 0:61364762ee0e 149 *****************************************************************************/
jmarkel44 0:61364762ee0e 150 void publishEvent(std::string output, const Control *control)
jmarkel44 0:61364762ee0e 151 {
jmarkel44 0:61364762ee0e 152
jmarkel44 0:61364762ee0e 153 EventReasonStruct_t ev;
jmarkel44 0:61364762ee0e 154 ModbusValue input_value;
jmarkel44 0:61364762ee0e 155 ModbusValue output_value;
jmarkel44 0:61364762ee0e 156 memset(&ev, 0, sizeof(ev));
jmarkel44 0:61364762ee0e 157
jmarkel44 0:61364762ee0e 158
jmarkel44 0:61364762ee0e 159 // if there's no control, that means the only control that was on
jmarkel44 0:61364762ee0e 160 // the relay stack has been destroyed, so we'll send a NO CONTROL
jmarkel44 0:61364762ee0e 161 // event code.
jmarkel44 0:61364762ee0e 162 if ( !control ) {
jmarkel44 0:61364762ee0e 163 ev.eventReason = EVENT_REASON_NO_CONTROL;
jmarkel44 0:61364762ee0e 164 ModbusMasterReadRegister(output, &output_value);
jmarkel44 0:61364762ee0e 165 strncpy(ev.outputTag, output.c_str(), sizeof(ev.outputTag));
jmarkel44 0:61364762ee0e 166 ev.outputValue = output_value.value;
jmarkel44 0:61364762ee0e 167 dumpEventRecord(ev);
jmarkel44 0:61364762ee0e 168 EventLoggerApi(ev);
jmarkel44 0:61364762ee0e 169 return;
jmarkel44 0:61364762ee0e 170 }
jmarkel44 0:61364762ee0e 171
jmarkel44 0:61364762ee0e 172 switch ( control->getControlType() ) {
jmarkel44 0:61364762ee0e 173 case CONTROL_SETPOINT:
jmarkel44 0:61364762ee0e 174 case CONTROL_COMPOSITE:
jmarkel44 0:61364762ee0e 175 ev.eventReason = EVENT_REASON_AUTO;
jmarkel44 0:61364762ee0e 176 strncpy(ev.inputTag, control->getInput().c_str(), sizeof(ev.inputTag));
jmarkel44 0:61364762ee0e 177 strncpy(ev.outputTag, output.c_str(), sizeof(ev.outputTag));
jmarkel44 0:61364762ee0e 178 ModbusMasterReadRegister(control->getInput(), &input_value);
jmarkel44 0:61364762ee0e 179 ModbusMasterReadRegister(output, &output_value);
jmarkel44 0:61364762ee0e 180 ev.inputValue = input_value.value;
jmarkel44 0:61364762ee0e 181 ev.outputValue = output_value.value;
jmarkel44 0:61364762ee0e 182 dumpEventRecord(ev);
jmarkel44 0:61364762ee0e 183 EventLoggerApi(ev);
jmarkel44 0:61364762ee0e 184 break;
jmarkel44 0:61364762ee0e 185
jmarkel44 0:61364762ee0e 186 case CONTROL_MANUAL:
jmarkel44 0:61364762ee0e 187 ev.eventReason = EVENT_REASON_MANUAL;
jmarkel44 0:61364762ee0e 188 strncpy(ev.outputTag, output.c_str(), sizeof(ev.outputTag));
jmarkel44 0:61364762ee0e 189 ModbusMasterReadRegister(output, &output_value);
jmarkel44 0:61364762ee0e 190 ev.outputValue = output_value.value;
jmarkel44 0:61364762ee0e 191 dumpEventRecord(ev);
jmarkel44 0:61364762ee0e 192 EventLoggerApi(ev);
jmarkel44 0:61364762ee0e 193 break;
jmarkel44 0:61364762ee0e 194
jmarkel44 0:61364762ee0e 195 case CONTROL_TIMER:
jmarkel44 0:61364762ee0e 196 ev.eventReason = EVENT_REASON_TIMER;
jmarkel44 0:61364762ee0e 197 strncpy(ev.outputTag, output.c_str(), sizeof(ev.outputTag));
jmarkel44 0:61364762ee0e 198 ModbusMasterReadRegister(output, &output_value);
jmarkel44 0:61364762ee0e 199 ev.outputValue = output_value.value;
jmarkel44 0:61364762ee0e 200 dumpEventRecord(ev);
jmarkel44 0:61364762ee0e 201 EventLoggerApi(ev);
jmarkel44 0:61364762ee0e 202 break;
jmarkel44 0:61364762ee0e 203
jmarkel44 0:61364762ee0e 204 case CONTROL_FAILSAFE:
jmarkel44 0:61364762ee0e 205 case CONTROL_SENSOR_ERROR:
jmarkel44 0:61364762ee0e 206 ev.eventReason = EVENT_REASON_FAILSAFE;
jmarkel44 0:61364762ee0e 207 strncpy(ev.inputTag, control->getInput().c_str(), sizeof(ev.inputTag));
jmarkel44 0:61364762ee0e 208 strncpy(ev.outputTag, output.c_str(), sizeof(ev.outputTag));
jmarkel44 0:61364762ee0e 209 ModbusMasterReadRegister(control->getInput(), &input_value);
jmarkel44 0:61364762ee0e 210 ModbusMasterReadRegister(output, &output_value);
jmarkel44 0:61364762ee0e 211 ev.inputValue = input_value.value;
jmarkel44 0:61364762ee0e 212 ev.outputValue = output_value.value;
jmarkel44 0:61364762ee0e 213 dumpEventRecord(ev);
jmarkel44 0:61364762ee0e 214 EventLoggerApi(ev);
jmarkel44 0:61364762ee0e 215 break;
jmarkel44 0:61364762ee0e 216
jmarkel44 0:61364762ee0e 217 default:
jmarkel44 0:61364762ee0e 218 logError("%s: unknown control type\n", __func__);
jmarkel44 0:61364762ee0e 219 break;
jmarkel44 0:61364762ee0e 220 }
jmarkel44 0:61364762ee0e 221 }
jmarkel44 0:61364762ee0e 222
jmarkel44 0:61364762ee0e 223 /*****************************************************************************
jmarkel44 0:61364762ee0e 224 * Function: writeOutputs
jmarkel44 0:61364762ee0e 225 * Description: send a message to the modbus master of who's in control
jmarkel44 0:61364762ee0e 226 *
jmarkel44 0:61364762ee0e 227 *
jmarkel44 0:61364762ee0e 228 * @param[in] id -> control identifier
jmarkel44 0:61364762ee0e 229 * @param[in] output_tag -> the output to write
jmarkel44 0:61364762ee0e 230 * @return none
jmarkel44 0:61364762ee0e 231 *****************************************************************************/
jmarkel44 0:61364762ee0e 232 static void writeOutputs(const std::string id, const std::string output_tag)
jmarkel44 0:61364762ee0e 233 {
jmarkel44 0:61364762ee0e 234 (void) id;
jmarkel44 0:61364762ee0e 235
jmarkel44 0:61364762ee0e 236 if ( output_tag.empty() ) {
jmarkel44 0:61364762ee0e 237 logError("%s: invalid output tag", __func__);
jmarkel44 0:61364762ee0e 238 return;
jmarkel44 0:61364762ee0e 239 }
jmarkel44 0:61364762ee0e 240
jmarkel44 0:61364762ee0e 241 StringOutputVector_t::const_iterator pos;
jmarkel44 0:61364762ee0e 242
jmarkel44 0:61364762ee0e 243 // find the output
jmarkel44 0:61364762ee0e 244 pos = outputMap.find(output_tag);
jmarkel44 0:61364762ee0e 245 if ( pos != outputMap.end() ) {
jmarkel44 0:61364762ee0e 246 if ( pos->second.empty() ) {
jmarkel44 0:61364762ee0e 247 // we found the output but nothing's controlling it...
jmarkel44 0:61364762ee0e 248 ModbusMasterWriteRegister(pos->first, RELAY_STATUS_NOT_CONTROLLED);
jmarkel44 0:61364762ee0e 249 publishEvent(pos->first, NULL);
jmarkel44 0:61364762ee0e 250 } else {
jmarkel44 0:61364762ee0e 251 // get the mapped state for the highest priority control
jmarkel44 0:61364762ee0e 252 int mappedState = pos->second.begin()->getMappedState();
jmarkel44 0:61364762ee0e 253
jmarkel44 0:61364762ee0e 254 // read the register value for this output
jmarkel44 0:61364762ee0e 255 ModbusValue value;
jmarkel44 0:61364762ee0e 256 ModbusMasterReadRegister(pos->first, &value);
jmarkel44 0:61364762ee0e 257
jmarkel44 0:61364762ee0e 258 // a new higher priority control is manipulating the output,
jmarkel44 0:61364762ee0e 259 // so send the new values to the modbus and publish an event
jmarkel44 0:61364762ee0e 260 if ( value.value != mappedState ) {
jmarkel44 0:61364762ee0e 261 ModbusMasterWriteRegister(pos->first, mappedState);
jmarkel44 0:61364762ee0e 262 Control t = *(pos->second.begin());
jmarkel44 0:61364762ee0e 263 publishEvent(pos->first, &t);
jmarkel44 0:61364762ee0e 264 }
jmarkel44 0:61364762ee0e 265 }
jmarkel44 0:61364762ee0e 266 // TODO: This may be a virtual output, so we'll need to see if it
jmarkel44 0:61364762ee0e 267 // exists in the vregmap
jmarkel44 0:61364762ee0e 268 } else {
jmarkel44 0:61364762ee0e 269 logError("%s failed to find the selected output %s",
jmarkel44 0:61364762ee0e 270 __func__, output_tag.c_str());
jmarkel44 0:61364762ee0e 271 }
jmarkel44 0:61364762ee0e 272 }
jmarkel44 0:61364762ee0e 273
jmarkel44 0:61364762ee0e 274 /*****************************************************************************
jmarkel44 0:61364762ee0e 275 * Function: createOutput
jmarkel44 0:61364762ee0e 276 * Description:
jmarkel44 0:61364762ee0e 277 *
jmarkel44 0:61364762ee0e 278 * @param outputFile -> name of output file
jmarkel44 0:61364762ee0e 279 * @return none
jmarkel44 0:61364762ee0e 280 *****************************************************************************/
jmarkel44 0:61364762ee0e 281 static int createOutput(const char *outputFile)
jmarkel44 0:61364762ee0e 282 {
jmarkel44 0:61364762ee0e 283 char dataBuf[MAX_FILE_SIZE];
jmarkel44 0:61364762ee0e 284 bool status = GLOBAL_mdot->readUserFile(outputFile, (void *)dataBuf, sizeof(dataBuf));
jmarkel44 0:61364762ee0e 285 if ( status != true ) {
jmarkel44 0:61364762ee0e 286 logError("%s failed to read %s", __func__, outputFile);
jmarkel44 0:61364762ee0e 287 return -1;
jmarkel44 0:61364762ee0e 288 }
jmarkel44 0:61364762ee0e 289
jmarkel44 0:61364762ee0e 290 cJSON * root = cJSON_Parse(dataBuf);
jmarkel44 0:61364762ee0e 291 if ( !cJSON_HasObjectItem(root, "id") ) {
jmarkel44 0:61364762ee0e 292 logError("%s: error extracting expected tags", __func__);
jmarkel44 0:61364762ee0e 293 cJSON_Delete(root);
jmarkel44 0:61364762ee0e 294 return -1;
jmarkel44 0:61364762ee0e 295 }
jmarkel44 0:61364762ee0e 296
jmarkel44 0:61364762ee0e 297 std::string id = cJSON_GetObjectItem(root,"id")->valuestring;
jmarkel44 0:61364762ee0e 298 cJSON_Delete(root);
jmarkel44 0:61364762ee0e 299
jmarkel44 0:61364762ee0e 300 std::vector<Control> v;
jmarkel44 0:61364762ee0e 301 outputMap[id] = v;
jmarkel44 0:61364762ee0e 302
jmarkel44 0:61364762ee0e 303 return 0;
jmarkel44 0:61364762ee0e 304 }
jmarkel44 0:61364762ee0e 305
jmarkel44 0:61364762ee0e 306 /*****************************************************************************
jmarkel44 0:61364762ee0e 307 * Function: enableOutputReqHandler
jmarkel44 0:61364762ee0e 308 * Description: handle a request to enable an output
jmarkel44 0:61364762ee0e 309 *
jmarkel44 0:61364762ee0e 310 * @param[in] msg -> the message request
jmarkel44 0:61364762ee0e 311 * @return -1 on error
jmarkel44 0:61364762ee0e 312 *****************************************************************************/
jmarkel44 0:61364762ee0e 313 static int enableOutputReqHandler(OutputControlMsg_t *msg)
jmarkel44 0:61364762ee0e 314 {
jmarkel44 0:61364762ee0e 315 // attempt to find the output in the map
jmarkel44 0:61364762ee0e 316 StringOutputVector_t::iterator pos;
jmarkel44 0:61364762ee0e 317
jmarkel44 0:61364762ee0e 318 pos = outputMap.find(msg->output_tag);
jmarkel44 0:61364762ee0e 319 if ( pos == outputMap.end() ) {
jmarkel44 0:61364762ee0e 320 logError("%s: failed to find the designated output %s\n",
jmarkel44 0:61364762ee0e 321 __func__, msg->output_tag);
jmarkel44 0:61364762ee0e 322 return -1;
jmarkel44 0:61364762ee0e 323 }
jmarkel44 0:61364762ee0e 324
jmarkel44 0:61364762ee0e 325 if ( pos->second.empty() ) {
jmarkel44 0:61364762ee0e 326 // this is a new request
jmarkel44 0:61364762ee0e 327 std::string cid(msg->id);
jmarkel44 0:61364762ee0e 328 std::string input(msg->input_tag);
jmarkel44 0:61364762ee0e 329 Control c(cid, msg->controlType, input, msg->priority, CONTROL_ON);
jmarkel44 0:61364762ee0e 330 pos->second.push_back(c);
jmarkel44 0:61364762ee0e 331 } else {
jmarkel44 0:61364762ee0e 332 // find this control in the list
jmarkel44 0:61364762ee0e 333 std::vector<Control>::iterator v;
jmarkel44 0:61364762ee0e 334 for ( v = pos->second.begin(); v != pos->second.end(); ++v ) {
jmarkel44 0:61364762ee0e 335 if ( strcmp(v->getId().c_str(), msg->id) == 0 ) {
jmarkel44 0:61364762ee0e 336 v->setState(CONTROL_ON);
jmarkel44 0:61364762ee0e 337 break;
jmarkel44 0:61364762ee0e 338 }
jmarkel44 0:61364762ee0e 339 }
jmarkel44 0:61364762ee0e 340 if ( v == pos->second.end() ) {
jmarkel44 0:61364762ee0e 341 // this is a new request, so add it and sort the vector
jmarkel44 0:61364762ee0e 342 std::string cid(msg->id);
jmarkel44 0:61364762ee0e 343 std::string input(msg->input_tag);
jmarkel44 0:61364762ee0e 344 Control c(cid, msg->controlType, input, msg->priority, CONTROL_ON);
jmarkel44 0:61364762ee0e 345 pos->second.push_back(c);
jmarkel44 0:61364762ee0e 346 std::sort(pos->second.begin(), pos->second.end());
jmarkel44 0:61364762ee0e 347 }
jmarkel44 0:61364762ee0e 348 }
jmarkel44 0:61364762ee0e 349
jmarkel44 0:61364762ee0e 350 return 0;
jmarkel44 0:61364762ee0e 351 }
jmarkel44 0:61364762ee0e 352
jmarkel44 0:61364762ee0e 353 /*****************************************************************************
jmarkel44 0:61364762ee0e 354 * Function: disableOutputReqHandler
jmarkel44 0:61364762ee0e 355 * Description: handle a request to disable an output
jmarkel44 0:61364762ee0e 356 *
jmarkel44 0:61364762ee0e 357 * @param[in] msg -> the message request
jmarkel44 0:61364762ee0e 358 * @return none
jmarkel44 0:61364762ee0e 359 *****************************************************************************/
jmarkel44 0:61364762ee0e 360 static int disableOutputReqHandler(OutputControlMsg_t *msg)
jmarkel44 0:61364762ee0e 361 {
jmarkel44 0:61364762ee0e 362 // attempt to find the output in the map
jmarkel44 0:61364762ee0e 363 StringOutputVector_t::iterator pos;
jmarkel44 0:61364762ee0e 364
jmarkel44 0:61364762ee0e 365 pos = outputMap.find(msg->output_tag);
jmarkel44 0:61364762ee0e 366 if ( pos == outputMap.end() ) {
jmarkel44 0:61364762ee0e 367 logError("%s: failed to find the designated output %s\n",
jmarkel44 0:61364762ee0e 368 __func__, msg->output_tag);
jmarkel44 0:61364762ee0e 369 return -1;
jmarkel44 0:61364762ee0e 370 }
jmarkel44 0:61364762ee0e 371
jmarkel44 0:61364762ee0e 372 // if the control list is empty, push this control on the list
jmarkel44 0:61364762ee0e 373 if ( pos->second.empty() ) {
jmarkel44 0:61364762ee0e 374 std::string cid(msg->id);
jmarkel44 0:61364762ee0e 375 std::string input(msg->input_tag);
jmarkel44 0:61364762ee0e 376 Control c(cid, msg->controlType, input, msg->priority, CONTROL_OFF);
jmarkel44 0:61364762ee0e 377 pos->second.push_back(c);
jmarkel44 0:61364762ee0e 378 } else {
jmarkel44 0:61364762ee0e 379 // find this control in the list
jmarkel44 0:61364762ee0e 380 std::vector<Control>::iterator v;
jmarkel44 0:61364762ee0e 381 for ( v = pos->second.begin(); v != pos->second.end(); ++v ) {
jmarkel44 0:61364762ee0e 382 if ( strcmp(v->getId().c_str(), msg->id) == 0 ) {
jmarkel44 0:61364762ee0e 383 v->setState(CONTROL_OFF);
jmarkel44 0:61364762ee0e 384 break;
jmarkel44 0:61364762ee0e 385 }
jmarkel44 0:61364762ee0e 386 }
jmarkel44 0:61364762ee0e 387
jmarkel44 0:61364762ee0e 388 if ( v == pos->second.end() ) {
jmarkel44 0:61364762ee0e 389 // this is a new request, so add it and sort the vector
jmarkel44 0:61364762ee0e 390 std::string cid(msg->id);
jmarkel44 0:61364762ee0e 391 std::string input(msg->input_tag);
jmarkel44 0:61364762ee0e 392 Control c(cid, msg->controlType, input, msg->priority, CONTROL_OFF);
jmarkel44 0:61364762ee0e 393 pos->second.push_back(c);
jmarkel44 0:61364762ee0e 394 std::sort(pos->second.begin(), pos->second.end());
jmarkel44 0:61364762ee0e 395 }
jmarkel44 0:61364762ee0e 396 }
jmarkel44 0:61364762ee0e 397
jmarkel44 0:61364762ee0e 398 return 0;
jmarkel44 0:61364762ee0e 399 }
jmarkel44 0:61364762ee0e 400
jmarkel44 0:61364762ee0e 401 /*****************************************************************************
jmarkel44 0:61364762ee0e 402 * Function: unregisterControl
jmarkel44 0:61364762ee0e 403 * Description:
jmarkel44 0:61364762ee0e 404 *
jmarkel44 0:61364762ee0e 405 * @param id -> control identifier
jmarkel44 0:61364762ee0e 406 * @param pri -> priority
jmarkel44 0:61364762ee0e 407 * @param output -> output (e.g. "o_rly05")
jmarkel44 0:61364762ee0e 408 *
jmarkel44 0:61364762ee0e 409 * @return 0 on success; -1 on error
jmarkel44 0:61364762ee0e 410 *****************************************************************************/
jmarkel44 0:61364762ee0e 411 static int unregisterControl(const char *id, unsigned int pri, const char *output)
jmarkel44 0:61364762ee0e 412 {
jmarkel44 0:61364762ee0e 413 // attempt to find the output in the map
jmarkel44 0:61364762ee0e 414 StringOutputVector_t::iterator pos;
jmarkel44 0:61364762ee0e 415 bool found = false;
jmarkel44 0:61364762ee0e 416
jmarkel44 0:61364762ee0e 417 pos = outputMap.find(output);
jmarkel44 0:61364762ee0e 418 if ( pos == outputMap.end() ) {
jmarkel44 0:61364762ee0e 419 logError("%s: failed to find the designated output %s\n",
jmarkel44 0:61364762ee0e 420 __func__, output);
jmarkel44 0:61364762ee0e 421 return -1;
jmarkel44 0:61364762ee0e 422 }
jmarkel44 0:61364762ee0e 423
jmarkel44 0:61364762ee0e 424 // find the control in the list
jmarkel44 0:61364762ee0e 425 std::vector<Control>::iterator v;
jmarkel44 0:61364762ee0e 426 for ( v = pos->second.begin(); v != pos->second.end(); ++v) {
jmarkel44 0:61364762ee0e 427 if ( strcmp(v->getId().c_str(), id) == 0 ) {
jmarkel44 0:61364762ee0e 428 pos->second.erase(v);
jmarkel44 0:61364762ee0e 429 found = true;
jmarkel44 0:61364762ee0e 430 break;
jmarkel44 0:61364762ee0e 431 }
jmarkel44 0:61364762ee0e 432 }
jmarkel44 0:61364762ee0e 433
jmarkel44 0:61364762ee0e 434 if ( !found ) {
jmarkel44 0:61364762ee0e 435 logError("%s: failed to find control %s in list", __func__, id);
jmarkel44 0:61364762ee0e 436 return -1;
jmarkel44 0:61364762ee0e 437 }
jmarkel44 0:61364762ee0e 438 return 0;
jmarkel44 0:61364762ee0e 439 }
jmarkel44 0:61364762ee0e 440
jmarkel44 0:61364762ee0e 441 /*****************************************************************************
jmarkel44 0:61364762ee0e 442 * Function: loadPersistentOutputs
jmarkel44 0:61364762ee0e 443 * Description: build the output map
jmarkel44 0:61364762ee0e 444 *
jmarkel44 0:61364762ee0e 445 * @param none
jmarkel44 0:61364762ee0e 446 * @return 0 on success; -1 of failure
jmarkel44 0:61364762ee0e 447 *****************************************************************************/
jmarkel44 0:61364762ee0e 448 static int loadPersistentOutputs(void)
jmarkel44 0:61364762ee0e 449 {
jmarkel44 0:61364762ee0e 450 bool status;
jmarkel44 0:61364762ee0e 451 cJSON *root;
jmarkel44 0:61364762ee0e 452 int rc = 0;
jmarkel44 0:61364762ee0e 453
jmarkel44 0:61364762ee0e 454 printf("\rLoading persistent outputs:\n");
jmarkel44 0:61364762ee0e 455
jmarkel44 0:61364762ee0e 456 std::vector<std::string> file_list = GLOBAL_mdot->listUserFiles();
jmarkel44 0:61364762ee0e 457
jmarkel44 0:61364762ee0e 458 for (std::vector<std::string>::const_iterator i = file_list.begin(); i != file_list.end(); ++i) {
jmarkel44 0:61364762ee0e 459 // load in all of the output files
jmarkel44 0:61364762ee0e 460 if( strncmp( i->c_str(), OUTPUT_STR, strlen(OUTPUT_STR)) == 0 ||
jmarkel44 0:61364762ee0e 461 strncmp( i->c_str(), VOUTPUT_STR, strlen(VOUTPUT_STR)) == 0) {
jmarkel44 0:61364762ee0e 462 char scratchBuf[MAX_FILE_SIZE];
jmarkel44 0:61364762ee0e 463
jmarkel44 0:61364762ee0e 464 status = GLOBAL_mdot->readUserFile(i->c_str(), scratchBuf, MAX_FILE_SIZE);
jmarkel44 0:61364762ee0e 465 if( status != true ) {
jmarkel44 0:61364762ee0e 466 logError("%s: failed to read %s", __func__, i->c_str());
jmarkel44 0:61364762ee0e 467 rc = -1;
jmarkel44 0:61364762ee0e 468 } else {
jmarkel44 0:61364762ee0e 469 logInfo("%s: successfully read %s", __func__, i->c_str());
jmarkel44 0:61364762ee0e 470 }
jmarkel44 0:61364762ee0e 471
jmarkel44 0:61364762ee0e 472 root = cJSON_Parse(scratchBuf);
jmarkel44 0:61364762ee0e 473 std::string id = cJSON_GetObjectItem(root,"id")->valuestring;
jmarkel44 0:61364762ee0e 474 printf("\r output %s loaded\n", i->c_str());
jmarkel44 0:61364762ee0e 475 cJSON_Delete(root);
jmarkel44 0:61364762ee0e 476
jmarkel44 0:61364762ee0e 477 // emplace the empty control vector into the output map
jmarkel44 0:61364762ee0e 478 std::vector<Control> v;
jmarkel44 0:61364762ee0e 479 outputMap[id] = v;
jmarkel44 0:61364762ee0e 480 }
jmarkel44 0:61364762ee0e 481 }
jmarkel44 0:61364762ee0e 482 return rc;
jmarkel44 0:61364762ee0e 483 }
jmarkel44 0:61364762ee0e 484
jmarkel44 0:61364762ee0e 485 /*****************************************************************************
jmarkel44 0:61364762ee0e 486 * Function: dumpEventRecord
jmarkel44 0:61364762ee0e 487 * Description: display the contents of an event record
jmarkel44 0:61364762ee0e 488 *
jmarkel44 0:61364762ee0e 489 * @param[in] ev -> the event structure
jmarkel44 0:61364762ee0e 490 * @return none
jmarkel44 0:61364762ee0e 491 *****************************************************************************/
jmarkel44 0:61364762ee0e 492 static void dumpEventRecord(EventReasonStruct_t &ev)
jmarkel44 0:61364762ee0e 493 {
jmarkel44 0:61364762ee0e 494 const char *mapper[] = { "auto",
jmarkel44 0:61364762ee0e 495 "manual",
jmarkel44 0:61364762ee0e 496 "timer",
jmarkel44 0:61364762ee0e 497 "flow",
jmarkel44 0:61364762ee0e 498 "failsafe",
jmarkel44 0:61364762ee0e 499 "no control"
jmarkel44 0:61364762ee0e 500 };
jmarkel44 0:61364762ee0e 501
jmarkel44 0:61364762ee0e 502 time_t rawtime;
jmarkel44 0:61364762ee0e 503 time(&rawtime);
jmarkel44 0:61364762ee0e 504
jmarkel44 0:61364762ee0e 505 int iyr=0, imo=0, idy=0, ihr=0, imn=0, isc=0;
jmarkel44 0:61364762ee0e 506 #undef TODO_ICE
jmarkel44 0:61364762ee0e 507 #if 0
jmarkel44 0:61364762ee0e 508 rtc_get_time(&iyr, &imo, &idy, &ihr, &imn, &isc);
jmarkel44 0:61364762ee0e 509 #endif
jmarkel44 0:61364762ee0e 510
jmarkel44 0:61364762ee0e 511 printf("\rEVENT RECORD (%04d-%02d-%02d %02d:%02d:%02d)\r\n",
jmarkel44 0:61364762ee0e 512 iyr, imo, idy, ihr, imn, isc);
jmarkel44 0:61364762ee0e 513 printf("\rev.eventReason = %d (%s)\n", ev.eventReason, mapper[ev.eventReason]);
jmarkel44 0:61364762ee0e 514 printf("\rev.inputTag = %s\n", ev.inputTag[0] ? ev.inputTag : "empty");
jmarkel44 0:61364762ee0e 515 printf("\rev.outputTag = %s\n", ev.outputTag[0] ? ev.outputTag : "empty");
jmarkel44 0:61364762ee0e 516 printf("\rev.inputValue = %.02f\n", ev.inputValue);
jmarkel44 0:61364762ee0e 517 printf("\rev.outputValue = %.02f (%s)\n", ev.outputValue,
jmarkel44 0:61364762ee0e 518 ((unsigned int)ev.outputValue & 1 == 1) ? "on" : "off");
jmarkel44 0:61364762ee0e 519 }
jmarkel44 0:61364762ee0e 520
jmarkel44 0:61364762ee0e 521 /*****************************************************************************
jmarkel44 0:61364762ee0e 522 * Function: DisplayOutputs
jmarkel44 0:61364762ee0e 523 * Description: Display a list of outputs and their controls
jmarkel44 0:61364762ee0e 524 *
jmarkel44 0:61364762ee0e 525 * @param none
jmarkel44 0:61364762ee0e 526 * @return none
jmarkel44 0:61364762ee0e 527 *****************************************************************************/
jmarkel44 0:61364762ee0e 528 void DisplayOutputs(void)
jmarkel44 0:61364762ee0e 529 {
jmarkel44 0:61364762ee0e 530 StringOutputVector_t::iterator pos;
jmarkel44 0:61364762ee0e 531
jmarkel44 0:61364762ee0e 532 for ( pos = outputMap.begin(); pos != outputMap.end(); ++pos ) {
jmarkel44 0:61364762ee0e 533 if ( pos->second.empty() ) {
jmarkel44 0:61364762ee0e 534 printf("\r [%s]-> [no controls] \n", pos->first.c_str());
jmarkel44 0:61364762ee0e 535 } else {
jmarkel44 0:61364762ee0e 536 printf("\r [%s]-> ", pos->first.c_str());
jmarkel44 0:61364762ee0e 537 std::vector<Control>::iterator i;
jmarkel44 0:61364762ee0e 538 for ( i = pos->second.begin(); i != pos->second.end(); ++i ) {
jmarkel44 0:61364762ee0e 539 i->display();
jmarkel44 0:61364762ee0e 540 }
jmarkel44 0:61364762ee0e 541 printf("\n");
jmarkel44 0:61364762ee0e 542 }
jmarkel44 0:61364762ee0e 543 }
jmarkel44 0:61364762ee0e 544 printf("\r\n");
jmarkel44 0:61364762ee0e 545 }