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.
Diff: ICE-Application/src/ConfigurationHandler/Controls/TimerControl.cpp
- Revision:
- 2:02cb20446785
- Parent:
- 1:b2e90cda7a5a
--- a/ICE-Application/src/ConfigurationHandler/Controls/TimerControl.cpp Tue Jan 24 19:06:45 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,467 +0,0 @@ -/****************************************************************************** - * - * File: TimerControl.cpp - * Desciption: ICE Timer Control Class implementation - * - *****************************************************************************/ -#include "TimerControl.h" -#include "ModbusMasterApi.h" -#include "ICELog.h" -#include "cJSON.h" -#include "global.h" -#include "timerUtils.h" -#include "utilities.h" -#include <string> -#include <iostream> -#include <iomanip> - -// for debugging - this can be set via the console command: -// "debug-sp 1 or debug-sp 0 -bool debugTimerControl = false; - -static void debug(const char *fmt, ...) -{ - if ( debugTimerControl ) { - va_list vargs; - va_start(vargs, fmt); - vfprintf(stdout, fmt, vargs); - va_end(vargs); - } -} - -#ifdef MDOT_ICE -extern mDot *GLOBAL_mdot; -#endif - -// -// method: load -// description: load the pertinents from the control file -// -// @param _controlFile -// @return true if loaded; false otherwise -// -bool TimerControl::load(std::string _controlFile) -{ - controlFile = _controlFile; - - char dataBuf[MAX_FILE_SIZE]; - // read the control data - bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf)); - if ( rc != true ) { - logError("%s: failed to read %s", __func__, controlFile.c_str()); - return false; - } - - // validate the control data - if ( !validateControlData(dataBuf) ) { - logError("%s: failed to validate control data", __func__); - return false; - } - - // copy the control data - copyControlData(dataBuf); - - ModbusValue val; - // validate the output - if ( ModbusMasterReadRegister(output, &val) == false ) { - logError("%s failed to find %s", id.c_str(), output.c_str()); - return false; - } - - isVirtualOutput = Util_isVirtualOutput(output) ? true : false; - - return true; - -} - -// -// method: validateControlData -// description: validates the data in the control file -// -// @param[in] dataBuf -> JSON formatted string -// @param[out] non -// @return true if valid; false otherwise -// -bool TimerControl::validateControlData(const char *buf) -{ - bool rc = true; - cJSON * root = cJSON_Parse(buf); - - if ( !cJSON_HasObjectItem(root, "id") || - !cJSON_HasObjectItem(root, "output") || - !cJSON_HasObjectItem(root, "priority") || - !cJSON_HasObjectItem(root, "day") || - !cJSON_HasObjectItem(root, "startHour") || - !cJSON_HasObjectItem(root, "startMin") || - !cJSON_HasObjectItem(root, "startSec") || - !cJSON_HasObjectItem(root, "duration") || - !cJSON_HasObjectItem(root, "week")) { - logError("%s: control file is missing expected tags", __func__); - rc = false; - } - cJSON_Delete(root); - return rc; -} - -// -// method: copyControlData -// description: copy JSON formatted control data to object -// -// @param[in] dataBuf -> JSON formatted data -// @param[out] none -// @return none -// -void TimerControl::copyControlData(const char *buf) -{ - cJSON *root = cJSON_Parse(buf); - - id = cJSON_GetObjectItem(root,"id")->valuestring; - output = cJSON_GetObjectItem(root, "output")->valuestring; - priority = (unsigned int)atoi(cJSON_GetObjectItem(root, "priority")->valuestring); - std::string day_str = cJSON_GetObjectItem(root, "day")->valuestring; - - if ( day_str == "sun" ) { - day = DAY_SCHEDULE_SUNDAY_MASK; - } else if ( day_str == "mon" ) { - day = DAY_SCHEDULE_MONDAY_MASK; - } else if ( day_str == "tue" ) { - day = DAY_SCHEDULE_TUESDAY_MASK; - } else if ( day_str == "wed" ) { - day = DAY_SCHEDULE_WEDNESDAY_MASK; - } else if ( day_str == "thu" ) { - day = DAY_SCHEDULE_THURSDAY_MASK; - } else if ( day_str == "fri" ) { - day = DAY_SCHEDULE_FRIDAY_MASK; - } else if ( day_str == "sat" ) { - day = DAY_SCHEDULE_SATURDAY_MASK; - } else { - debug("\r%s:%s-> one-shot timer found\n", __func__, id.c_str()); - day = DAY_SCHEDULE_NOT_SPECIFIED; // one-shot timer - } - - startHour = atoi(cJSON_GetObjectItem(root, "startHour")->valuestring); - startMin = atoi(cJSON_GetObjectItem(root, "startMin")->valuestring); - startSec = atoi(cJSON_GetObjectItem(root, "startSec")->valuestring); - duration = atoi(cJSON_GetObjectItem(root, "duration")->valuestring); - - std::string week_str = cJSON_GetObjectItem(root, "week")->valuestring; - if ( week_str == "every" ) { - week = WEEKLY_CHOICE_EVERY_WEEK; - } else if ( week_str == "first" ) { - week = WEEKLY_CHOICE_FIRST_WEEK; - } else if ( week_str == "second" ) { - week = WEEKLY_CHOICE_SECOND_WEEK; - } else if ( week_str == "third" ) { - week = WEEKLY_CHOICE_THIRD_WEEK; - } else if ( week_str == "fourth" ) { - week = WEEKLY_CHOICE_FOURTH_WEEK; - } else if ( week_str == "last" ) { - week = WEEKLY_CHOICE_LAST_WEEK; - } else if ( week_str == "everyother") { - week = WEEKLY_CHOICE_EVERYOTHER_WEEK; - } else { - week = WEEKLY_CHOICE_NOT_SPECIFIED; // one-shot timer - } - - cJSON_Delete(root); -} - -// -// method: start -// description: initialize the control -// -// @param none -// @return none -// -void TimerControl::start(void) -{ - // calculate the next scheduled start time - if ( day == DAY_SCHEDULE_NOT_SPECIFIED ) { - // start running right away - nextScheduledStartTime = time(0); - debug("\r%s: %s is a one-shot timer.\n", __func__, id.c_str()); - } else { - nextScheduledStartTime = time(0) + calcStartTime(); - } - struct tm * timeinfo; - timeinfo = localtime((time_t*)&nextScheduledStartTime); - debug("Timer %s started, begins at %s", this->id.c_str(), asctime(timeinfo)); - - currentState = STATE_OFF; -} - -// -// method: update -// description: run the state machine -// -// @param none -// @return OK on success; error otherwise -// -TimerControlError_t TimerControl::update(void) -{ - TimerControlError_t rc = TIMER_CONTROL_OK; - - unsigned long currentTime = time(0); - - switch ( this->currentState ) { - case STATE_INIT: - // do nothing; timer is waiting for start signal - break; - case STATE_OFF: { - if ( currentTime >= nextScheduledStartTime && - currentTime <= nextScheduledStartTime + duration ) { - currentState = STATE_RUNNING; - this->startFeed(); - startTime = currentTime; // record the actual start time - debug("\r%s: [OFF]->in timing window->[RUNNING] %s\n", id.c_str(), displayTime()); - } - break; - } - case STATE_RUNNING: - if ( currentTime >= startTime + duration ) { - this->stopFeed(); - currentState = STATE_FINISHED; - debug("\r%s: [RUNNING]->time elapsed->[OFF] %s\n", id.c_str(), displayTime()); - } - break; - case STATE_FINISHED: - if ( day == DAY_SCHEDULE_NOT_SPECIFIED || week == WEEKLY_CHOICE_NOT_SPECIFIED ) { - // one shot-timer, just disable it. - nextScheduledStartTime = 0; - startTime = 0; - currentState = STATE_DISABLED; - debug("\r%s: [FINISHED]->one shot timer->[DISABLED] %s\n", id.c_str(), displayTime()); - } else { - // calculate the next scheduled start time - nextScheduledStartTime = time(0) + calcStartTime(); - startTime = 0; - // unregister with the output task - currentState = STATE_OFF; - debug("\r%s: [FINISHED]->time elapsed->[OFF] %s\n", id.c_str(), displayTime()); - } - this->unregisterControl(); - break; - case STATE_DISABLED: - // do nothing - break; - default: - logError("%s: unknown state %d", __func__, this->currentState); - rc = TIMER_CONTROL_UNK_STATE; - break; - } - return rc; -} - -// -// method: startFeed -// description: signal the output thread to start a feed -// -// @param none -// @return none -void TimerControl::startFeed(void) -{ - logInfo("%s: %s attempting to start feed on relay %s\n", - __func__, controlFile.c_str(), output.c_str()); - - if ( isVirtualOutput ) { - // write to the virtual register map - ModbusMasterWriteRegister(output, 1.0); - } else { - // send a message to the output thread - OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); - memset(output_mail, 0, sizeof(OutputControlMsg_t)); - - output_mail->action = ACTION_CONTROL_ON; - output_mail->controlType = CONTROL_TIMER; - output_mail->priority = priority; - - strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); - strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); - OutputMasterMailBox.put(output_mail); - } -} - -// -// method: stopFeed -// description: signal the output thread to stop a feed -// -// @param none -// @return none -// -void TimerControl::stopFeed(void) -{ - logInfo("%s: %s attempting to start feed on relay %s\n", - __func__, controlFile.c_str(), output.c_str()); - - if ( isVirtualOutput ) { - // write to the virtual register map - ModbusMasterWriteRegister(output, 0.0); - } else { - // send a message to the output thread - OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); - memset(output_mail, 0, sizeof(OutputControlMsg_t)); - - output_mail->action = ACTION_CONTROL_OFF; - output_mail->controlType = CONTROL_TIMER; - output_mail->priority = priority; - - strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); - strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); - OutputMasterMailBox.put(output_mail); - } -} - -// -// method: unregisterControl -// description: send OFF indication to Output Master for this control's -// relay -// -// @param none -// @return none -// -void TimerControl::unregisterControl(void) -{ - logInfo("%s: %s attempting to unregister %s\n", - __func__, id.c_str(), controlFile.c_str()); - - if ( isVirtualOutput ) { - ModbusMasterWriteRegister(output, 0.0); - } else { - - OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); - memset(output_mail, 0, sizeof(OutputControlMsg_t)); - - output_mail->action = ACTION_CONTROL_UNREGISTER; - output_mail->controlType = CONTROL_TIMER; - output_mail->priority = priority; - strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); - strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); - - OutputMasterMailBox.put(output_mail); - } -} - -// -// method: calcStarTime -// description: calculate the number of seconds until the next -// timer starts. -// -// @param[in] none -// @param[out] none -// @return none -// -unsigned long TimerControl::calcStartTime(void) const -{ - TSC_SCHED_ELEM schedTimeDate; - TSC_SCHED_ELEM pNowTimeDate; - unsigned long pDiffInSeconds; - CNTL_HR_MIN_STRUCT startTime; - - startTime.hour = startHour; - startTime.minute = startMin; - startTime.second = startSec; - - pNowTimeDate.calTime = time( NULL ); - localtime_r( &pNowTimeDate.calTime, &pNowTimeDate.requestTime ); - - pNowTimeDate.schedule.startDate.year = pNowTimeDate.requestTime.tm_year - 100; /* years since 1900 */ - pNowTimeDate.schedule.startDate.year += 2000; - pNowTimeDate.schedule.startDate.month = pNowTimeDate.requestTime.tm_mon + 1; /* months 1 - 12 */ - pNowTimeDate.schedule.startDate.day = pNowTimeDate.requestTime.tm_mday; - pNowTimeDate.schedule.startTime.hour = pNowTimeDate.requestTime.tm_hour; - pNowTimeDate.schedule.startTime.minute = pNowTimeDate.requestTime.tm_min; - pNowTimeDate.schedule.startTime.second = pNowTimeDate.requestTime.tm_sec; - - /* setup schedTimeDate with the current date, time and the required schedule */ - schedTimeDate.schedule.startDate = pNowTimeDate.schedule.startDate; - schedTimeDate.schedule.startTime = startTime; - schedTimeDate.schedule.dailySchedule = day; - schedTimeDate.schedule.weeklySchedule = (WEEKLY_CHOICES)week; - schedTimeDate.calTime = pNowTimeDate.calTime; - schedTimeDate.requestTime = pNowTimeDate.requestTime; - - TSCutilComputeStartDate( &schedTimeDate ); - Util_dateTimeDiff( &pNowTimeDate.schedule, &schedTimeDate.schedule, &pDiffInSeconds ); - - return pDiffInSeconds; -} - -const char* TimerControl::displayTime(void) -{ - struct tm * timeinfo; - time_t currentTime = time(0); - timeinfo = localtime(¤tTime); - return asctime(timeinfo); -} - -// -// method: display -// description: display the elements of this timer control object -// -// @param none -// @return none -// -void TimerControl::display(void) -{ - string mapper[] = { "INIT", - "OFF", - "RUNNING", - "FINISHED", - "DISABLED" - }; - - printf("\r\n"); - std::string day_str; - if ( day == DAY_SCHEDULE_SUNDAY_MASK ) { - day_str = "Sun"; - } else if ( day == DAY_SCHEDULE_MONDAY_MASK ) { - day_str = "Mon"; - } else if ( day == DAY_SCHEDULE_TUESDAY_MASK ) { - day_str = "Tue"; - } else if ( day == DAY_SCHEDULE_WEDNESDAY_MASK ) { - day_str = "Wed"; - } else if ( day == DAY_SCHEDULE_THURSDAY_MASK ) { - day_str = "Thu"; - } else if ( day == DAY_SCHEDULE_FRIDAY_MASK ) { - day_str = "Fri"; - } else if ( day == DAY_SCHEDULE_SATURDAY_MASK ) { - day_str = "Sat"; - } - std::string week_str; - if ( week == WEEKLY_CHOICE_EVERY_WEEK ) { - week_str = "every"; - } else if ( week == WEEKLY_CHOICE_FIRST_WEEK ) { - week_str = "first"; - } else if ( week == WEEKLY_CHOICE_SECOND_WEEK ) { - week_str = "second"; - } else if ( week == WEEKLY_CHOICE_THIRD_WEEK ) { - week_str = "third"; - } else if ( week == WEEKLY_CHOICE_FOURTH_WEEK ) { - week_str = "fourth"; - } else if ( week == WEEKLY_CHOICE_LAST_WEEK ) { - week_str = "last"; - } else if ( week == WEEKLY_CHOICE_EVERYOTHER_WEEK ) { - week_str = "everyother"; - } - - char time_str[12]; - snprintf(time_str, sizeof(time_str), "%02d:%02d:%02d", startHour, startMin, startSec); - - cout << left << setw(8) << setfill(' ') << "timer:"; - cout << left << setw(32) << setfill(' ') << controlFile; - cout << left << setw(12) << setfill(' ') << id; - cout << "output: " << left << setw(16) << setfill(' ') << output; - cout << left << setw(6) << setfill(' ') << priority; - cout << "(" << setw(12) << week_str << ")" << day_str << "-> "; - cout << left << setw(12) << setfill(' ') << time_str; - cout << left << setw(10) << "duration: " << left << setw(6) << setfill(' ') << duration; - cout << left << setw(10) << setfill(' ') << mapper[currentState]; - if ( currentState == STATE_RUNNING ) { - cout << left << setw(11) << setfill(' ') << "ends in: " << (startTime + duration) - time(NULL) << " seconds "; - } else if ( currentState == STATE_FINISHED || currentState == STATE_DISABLED ) { - // show nothing - } else { - cout << left << setw(11) << setfill(' ') << "starts in: " << calcStartTime() << " seconds "; - } - cout.flush(); -}