Erick / Mbed 2 deprecated ICE_BLE_TEST

Dependencies:   NaturalTinyShell_ice libmDot-12Sept mbed-rtos mbed

Fork of ICE by Erick

src/ConfigurationHandler/Controls/TimerControl.cpp

Committer:
jmarkel44
Date:
2016-09-27
Revision:
136:6ad7ba157b70
Parent:
133:c871de2d2b90
Child:
141:d924caf402c2

File content as of revision 136:6ad7ba157b70:

/******************************************************************************
 *
 * File:                TimerControl.cpp
 * Desciption:          ICE Timer Control Class implementation
 *
 *****************************************************************************/
#include "TimerControl.h"
#include "mDot.h"
#include "MbedJSONValue.h"
#include "global.h"
#include <string>

extern mDot *GLOBAL_mdot;

//
// method:      load
// description: load the pertinents from the control file
//
// @param       _controlFile
// @return      true if loaded; false otherwise
//
bool TimerControl::load(string _controlFile)
{
    MbedJSONValue json_value;           // json parsing element

    // try to open the control file
    mDot::mdot_file file = GLOBAL_mdot->openUserFile(_controlFile.c_str(), mDot::FM_RDONLY);
    if ( file.fd < 0 ) {
        return false;
    }

    // read the data into a buffer
    char dataBuf[1024];

    int bytes_read = GLOBAL_mdot->readUserFile(file, (void *)dataBuf, sizeof(dataBuf));
    if ( bytes_read != sizeof(dataBuf) ) {
        logError("%s: failed to read %d bytes from %s", __func__, sizeof(dataBuf), controlFile.c_str());
        return false;
    }

    // close the file
    GLOBAL_mdot->closeUserFile(file);

    parse(json_value, dataBuf);

    // the pertinents
    controlFile = _controlFile;
    id          = json_value["id"].get<string>();
    output      = json_value["output"].get<string>();

    // create the schedule
    Schedule_t s;
    s.priority  = atol(json_value["priority"].get<string>().c_str());
    s.startTime = atol(json_value["starttime"].get<string>().c_str());
    s.duration  = atol(json_value["duration"].get<string>().c_str());

    // push it on the list
    schedule.push_back(s);

    return true;
}

//
// method:      start
// description: initialize the control
//
// @param       none
// @return      none
//
void TimerControl::start(void)
{
    currentState = STATE_OFF;
    vector<Schedule_t>::iterator pos;
    
    if ( schedule.empty() ) return;
    #if 0 
    for ( pos = schedule.begin(); pos != schedule.end(); ++pos ) {
        if ( (pos->startTime + pos->duration) < time(NULL) ) {
            schedule.erase(pos);
        }
    }
    #endif
}

//
// method:      timerStart
// description: examine the timestamp to determine if the timer control
//              should be running
//
// @param       none
// @return      true if timer should be running; false otherwise
//
bool TimerControl::timerStart(void)
{
    // schedules should be sorted in order, so always check the first
    if ( !schedule.empty() ) {
        unsigned long currentTime = time(NULL);
        // does it fit?
        if ( currentTime < schedule.front().startTime ) {
            return false;
        }
        if ( currentTime >= schedule.front().startTime &&
                currentTime < (schedule.front().startTime + schedule.front().duration) ) {
            logInfo("%s signals feed start", __func__);
            return true;
        } else {
            logInfo("%s: schedule for %s has expired", __func__, id.c_str());
            schedule.erase(schedule.begin());
            this->unregisterControl();
        }
    }
    return false;
}

//
// method:      timerStop
// description: determines if a running timer should has reached its duration
//
// @param       none
// @return      true if the timer has expired; false otherwise
//
bool TimerControl::timerStop(void)
{
    // if current time is greater than start time + feed duration...
    if ( time(NULL) >= (schedule.front().startTime + schedule.front().duration) ) {
        logInfo("%s signals a feed stop", __func__);
        return true;
    }
    return false;
}

//
// method:      update
// description: run the simplified state machine
//
// @param       none
// @return      none
//
void TimerControl::update(void)
{
    switch ( this->currentState ) {
        case STATE_OFF:
            if ( this->timerStart() ) {
                currentState = STATE_RUNNING;
                this->startFeed();
            }
            break;
        case STATE_RUNNING:
            if ( this->timerStop() ) {
                currentState = STATE_OFF;
                this->stopFeed();
            }
            break;
        case STATE_DISABLED:
            // not implelmented
        default:
            break;
    }
}

//
// 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());

    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    = this->schedule.front().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());

    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    = this->schedule.front().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__, controlFile.c_str());

    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     = this->schedule.front().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);
}

//
// methid:      display
// description: display the elements of this timer control object
//
// @param       none
// @return      none
//
void TimerControl::display(void)
{
    string mapper[] = { "OFF",
                        "RUNNING",
                        "DISABLED"
                      };

    printf("\r      controlFile : %s   \n", controlFile.c_str());
    printf("\r               id : %s   \n", id.c_str());
    printf("\r           output : %s   \n", output.c_str());

    std::vector<Schedule_t>::iterator pos;

    int counter = 0;
    if ( schedule.empty() ) {
        printf("\rNo scheduled timers\r\n");
        return;
    } else {
        for ( pos = schedule.begin(); pos != schedule.end(); ++pos ) {
            printf("\r Schedule %d\n", ++counter);
            printf("\r         priority : %u \n", pos->priority);
            printf("\r       start time : %lu\n", pos->startTime);
            printf("\r         duration : %u sec\n", pos->duration);
            printf("\r         end time : %lu\n", pos->startTime + pos->duration);
            printf("\r     current time : %lu\n", time(NULL));
            printf("\r       expires in : %lu sec\n", (pos->startTime + pos->duration) - time(NULL));
        }
    }
    printf("\r    current State : %s\n", mapper[currentState].c_str());
}