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/TimerControl.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: TimerControl.cpp |
jmarkel44 | 0:61364762ee0e | 4 | * Desciption: ICE Timer Control Class implementation |
jmarkel44 | 0:61364762ee0e | 5 | * |
jmarkel44 | 0:61364762ee0e | 6 | *****************************************************************************/ |
jmarkel44 | 0:61364762ee0e | 7 | #include "TimerControl.h" |
jmarkel44 | 0:61364762ee0e | 8 | #include "ModbusMasterApi.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 | #include "timerUtils.h" |
jmarkel44 | 0:61364762ee0e | 13 | #include "utilities.h" |
jmarkel44 | 0:61364762ee0e | 14 | #include <string> |
jmarkel44 | 0:61364762ee0e | 15 | #include <iostream> |
jmarkel44 | 0:61364762ee0e | 16 | #include <iomanip> |
jmarkel44 | 0:61364762ee0e | 17 | |
jmarkel44 | 0:61364762ee0e | 18 | // for debugging - this can be set via the console command: |
jmarkel44 | 0:61364762ee0e | 19 | // "debug-sp 1 or debug-sp 0 |
jmarkel44 | 0:61364762ee0e | 20 | bool debugTimerControl = false; |
jmarkel44 | 0:61364762ee0e | 21 | |
jmarkel44 | 0:61364762ee0e | 22 | static void debug(const char *fmt, ...) |
jmarkel44 | 0:61364762ee0e | 23 | { |
jmarkel44 | 0:61364762ee0e | 24 | if ( debugTimerControl ) { |
jmarkel44 | 0:61364762ee0e | 25 | va_list vargs; |
jmarkel44 | 0:61364762ee0e | 26 | va_start(vargs, fmt); |
jmarkel44 | 0:61364762ee0e | 27 | vfprintf(stdout, fmt, vargs); |
jmarkel44 | 0:61364762ee0e | 28 | va_end(vargs); |
jmarkel44 | 0:61364762ee0e | 29 | } |
jmarkel44 | 0:61364762ee0e | 30 | } |
jmarkel44 | 0:61364762ee0e | 31 | |
jmarkel44 | 0:61364762ee0e | 32 | #ifdef MDOT_ICE |
jmarkel44 | 0:61364762ee0e | 33 | extern mDot *GLOBAL_mdot; |
jmarkel44 | 0:61364762ee0e | 34 | #endif |
jmarkel44 | 0:61364762ee0e | 35 | |
jmarkel44 | 0:61364762ee0e | 36 | // |
jmarkel44 | 0:61364762ee0e | 37 | // method: load |
jmarkel44 | 0:61364762ee0e | 38 | // description: load the pertinents from the control file |
jmarkel44 | 0:61364762ee0e | 39 | // |
jmarkel44 | 0:61364762ee0e | 40 | // @param _controlFile |
jmarkel44 | 0:61364762ee0e | 41 | // @return true if loaded; false otherwise |
jmarkel44 | 0:61364762ee0e | 42 | // |
jmarkel44 | 0:61364762ee0e | 43 | bool TimerControl::load(std::string _controlFile) |
jmarkel44 | 0:61364762ee0e | 44 | { |
jmarkel44 | 0:61364762ee0e | 45 | controlFile = _controlFile; |
jmarkel44 | 0:61364762ee0e | 46 | |
jmarkel44 | 0:61364762ee0e | 47 | char dataBuf[MAX_FILE_SIZE]; |
jmarkel44 | 0:61364762ee0e | 48 | // read the control data |
jmarkel44 | 0:61364762ee0e | 49 | bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf)); |
jmarkel44 | 0:61364762ee0e | 50 | if ( rc != true ) { |
jmarkel44 | 0:61364762ee0e | 51 | logError("%s: failed to read %s", __func__, controlFile.c_str()); |
jmarkel44 | 0:61364762ee0e | 52 | return false; |
jmarkel44 | 0:61364762ee0e | 53 | } |
jmarkel44 | 0:61364762ee0e | 54 | |
jmarkel44 | 0:61364762ee0e | 55 | // validate the control data |
jmarkel44 | 0:61364762ee0e | 56 | if ( !validateControlData(dataBuf) ) { |
jmarkel44 | 0:61364762ee0e | 57 | logError("%s: failed to validate control data", __func__); |
jmarkel44 | 0:61364762ee0e | 58 | return false; |
jmarkel44 | 0:61364762ee0e | 59 | } |
jmarkel44 | 0:61364762ee0e | 60 | |
jmarkel44 | 0:61364762ee0e | 61 | // copy the control data |
jmarkel44 | 0:61364762ee0e | 62 | copyControlData(dataBuf); |
jmarkel44 | 0:61364762ee0e | 63 | |
jmarkel44 | 0:61364762ee0e | 64 | ModbusValue val; |
jmarkel44 | 0:61364762ee0e | 65 | // validate the output |
jmarkel44 | 0:61364762ee0e | 66 | if ( ModbusMasterReadRegister(output, &val) == false ) { |
jmarkel44 | 0:61364762ee0e | 67 | logError("%s failed to find %s", id.c_str(), output.c_str()); |
jmarkel44 | 0:61364762ee0e | 68 | return false; |
jmarkel44 | 0:61364762ee0e | 69 | } |
jmarkel44 | 0:61364762ee0e | 70 | |
jmarkel44 | 0:61364762ee0e | 71 | isVirtualOutput = Util_isVirtualOutput(output) ? true : false; |
jmarkel44 | 0:61364762ee0e | 72 | |
jmarkel44 | 0:61364762ee0e | 73 | return true; |
jmarkel44 | 0:61364762ee0e | 74 | |
jmarkel44 | 0:61364762ee0e | 75 | } |
jmarkel44 | 0:61364762ee0e | 76 | |
jmarkel44 | 0:61364762ee0e | 77 | // |
jmarkel44 | 0:61364762ee0e | 78 | // method: validateControlData |
jmarkel44 | 0:61364762ee0e | 79 | // description: validates the data in the control file |
jmarkel44 | 0:61364762ee0e | 80 | // |
jmarkel44 | 0:61364762ee0e | 81 | // @param[in] dataBuf -> JSON formatted string |
jmarkel44 | 0:61364762ee0e | 82 | // @param[out] non |
jmarkel44 | 0:61364762ee0e | 83 | // @return true if valid; false otherwise |
jmarkel44 | 0:61364762ee0e | 84 | // |
jmarkel44 | 0:61364762ee0e | 85 | bool TimerControl::validateControlData(const char *buf) |
jmarkel44 | 0:61364762ee0e | 86 | { |
jmarkel44 | 0:61364762ee0e | 87 | bool rc = true; |
jmarkel44 | 0:61364762ee0e | 88 | cJSON * root = cJSON_Parse(buf); |
jmarkel44 | 0:61364762ee0e | 89 | |
jmarkel44 | 0:61364762ee0e | 90 | if ( !cJSON_HasObjectItem(root, "id") || |
jmarkel44 | 0:61364762ee0e | 91 | !cJSON_HasObjectItem(root, "output") || |
jmarkel44 | 0:61364762ee0e | 92 | !cJSON_HasObjectItem(root, "priority") || |
jmarkel44 | 0:61364762ee0e | 93 | !cJSON_HasObjectItem(root, "day") || |
jmarkel44 | 0:61364762ee0e | 94 | !cJSON_HasObjectItem(root, "startHour") || |
jmarkel44 | 0:61364762ee0e | 95 | !cJSON_HasObjectItem(root, "startMin") || |
jmarkel44 | 0:61364762ee0e | 96 | !cJSON_HasObjectItem(root, "startSec") || |
jmarkel44 | 0:61364762ee0e | 97 | !cJSON_HasObjectItem(root, "duration") || |
jmarkel44 | 0:61364762ee0e | 98 | !cJSON_HasObjectItem(root, "week")) { |
jmarkel44 | 0:61364762ee0e | 99 | logError("%s: control file is missing expected tags", __func__); |
jmarkel44 | 0:61364762ee0e | 100 | rc = false; |
jmarkel44 | 0:61364762ee0e | 101 | } |
jmarkel44 | 0:61364762ee0e | 102 | cJSON_Delete(root); |
jmarkel44 | 0:61364762ee0e | 103 | return rc; |
jmarkel44 | 0:61364762ee0e | 104 | } |
jmarkel44 | 0:61364762ee0e | 105 | |
jmarkel44 | 0:61364762ee0e | 106 | // |
jmarkel44 | 0:61364762ee0e | 107 | // method: copyControlData |
jmarkel44 | 0:61364762ee0e | 108 | // description: copy JSON formatted control data to object |
jmarkel44 | 0:61364762ee0e | 109 | // |
jmarkel44 | 0:61364762ee0e | 110 | // @param[in] dataBuf -> JSON formatted data |
jmarkel44 | 0:61364762ee0e | 111 | // @param[out] none |
jmarkel44 | 0:61364762ee0e | 112 | // @return none |
jmarkel44 | 0:61364762ee0e | 113 | // |
jmarkel44 | 0:61364762ee0e | 114 | void TimerControl::copyControlData(const char *buf) |
jmarkel44 | 0:61364762ee0e | 115 | { |
jmarkel44 | 0:61364762ee0e | 116 | cJSON *root = cJSON_Parse(buf); |
jmarkel44 | 0:61364762ee0e | 117 | |
jmarkel44 | 0:61364762ee0e | 118 | id = cJSON_GetObjectItem(root,"id")->valuestring; |
jmarkel44 | 0:61364762ee0e | 119 | output = cJSON_GetObjectItem(root, "output")->valuestring; |
jmarkel44 | 0:61364762ee0e | 120 | priority = (unsigned int)atoi(cJSON_GetObjectItem(root, "priority")->valuestring); |
jmarkel44 | 0:61364762ee0e | 121 | std::string day_str = cJSON_GetObjectItem(root, "day")->valuestring; |
jmarkel44 | 0:61364762ee0e | 122 | |
jmarkel44 | 0:61364762ee0e | 123 | if ( day_str == "sun" ) { |
jmarkel44 | 0:61364762ee0e | 124 | day = DAY_SCHEDULE_SUNDAY_MASK; |
jmarkel44 | 0:61364762ee0e | 125 | } else if ( day_str == "mon" ) { |
jmarkel44 | 0:61364762ee0e | 126 | day = DAY_SCHEDULE_MONDAY_MASK; |
jmarkel44 | 0:61364762ee0e | 127 | } else if ( day_str == "tue" ) { |
jmarkel44 | 0:61364762ee0e | 128 | day = DAY_SCHEDULE_TUESDAY_MASK; |
jmarkel44 | 0:61364762ee0e | 129 | } else if ( day_str == "wed" ) { |
jmarkel44 | 0:61364762ee0e | 130 | day = DAY_SCHEDULE_WEDNESDAY_MASK; |
jmarkel44 | 0:61364762ee0e | 131 | } else if ( day_str == "thu" ) { |
jmarkel44 | 0:61364762ee0e | 132 | day = DAY_SCHEDULE_THURSDAY_MASK; |
jmarkel44 | 0:61364762ee0e | 133 | } else if ( day_str == "fri" ) { |
jmarkel44 | 0:61364762ee0e | 134 | day = DAY_SCHEDULE_FRIDAY_MASK; |
jmarkel44 | 0:61364762ee0e | 135 | } else if ( day_str == "sat" ) { |
jmarkel44 | 0:61364762ee0e | 136 | day = DAY_SCHEDULE_SATURDAY_MASK; |
jmarkel44 | 0:61364762ee0e | 137 | } else { |
jmarkel44 | 0:61364762ee0e | 138 | debug("\r%s:%s-> one-shot timer found\n", __func__, id.c_str()); |
jmarkel44 | 0:61364762ee0e | 139 | day = DAY_SCHEDULE_NOT_SPECIFIED; // one-shot timer |
jmarkel44 | 0:61364762ee0e | 140 | } |
jmarkel44 | 0:61364762ee0e | 141 | |
jmarkel44 | 0:61364762ee0e | 142 | startHour = atoi(cJSON_GetObjectItem(root, "startHour")->valuestring); |
jmarkel44 | 0:61364762ee0e | 143 | startMin = atoi(cJSON_GetObjectItem(root, "startMin")->valuestring); |
jmarkel44 | 0:61364762ee0e | 144 | startSec = atoi(cJSON_GetObjectItem(root, "startSec")->valuestring); |
jmarkel44 | 0:61364762ee0e | 145 | duration = atoi(cJSON_GetObjectItem(root, "duration")->valuestring); |
jmarkel44 | 0:61364762ee0e | 146 | |
jmarkel44 | 0:61364762ee0e | 147 | std::string week_str = cJSON_GetObjectItem(root, "week")->valuestring; |
jmarkel44 | 0:61364762ee0e | 148 | if ( week_str == "every" ) { |
jmarkel44 | 0:61364762ee0e | 149 | week = WEEKLY_CHOICE_EVERY_WEEK; |
jmarkel44 | 0:61364762ee0e | 150 | } else if ( week_str == "first" ) { |
jmarkel44 | 0:61364762ee0e | 151 | week = WEEKLY_CHOICE_FIRST_WEEK; |
jmarkel44 | 0:61364762ee0e | 152 | } else if ( week_str == "second" ) { |
jmarkel44 | 0:61364762ee0e | 153 | week = WEEKLY_CHOICE_SECOND_WEEK; |
jmarkel44 | 0:61364762ee0e | 154 | } else if ( week_str == "third" ) { |
jmarkel44 | 0:61364762ee0e | 155 | week = WEEKLY_CHOICE_THIRD_WEEK; |
jmarkel44 | 0:61364762ee0e | 156 | } else if ( week_str == "fourth" ) { |
jmarkel44 | 0:61364762ee0e | 157 | week = WEEKLY_CHOICE_FOURTH_WEEK; |
jmarkel44 | 0:61364762ee0e | 158 | } else if ( week_str == "last" ) { |
jmarkel44 | 0:61364762ee0e | 159 | week = WEEKLY_CHOICE_LAST_WEEK; |
jmarkel44 | 0:61364762ee0e | 160 | } else if ( week_str == "everyother") { |
jmarkel44 | 0:61364762ee0e | 161 | week = WEEKLY_CHOICE_EVERYOTHER_WEEK; |
jmarkel44 | 0:61364762ee0e | 162 | } else { |
jmarkel44 | 0:61364762ee0e | 163 | week = WEEKLY_CHOICE_NOT_SPECIFIED; // one-shot timer |
jmarkel44 | 0:61364762ee0e | 164 | } |
jmarkel44 | 0:61364762ee0e | 165 | |
jmarkel44 | 0:61364762ee0e | 166 | cJSON_Delete(root); |
jmarkel44 | 0:61364762ee0e | 167 | } |
jmarkel44 | 0:61364762ee0e | 168 | |
jmarkel44 | 0:61364762ee0e | 169 | // |
jmarkel44 | 0:61364762ee0e | 170 | // method: start |
jmarkel44 | 0:61364762ee0e | 171 | // description: initialize the control |
jmarkel44 | 0:61364762ee0e | 172 | // |
jmarkel44 | 0:61364762ee0e | 173 | // @param none |
jmarkel44 | 0:61364762ee0e | 174 | // @return none |
jmarkel44 | 0:61364762ee0e | 175 | // |
jmarkel44 | 0:61364762ee0e | 176 | void TimerControl::start(void) |
jmarkel44 | 0:61364762ee0e | 177 | { |
jmarkel44 | 0:61364762ee0e | 178 | // calculate the next scheduled start time |
jmarkel44 | 0:61364762ee0e | 179 | if ( day == DAY_SCHEDULE_NOT_SPECIFIED ) { |
jmarkel44 | 0:61364762ee0e | 180 | // start running right away |
jmarkel44 | 0:61364762ee0e | 181 | nextScheduledStartTime = time(0); |
jmarkel44 | 0:61364762ee0e | 182 | debug("\r%s: %s is a one-shot timer.\n", __func__, id.c_str()); |
jmarkel44 | 0:61364762ee0e | 183 | } else { |
jmarkel44 | 0:61364762ee0e | 184 | nextScheduledStartTime = time(0) + calcStartTime(); |
jmarkel44 | 0:61364762ee0e | 185 | } |
jmarkel44 | 0:61364762ee0e | 186 | struct tm * timeinfo; |
jmarkel44 | 0:61364762ee0e | 187 | timeinfo = localtime((time_t*)&nextScheduledStartTime); |
jmarkel44 | 0:61364762ee0e | 188 | debug("Timer %s started, begins at %s", this->id.c_str(), asctime(timeinfo)); |
jmarkel44 | 0:61364762ee0e | 189 | |
jmarkel44 | 0:61364762ee0e | 190 | currentState = STATE_OFF; |
jmarkel44 | 0:61364762ee0e | 191 | } |
jmarkel44 | 0:61364762ee0e | 192 | |
jmarkel44 | 0:61364762ee0e | 193 | // |
jmarkel44 | 0:61364762ee0e | 194 | // method: update |
jmarkel44 | 0:61364762ee0e | 195 | // description: run the state machine |
jmarkel44 | 0:61364762ee0e | 196 | // |
jmarkel44 | 0:61364762ee0e | 197 | // @param none |
jmarkel44 | 0:61364762ee0e | 198 | // @return OK on success; error otherwise |
jmarkel44 | 0:61364762ee0e | 199 | // |
jmarkel44 | 0:61364762ee0e | 200 | TimerControlError_t TimerControl::update(void) |
jmarkel44 | 0:61364762ee0e | 201 | { |
jmarkel44 | 0:61364762ee0e | 202 | TimerControlError_t rc = TIMER_CONTROL_OK; |
jmarkel44 | 0:61364762ee0e | 203 | |
jmarkel44 | 0:61364762ee0e | 204 | unsigned long currentTime = time(0); |
jmarkel44 | 0:61364762ee0e | 205 | |
jmarkel44 | 0:61364762ee0e | 206 | switch ( this->currentState ) { |
jmarkel44 | 0:61364762ee0e | 207 | case STATE_INIT: |
jmarkel44 | 0:61364762ee0e | 208 | // do nothing; timer is waiting for start signal |
jmarkel44 | 0:61364762ee0e | 209 | break; |
jmarkel44 | 0:61364762ee0e | 210 | case STATE_OFF: { |
jmarkel44 | 0:61364762ee0e | 211 | if ( currentTime >= nextScheduledStartTime && |
jmarkel44 | 0:61364762ee0e | 212 | currentTime <= nextScheduledStartTime + duration ) { |
jmarkel44 | 0:61364762ee0e | 213 | currentState = STATE_RUNNING; |
jmarkel44 | 0:61364762ee0e | 214 | this->startFeed(); |
jmarkel44 | 0:61364762ee0e | 215 | startTime = currentTime; // record the actual start time |
jmarkel44 | 0:61364762ee0e | 216 | debug("\r%s: [OFF]->in timing window->[RUNNING] %s\n", id.c_str(), displayTime()); |
jmarkel44 | 0:61364762ee0e | 217 | } |
jmarkel44 | 0:61364762ee0e | 218 | break; |
jmarkel44 | 0:61364762ee0e | 219 | } |
jmarkel44 | 0:61364762ee0e | 220 | case STATE_RUNNING: |
jmarkel44 | 0:61364762ee0e | 221 | if ( currentTime >= startTime + duration ) { |
jmarkel44 | 0:61364762ee0e | 222 | this->stopFeed(); |
jmarkel44 | 0:61364762ee0e | 223 | currentState = STATE_FINISHED; |
jmarkel44 | 0:61364762ee0e | 224 | debug("\r%s: [RUNNING]->time elapsed->[OFF] %s\n", id.c_str(), displayTime()); |
jmarkel44 | 0:61364762ee0e | 225 | } |
jmarkel44 | 0:61364762ee0e | 226 | break; |
jmarkel44 | 0:61364762ee0e | 227 | case STATE_FINISHED: |
jmarkel44 | 0:61364762ee0e | 228 | if ( day == DAY_SCHEDULE_NOT_SPECIFIED || week == WEEKLY_CHOICE_NOT_SPECIFIED ) { |
jmarkel44 | 0:61364762ee0e | 229 | // one shot-timer, just disable it. |
jmarkel44 | 0:61364762ee0e | 230 | nextScheduledStartTime = 0; |
jmarkel44 | 0:61364762ee0e | 231 | startTime = 0; |
jmarkel44 | 0:61364762ee0e | 232 | currentState = STATE_DISABLED; |
jmarkel44 | 0:61364762ee0e | 233 | debug("\r%s: [FINISHED]->one shot timer->[DISABLED] %s\n", id.c_str(), displayTime()); |
jmarkel44 | 0:61364762ee0e | 234 | } else { |
jmarkel44 | 0:61364762ee0e | 235 | // calculate the next scheduled start time |
jmarkel44 | 0:61364762ee0e | 236 | nextScheduledStartTime = time(0) + calcStartTime(); |
jmarkel44 | 0:61364762ee0e | 237 | startTime = 0; |
jmarkel44 | 0:61364762ee0e | 238 | // unregister with the output task |
jmarkel44 | 0:61364762ee0e | 239 | currentState = STATE_OFF; |
jmarkel44 | 0:61364762ee0e | 240 | debug("\r%s: [FINISHED]->time elapsed->[OFF] %s\n", id.c_str(), displayTime()); |
jmarkel44 | 0:61364762ee0e | 241 | } |
jmarkel44 | 0:61364762ee0e | 242 | this->unregisterControl(); |
jmarkel44 | 0:61364762ee0e | 243 | break; |
jmarkel44 | 0:61364762ee0e | 244 | case STATE_DISABLED: |
jmarkel44 | 0:61364762ee0e | 245 | // do nothing |
jmarkel44 | 0:61364762ee0e | 246 | break; |
jmarkel44 | 0:61364762ee0e | 247 | default: |
jmarkel44 | 0:61364762ee0e | 248 | logError("%s: unknown state %d", __func__, this->currentState); |
jmarkel44 | 0:61364762ee0e | 249 | rc = TIMER_CONTROL_UNK_STATE; |
jmarkel44 | 0:61364762ee0e | 250 | break; |
jmarkel44 | 0:61364762ee0e | 251 | } |
jmarkel44 | 0:61364762ee0e | 252 | return rc; |
jmarkel44 | 0:61364762ee0e | 253 | } |
jmarkel44 | 0:61364762ee0e | 254 | |
jmarkel44 | 0:61364762ee0e | 255 | // |
jmarkel44 | 0:61364762ee0e | 256 | // method: startFeed |
jmarkel44 | 0:61364762ee0e | 257 | // description: signal the output thread to start a feed |
jmarkel44 | 0:61364762ee0e | 258 | // |
jmarkel44 | 0:61364762ee0e | 259 | // @param none |
jmarkel44 | 0:61364762ee0e | 260 | // @return none |
jmarkel44 | 0:61364762ee0e | 261 | void TimerControl::startFeed(void) |
jmarkel44 | 0:61364762ee0e | 262 | { |
jmarkel44 | 0:61364762ee0e | 263 | logInfo("%s: %s attempting to start feed on relay %s\n", |
jmarkel44 | 0:61364762ee0e | 264 | __func__, controlFile.c_str(), output.c_str()); |
jmarkel44 | 0:61364762ee0e | 265 | |
jmarkel44 | 0:61364762ee0e | 266 | if ( isVirtualOutput ) { |
jmarkel44 | 0:61364762ee0e | 267 | // write to the virtual register map |
jmarkel44 | 0:61364762ee0e | 268 | ModbusMasterWriteRegister(output, 1.0); |
jmarkel44 | 0:61364762ee0e | 269 | } else { |
jmarkel44 | 0:61364762ee0e | 270 | // send a message to the output thread |
jmarkel44 | 0:61364762ee0e | 271 | OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); |
jmarkel44 | 0:61364762ee0e | 272 | memset(output_mail, 0, sizeof(OutputControlMsg_t)); |
jmarkel44 | 0:61364762ee0e | 273 | |
jmarkel44 | 0:61364762ee0e | 274 | output_mail->action = ACTION_CONTROL_ON; |
jmarkel44 | 0:61364762ee0e | 275 | output_mail->controlType = CONTROL_TIMER; |
jmarkel44 | 0:61364762ee0e | 276 | output_mail->priority = priority; |
jmarkel44 | 0:61364762ee0e | 277 | |
jmarkel44 | 0:61364762ee0e | 278 | strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); |
jmarkel44 | 0:61364762ee0e | 279 | strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); |
jmarkel44 | 0:61364762ee0e | 280 | OutputMasterMailBox.put(output_mail); |
jmarkel44 | 0:61364762ee0e | 281 | } |
jmarkel44 | 0:61364762ee0e | 282 | } |
jmarkel44 | 0:61364762ee0e | 283 | |
jmarkel44 | 0:61364762ee0e | 284 | // |
jmarkel44 | 0:61364762ee0e | 285 | // method: stopFeed |
jmarkel44 | 0:61364762ee0e | 286 | // description: signal the output thread to stop a feed |
jmarkel44 | 0:61364762ee0e | 287 | // |
jmarkel44 | 0:61364762ee0e | 288 | // @param none |
jmarkel44 | 0:61364762ee0e | 289 | // @return none |
jmarkel44 | 0:61364762ee0e | 290 | // |
jmarkel44 | 0:61364762ee0e | 291 | void TimerControl::stopFeed(void) |
jmarkel44 | 0:61364762ee0e | 292 | { |
jmarkel44 | 0:61364762ee0e | 293 | logInfo("%s: %s attempting to start feed on relay %s\n", |
jmarkel44 | 0:61364762ee0e | 294 | __func__, controlFile.c_str(), output.c_str()); |
jmarkel44 | 0:61364762ee0e | 295 | |
jmarkel44 | 0:61364762ee0e | 296 | if ( isVirtualOutput ) { |
jmarkel44 | 0:61364762ee0e | 297 | // write to the virtual register map |
jmarkel44 | 0:61364762ee0e | 298 | ModbusMasterWriteRegister(output, 0.0); |
jmarkel44 | 0:61364762ee0e | 299 | } else { |
jmarkel44 | 0:61364762ee0e | 300 | // send a message to the output thread |
jmarkel44 | 0:61364762ee0e | 301 | OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); |
jmarkel44 | 0:61364762ee0e | 302 | memset(output_mail, 0, sizeof(OutputControlMsg_t)); |
jmarkel44 | 0:61364762ee0e | 303 | |
jmarkel44 | 0:61364762ee0e | 304 | output_mail->action = ACTION_CONTROL_OFF; |
jmarkel44 | 0:61364762ee0e | 305 | output_mail->controlType = CONTROL_TIMER; |
jmarkel44 | 0:61364762ee0e | 306 | output_mail->priority = priority; |
jmarkel44 | 0:61364762ee0e | 307 | |
jmarkel44 | 0:61364762ee0e | 308 | strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); |
jmarkel44 | 0:61364762ee0e | 309 | strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); |
jmarkel44 | 0:61364762ee0e | 310 | OutputMasterMailBox.put(output_mail); |
jmarkel44 | 0:61364762ee0e | 311 | } |
jmarkel44 | 0:61364762ee0e | 312 | } |
jmarkel44 | 0:61364762ee0e | 313 | |
jmarkel44 | 0:61364762ee0e | 314 | // |
jmarkel44 | 0:61364762ee0e | 315 | // method: unregisterControl |
jmarkel44 | 0:61364762ee0e | 316 | // description: send OFF indication to Output Master for this control's |
jmarkel44 | 0:61364762ee0e | 317 | // relay |
jmarkel44 | 0:61364762ee0e | 318 | // |
jmarkel44 | 0:61364762ee0e | 319 | // @param none |
jmarkel44 | 0:61364762ee0e | 320 | // @return none |
jmarkel44 | 0:61364762ee0e | 321 | // |
jmarkel44 | 0:61364762ee0e | 322 | void TimerControl::unregisterControl(void) |
jmarkel44 | 0:61364762ee0e | 323 | { |
jmarkel44 | 0:61364762ee0e | 324 | logInfo("%s: %s attempting to unregister %s\n", |
jmarkel44 | 0:61364762ee0e | 325 | __func__, id.c_str(), controlFile.c_str()); |
jmarkel44 | 0:61364762ee0e | 326 | |
jmarkel44 | 0:61364762ee0e | 327 | if ( isVirtualOutput ) { |
jmarkel44 | 0:61364762ee0e | 328 | ModbusMasterWriteRegister(output, 0.0); |
jmarkel44 | 0:61364762ee0e | 329 | } else { |
jmarkel44 | 0:61364762ee0e | 330 | |
jmarkel44 | 0:61364762ee0e | 331 | OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); |
jmarkel44 | 0:61364762ee0e | 332 | memset(output_mail, 0, sizeof(OutputControlMsg_t)); |
jmarkel44 | 0:61364762ee0e | 333 | |
jmarkel44 | 0:61364762ee0e | 334 | output_mail->action = ACTION_CONTROL_UNREGISTER; |
jmarkel44 | 0:61364762ee0e | 335 | output_mail->controlType = CONTROL_TIMER; |
jmarkel44 | 0:61364762ee0e | 336 | output_mail->priority = priority; |
jmarkel44 | 0:61364762ee0e | 337 | strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); |
jmarkel44 | 0:61364762ee0e | 338 | strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); |
jmarkel44 | 0:61364762ee0e | 339 | |
jmarkel44 | 0:61364762ee0e | 340 | OutputMasterMailBox.put(output_mail); |
jmarkel44 | 0:61364762ee0e | 341 | } |
jmarkel44 | 0:61364762ee0e | 342 | } |
jmarkel44 | 0:61364762ee0e | 343 | |
jmarkel44 | 0:61364762ee0e | 344 | // |
jmarkel44 | 0:61364762ee0e | 345 | // method: calcStarTime |
jmarkel44 | 0:61364762ee0e | 346 | // description: calculate the number of seconds until the next |
jmarkel44 | 0:61364762ee0e | 347 | // timer starts. |
jmarkel44 | 0:61364762ee0e | 348 | // |
jmarkel44 | 0:61364762ee0e | 349 | // @param[in] none |
jmarkel44 | 0:61364762ee0e | 350 | // @param[out] none |
jmarkel44 | 0:61364762ee0e | 351 | // @return none |
jmarkel44 | 0:61364762ee0e | 352 | // |
jmarkel44 | 0:61364762ee0e | 353 | unsigned long TimerControl::calcStartTime(void) const |
jmarkel44 | 0:61364762ee0e | 354 | { |
jmarkel44 | 0:61364762ee0e | 355 | TSC_SCHED_ELEM schedTimeDate; |
jmarkel44 | 0:61364762ee0e | 356 | TSC_SCHED_ELEM pNowTimeDate; |
jmarkel44 | 0:61364762ee0e | 357 | unsigned long pDiffInSeconds; |
jmarkel44 | 0:61364762ee0e | 358 | CNTL_HR_MIN_STRUCT startTime; |
jmarkel44 | 0:61364762ee0e | 359 | |
jmarkel44 | 0:61364762ee0e | 360 | startTime.hour = startHour; |
jmarkel44 | 0:61364762ee0e | 361 | startTime.minute = startMin; |
jmarkel44 | 0:61364762ee0e | 362 | startTime.second = startSec; |
jmarkel44 | 0:61364762ee0e | 363 | |
jmarkel44 | 0:61364762ee0e | 364 | pNowTimeDate.calTime = time( NULL ); |
jmarkel44 | 0:61364762ee0e | 365 | localtime_r( &pNowTimeDate.calTime, &pNowTimeDate.requestTime ); |
jmarkel44 | 0:61364762ee0e | 366 | |
jmarkel44 | 0:61364762ee0e | 367 | pNowTimeDate.schedule.startDate.year = pNowTimeDate.requestTime.tm_year - 100; /* years since 1900 */ |
jmarkel44 | 0:61364762ee0e | 368 | pNowTimeDate.schedule.startDate.year += 2000; |
jmarkel44 | 0:61364762ee0e | 369 | pNowTimeDate.schedule.startDate.month = pNowTimeDate.requestTime.tm_mon + 1; /* months 1 - 12 */ |
jmarkel44 | 0:61364762ee0e | 370 | pNowTimeDate.schedule.startDate.day = pNowTimeDate.requestTime.tm_mday; |
jmarkel44 | 0:61364762ee0e | 371 | pNowTimeDate.schedule.startTime.hour = pNowTimeDate.requestTime.tm_hour; |
jmarkel44 | 0:61364762ee0e | 372 | pNowTimeDate.schedule.startTime.minute = pNowTimeDate.requestTime.tm_min; |
jmarkel44 | 0:61364762ee0e | 373 | pNowTimeDate.schedule.startTime.second = pNowTimeDate.requestTime.tm_sec; |
jmarkel44 | 0:61364762ee0e | 374 | |
jmarkel44 | 0:61364762ee0e | 375 | /* setup schedTimeDate with the current date, time and the required schedule */ |
jmarkel44 | 0:61364762ee0e | 376 | schedTimeDate.schedule.startDate = pNowTimeDate.schedule.startDate; |
jmarkel44 | 0:61364762ee0e | 377 | schedTimeDate.schedule.startTime = startTime; |
jmarkel44 | 0:61364762ee0e | 378 | schedTimeDate.schedule.dailySchedule = day; |
jmarkel44 | 0:61364762ee0e | 379 | schedTimeDate.schedule.weeklySchedule = (WEEKLY_CHOICES)week; |
jmarkel44 | 0:61364762ee0e | 380 | schedTimeDate.calTime = pNowTimeDate.calTime; |
jmarkel44 | 0:61364762ee0e | 381 | schedTimeDate.requestTime = pNowTimeDate.requestTime; |
jmarkel44 | 0:61364762ee0e | 382 | |
jmarkel44 | 0:61364762ee0e | 383 | TSCutilComputeStartDate( &schedTimeDate ); |
jmarkel44 | 0:61364762ee0e | 384 | Util_dateTimeDiff( &pNowTimeDate.schedule, &schedTimeDate.schedule, &pDiffInSeconds ); |
jmarkel44 | 0:61364762ee0e | 385 | |
jmarkel44 | 0:61364762ee0e | 386 | return pDiffInSeconds; |
jmarkel44 | 0:61364762ee0e | 387 | } |
jmarkel44 | 0:61364762ee0e | 388 | |
jmarkel44 | 0:61364762ee0e | 389 | const char* TimerControl::displayTime(void) |
jmarkel44 | 0:61364762ee0e | 390 | { |
jmarkel44 | 0:61364762ee0e | 391 | struct tm * timeinfo; |
jmarkel44 | 0:61364762ee0e | 392 | time_t currentTime = time(0); |
jmarkel44 | 0:61364762ee0e | 393 | timeinfo = localtime(¤tTime); |
jmarkel44 | 0:61364762ee0e | 394 | return asctime(timeinfo); |
jmarkel44 | 0:61364762ee0e | 395 | } |
jmarkel44 | 0:61364762ee0e | 396 | |
jmarkel44 | 0:61364762ee0e | 397 | // |
jmarkel44 | 0:61364762ee0e | 398 | // method: display |
jmarkel44 | 0:61364762ee0e | 399 | // description: display the elements of this timer control object |
jmarkel44 | 0:61364762ee0e | 400 | // |
jmarkel44 | 0:61364762ee0e | 401 | // @param none |
jmarkel44 | 0:61364762ee0e | 402 | // @return none |
jmarkel44 | 0:61364762ee0e | 403 | // |
jmarkel44 | 0:61364762ee0e | 404 | void TimerControl::display(void) |
jmarkel44 | 0:61364762ee0e | 405 | { |
jmarkel44 | 0:61364762ee0e | 406 | string mapper[] = { "INIT", |
jmarkel44 | 0:61364762ee0e | 407 | "OFF", |
jmarkel44 | 0:61364762ee0e | 408 | "RUNNING", |
jmarkel44 | 0:61364762ee0e | 409 | "FINISHED", |
jmarkel44 | 0:61364762ee0e | 410 | "DISABLED" |
jmarkel44 | 0:61364762ee0e | 411 | }; |
jmarkel44 | 0:61364762ee0e | 412 | |
jmarkel44 | 0:61364762ee0e | 413 | printf("\r\n"); |
jmarkel44 | 0:61364762ee0e | 414 | std::string day_str; |
jmarkel44 | 0:61364762ee0e | 415 | if ( day == DAY_SCHEDULE_SUNDAY_MASK ) { |
jmarkel44 | 0:61364762ee0e | 416 | day_str = "Sun"; |
jmarkel44 | 0:61364762ee0e | 417 | } else if ( day == DAY_SCHEDULE_MONDAY_MASK ) { |
jmarkel44 | 0:61364762ee0e | 418 | day_str = "Mon"; |
jmarkel44 | 0:61364762ee0e | 419 | } else if ( day == DAY_SCHEDULE_TUESDAY_MASK ) { |
jmarkel44 | 0:61364762ee0e | 420 | day_str = "Tue"; |
jmarkel44 | 0:61364762ee0e | 421 | } else if ( day == DAY_SCHEDULE_WEDNESDAY_MASK ) { |
jmarkel44 | 0:61364762ee0e | 422 | day_str = "Wed"; |
jmarkel44 | 0:61364762ee0e | 423 | } else if ( day == DAY_SCHEDULE_THURSDAY_MASK ) { |
jmarkel44 | 0:61364762ee0e | 424 | day_str = "Thu"; |
jmarkel44 | 0:61364762ee0e | 425 | } else if ( day == DAY_SCHEDULE_FRIDAY_MASK ) { |
jmarkel44 | 0:61364762ee0e | 426 | day_str = "Fri"; |
jmarkel44 | 0:61364762ee0e | 427 | } else if ( day == DAY_SCHEDULE_SATURDAY_MASK ) { |
jmarkel44 | 0:61364762ee0e | 428 | day_str = "Sat"; |
jmarkel44 | 0:61364762ee0e | 429 | } |
jmarkel44 | 0:61364762ee0e | 430 | std::string week_str; |
jmarkel44 | 0:61364762ee0e | 431 | if ( week == WEEKLY_CHOICE_EVERY_WEEK ) { |
jmarkel44 | 0:61364762ee0e | 432 | week_str = "every"; |
jmarkel44 | 0:61364762ee0e | 433 | } else if ( week == WEEKLY_CHOICE_FIRST_WEEK ) { |
jmarkel44 | 0:61364762ee0e | 434 | week_str = "first"; |
jmarkel44 | 0:61364762ee0e | 435 | } else if ( week == WEEKLY_CHOICE_SECOND_WEEK ) { |
jmarkel44 | 0:61364762ee0e | 436 | week_str = "second"; |
jmarkel44 | 0:61364762ee0e | 437 | } else if ( week == WEEKLY_CHOICE_THIRD_WEEK ) { |
jmarkel44 | 0:61364762ee0e | 438 | week_str = "third"; |
jmarkel44 | 0:61364762ee0e | 439 | } else if ( week == WEEKLY_CHOICE_FOURTH_WEEK ) { |
jmarkel44 | 0:61364762ee0e | 440 | week_str = "fourth"; |
jmarkel44 | 0:61364762ee0e | 441 | } else if ( week == WEEKLY_CHOICE_LAST_WEEK ) { |
jmarkel44 | 0:61364762ee0e | 442 | week_str = "last"; |
jmarkel44 | 0:61364762ee0e | 443 | } else if ( week == WEEKLY_CHOICE_EVERYOTHER_WEEK ) { |
jmarkel44 | 0:61364762ee0e | 444 | week_str = "everyother"; |
jmarkel44 | 0:61364762ee0e | 445 | } |
jmarkel44 | 0:61364762ee0e | 446 | |
jmarkel44 | 0:61364762ee0e | 447 | char time_str[12]; |
jmarkel44 | 0:61364762ee0e | 448 | snprintf(time_str, sizeof(time_str), "%02d:%02d:%02d", startHour, startMin, startSec); |
jmarkel44 | 0:61364762ee0e | 449 | |
jmarkel44 | 0:61364762ee0e | 450 | cout << left << setw(8) << setfill(' ') << "timer:"; |
jmarkel44 | 0:61364762ee0e | 451 | cout << left << setw(32) << setfill(' ') << controlFile; |
jmarkel44 | 0:61364762ee0e | 452 | cout << left << setw(12) << setfill(' ') << id; |
jmarkel44 | 0:61364762ee0e | 453 | cout << "output: " << left << setw(16) << setfill(' ') << output; |
jmarkel44 | 0:61364762ee0e | 454 | cout << left << setw(6) << setfill(' ') << priority; |
jmarkel44 | 0:61364762ee0e | 455 | cout << "(" << setw(12) << week_str << ")" << day_str << "-> "; |
jmarkel44 | 0:61364762ee0e | 456 | cout << left << setw(12) << setfill(' ') << time_str; |
jmarkel44 | 0:61364762ee0e | 457 | cout << left << setw(10) << "duration: " << left << setw(6) << setfill(' ') << duration; |
jmarkel44 | 0:61364762ee0e | 458 | cout << left << setw(10) << setfill(' ') << mapper[currentState]; |
jmarkel44 | 0:61364762ee0e | 459 | if ( currentState == STATE_RUNNING ) { |
jmarkel44 | 0:61364762ee0e | 460 | cout << left << setw(11) << setfill(' ') << "ends in: " << (startTime + duration) - time(NULL) << " seconds "; |
jmarkel44 | 0:61364762ee0e | 461 | } else if ( currentState == STATE_FINISHED || currentState == STATE_DISABLED ) { |
jmarkel44 | 0:61364762ee0e | 462 | // show nothing |
jmarkel44 | 0:61364762ee0e | 463 | } else { |
jmarkel44 | 0:61364762ee0e | 464 | cout << left << setw(11) << setfill(' ') << "starts in: " << calcStartTime() << " seconds "; |
jmarkel44 | 0:61364762ee0e | 465 | } |
jmarkel44 | 0:61364762ee0e | 466 | cout.flush(); |
jmarkel44 | 0:61364762ee0e | 467 | } |