Machine Vision Status TCP Server

Dependencies:   C12832 EthernetInterface mbed-rtos mbed ConfigFile

Files at this revision

API Documentation at this revision

Comitter:
dwini
Date:
Thu Mar 05 13:18:28 2015 +0000
Parent:
0:bef69e35f486
Child:
2:a8eebf64cd3e
Commit message:
Create TCP Daemon and some logging (most of TRex code).

Changed in this revision

Log.h Show annotated file Show diff for this revision Revisions of this file
TcpDaemon.cpp Show annotated file Show diff for this revision Revisions of this file
TcpDaemon.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Log.h	Thu Mar 05 13:18:28 2015 +0000
@@ -0,0 +1,81 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctime>
+
+#ifndef LOG_HEADER
+#define LOG_HEADER
+
+#define DEBUG_MODE 1
+
+using namespace std;
+
+namespace MachineVision{
+    
+    class Log{
+        public:
+            static void e(char* fmt, ...) {
+                char buffer [80];
+                Log::getTimestamp(buffer);
+
+                va_list args;
+                va_start(args,fmt);
+                printf("%s ", buffer);
+                printf("[ERROR] ");
+                vprintf(fmt,args);
+                va_end(args);
+            }
+
+            static void w(char* fmt, ...) {
+                char buffer [80];
+                Log::getTimestamp(buffer);
+
+                va_list args;
+                va_start(args,fmt);
+                printf("%s ", buffer);
+                printf("[WARNING] ");
+                vprintf(fmt,args);
+                va_end(args);
+            }
+
+            static void d(char* fmt, ...) {
+                #ifdef DEBUG_MODE
+                char buffer [80];
+                Log::getTimestamp(buffer);
+
+                va_list args;
+                va_start(args,fmt);
+                printf("%s ", buffer);
+                printf("[DEBUG] ");
+                vprintf(fmt,args);
+                va_end(args);
+                #endif
+            }
+
+            static void v(char* fmt, ...) {
+                #ifdef DEBUG_MODE
+                char buffer [80];
+                Log::getTimestamp(buffer);
+
+                va_list args;
+                va_start(args,fmt);
+                printf("%s ", buffer);
+                printf("[VERBOSE] ");
+                vprintf(fmt,args);
+                va_end(args);
+                #endif
+            }
+
+        private:
+            static void getTimestamp(char * buffer) {
+                time_t rawtime;
+                struct tm * timeinfo;
+
+                time (&rawtime);
+                timeinfo = localtime (&rawtime);
+
+                strftime(buffer, 80, "%d-%m-%Y|%H:%M:%S", timeinfo);
+            }
+    };
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TcpDaemon.cpp	Thu Mar 05 13:18:28 2015 +0000
@@ -0,0 +1,109 @@
+#include "TcpDaemon.h"
+#include "Log.h"
+
+// Incomming message end
+#define END_MSG_SEQUENCE "\r\n"
+
+namespace MachineVision{
+    /*
+     * TcpDaemon constructor
+     *
+     * @server_port the port the daemon will be listening on
+     */
+    TcpDaemon::TcpDaemon(int server_port) {
+        this->server_port = server_port;
+        this->keepListening = true;
+    }
+
+    /*
+     * Make the daemon start listening for incoming connections
+     */
+    void TcpDaemon::startListening() {
+        if (this->bindSocket()) {
+            this->doListen();
+        }
+    }
+
+    /*
+     * Bind to server socket
+     *
+     * @return true on success
+     */
+    bool TcpDaemon::bindSocket() {
+        if(server.bind(server_port) < 0) {
+            Log::e("Bind failed. Error\r\n");
+            return false;
+        } else {
+            Log::d("Bind ok\r\n");
+            return true;
+        }
+    }
+
+    /*
+     * Listen for incoming connections
+     */
+    void TcpDaemon::doListen() {
+       
+        // Listen for incoming connection
+        if (server.listen(MAX_BACKLOG) < 0) {
+            Log::w("Listen failed\r\n");
+            return;
+        }
+        
+        while (this->keepListening) {
+            Log::d("Listening for incoming connection ...\r\n");
+            
+            // Accept connection from an incoming client
+            if (server.accept(client) < 0) {
+                Log::w("Client accept failed\r\n");
+            } else {
+                Log::d("Client connected: %s\r\n", client.get_address());
+                
+                // Set non-blocking
+                client.set_blocking(false, TCP_TIMEOUT);
+                
+                while (client.is_connected()) {
+                    // Keep receiving messages from the client
+                    int read_size = 0;
+                    int total_read_size = 0;
+                    char * end = NULL;
+                    
+                    while((read_size = client.receive(buffer, BUFFER_SIZE)) > 0) {
+                        total_read_size = read_size;
+                        
+                        // Null-terminate string
+                        this->buffer[total_read_size] = '\0';
+                        Log::v("Received partial: %s\r\n", this->buffer);
+
+                        // Keep reading until full message is received
+                        end = strstr(this->buffer, END_MSG_SEQUENCE);        // Find END_MSG_SEQUENCE
+                        while (total_read_size < BUFFER_SIZE && end == NULL) {
+                            read_size = client.receive(this->buffer+total_read_size, BUFFER_SIZE-total_read_size);
+                            if (read_size != -1) {
+                                total_read_size += read_size;
+                                end = strstr(this->buffer, END_MSG_SEQUENCE);
+                            }
+                            Log::v("Waiting for rest of message\r\n");
+                        }
+                    }
+                    
+                    if (total_read_size > 0) {
+                        if (end == NULL) {
+                            Log::w("Buffer full\r\n");
+                        } else {
+                            // Null-terminate string
+                            this->buffer[total_read_size] = '\0';
+                            
+                            // Full string received, lets do our thing
+                            Log::v("Received: %s", this->buffer);
+                        }
+                    }
+                }
+                
+                Log::d("Client disconnected\r\n");
+                fflush(stdout);
+                client.close();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TcpDaemon.h	Thu Mar 05 13:18:28 2015 +0000
@@ -0,0 +1,51 @@
+#include "EthernetInterface.h"
+
+#ifndef TCP_DAEMON_HEADER
+#define TCP_DAEMON_HEADER
+
+#define MAX_BACKLOG 1
+
+namespace MachineVision{
+    
+    class TcpDaemon{
+        public:
+            const static int BUFFER_SIZE = 512;
+            const static int TCP_TIMEOUT = 1000;
+
+        private:
+            int server_port;
+            TCPSocketServer server;
+            TCPSocketConnection client;
+
+            char buffer[BUFFER_SIZE+1];
+            bool keepListening;
+
+        public:
+            /*
+             * TcpDaemon constructor
+             *
+             * @server_port the port the daemon will be listening on
+             */
+            TcpDaemon(int server_port);
+
+            /*
+             * Make the daemon start listening for incoming connections
+             */
+            void startListening();
+
+        private:
+            /*
+             * Bind to server socket
+             *
+             * @return true on success
+             */
+            bool bindSocket();
+
+            /*
+             * Listen for incoming connections
+             */
+            void doListen();
+    };
+}
+
+#endif
--- a/main.cpp	Thu Mar 05 10:10:22 2015 +0000
+++ b/main.cpp	Thu Mar 05 13:18:28 2015 +0000
@@ -1,8 +1,12 @@
 #include "mbed.h"
 #include "EthernetInterface.h"
 #include "C12832.h"
+#include "Log.h"
+#include "TcpDaemon.h"
 
-#define ECHO_SERVER_PORT   6666
+#define MAX_BACKLOG 1
+#define TCP_SERVER_PORT 6666
+
 #define LCD_LINE_HEIGHT 12
 #define DELAY_INDICATION 0
 
@@ -11,17 +15,21 @@
 #define STR_CLEAR "CLEAR"
 
 Serial pc(USBTX,USBRX);
-DigitalOut myled(LED1);
+DigitalOut error_led(LED1);
 C12832 lcd(p5, p7, p6, p8, p11);
 
 PwmOut rOut (p23);
 PwmOut gOut (p24);
 PwmOut bOut (p25);
 
+using namespace MachineVision;
+
 void setLcdServerInfo(char * ip) {
     lcd.cls();
     lcd.locate(0,0);
-    lcd.printf("IP: %s - Port: %d", ip, ECHO_SERVER_PORT);
+    lcd.printf("IP: %s", ip);
+    lcd.locate(0,14);
+    lcd.printf("Port: %d", TCP_SERVER_PORT);
 }
 
 void setRGB(int r, int g, int b) {
@@ -55,20 +63,7 @@
     initRgb();
     
     pc.baud(115200);
-    EthernetInterface eth;
-    printf("Requesting IP address from DHCP\r\n");
-    eth.init();         //Use DHCP
-    eth.connect();
-    printf("IP Address is %s\r\n", eth.getIPAddress());
-    printf("Listening on port %d\r\n", ECHO_SERVER_PORT);
-    
-    // Set ip on LCD
-    setLcdServerInfo(eth.getIPAddress());
-    
-    TCPSocketServer server;
-    server.bind(ECHO_SERVER_PORT);
-    server.listen();
-    
+        
     // Status check
     for (int i = 0; i < 4; i++) {
         indicateOk();
@@ -76,43 +71,30 @@
     }
     clearRGB();
     
-    while (true) {
-        printf("Awaiting client connection ...\r\n");
-        setLcdServerInfo(eth.getIPAddress());
-        lcd.locate(0, LCD_LINE_HEIGHT);
-        lcd.printf("Awaiting connection ...");
+    EthernetInterface eth;
+    Log::v("Requesting IP address from DHCP\r\n");
+    eth.init();         //Use DHCP
+    
+    if (eth.connect() < 0) {
+        Log::w("Could not retrieve IP address from DHCP\r\n");
+        setLcdServerInfo("No ip address");
+    } else {
+        Log::v("IP Address is %s\r\n", eth.getIPAddress());
         
-        TCPSocketConnection client;
-        server.accept(client);
-        //client.set_blocking(false, 5000);   // Timeout after (1.5)s
-        
-        printf("Client connected: %s\r\n", client.get_address());
+        // Set ip on LCD
         setLcdServerInfo(eth.getIPAddress());
-        lcd.locate(0, LCD_LINE_HEIGHT);
-        lcd.printf("Client: %s", client.get_address());
-
-        char buffer[256];
-        while (true) {
-            int n = client.receive(buffer, sizeof(buffer));
-            if (n <= 0) {
-                break;
-            } else {
-                if (strcmp(STR_FAIL, buffer) == 0) {
-                    printf("Received FAIL\r\n");
-                    indicateFail();
-                } else if (strcmp(STR_OK, buffer) == 0) {
-                    printf("Received OK\r\n");
-                    indicateOk();
-                } else if (strcmp(STR_CLEAR, buffer) == 0) {
-                    printf("Clearing\r\n");
-                    clearRGB();
-                } else {
-                    printf("Unknown message %s\r\n", buffer);
-                }
-            }
-        }
-        
-        printf("Client disconnected\r\n");        
-        client.close();
+    
+        // Start the daemon
+        TcpDaemon daemon(TCP_SERVER_PORT);
+        Log::v("TCP daemon listening @ TCP_SERVER_PORT = %d\r\n", TCP_SERVER_PORT);
+        daemon.startListening();
+    }
+    
+    // Should never be reached
+    while (true) {
+        error_led = 1;
+        wait(0.25);
+        error_led = 0;
+        wait(0.25);
     }
 }