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.
ICE-Application/src/ConfigurationHandler/Controls/SensorErrorControl.cpp@0:61364762ee0e, 2017-01-24 (annotated)
- 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?
User | Revision | Line number | New contents of line |
---|---|---|---|
jmarkel44 | 0:61364762ee0e | 1 | /****************************************************************************** |
jmarkel44 | 0:61364762ee0e | 2 | * |
jmarkel44 | 0:61364762ee0e | 3 | * File: SensorErrorControl.cpp |
jmarkel44 | 0:61364762ee0e | 4 | * Desciption: ICE Sensor Error Control class implementation |
jmarkel44 | 0:61364762ee0e | 5 | * |
jmarkel44 | 0:61364762ee0e | 6 | *****************************************************************************/ |
jmarkel44 | 0:61364762ee0e | 7 | #include "SensorErrorControl.h" |
jmarkel44 | 0:61364762ee0e | 8 | #include "cJSON.h" |
jmarkel44 | 0:61364762ee0e | 9 | #include "ModbusMasterApi.h" |
jmarkel44 | 0:61364762ee0e | 10 | #include "utilities.h" |
jmarkel44 | 0:61364762ee0e | 11 | #include "ICELog.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 | |
jmarkel44 | 0:61364762ee0e | 17 | using namespace std; |
jmarkel44 | 0:61364762ee0e | 18 | |
jmarkel44 | 0:61364762ee0e | 19 | // for debugging - this can be set via the console command: |
jmarkel44 | 0:61364762ee0e | 20 | // "debug-se 1 |
jmarkel44 | 0:61364762ee0e | 21 | bool debugSensorError = false; |
jmarkel44 | 0:61364762ee0e | 22 | |
jmarkel44 | 0:61364762ee0e | 23 | static void debug(const char *fmt, ...) |
jmarkel44 | 0:61364762ee0e | 24 | { |
jmarkel44 | 0:61364762ee0e | 25 | if ( debugSensorError ) { |
jmarkel44 | 0:61364762ee0e | 26 | va_list vargs; |
jmarkel44 | 0:61364762ee0e | 27 | va_start(vargs, fmt); |
jmarkel44 | 0:61364762ee0e | 28 | vfprintf(stdout, fmt, vargs); |
jmarkel44 | 0:61364762ee0e | 29 | va_end(vargs); |
jmarkel44 | 0:61364762ee0e | 30 | } |
jmarkel44 | 0:61364762ee0e | 31 | } |
jmarkel44 | 0:61364762ee0e | 32 | |
jmarkel44 | 0:61364762ee0e | 33 | // |
jmarkel44 | 0:61364762ee0e | 34 | // method: load |
jmarkel44 | 0:61364762ee0e | 35 | // description: load data from the control file |
jmarkel44 | 0:61364762ee0e | 36 | // |
jmarkel44 | 0:61364762ee0e | 37 | // @param[in] _controlFile -> the control file |
jmarkel44 | 0:61364762ee0e | 38 | // @return true if loaded; false otherwise |
jmarkel44 | 0:61364762ee0e | 39 | // |
jmarkel44 | 0:61364762ee0e | 40 | bool SensorErrorControl::load(const std::string _controlFile) |
jmarkel44 | 0:61364762ee0e | 41 | { |
jmarkel44 | 0:61364762ee0e | 42 | controlFile = _controlFile; |
jmarkel44 | 0:61364762ee0e | 43 | |
jmarkel44 | 0:61364762ee0e | 44 | // read the data into a buffer |
jmarkel44 | 0:61364762ee0e | 45 | char dataBuf[MAX_FILE_SIZE]; |
jmarkel44 | 0:61364762ee0e | 46 | |
jmarkel44 | 0:61364762ee0e | 47 | bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf)); |
jmarkel44 | 0:61364762ee0e | 48 | if ( rc != true ) { |
jmarkel44 | 0:61364762ee0e | 49 | logError("%s: failed to read %s", __func__, controlFile.c_str()); |
jmarkel44 | 0:61364762ee0e | 50 | // caller should destroy the object |
jmarkel44 | 0:61364762ee0e | 51 | return false; |
jmarkel44 | 0:61364762ee0e | 52 | } |
jmarkel44 | 0:61364762ee0e | 53 | |
jmarkel44 | 0:61364762ee0e | 54 | // validate the JSON formatted control data |
jmarkel44 | 0:61364762ee0e | 55 | if ( !validateControlData(dataBuf) ) { |
jmarkel44 | 0:61364762ee0e | 56 | logError("%s: failed to validate control data", __func__); |
jmarkel44 | 0:61364762ee0e | 57 | return false; |
jmarkel44 | 0:61364762ee0e | 58 | } |
jmarkel44 | 0:61364762ee0e | 59 | |
jmarkel44 | 0:61364762ee0e | 60 | // copy the control data |
jmarkel44 | 0:61364762ee0e | 61 | copyControlData(dataBuf); |
jmarkel44 | 0:61364762ee0e | 62 | |
jmarkel44 | 0:61364762ee0e | 63 | ModbusValue val; |
jmarkel44 | 0:61364762ee0e | 64 | // validate the input |
jmarkel44 | 0:61364762ee0e | 65 | if ( ModbusMasterReadRegister(input, &val) == false ) { |
jmarkel44 | 0:61364762ee0e | 66 | logError("%s failed to find input %s", id.c_str(), input.c_str()); |
jmarkel44 | 0:61364762ee0e | 67 | return false; |
jmarkel44 | 0:61364762ee0e | 68 | } |
jmarkel44 | 0:61364762ee0e | 69 | |
jmarkel44 | 0:61364762ee0e | 70 | isVirtualOutput = Util_isVirtualOutput(output) ? true : false; |
jmarkel44 | 0:61364762ee0e | 71 | return true; |
jmarkel44 | 0:61364762ee0e | 72 | } |
jmarkel44 | 0:61364762ee0e | 73 | |
jmarkel44 | 0:61364762ee0e | 74 | // |
jmarkel44 | 0:61364762ee0e | 75 | // @method: validateControlData |
jmarkel44 | 0:61364762ee0e | 76 | // @description: vaqlidate the JSON formatted string |
jmarkel44 | 0:61364762ee0e | 77 | // |
jmarkel44 | 0:61364762ee0e | 78 | // @param[in] buf -> JSON formatted string |
jmarkel44 | 0:61364762ee0e | 79 | // @param[out] none |
jmarkel44 | 0:61364762ee0e | 80 | // @return true if valid; false otherwise |
jmarkel44 | 0:61364762ee0e | 81 | // |
jmarkel44 | 0:61364762ee0e | 82 | bool SensorErrorControl::validateControlData(const char *buf) |
jmarkel44 | 0:61364762ee0e | 83 | { |
jmarkel44 | 0:61364762ee0e | 84 | bool rc = true; |
jmarkel44 | 0:61364762ee0e | 85 | |
jmarkel44 | 0:61364762ee0e | 86 | // parse the data |
jmarkel44 | 0:61364762ee0e | 87 | cJSON * root = cJSON_Parse(buf); |
jmarkel44 | 0:61364762ee0e | 88 | |
jmarkel44 | 0:61364762ee0e | 89 | if ( !cJSON_HasObjectItem(root, "id") || |
jmarkel44 | 0:61364762ee0e | 90 | !cJSON_HasObjectItem(root, "priority") || |
jmarkel44 | 0:61364762ee0e | 91 | !cJSON_HasObjectItem(root, "input") || |
jmarkel44 | 0:61364762ee0e | 92 | !cJSON_HasObjectItem(root, "output") || |
jmarkel44 | 0:61364762ee0e | 93 | !cJSON_HasObjectItem(root, "dutyCycle") || |
jmarkel44 | 0:61364762ee0e | 94 | !cJSON_HasObjectItem(root, "interval") ) { |
jmarkel44 | 0:61364762ee0e | 95 | logError("%s: control file is missing expected tags", __func__); |
jmarkel44 | 0:61364762ee0e | 96 | rc = false; |
jmarkel44 | 0:61364762ee0e | 97 | } |
jmarkel44 | 0:61364762ee0e | 98 | |
jmarkel44 | 0:61364762ee0e | 99 | cJSON_Delete(root); |
jmarkel44 | 0:61364762ee0e | 100 | return rc; |
jmarkel44 | 0:61364762ee0e | 101 | } |
jmarkel44 | 0:61364762ee0e | 102 | |
jmarkel44 | 0:61364762ee0e | 103 | // |
jmarkel44 | 0:61364762ee0e | 104 | // method: copyControlData |
jmarkel44 | 0:61364762ee0e | 105 | // description: copy the data from the control file to the object |
jmarkel44 | 0:61364762ee0e | 106 | // |
jmarkel44 | 0:61364762ee0e | 107 | // @param[in] buf -> JSON formatted string |
jmarkel44 | 0:61364762ee0e | 108 | // @param[out] none |
jmarkel44 | 0:61364762ee0e | 109 | // @return none |
jmarkel44 | 0:61364762ee0e | 110 | // |
jmarkel44 | 0:61364762ee0e | 111 | void SensorErrorControl::copyControlData(const char *buf) |
jmarkel44 | 0:61364762ee0e | 112 | { |
jmarkel44 | 0:61364762ee0e | 113 | cJSON *root = cJSON_Parse(buf); |
jmarkel44 | 0:61364762ee0e | 114 | |
jmarkel44 | 0:61364762ee0e | 115 | id = cJSON_GetObjectItem(root, "id")->valuestring; |
jmarkel44 | 0:61364762ee0e | 116 | priority = atoi(cJSON_GetObjectItem(root, "priority")->valuestring); |
jmarkel44 | 0:61364762ee0e | 117 | input = cJSON_GetObjectItem(root, "input")->valuestring; |
jmarkel44 | 0:61364762ee0e | 118 | output = cJSON_GetObjectItem(root, "output")->valuestring; |
jmarkel44 | 0:61364762ee0e | 119 | dutyCycle.dutyCycle = atoi(cJSON_GetObjectItem(root, "dutyCycle")->valuestring); |
jmarkel44 | 0:61364762ee0e | 120 | dutyCycle.interval = atoi(cJSON_GetObjectItem(root, "interval")->valuestring); |
jmarkel44 | 0:61364762ee0e | 121 | |
jmarkel44 | 0:61364762ee0e | 122 | cJSON_Delete(root); |
jmarkel44 | 0:61364762ee0e | 123 | } |
jmarkel44 | 0:61364762ee0e | 124 | |
jmarkel44 | 0:61364762ee0e | 125 | // |
jmarkel44 | 0:61364762ee0e | 126 | // @method: start |
jmarkel44 | 0:61364762ee0e | 127 | // @description: put the control in the start state |
jmarkel44 | 0:61364762ee0e | 128 | // |
jmarkel44 | 0:61364762ee0e | 129 | // @param[in] none |
jmarkel44 | 0:61364762ee0e | 130 | // @param[out] none |
jmarkel44 | 0:61364762ee0e | 131 | // @return none |
jmarkel44 | 0:61364762ee0e | 132 | // |
jmarkel44 | 0:61364762ee0e | 133 | void SensorErrorControl::start(void) |
jmarkel44 | 0:61364762ee0e | 134 | { |
jmarkel44 | 0:61364762ee0e | 135 | currentState = STATE_START; |
jmarkel44 | 0:61364762ee0e | 136 | } |
jmarkel44 | 0:61364762ee0e | 137 | |
jmarkel44 | 0:61364762ee0e | 138 | // |
jmarkel44 | 0:61364762ee0e | 139 | // @method update |
jmarkel44 | 0:61364762ee0e | 140 | // @description run the simplified state machine |
jmarkel44 | 0:61364762ee0e | 141 | // |
jmarkel44 | 0:61364762ee0e | 142 | // @param[in] none |
jmarkel44 | 0:61364762ee0e | 143 | // @param[out] none |
jmarkel44 | 0:61364762ee0e | 144 | // @return OK on success; error otherwise |
jmarkel44 | 0:61364762ee0e | 145 | // |
jmarkel44 | 0:61364762ee0e | 146 | SensorErrorControlError_t SensorErrorControl::update(void) |
jmarkel44 | 0:61364762ee0e | 147 | { |
jmarkel44 | 0:61364762ee0e | 148 | SensorErrorControlError_t rc = SENSOR_ERROR_CONTROL_OK; |
jmarkel44 | 0:61364762ee0e | 149 | |
jmarkel44 | 0:61364762ee0e | 150 | switch (this->currentState) { |
jmarkel44 | 0:61364762ee0e | 151 | case STATE_INIT: |
jmarkel44 | 0:61364762ee0e | 152 | // do nothing: control must be programmatically started |
jmarkel44 | 0:61364762ee0e | 153 | break; |
jmarkel44 | 0:61364762ee0e | 154 | case STATE_START: |
jmarkel44 | 0:61364762ee0e | 155 | if ( this->isSensorError() ) { |
jmarkel44 | 0:61364762ee0e | 156 | if ( dutyCycle.dutyCycle > 0 ) { |
jmarkel44 | 0:61364762ee0e | 157 | this->startDutyTimer(); |
jmarkel44 | 0:61364762ee0e | 158 | this->currentState = STATE_DUTY_CYCLE_ON; |
jmarkel44 | 0:61364762ee0e | 159 | sendMailToOutput(ACTION_CONTROL_ON); |
jmarkel44 | 0:61364762ee0e | 160 | debug("\r%s: [STARTUP]->sensor error->[DUTY_CYCLE_ON] time=%lu\n", id.c_str(), time(0)); |
jmarkel44 | 0:61364762ee0e | 161 | } else { |
jmarkel44 | 0:61364762ee0e | 162 | // this is a fixed-off state |
jmarkel44 | 0:61364762ee0e | 163 | this->stopDutyTimer(); // probably not needed |
jmarkel44 | 0:61364762ee0e | 164 | this->currentState = STATE_DUTY_CYCLE_OFF; |
jmarkel44 | 0:61364762ee0e | 165 | // tell the output task to turn off the relay |
jmarkel44 | 0:61364762ee0e | 166 | sendMailToOutput(ACTION_CONTROL_OFF); |
jmarkel44 | 0:61364762ee0e | 167 | debug("\r%s: [STARTUP]->sensor error (no duty)->[DUTY_CYCLE_OFF] %lu\n", id.c_str(), time(0)); |
jmarkel44 | 0:61364762ee0e | 168 | } |
jmarkel44 | 0:61364762ee0e | 169 | } else { |
jmarkel44 | 0:61364762ee0e | 170 | // input signal is OK |
jmarkel44 | 0:61364762ee0e | 171 | debug("\r%s: [STARTUP]->OK->[OFF] %lu\n", id.c_str(), time(0)); |
jmarkel44 | 0:61364762ee0e | 172 | this->currentState = STATE_CONTROL_OFF; |
jmarkel44 | 0:61364762ee0e | 173 | } |
jmarkel44 | 0:61364762ee0e | 174 | break; |
jmarkel44 | 0:61364762ee0e | 175 | case STATE_CONTROL_OFF: |
jmarkel44 | 0:61364762ee0e | 176 | if ( isSensorError() ) { |
jmarkel44 | 0:61364762ee0e | 177 | if ( dutyCycle.dutyCycle > 0 ) { |
jmarkel44 | 0:61364762ee0e | 178 | this->startDutyTimer(); |
jmarkel44 | 0:61364762ee0e | 179 | this->currentState = STATE_DUTY_CYCLE_ON; |
jmarkel44 | 0:61364762ee0e | 180 | sendMailToOutput(ACTION_CONTROL_ON); |
jmarkel44 | 0:61364762ee0e | 181 | debug("\r%s: [STARTUP]->sensor error->[DUTY_CYCLE_ON] %lu\n", id.c_str(), time(0)); |
jmarkel44 | 0:61364762ee0e | 182 | } else { |
jmarkel44 | 0:61364762ee0e | 183 | // this is a fixed off state |
jmarkel44 | 0:61364762ee0e | 184 | this->stopDutyTimer(); // probably not needed |
jmarkel44 | 0:61364762ee0e | 185 | this->currentState = STATE_DUTY_CYCLE_OFF; |
jmarkel44 | 0:61364762ee0e | 186 | // tell the output task to turn off the relay |
jmarkel44 | 0:61364762ee0e | 187 | sendMailToOutput(ACTION_CONTROL_OFF); |
jmarkel44 | 0:61364762ee0e | 188 | debug("\r%s: [STARTUP]->sensor error (no duty)->[DUTY_CYCLE_OFF] %lu\n", id.c_str(), time(0)); |
jmarkel44 | 0:61364762ee0e | 189 | } |
jmarkel44 | 0:61364762ee0e | 190 | } else { |
jmarkel44 | 0:61364762ee0e | 191 | // input signal is OK, so don't do anything |
jmarkel44 | 0:61364762ee0e | 192 | } |
jmarkel44 | 0:61364762ee0e | 193 | break; |
jmarkel44 | 0:61364762ee0e | 194 | case STATE_DUTY_CYCLE_ON: |
jmarkel44 | 0:61364762ee0e | 195 | if ( !isSensorError() ) { |
jmarkel44 | 0:61364762ee0e | 196 | this->stopDutyTimer(); |
jmarkel44 | 0:61364762ee0e | 197 | this->currentState = STATE_CONTROL_OFF; |
jmarkel44 | 0:61364762ee0e | 198 | this->unregisterControl(); |
jmarkel44 | 0:61364762ee0e | 199 | debug("\r%s: [DUTY_CYCLE_ON]->no error->[OFF] %lu\n", id.c_str(), time(0)); |
jmarkel44 | 0:61364762ee0e | 200 | |
jmarkel44 | 0:61364762ee0e | 201 | } else if ( dutyOnExpired() ) |
jmarkel44 | 0:61364762ee0e | 202 | if ( dutyCycle.dutyCycle < 100 ) { |
jmarkel44 | 0:61364762ee0e | 203 | this->currentState = STATE_DUTY_CYCLE_OFF; |
jmarkel44 | 0:61364762ee0e | 204 | sendMailToOutput(ACTION_CONTROL_OFF); |
jmarkel44 | 0:61364762ee0e | 205 | debug("\r%s: [DUTY_CYCLE_ON]->on expired->[DUTY_CYCLE_OFF] %lu\n", id.c_str(), time(0)); |
jmarkel44 | 0:61364762ee0e | 206 | } else { |
jmarkel44 | 0:61364762ee0e | 207 | // fixed-on state |
jmarkel44 | 0:61364762ee0e | 208 | // do nothing - we'll need to wait for the sensor error |
jmarkel44 | 0:61364762ee0e | 209 | // to clear before something can happen |
jmarkel44 | 0:61364762ee0e | 210 | } |
jmarkel44 | 0:61364762ee0e | 211 | break; |
jmarkel44 | 0:61364762ee0e | 212 | case STATE_DUTY_CYCLE_OFF: |
jmarkel44 | 0:61364762ee0e | 213 | if ( !isSensorError() ) { |
jmarkel44 | 0:61364762ee0e | 214 | // there is no sensor error, so unregister the control and cleanup |
jmarkel44 | 0:61364762ee0e | 215 | this->stopDutyTimer(); |
jmarkel44 | 0:61364762ee0e | 216 | this->currentState = STATE_CONTROL_OFF; |
jmarkel44 | 0:61364762ee0e | 217 | this->unregisterControl(); |
jmarkel44 | 0:61364762ee0e | 218 | debug("\r%s: [DUTY_CYCLE_OFF]->no error->[OFF] %lu\n", id.c_str(), time(0)); |
jmarkel44 | 0:61364762ee0e | 219 | stopDutyTimer(); |
jmarkel44 | 0:61364762ee0e | 220 | } else if ( dutyOffExpired() ) { |
jmarkel44 | 0:61364762ee0e | 221 | if ( dutyCycle.dutyCycle > 0 ) { |
jmarkel44 | 0:61364762ee0e | 222 | // we go back to the OFF state so the start and expiration |
jmarkel44 | 0:61364762ee0e | 223 | // times are recalculated |
jmarkel44 | 0:61364762ee0e | 224 | this->currentState = STATE_CONTROL_OFF; |
jmarkel44 | 0:61364762ee0e | 225 | sendMailToOutput(ACTION_CONTROL_OFF); |
jmarkel44 | 0:61364762ee0e | 226 | debug("\r%s: [DUTY_CYCLE_OFF]->off expired->[OFF] %lu\n", id.c_str(), time(0)); |
jmarkel44 | 0:61364762ee0e | 227 | } else { |
jmarkel44 | 0:61364762ee0e | 228 | // fixed-off state |
jmarkel44 | 0:61364762ee0e | 229 | // do nothing - we'll need to wait for the sensor error |
jmarkel44 | 0:61364762ee0e | 230 | // to clear before something can happen |
jmarkel44 | 0:61364762ee0e | 231 | } |
jmarkel44 | 0:61364762ee0e | 232 | } |
jmarkel44 | 0:61364762ee0e | 233 | break; |
jmarkel44 | 0:61364762ee0e | 234 | default: |
jmarkel44 | 0:61364762ee0e | 235 | logError("%s: unknown state\n", __func__); |
jmarkel44 | 0:61364762ee0e | 236 | rc = SENSOR_ERROR_CONTROL_UNK_STATE; |
jmarkel44 | 0:61364762ee0e | 237 | break; |
jmarkel44 | 0:61364762ee0e | 238 | } |
jmarkel44 | 0:61364762ee0e | 239 | return rc; |
jmarkel44 | 0:61364762ee0e | 240 | } |
jmarkel44 | 0:61364762ee0e | 241 | |
jmarkel44 | 0:61364762ee0e | 242 | // |
jmarkel44 | 0:61364762ee0e | 243 | // @method: isSensorError |
jmarkel44 | 0:61364762ee0e | 244 | // @description: reads the modbus register to get the error condition of |
jmarkel44 | 0:61364762ee0e | 245 | // the input signal |
jmarkel44 | 0:61364762ee0e | 246 | // |
jmarkel44 | 0:61364762ee0e | 247 | // @param[in] none |
jmarkel44 | 0:61364762ee0e | 248 | // @param[out] none |
jmarkel44 | 0:61364762ee0e | 249 | // @return true if in error; false otherwise |
jmarkel44 | 0:61364762ee0e | 250 | // |
jmarkel44 | 0:61364762ee0e | 251 | bool SensorErrorControl::isSensorError() |
jmarkel44 | 0:61364762ee0e | 252 | { |
jmarkel44 | 0:61364762ee0e | 253 | ModbusValue val; |
jmarkel44 | 0:61364762ee0e | 254 | |
jmarkel44 | 0:61364762ee0e | 255 | if ( ModbusMasterReadRegister(this->input, &val) != true ) { |
jmarkel44 | 0:61364762ee0e | 256 | logError("Failed to read %s\n", this->input.c_str()); |
jmarkel44 | 0:61364762ee0e | 257 | return true; |
jmarkel44 | 0:61364762ee0e | 258 | } else if ( val.errflag ) { |
jmarkel44 | 0:61364762ee0e | 259 | // input is in sensor error |
jmarkel44 | 0:61364762ee0e | 260 | return true; |
jmarkel44 | 0:61364762ee0e | 261 | } |
jmarkel44 | 0:61364762ee0e | 262 | return false; |
jmarkel44 | 0:61364762ee0e | 263 | } |
jmarkel44 | 0:61364762ee0e | 264 | |
jmarkel44 | 0:61364762ee0e | 265 | // |
jmarkel44 | 0:61364762ee0e | 266 | // @method: dutyOnExpired |
jmarkel44 | 0:61364762ee0e | 267 | // @description: returns true of duty ON time expired |
jmarkel44 | 0:61364762ee0e | 268 | // |
jmarkel44 | 0:61364762ee0e | 269 | // @param[in] none |
jmarkel44 | 0:61364762ee0e | 270 | // @param[out] none |
jmarkel44 | 0:61364762ee0e | 271 | // @return true if expired; false otherwise |
jmarkel44 | 0:61364762ee0e | 272 | // |
jmarkel44 | 0:61364762ee0e | 273 | bool SensorErrorControl::dutyOnExpired(void) |
jmarkel44 | 0:61364762ee0e | 274 | { |
jmarkel44 | 0:61364762ee0e | 275 | return (time(0) >= duty_timer.offTime); |
jmarkel44 | 0:61364762ee0e | 276 | } |
jmarkel44 | 0:61364762ee0e | 277 | |
jmarkel44 | 0:61364762ee0e | 278 | // |
jmarkel44 | 0:61364762ee0e | 279 | // @method: dutyOffExpired |
jmarkel44 | 0:61364762ee0e | 280 | // @description: returns true of duty OFF time expired |
jmarkel44 | 0:61364762ee0e | 281 | // |
jmarkel44 | 0:61364762ee0e | 282 | // @param[in] none |
jmarkel44 | 0:61364762ee0e | 283 | // @param[out] none |
jmarkel44 | 0:61364762ee0e | 284 | // @return true if expired; false otherwise |
jmarkel44 | 0:61364762ee0e | 285 | // |
jmarkel44 | 0:61364762ee0e | 286 | bool SensorErrorControl::dutyOffExpired(void) |
jmarkel44 | 0:61364762ee0e | 287 | { |
jmarkel44 | 0:61364762ee0e | 288 | return (duty_timer.expirationTime < time(0)); |
jmarkel44 | 0:61364762ee0e | 289 | } |
jmarkel44 | 0:61364762ee0e | 290 | |
jmarkel44 | 0:61364762ee0e | 291 | // |
jmarkel44 | 0:61364762ee0e | 292 | // method: startDutyTimer |
jmarkel44 | 0:61364762ee0e | 293 | // descrption: start the sensor error duty-timer |
jmarkel44 | 0:61364762ee0e | 294 | // |
jmarkel44 | 0:61364762ee0e | 295 | // @param none |
jmarkel44 | 0:61364762ee0e | 296 | // @return none |
jmarkel44 | 0:61364762ee0e | 297 | // |
jmarkel44 | 0:61364762ee0e | 298 | void SensorErrorControl::startDutyTimer(void) |
jmarkel44 | 0:61364762ee0e | 299 | { |
jmarkel44 | 0:61364762ee0e | 300 | unsigned long currentTime = time(0); |
jmarkel44 | 0:61364762ee0e | 301 | unsigned long period = dutyCycle.interval * 60; |
jmarkel44 | 0:61364762ee0e | 302 | |
jmarkel44 | 0:61364762ee0e | 303 | duty_timer.offTime = currentTime + ((double)period * ((double)dutyCycle.dutyCycle/100.0)); |
jmarkel44 | 0:61364762ee0e | 304 | duty_timer.expirationTime = currentTime + period; |
jmarkel44 | 0:61364762ee0e | 305 | |
jmarkel44 | 0:61364762ee0e | 306 | debug("\r%s:%s-> currentTime = %lu\n", __func__, id.c_str(), currentTime); |
jmarkel44 | 0:61364762ee0e | 307 | debug("\r%s:%s-> off Time = %lu\n", __func__, id.c_str(), duty_timer.offTime); |
jmarkel44 | 0:61364762ee0e | 308 | debug("\r%s:%s-> expiration = %lu\n", __func__, id.c_str(), duty_timer.expirationTime); |
jmarkel44 | 0:61364762ee0e | 309 | } |
jmarkel44 | 0:61364762ee0e | 310 | |
jmarkel44 | 0:61364762ee0e | 311 | // |
jmarkel44 | 0:61364762ee0e | 312 | // method: stopDutyTimer |
jmarkel44 | 0:61364762ee0e | 313 | // descrption: stop the sensor error duty-timer |
jmarkel44 | 0:61364762ee0e | 314 | // |
jmarkel44 | 0:61364762ee0e | 315 | // @param none |
jmarkel44 | 0:61364762ee0e | 316 | // @return none |
jmarkel44 | 0:61364762ee0e | 317 | // |
jmarkel44 | 0:61364762ee0e | 318 | void SensorErrorControl::stopDutyTimer(void) |
jmarkel44 | 0:61364762ee0e | 319 | { |
jmarkel44 | 0:61364762ee0e | 320 | memset(&duty_timer, 0, sizeof(duty_timer)); |
jmarkel44 | 0:61364762ee0e | 321 | } |
jmarkel44 | 0:61364762ee0e | 322 | |
jmarkel44 | 0:61364762ee0e | 323 | // |
jmarkel44 | 0:61364762ee0e | 324 | // method: sendMailToOutput |
jmarkel44 | 0:61364762ee0e | 325 | // description: send a message to the output thread |
jmarkel44 | 0:61364762ee0e | 326 | // |
jmarkel44 | 0:61364762ee0e | 327 | // @param[in] action -> on, off, etc. |
jmarkel44 | 0:61364762ee0e | 328 | // @param[out] none |
jmarkel44 | 0:61364762ee0e | 329 | // @return |
jmarkel44 | 0:61364762ee0e | 330 | // |
jmarkel44 | 0:61364762ee0e | 331 | void SensorErrorControl::sendMailToOutput(OutputAction action) |
jmarkel44 | 0:61364762ee0e | 332 | { |
jmarkel44 | 0:61364762ee0e | 333 | |
jmarkel44 | 0:61364762ee0e | 334 | if ( isVirtualOutput ) { |
jmarkel44 | 0:61364762ee0e | 335 | debug("%s:%s updating the virtual output %s\n", __func__, id.c_str(), output.c_str()); |
jmarkel44 | 0:61364762ee0e | 336 | ModbusMasterWriteRegister(this->output, |
jmarkel44 | 0:61364762ee0e | 337 | (action == ACTION_CONTROL_ON) ? 1.0 : 0.0); |
jmarkel44 | 0:61364762ee0e | 338 | } else { |
jmarkel44 | 0:61364762ee0e | 339 | debug("%s:%s sensor error control attempting to send action %d\n", |
jmarkel44 | 0:61364762ee0e | 340 | __func__, id.c_str(), action); |
jmarkel44 | 0:61364762ee0e | 341 | |
jmarkel44 | 0:61364762ee0e | 342 | OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); |
jmarkel44 | 0:61364762ee0e | 343 | memset(output_mail, 0, sizeof(OutputControlMsg_t)); |
jmarkel44 | 0:61364762ee0e | 344 | |
jmarkel44 | 0:61364762ee0e | 345 | output_mail->action = action; |
jmarkel44 | 0:61364762ee0e | 346 | output_mail->controlType = CONTROL_SENSOR_ERROR; |
jmarkel44 | 0:61364762ee0e | 347 | output_mail->priority = this->priority; |
jmarkel44 | 0:61364762ee0e | 348 | |
jmarkel44 | 0:61364762ee0e | 349 | strncpy(output_mail->input_tag, this->input.c_str(), sizeof(output_mail->input_tag)-1); |
jmarkel44 | 0:61364762ee0e | 350 | strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); |
jmarkel44 | 0:61364762ee0e | 351 | strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); |
jmarkel44 | 0:61364762ee0e | 352 | |
jmarkel44 | 0:61364762ee0e | 353 | OutputMasterMailBox.put(output_mail); |
jmarkel44 | 0:61364762ee0e | 354 | } |
jmarkel44 | 0:61364762ee0e | 355 | } |
jmarkel44 | 0:61364762ee0e | 356 | |
jmarkel44 | 0:61364762ee0e | 357 | // |
jmarkel44 | 0:61364762ee0e | 358 | // @method: unregisterControl |
jmarkel44 | 0:61364762ee0e | 359 | // @description: unregister the control with the output task |
jmarkel44 | 0:61364762ee0e | 360 | // |
jmarkel44 | 0:61364762ee0e | 361 | // @param[in] none |
jmarkel44 | 0:61364762ee0e | 362 | // @param[out] none |
jmarkel44 | 0:61364762ee0e | 363 | // @return none |
jmarkel44 | 0:61364762ee0e | 364 | // |
jmarkel44 | 0:61364762ee0e | 365 | void SensorErrorControl::unregisterControl(void) |
jmarkel44 | 0:61364762ee0e | 366 | { |
jmarkel44 | 0:61364762ee0e | 367 | if ( isVirtualOutput ) { |
jmarkel44 | 0:61364762ee0e | 368 | debug("%s: %s attempting to unregister virtual output %s\n", __func__, id.c_str(), output.c_str()); |
jmarkel44 | 0:61364762ee0e | 369 | ModbusMasterWriteRegister(output, 0.0); |
jmarkel44 | 0:61364762ee0e | 370 | } else { |
jmarkel44 | 0:61364762ee0e | 371 | debug("%s: %s attempting to unregister output %s\n", |
jmarkel44 | 0:61364762ee0e | 372 | __func__, id.c_str(), output.c_str()); |
jmarkel44 | 0:61364762ee0e | 373 | |
jmarkel44 | 0:61364762ee0e | 374 | OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); |
jmarkel44 | 0:61364762ee0e | 375 | memset(output_mail, 0, sizeof(OutputControlMsg_t)); |
jmarkel44 | 0:61364762ee0e | 376 | |
jmarkel44 | 0:61364762ee0e | 377 | output_mail->action = ACTION_CONTROL_UNREGISTER; |
jmarkel44 | 0:61364762ee0e | 378 | output_mail->controlType = CONTROL_FAILSAFE; |
jmarkel44 | 0:61364762ee0e | 379 | output_mail->priority = this->priority; |
jmarkel44 | 0:61364762ee0e | 380 | strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); |
jmarkel44 | 0:61364762ee0e | 381 | strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); |
jmarkel44 | 0:61364762ee0e | 382 | |
jmarkel44 | 0:61364762ee0e | 383 | OutputMasterMailBox.put(output_mail); |
jmarkel44 | 0:61364762ee0e | 384 | } |
jmarkel44 | 0:61364762ee0e | 385 | } |
jmarkel44 | 0:61364762ee0e | 386 | |
jmarkel44 | 0:61364762ee0e | 387 | // |
jmarkel44 | 0:61364762ee0e | 388 | // @method: display |
jmarkel44 | 0:61364762ee0e | 389 | // @description: show the pertinents |
jmarkel44 | 0:61364762ee0e | 390 | // |
jmarkel44 | 0:61364762ee0e | 391 | // @param[in] none |
jmarkel44 | 0:61364762ee0e | 392 | // @param[out] none |
jmarkel44 | 0:61364762ee0e | 393 | // @return none |
jmarkel44 | 0:61364762ee0e | 394 | // |
jmarkel44 | 0:61364762ee0e | 395 | void SensorErrorControl::display(void) |
jmarkel44 | 0:61364762ee0e | 396 | { |
jmarkel44 | 0:61364762ee0e | 397 | const char *mapper[] = { "INIT", |
jmarkel44 | 0:61364762ee0e | 398 | "START", |
jmarkel44 | 0:61364762ee0e | 399 | "OFF", |
jmarkel44 | 0:61364762ee0e | 400 | "DUTY CYCLE ON", |
jmarkel44 | 0:61364762ee0e | 401 | "DUTY CYCLE OFF", |
jmarkel44 | 0:61364762ee0e | 402 | "invalid" |
jmarkel44 | 0:61364762ee0e | 403 | }; |
jmarkel44 | 0:61364762ee0e | 404 | |
jmarkel44 | 0:61364762ee0e | 405 | printf("\r\n"); |
jmarkel44 | 0:61364762ee0e | 406 | std::cout << left << setw(10) << setfill(' ') << "sensor error: "; |
jmarkel44 | 0:61364762ee0e | 407 | std::cout << left << setw(40) << setfill(' ') << controlFile; |
jmarkel44 | 0:61364762ee0e | 408 | std::cout << left << setw(20) << setfill(' ') << id; |
jmarkel44 | 0:61364762ee0e | 409 | std::cout << left << setw(6) << setfill(' ') << priority; |
jmarkel44 | 0:61364762ee0e | 410 | std::cout << left << setw(20) << setfill(' ') << input; |
jmarkel44 | 0:61364762ee0e | 411 | std::cout << left << setw(20) << setfill(' ') << output; |
jmarkel44 | 0:61364762ee0e | 412 | std::cout << left << setw(16) << setfill(' ') << mapper[currentState]; |
jmarkel44 | 0:61364762ee0e | 413 | std::cout << "duty cycle: " << left << setw(4) << setfill(' ') << dutyCycle.dutyCycle; |
jmarkel44 | 0:61364762ee0e | 414 | std::cout << "interval: " << left << setw(4) << setfill(' ') << dutyCycle.interval; |
jmarkel44 | 0:61364762ee0e | 415 | |
jmarkel44 | 0:61364762ee0e | 416 | std::cout.flush(); |
jmarkel44 | 0:61364762ee0e | 417 | } |
jmarkel44 | 0:61364762ee0e | 418 |