Erick / Mbed 2 deprecated ICE_BLE_TEST

Dependencies:   NaturalTinyShell_ice libmDot-12Sept mbed-rtos mbed

Fork of ICE by Erick

src/ConfigurationHandler/Controls/SetpointControl.cpp

Committer:
jmarkel44
Date:
2016-10-06
Revision:
192:052a419837fa
Parent:
183:44f7fea6b208
Child:
193:3acbcc2f6fcb

File content as of revision 192:052a419837fa:

/******************************************************************************
 *
 * File:                SetpointControl.cpp
 * Desciption:          ICE Setpoint Control class implementation
 *
 *****************************************************************************/
#include "SetpointControl.h"
#include "mDot.h"
#include "MbedJSONValue.h"
#include "ModbusMasterApi.h"
#include "global.h"
#include <string>

extern mDot *GLOBAL_mdot;

// Method:          load
// Description:     open the configuration file and assign data to the
//                  setpoint control object
//
// @param           controlFile -> name of the control file
// @return          true if data is assigned; false on error

bool SetpointControl::load(string _controlFile)
{
    MbedJSONValue json_value;           // JSON parsing element
    controlFile = _controlFile;

    // open and read from 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[MAX_FILE_SIZE];

    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());
        // caller should destroy the object
        return false;
    }

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

    // parse the json data
    parse(json_value, dataBuf);

    if ( !json_value.hasMember("id")        ||
            !json_value.hasMember("priority")  ||
            !json_value.hasMember("input")     ||
            !json_value.hasMember("output")    ||
            !json_value.hasMember("setpoint")  ||
            !json_value.hasMember("prodfact")  ||
            !json_value.hasMember("actingDir") ||
            !json_value.hasMember("halert")    ||
            !json_value.hasMember("lalert")    ||
            !json_value.hasMember("hfs")       ||
            !json_value.hasMember("lfs")       ||
            !json_value.hasMember("tol") ) {
        logError("Setpoint Control file is missing expexted tags");
        return false;
    }

    id              = json_value     ["id"].get<string>();
    priority        = atoi(json_value["priority"].get<string>().c_str());
    input           = json_value     ["input"].get<string>();
    output          = json_value     ["output"].get<string>();
    setpoint        = atof(json_value["setpoint"].get<string>().c_str());
    productFactor   = atof(json_value["prodfact"].get<string>().c_str());
    actingDir       = atoi(json_value["actingDir"].get<string>().c_str());
    highAlert       = atof(json_value["halert"].get<string>().c_str());
    lowAlert        = atof(json_value["lalert"].get<string>().c_str());
    highFailsafe    = atof(json_value["hfs"].get<string>().c_str());
    lowFailsafe     = atof(json_value["lfs"].get<string>().c_str());
    tolerance       = atof(json_value["tol"].get<string>().c_str());

    return true;        // object created successfully
}

// Method:          start
// Description:     start the setpoint control
//
// @param           none
// @return          none

void SetpointControl::start(void)
{
    // this is the initial state; what else needs to be done??
    this->currentState = STATE_STARTUP;
}

// Method:          update
// Description:     based on the state of the control, check for
//                  under limit and over limit values, adjust the
//                  state accordingly
//
// @param           none
// @return          none

void SetpointControl::update(void)
{
    switch (this->currentState) {
        case STATE_INIT:
            // do nothing
            break;
        case STATE_STARTUP:
            if ( this->underLimit() ) {
                // start the feed right away
                this->startFeed();
                this->currentState = STATE_CONTROL_ON;
            } else {
                this->currentState = STATE_CONTROL_OFF;
                this->stopFeed();
            }
            break;
        case STATE_CONTROL_ON:
            if ( this->overLimit() ) {
                // stop the feed
                this->stopFeed();
                this->currentState = STATE_CONTROL_OFF;
            } else {
                // do nothing
            }
            break;
        case STATE_CONTROL_OFF:
            if ( this->underLimit() ) {
                // start the feed
                this->startFeed();
                this->currentState = STATE_CONTROL_ON;
            } else {
                // do nothing
            }
            break;
            //case STATE_CONTROL_DISABLED:
            //case STATE_CONTROL_PAUSED:
        default:
            break;
    }
}

