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

Committer:
dudanian
Date:
Tue Dec 02 17:22:43 2014 +0000
Revision:
0:4e6ae21cbd31
Child:
1:c47a2f0816bb
initial draft

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudanian 0:4e6ae21cbd31 1 #include "mbed.h"
dudanian 0:4e6ae21cbd31 2 #include "rtos.h"
dudanian 0:4e6ae21cbd31 3 #include "EthernetInterface.h"
dudanian 0:4e6ae21cbd31 4 #include "uLCD_4DGL.h"
dudanian 0:4e6ae21cbd31 5 #include "Clock.h"
dudanian 0:4e6ae21cbd31 6 #include <string>
dudanian 0:4e6ae21cbd31 7 #include <sstream>
dudanian 0:4e6ae21cbd31 8 #include <vector>
dudanian 0:4e6ae21cbd31 9
dudanian 0:4e6ae21cbd31 10 uLCD_4DGL uLCD(p28,p27,p30);
dudanian 0:4e6ae21cbd31 11 Serial pc(USBTX, USBRX);
dudanian 0:4e6ae21cbd31 12 Mutex cMutex;
dudanian 0:4e6ae21cbd31 13 Mutex sMutex;
dudanian 0:4e6ae21cbd31 14 Clock clk;
dudanian 0:4e6ae21cbd31 15 EthernetInterface eth;
dudanian 0:4e6ae21cbd31 16
dudanian 0:4e6ae21cbd31 17 /**
dudanian 0:4e6ae21cbd31 18 * Function to get a command from the virtual serial connection.
dudanian 0:4e6ae21cbd31 19 * Will prompt the serial port for a command and read a command
dudanian 0:4e6ae21cbd31 20 * into a buffer and convert that buffer to a string object. This
dudanian 0:4e6ae21cbd31 21 * function should only be used while testing without a connection.
dudanian 0:4e6ae21cbd31 22 */
dudanian 0:4e6ae21cbd31 23 string getCommand() {
dudanian 0:4e6ae21cbd31 24 char buffer[100];
dudanian 0:4e6ae21cbd31 25 char next = 0;
dudanian 0:4e6ae21cbd31 26 int i = 0;
dudanian 0:4e6ae21cbd31 27 sMutex.lock();
dudanian 0:4e6ae21cbd31 28 pc.printf("Enter a command: \n\r");
dudanian 0:4e6ae21cbd31 29 sMutex.unlock();
dudanian 0:4e6ae21cbd31 30 do {
dudanian 0:4e6ae21cbd31 31 sMutex.lock();
dudanian 0:4e6ae21cbd31 32 if (pc.readable()) {
dudanian 0:4e6ae21cbd31 33 next = pc.getc();
dudanian 0:4e6ae21cbd31 34 buffer[i++] = next;
dudanian 0:4e6ae21cbd31 35 }
dudanian 0:4e6ae21cbd31 36 sMutex.unlock();
dudanian 0:4e6ae21cbd31 37 Thread::wait(0.1);
dudanian 0:4e6ae21cbd31 38 } while (next != '\r');
dudanian 0:4e6ae21cbd31 39
dudanian 0:4e6ae21cbd31 40 buffer[i] = '\0';
dudanian 0:4e6ae21cbd31 41 sMutex.lock();
dudanian 0:4e6ae21cbd31 42 pc.printf("Command entered: %s\n\r", buffer);
dudanian 0:4e6ae21cbd31 43 sMutex.unlock();
dudanian 0:4e6ae21cbd31 44 return string(buffer);
dudanian 0:4e6ae21cbd31 45 }
dudanian 0:4e6ae21cbd31 46
dudanian 0:4e6ae21cbd31 47 /**
dudanian 0:4e6ae21cbd31 48 * Function to take a string command and break it into tokens of words/numbers.
dudanian 0:4e6ae21cbd31 49 * These tokens will be added to the vector given as an argument and can then be
dudanian 0:4e6ae21cbd31 50 * parsed to execute a command.
dudanian 0:4e6ae21cbd31 51 */
dudanian 0:4e6ae21cbd31 52 vector<string>& splitCommand(const string &command, vector<string> &tokens) {
dudanian 0:4e6ae21cbd31 53 string buf;
dudanian 0:4e6ae21cbd31 54 stringstream ss(command);
dudanian 0:4e6ae21cbd31 55
dudanian 0:4e6ae21cbd31 56 while (ss >> buf)
dudanian 0:4e6ae21cbd31 57 tokens.push_back(buf);
dudanian 0:4e6ae21cbd31 58
dudanian 0:4e6ae21cbd31 59 return tokens;
dudanian 0:4e6ae21cbd31 60 }
dudanian 0:4e6ae21cbd31 61
dudanian 0:4e6ae21cbd31 62 /**
dudanian 0:4e6ae21cbd31 63 * Function to actually parse and execute a given command. If the command is not
dudanian 0:4e6ae21cbd31 64 * supported, an error function will be called to give feedback.
dudanian 0:4e6ae21cbd31 65 */
dudanian 0:4e6ae21cbd31 66 void parseCommand(const vector<string> &tokens) {
dudanian 0:4e6ae21cbd31 67 sMutex.lock();
dudanian 0:4e6ae21cbd31 68 pc.printf("number of tokens: %d\n\r", tokens.size());
dudanian 0:4e6ae21cbd31 69 sMutex.unlock();
dudanian 0:4e6ae21cbd31 70
dudanian 0:4e6ae21cbd31 71 if (tokens.size() < 2) {
dudanian 0:4e6ae21cbd31 72 // error message
dudanian 0:4e6ae21cbd31 73 return;
dudanian 0:4e6ae21cbd31 74 }
dudanian 0:4e6ae21cbd31 75
dudanian 0:4e6ae21cbd31 76 string operation = tokens[0];
dudanian 0:4e6ae21cbd31 77 string destination = tokens[1];
dudanian 0:4e6ae21cbd31 78
dudanian 0:4e6ae21cbd31 79 if (operation == "set") {
dudanian 0:4e6ae21cbd31 80 if (destination == "time") {
dudanian 0:4e6ae21cbd31 81 int hour = atoi(tokens[2].c_str());
dudanian 0:4e6ae21cbd31 82 int minute = atoi(tokens[3].c_str());
dudanian 0:4e6ae21cbd31 83 int period = tokens.at(4) == "am" ? AM : PM;
dudanian 0:4e6ae21cbd31 84 cMutex.lock();
dudanian 0:4e6ae21cbd31 85 clk.setTime(hour, minute, period);
dudanian 0:4e6ae21cbd31 86 cMutex.unlock();
dudanian 0:4e6ae21cbd31 87 } else if (destination == "alarm") {
dudanian 0:4e6ae21cbd31 88 int hours = atoi(tokens[2].c_str());
dudanian 0:4e6ae21cbd31 89 int minutes = atoi(tokens[3].c_str());
dudanian 0:4e6ae21cbd31 90 } else if (destination == "timezone") {
dudanian 0:4e6ae21cbd31 91 int timezone = atoi(tokens[2].c_str());
dudanian 0:4e6ae21cbd31 92 cMutex.lock();
dudanian 0:4e6ae21cbd31 93 clk.setTimezone(timezone);
dudanian 0:4e6ae21cbd31 94 cMutex.unlock();
dudanian 0:4e6ae21cbd31 95 } else {
dudanian 0:4e6ae21cbd31 96 //return error message
dudanian 0:4e6ae21cbd31 97 }
dudanian 0:4e6ae21cbd31 98 } else if (operation == "sync") {
dudanian 0:4e6ae21cbd31 99 if (destination == "time") {
dudanian 0:4e6ae21cbd31 100
dudanian 0:4e6ae21cbd31 101 cMutex.lock();
dudanian 0:4e6ae21cbd31 102 if (clk.syncTime() == 0) {
dudanian 0:4e6ae21cbd31 103 sMutex.lock();
dudanian 0:4e6ae21cbd31 104 pc.printf("Set time successfully\r\n");
dudanian 0:4e6ae21cbd31 105 } else {
dudanian 0:4e6ae21cbd31 106 sMutex.lock();
dudanian 0:4e6ae21cbd31 107 pc.printf("Error\r\n");
dudanian 0:4e6ae21cbd31 108 }
dudanian 0:4e6ae21cbd31 109 sMutex.unlock();
dudanian 0:4e6ae21cbd31 110 cMutex.unlock();
dudanian 0:4e6ae21cbd31 111 }
dudanian 0:4e6ae21cbd31 112 // return error message
dudanian 0:4e6ae21cbd31 113 }
dudanian 0:4e6ae21cbd31 114 }
dudanian 0:4e6ae21cbd31 115
dudanian 0:4e6ae21cbd31 116 /**
dudanian 0:4e6ae21cbd31 117 * Thread which updates the clock on the lcd while the main thread is waiting for
dudanian 0:4e6ae21cbd31 118 * or executing a command.
dudanian 0:4e6ae21cbd31 119 */
dudanian 0:4e6ae21cbd31 120 void lcdUpdateThread(void const *args) {
dudanian 0:4e6ae21cbd31 121 time_t time;
dudanian 0:4e6ae21cbd31 122 struct tm *timeinfo;
dudanian 0:4e6ae21cbd31 123 char buffer[20];
dudanian 0:4e6ae21cbd31 124
dudanian 0:4e6ae21cbd31 125 // set initial time
dudanian 0:4e6ae21cbd31 126 cMutex.lock();
dudanian 0:4e6ae21cbd31 127 clk.syncTime();
dudanian 0:4e6ae21cbd31 128 clk.setTimezone(-5);
dudanian 0:4e6ae21cbd31 129 cMutex.unlock();
dudanian 0:4e6ae21cbd31 130
dudanian 0:4e6ae21cbd31 131 // set lcd format
dudanian 0:4e6ae21cbd31 132 sMutex.lock();
dudanian 0:4e6ae21cbd31 133 uLCD.text_width(2);
dudanian 0:4e6ae21cbd31 134 uLCD.text_height(2);
dudanian 0:4e6ae21cbd31 135 uLCD.color(BLUE);
dudanian 0:4e6ae21cbd31 136 sMutex.unlock();
dudanian 0:4e6ae21cbd31 137
dudanian 0:4e6ae21cbd31 138 while (1) {
dudanian 0:4e6ae21cbd31 139 cMutex.lock();
dudanian 0:4e6ae21cbd31 140 time = clk.getTime();
dudanian 0:4e6ae21cbd31 141 cMutex.unlock();
dudanian 0:4e6ae21cbd31 142
dudanian 0:4e6ae21cbd31 143 timeinfo = localtime(&time);
dudanian 0:4e6ae21cbd31 144 strftime(buffer, 20, "%I:%M:%S %p", timeinfo);
dudanian 0:4e6ae21cbd31 145
dudanian 0:4e6ae21cbd31 146 sMutex.lock();
dudanian 0:4e6ae21cbd31 147 uLCD.locate(0,3);
dudanian 0:4e6ae21cbd31 148 uLCD.printf("%s", buffer);
dudanian 0:4e6ae21cbd31 149 sMutex.unlock();
dudanian 0:4e6ae21cbd31 150 Thread::wait(0.25);
dudanian 0:4e6ae21cbd31 151 }
dudanian 0:4e6ae21cbd31 152 }
dudanian 0:4e6ae21cbd31 153
dudanian 0:4e6ae21cbd31 154 /**
dudanian 0:4e6ae21cbd31 155 * main function which loops getting a command, parsing that command, and executing
dudanian 0:4e6ae21cbd31 156 * that command. It also starts a thread which updates the clock separate from the
dudanian 0:4e6ae21cbd31 157 * command execution.
dudanian 0:4e6ae21cbd31 158 */
dudanian 0:4e6ae21cbd31 159 int main() {
dudanian 0:4e6ae21cbd31 160 vector<string> tokens;
dudanian 0:4e6ae21cbd31 161
dudanian 0:4e6ae21cbd31 162 eth.init();
dudanian 0:4e6ae21cbd31 163 eth.connect();
dudanian 0:4e6ae21cbd31 164 wait(5); // I don't know why you have to wait...
dudanian 0:4e6ae21cbd31 165
dudanian 0:4e6ae21cbd31 166 pc.printf("%s\n\r", eth.getIPAddress());
dudanian 0:4e6ae21cbd31 167
dudanian 0:4e6ae21cbd31 168 Thread updateThread(lcdUpdateThread);
dudanian 0:4e6ae21cbd31 169
dudanian 0:4e6ae21cbd31 170 while (1) {
dudanian 0:4e6ae21cbd31 171 tokens.clear();
dudanian 0:4e6ae21cbd31 172 string command = getCommand();
dudanian 0:4e6ae21cbd31 173 splitCommand(command, tokens);
dudanian 0:4e6ae21cbd31 174 parseCommand(tokens);
dudanian 0:4e6ae21cbd31 175 }
dudanian 0:4e6ae21cbd31 176 }