Erick / Mbed 2 deprecated ICE_BLE_TEST

Dependencies:   NaturalTinyShell_ice libmDot-12Sept mbed-rtos mbed

Fork of ICE by Erick

src/OutputTask/OutputTask.cpp

Committer:
jmarkel44
Date:
2016-09-16
Revision:
71:34856d21f2bf
Parent:
70:7427f4959201
Child:
72:3754b352f156

File content as of revision 71:34856d21f2bf:

/******************************************************************************
 *
 * File:                OutputTask.cpp
 * Desciption:          source for the ICE Output task
 *
 *****************************************************************************/
#include "OutputTask.h"
#include "global.h"
#include "MbedJSONValue.h"
#include <vector>

// locals
static int  createOutput(const char *controlFile);
static void loadPersistentOutputs(void);

static int  enableOutputReq (const char* id, unsigned int pri, const char* output);
static int  disableOutputReq(const char *id, unsigned int pri, const char *output);
//static int  unregisterControl(const char *id, unsigned int pri, const char *output);

typedef enum {
    CONTROL_OFF = 0,
    CONTROL_ON  = 1
} ControlState;

class Control
{
private:
    string          id;
    unsigned int    priority;
    ControlState    state;
public:
    Control(string id, unsigned int priority, ControlState state) :
        id(id), priority(priority), state(state) {}
    void display() {
        printf("[%s | %s | %u]",
               id.c_str(), (state == CONTROL_ON) ? "ON" : "OFF", priority);
    }
    //void setId(string id) id(id) { }
    string getId() {
        return id;
    }
    void setState(ControlState _state) {
        state = _state;
    }
};


typedef std::map<string, vector<Control> > StringOutputVector_t;

StringOutputVector_t outputMap;

/*****************************************************************************
 * Function:            OutputTask
 * Description:         Main entry point for the Output Task
 *
 * @param               args -> not used
 * @return              none
 *****************************************************************************/
void OutputTask(void const *args)
{
    UNUSED(args);

    printf("\r%s has started...\n", __func__);

    loadPersistentOutputs();

    while (true) {
        // wait for an event
        osEvent evt = OutputMasterMailBox.get();
        if (evt.status == osEventMail) {
            OutputControlMsg_t *msg = (OutputControlMsg_t*) evt.value.p;
            printf("\r%s received message from someone...\n", __func__);
            printf("\rmsg->relay    = %s\n", msg->output);
            printf("\rmsg->state    = %s\n", msg->state == ON ? "ON" : "OFF");
            printf("\rmsg->priority = %u\n", msg->priority);

            switch ( msg->action ) {
                case ACTION_NEW:
                    // read the file and and create an output entry
                    (void) createOutput(msg->controlFile);
                    break;
                case ACTION_CONTROL_ON:
                    printf("\r%s is requesting ON control of %s\n",
                           msg->id, msg->output);
                    (void) enableOutputReq(msg->id, msg->priority, msg->output);
                    break;
                case ACTION_CONTROL_OFF:
                    printf("\r%s is requesting OFF control of %s\n",
                           msg->id, msg->output);
                    (void) disableOutputReq(msg->id, msg->priority, msg->output);
                    break;
                default:
                    break;
            }

            // free the message
            OutputMasterMailBox.free(msg);
        }
    }
}

/*****************************************************************************
 * Function:            DisplayOutputs
 * Description:         Display a list of outputs and its controls
 *
 * @param               args -> not used
 * @return              none
 *****************************************************************************/
void DisplayOutputs(void)
{
    StringOutputVector_t::iterator pos;

    for ( pos = outputMap.begin(); pos != outputMap.end(); ++pos ) {
        if ( pos->second.empty() ) {
            printf("\r  [%s]->[no controls]\n", pos->first.c_str());
        } else {
            printf("\r  [%s]->", pos->first.c_str());
            vector<Control>::iterator i;
            for ( i = pos->second.begin(); i != pos->second.end(); ++i ) {
                i->display();
            }
            printf("\n");
        }
    }
    printf("\r\n");
}