// Method:              overLimit
// Description:         (see @return)
//
// @param               none
// @return              true if product is over the upper limit for normal mode
//                      or under the limit for reverse mode; false otherwise

bool SetpointControl::overLimit(void)
{
    ModbusValue value;
    ModbusMasterReadRegister( input, &value );
    float flimit;

    if ( !actingDir ) {
        flimit = setpoint + tolerance;
        return (value.value > flimit);
    } else {
        flimit = setpoint - tolerance;
        return (value.value < flimit);
    }
}


// Method:              underLimit
// Description:         (see @return)
//
// @param               none
// @return              true if product is under lower limit for normal mode or
//                      over the upper limit for reverse mode; false otherwise

bool SetpointControl::underLimit(void)
{
    ModbusValue value;
    ModbusMasterReadRegister( input, &value );
    float  flimit;

    if ( !actingDir ) {
        flimit = setpoint - tolerance;
        return (value.value < flimit);
    } else {
        flimit = setpoint + tolerance;
        return (value.value > flimit);
    }
}

// Method:              startFeed()
// Description:         send ON indication to Output Master for this control's
//                      relay
//
// @param               none
// @return              none

void SetpointControl::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_SETPOINT;
    strncpy(output_mail->input_tag,  this->input.c_str(),  sizeof(output_mail->input_tag)-1);
    strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
    output_mail->priority = this->priority;
    strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
    OutputMasterMailBox.put(output_mail);
}

// Method:              stopFeed
// Description:         send OFF indication to Output Master for this control's
//                      relay
//
// @param               none
// @return              none

void SetpointControl::stopFeed(void)
{
    logInfo("%s: %s attempting to stop 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_SETPOINT;
    strncpy(output_mail->input_tag,  this->input.c_str(),  sizeof(output_mail->input_tag)-1);
    strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
    output_mail->priority = this->priority;
    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 SetpointControl::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_MANUAL;
    output_mail->priority     = this->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:              display
// Description:         display the control's information
//
// @param               none
// @return              none
void SetpointControl::display(void)
{
    // NOTE: this mapping must be 1:1 with "State" enumeration in SetpointControl.h
    string mapper[] = { "INIT",
                        "STARTUP",
                        "CONTROL_OFF",
                        "CONTROL_ON",
                        "CONTROL_DISABLE",
                        "CONTROL_PAUSE",
                        "CONTROL_MAX"
                      };


    ModbusValue inputValue;
    ModbusMasterReadRegister(input, &inputValue);

    printf("\r      controlFile : %s   \n", controlFile.c_str());
    printf("\r               id : %s   \n", id.c_str());
    printf("\r         priority : %d   \n", priority);
    printf("\r            input : %s   \n", input.c_str());
    printf("\r           output : %s   \n", output.c_str());
    printf("\r         setpoint : %0.2f\n", setpoint);
    printf("\r         prodfact : %0.2f\n", productFactor);
    printf("\r        actingDir : %s   \n", (actingDir) ? "DIRECT" : "INDIRECT");
    printf("\r           halert : %0.2f\n", highAlert);
    printf("\r           lalert : %0.2f\n", lowAlert);
    printf("\r              hfs : %0.2f\n", highFailsafe);
    printf("\r              lfs : %0.2f\n", lowFailsafe);
    printf("\r              tol : %0.2f\n", tolerance);
    printf("\r\n");
    printf("\r     currentState : %s\n",    mapper[currentState].c_str());
    printf("\r        high band : %0.2f\n", setpoint + tolerance);
    printf("\r  current reading : %0.2f [%s]\n", inputValue.value, inputValue.valid ? "valid" : "invalid");
    printf("\r         low band : %0.2f\n", setpoint - tolerance);
    printf("\r\n");
}