Mbed Clock application using an NTP connection to get internet time and a terminal interface to send commands

Dependencies:   4DGL-uLCD-SE EthernetInterface NTPClient mbed-rtos mbed SDFileSystem wavfile

main.cpp

Committer:
dudanian
Date:
2014-12-02
Revision:
0:4e6ae21cbd31
Child:
1:c47a2f0816bb

File content as of revision 0:4e6ae21cbd31:

#include "mbed.h"
#include "rtos.h"
#include "EthernetInterface.h"
#include "uLCD_4DGL.h"
#include "Clock.h"
#include <string>
#include <sstream>
#include <vector>

uLCD_4DGL uLCD(p28,p27,p30);
Serial pc(USBTX, USBRX);
Mutex cMutex;
Mutex sMutex;
Clock clk;
EthernetInterface eth;

/**
 * Function to get a command from the virtual serial connection.
 * Will prompt the serial port for a command and read a command
 * into a buffer and convert that buffer to a string object. This
 * function should only be used while testing without a connection.
 */
string getCommand() {
    char buffer[100];
    char next = 0;
    int i = 0;
    sMutex.lock();
    pc.printf("Enter a command: \n\r");
    sMutex.unlock();
    do {
        sMutex.lock();
        if (pc.readable()) {
            next = pc.getc();
            buffer[i++] = next;
        }
        sMutex.unlock();
        Thread::wait(0.1);
    } while (next != '\r');
    
    buffer[i] = '\0';
    sMutex.lock();
    pc.printf("Command entered: %s\n\r", buffer);
    sMutex.unlock();
    return string(buffer);
}

/**
 * Function to take a string command and break it into tokens of words/numbers.
 * These tokens will be added to the vector given as an argument and can then be 
 * parsed to execute a command.
 */
vector<string>& splitCommand(const string &command, vector<string> &tokens) {
    string buf;
    stringstream ss(command);

    while (ss >> buf)
        tokens.push_back(buf);

    return tokens;
}

/**
 * Function to actually parse and execute a given command. If the command is not
 * supported, an error function will be called to give feedback.
 */
void parseCommand(const vector<string> &tokens) {
    sMutex.lock();
    pc.printf("number of tokens: %d\n\r", tokens.size());
    sMutex.unlock();

    if (tokens.size() < 2) {
        // error message
        return;
    }
    
    string operation = tokens[0];
    string destination = tokens[1];
    
    if (operation == "set") {
        if (destination == "time") {
            int hour = atoi(tokens[2].c_str());
            int minute = atoi(tokens[3].c_str());
            int period = tokens.at(4) == "am" ? AM : PM;
            cMutex.lock();
            clk.setTime(hour, minute, period);
            cMutex.unlock();
        } else if (destination == "alarm") {
            int hours = atoi(tokens[2].c_str());
            int minutes = atoi(tokens[3].c_str());
        } else if (destination == "timezone") {
            int timezone = atoi(tokens[2].c_str());
            cMutex.lock();
            clk.setTimezone(timezone);
            cMutex.unlock();
        } else {
            //return error message
        }
    } else if (operation == "sync") {
        if (destination == "time") {

            cMutex.lock();            
            if (clk.syncTime() == 0) {
                sMutex.lock();
                pc.printf("Set time successfully\r\n");
            } else {
                sMutex.lock();
                pc.printf("Error\r\n");
            }
            sMutex.unlock();
            cMutex.unlock();
        }
        // return error message
    }
}

/**
 * Thread which updates the clock on the lcd while the main thread is waiting for 
 * or executing a command.
 */
void lcdUpdateThread(void const *args) {
    time_t time;
    struct tm *timeinfo;
    char buffer[20];
    
    // set initial time
    cMutex.lock();
    clk.syncTime();
    clk.setTimezone(-5);
    cMutex.unlock();
    
    // set lcd format
    sMutex.lock();
    uLCD.text_width(2);
    uLCD.text_height(2);
    uLCD.color(BLUE);
    sMutex.unlock();
    
    while (1) {
        cMutex.lock();
        time = clk.getTime();
        cMutex.unlock();
        
        timeinfo = localtime(&time);
        strftime(buffer, 20, "%I:%M:%S        %p", timeinfo);
        
        sMutex.lock();
        uLCD.locate(0,3);
        uLCD.printf("%s", buffer);
        sMutex.unlock();
        Thread::wait(0.25);
    }
}

/**
 * main function which loops getting a command, parsing that command, and executing
 * that command. It also starts a thread which updates the clock separate from the
 * command execution.
 */
int main() {
    vector<string> tokens;

    eth.init();
    eth.connect();
    wait(5); // I don't know why you have to wait...

    pc.printf("%s\n\r", eth.getIPAddress());
    
    Thread updateThread(lcdUpdateThread);

    while (1) {
        tokens.clear();
        string command = getCommand();
        splitCommand(command, tokens);
        parseCommand(tokens);
    }
}