/*****************************************************************************
 * Function:            DisplayOutputs
 * Description:         Display a list of outputs and its controls
 *
 * @param               args -> not used
 * @return              none
 *****************************************************************************/
static int createOutput(const char *controlFile)
{
    char dataBuf[1024];
    int status = GLOBAL_mdot->readUserFile(controlFile, (void *)dataBuf, sizeof(dataBuf));
    if ( status != true ) {
        logError("%s failed to read %s", __func__, controlFile);
        return -1;
    }

    MbedJSONValue json_value;
    parse(json_value, dataBuf);

    // extract the relay information
    string id = json_value["id"].get<string>();

    // maps doesn't allow duplicates, and the vector is empty for now
    vector<Control> v;
    outputMap[id] = v;

    return 0;
}


/*****************************************************************************
 * Function:            DisplayOutputs
 * Description:         Display a list of outputs and its controls
 *
 * @param               args -> not used
 * @return              none
 *****************************************************************************/
static int enableOutputReq(const char *id, unsigned int priority, const char *output)
{
    // attempt to find the output in the map
    StringOutputVector_t::iterator pos;

    pos = outputMap.find(output);
    if ( pos == outputMap.end() ) {
        printf("%s: failed to find the designated output %s\n",
               __func__, output);
        return -1;
    }

    if ( pos->second.empty() ) {
        // this is a new request
        string cid(id);
        Control c(cid, priority, CONTROL_ON);
        pos->second.push_back(c);
    } else {
        // find this control in the list
        vector<Control>::iterator v;
        for ( v = pos->second.begin(); v != pos->second.end(); ++v ) {
            if ( strcmp(v->getId().c_str(), id) == 0 )  {
                v->setState(CONTROL_ON);
            }
        }
    }

    return 0;
}


/*****************************************************************************
 * Function:            DisplayOutputs
 * Description:         Display a list of outputs and its controls
 *
 * @param               args -> not used
 * @return              none
 *****************************************************************************/
static int disableOutputReq(const char *id, unsigned int priority, const char *output)
{
    // attempt to find the output in the map
    StringOutputVector_t::iterator pos;

    pos = outputMap.find(output);
    if ( pos == outputMap.end() ) {
        printf("%s: failed to find the designated output %s\n",
               __func__, output);
        return -1;
    }

    // is the same id requesting?
    if ( pos->second.empty() ) {
        string cid(id);
        Control c(cid, priority, CONTROL_OFF);
        pos->second.push_back(c);
    } else {
        // find this control in the list
        vector<Control>::iterator v;
        for ( v = pos->second.begin(); v != pos->second.end(); ++v ) {
            if ( strcmp(v->getId().c_str(), id) == 0 )  {
                v->setState(CONTROL_OFF);
            }
        }
    }

    return 0;
}

static void loadPersistentOutputs(void)
{
    bool status;
    MbedJSONValue json_value;

    printf("\rLoading persistent controls\n");

    std::vector<mDot::mdot_file> file_list = GLOBAL_mdot->listUserFiles();

    for (std::vector<mDot::mdot_file>::iterator i = file_list.begin(); i != file_list.end(); ++i) {
        if( strncmp( i->name, OUTPUT_STR, strlen(OUTPUT_STR)) == 0 ) {

            logInfo("%s: FOUND OUTPUT FILE: %s", __func__, i->name);

            char scratchBuf[1024];

            status = GLOBAL_mdot->readUserFile(i->name, scratchBuf, 1024);
            if( status != true ) {
                logInfo("(%d)read file failed, status=%d", __LINE__, status);
            } else {
                logInfo("(%d)Read File SUCCESS: %s", __LINE__, scratchBuf );
            }

            parse( json_value, scratchBuf );

            string id = json_value["id"].get<string>();
            printf("\r   %s id = %s loaded\n", __func__, id.c_str());
            vector<Control> v;
            outputMap[id] = v;
        }
    }
}