Client of WebSocket protocol

Fork of WebSocketClient by Samuel Mokrani

Files at this revision

API Documentation at this revision

Comitter:
mauricioaschmitz
Date:
Fri Feb 24 20:06:49 2017 +0000
Parent:
7:4567996414a5
Commit message:
Added project prtgmdWebSocketClient

Changed in this revision

Websocket.cpp Show annotated file Show diff for this revision Revisions of this file
Websocket.h Show annotated file Show diff for this revision Revisions of this file
WebsocketCaptureMonitor.cpp Show annotated file Show diff for this revision Revisions of this file
WebsocketCaptureMonitor.h Show annotated file Show diff for this revision Revisions of this file
diff -r 4567996414a5 -r c9da00db9d33 Websocket.cpp
--- a/Websocket.cpp	Fri Feb 08 12:33:04 2013 +0000
+++ b/Websocket.cpp	Fri Feb 24 20:06:49 2017 +0000
@@ -1,7 +1,11 @@
 #include "Websocket.h"
+#include "Pmed_reset.h"
+#include "Log.h"
 
 #define MAX_TRY_WRITE 20
 #define MAX_TRY_READ 10
+#define MAX_TRY_CONNECT 50
+#define WAIT_CONNECT_TIME 10000
 
 //Debug is disabled by default
 #if 0
@@ -14,14 +18,166 @@
 #define ERR(x, ...) 
 #endif
 
-#define INFO(x, ...) printf("[WebSocket : INFO]"x"\r\n", ##__VA_ARGS__); 
+#define INFO(x, ...) printf("[WebSocket : INFO]"x"\r\n", ##__VA_ARGS__);
+
+char * Websocket::captureMessage;
+bool Websocket::haveMessage;
+bool Websocket::isConect;
+bool disconnectedWS = false;
 
-Websocket::Websocket(char * url) {
+void Websocket::Websocket_Thread(void const *arg)
+{
+    //Log::writeEntry("WebSocket Thread Start");
+    printf("Thread WebSocket Iniciada\r\n");
+    int i = 0, f = 0;
+    char *comando = NULL;
+    char *tomada = NULL;
+    char *canal = NULL;
+    char *limite = NULL;
+    char server[30];
+    char buffer[1024] = {};
+    //bool external = false;
+    strcpy(server, "ws://");
+    strcat(server, Settings::get_networkServer());
+    strcat(server, ":8080");
+    
+    //printf("Servidor WS: %s", server);
+    
+    Websocket ws(server);
+    
+    while(1){
+        if(ws.is_connected()){
+            if (f == 0){
+                //Log::writeEntry("WebSocket Conectado.");
+                //printf("\nMensagem do MBED para servidor WebSocket em PHP\n\n");
+                //ws.send("#*MBEDStart*#Mensagem do MBED para servidor WebSocket em PHP\n"); //mensagem para registrar login do mbed no banco de dados (ainda por implementar)
+                f = 1;
+            }
+            if(disconnectedWS != false){
+                disconnectedWS = false;
+            }
+            if(haveMessage){
+                ws.send(captureMessage);
+                haveMessage = false;
+                captureMessage = NULL;
+            }    
+            if (ws.read(buffer)) {
+                //ws.send("#*MBEDTest*#");
+                //printf("Recebido Mensagem WebSocket: %s\r\n", buffer);
+                comando = strtok(buffer, ":");
+                if(strcmp(comando, "test") == 0){
+                    //printf("\r\nRecebido por WebSocket o Comando de Teste.");
+                    ws.send("#*MBEDTest*#");
+                    //Log::writeEntry("Recebido por WebSocket o Comando de Teste.");
+                }
+                if(strcmp(comando, "capture") == 0){
+                    tomada = strtok(NULL, ":");
+                    canal = strtok(NULL, " ");
+                    /*
+                    printf("Comando: %s\n", comando);
+                    printf("Tomada: %s\n", tomada);
+                    printf("Canal: %s\n", canal);
+                    printf("Tamanho da string: %d\n", strlen(buffer));
+                    */
+                    
+                    EventDetector::externalCapture(atoi(tomada), canal[0]);
+                }
+                if(strcmp(comando, "reset") == 0){
+                    Pmed_reset("Reiniciando o MBED por WebSocket.");
+                }
+                
+                if(strcmp(comando, "setLimit") == 0 || strcmp(comando, "setStandByLimit") == 0){
+                    tomada = strtok(NULL, ":");
+                    canal = strtok(NULL, ":");
+                    limite = strtok(NULL, " ");
+                    for(i=0; (unsigned)i < _PRTGMD_SETTINGS_MAX_NUMBER_OF_OUTLETS_; i++){
+                        if(atoi(tomada) == Settings::get_outlet(i)){
+                            if(strcmp(comando, "setLimit") == 0){
+                                if(strcmp(canal, "p") == 0){
+                                    printf("Entrou canal fase e setou limite %s para tomada %s\r\n", limite, tomada);
+                                    Settings::set_limit(i*2,strtod(limite, NULL));
+                                }
+                                if(strcmp(canal, "d") == 0){
+                                    printf("Entrou canal fuga e setou limite %s para tomada %s\r\n", limite, tomada);
+                                    Settings::set_limit(i*2+1,strtod(limite, NULL));
+                                }
+                            }
+                            if(strcmp(comando, "setStandByLimit") == 0){
+                                if(strcmp(canal, "p") == 0){
+                                    printf("Entrou canal StandBy de fase e setou limite %s para tomada %s\r\n", limite, tomada);
+                                    Settings::set_standbyLimit(i*2,strtod(limite, NULL));
+                                }
+                                if(strcmp(canal, "d") == 0){
+                                    printf("Entrou canal StandBy de fuga e setou limite %s para tomada %s\r\n", limite, tomada);
+                                    Settings::set_standbyLimit(i*2+1,strtod(limite, NULL));
+                                }
+                            }
+                            break;
+                        }else{
+                            if(i == _PRTGMD_SETTINGS_MAX_NUMBER_OF_OUTLETS_ - 1){
+                                printf("Tomada %d nao encontrada para atualizar limite!\r\n", atoi(tomada));
+                            }
+                        }
+                    }
+                    //printf("Comando: %s\n", comando);
+                    //printf("Tomada: %d\n", atoi(tomada));
+                    //printf("Canal: %s\n", canal);
+                    //printf("Limite: %f\n", strtod(limite, NULL));
+                }
+                /*
+                if(strcmp(comando, "iniciar") == 0){
+                    printf("\n\nChegou o Iniciar!!!\n\n");
+                    external = true;
+                }
+                if(strcmp(comando, "parar") == 0){
+                    printf("\n\nChegou o Parar!!!\n\n");
+                    external = false;
+                }
+                if(external){
+                    
+                }*/
+            }
+            /*
+            if (!ws.is_connected()){
+                printf("Caiu a conexao!!!\n");
+                Thread::wait(Settings::get_delayTry());
+                for(int i=0; i < MAX_TRY_CONNECT; i++){
+                    Thread::wait(Settings::get_delayTry());
+                    //if(ws.connect()){
+                      //  break;
+                    //}
+                }
+                //Websocket ws("ws://192.168.103.101:8080");
+                ws.connect();
+            }*/
+        }else{
+            if(!disconnectedWS){
+                if(ws.close()){
+                    disconnectedWS = true;
+                    Log::writeEntry("WebSocket Desconectado.");
+                }
+            }
+            Thread::wait(WAIT_CONNECT_TIME);
+            if(ws.connect()){
+                //Log::writeEntry("WebSocket Conectado.");
+                printf("Thread WebSocket Conectou no Servidor %s\r\n", Settings::get_networkServer());
+            }
+            //Thread::wait(10000);
+        }
+    }
+    
+}
+
+Websocket::Websocket(char const * url) {
     fillFields(url);
     socket.set_blocking(false, 400);
 }
 
-void Websocket::fillFields(char * url) {
+bool Websocket::wsIsConnected(){
+    return isConect;
+}
+
+void Websocket::fillFields(char const * url) {
   int ret = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
   if(ret)
   {
@@ -119,7 +275,7 @@
 
     while (socket.connect(host, port) < 0) {
         ERR("Unable to connect to (%s) on port (%d)", host, port);
-        wait(0.2);
+        Thread::wait(200);
         return false;
     }
 
@@ -141,19 +297,18 @@
 
     sprintf(cmd, "Sec-WebSocket-Version: 13\r\n\r\n");
     int ret = write(cmd, strlen(cmd));
-    if (ret != strlen(cmd)) {
+    if ((unsigned)ret != strlen(cmd)) {
         close();
         ERR("Could not send request");
         return false;
     }
-
+    
     ret = read(cmd, 200, 100);
     if (ret < 0) {
         close();
         ERR("Could not receive answer\r\n");
         return false;
     }
-
     cmd[ret] = '\0';
     DBG("recv: %s\r\n", cmd);
 
@@ -171,8 +326,8 @@
         close();
         return false;
     }
-
-    INFO("\r\nhost: %s\r\npath: %s\r\nport: %d\r\n\r\n", host, path, port);
+    
+    //INFO("\r\nhost: %s\r\npath: %s\r\nport: %d\r\n\r\n", host, path, port);
     return true;
 }
 
@@ -290,7 +445,7 @@
     if (nb != len_msg)
         return false;
 
-    for (i = 0; i < len_msg; i++) {
+    for (i = 0; (unsigned)i < len_msg; i++) {
         message[i] = message[i] ^ mask[i % 4];
     }
 
@@ -300,10 +455,10 @@
 }
 
 bool Websocket::close() {
-    if (!is_connected())
-        return false;
+    //if (!is_connected())
+        //return false;
 
-    int ret = socket.close();
+    int ret = socket.close(true);
     if (ret < 0) {
         ERR("Could not disconnect");
         return false;
@@ -312,6 +467,7 @@
 }
 
 bool Websocket::is_connected() {
+    isConect = socket.is_connected();
     return socket.is_connected();
 }
 
diff -r 4567996414a5 -r c9da00db9d33 Websocket.h
--- a/Websocket.h	Fri Feb 08 12:33:04 2013 +0000
+++ b/Websocket.h	Fri Feb 24 20:06:49 2017 +0000
@@ -32,8 +32,12 @@
 #define WEBSOCKET_H
 
 #include "mbed.h"
+#include "rtos.h"
 
 #include "TCPSocketConnection.h"
+#include "EventDetector.h"
+
+extern void Websocket_Thread(void const *arg);
 
 /** Websocket client Class.
  *
@@ -68,12 +72,34 @@
 class Websocket
 {
     public:
+    
+        /*
+        * Prepare message get from mailbox
+        *
+        * 
+        */
+        static void ReceiveMessage(char * dados){ haveMessage = true; captureMessage = dados; }
+        
+        /*
+        * Get status of connection
+        *
+        * 
+        */
+        static bool wsIsConnected();
+        
+        
+        /**
+        * Thread to start Websocket
+        *
+        */
+        static void Websocket_Thread(void const *arg);
+        
         /**
         * Constructor
         *
         * @param url The Websocket url in the form "ws://ip_domain[:port]/path" (by default: port = 80)
         */
-        Websocket(char * url);
+        Websocket(char const * url);
 
         /**
         * Connect to the websocket url
@@ -123,7 +149,7 @@
 
     private:
 
-        void fillFields(char * url);
+        void fillFields(char const * url);
         int parseURL(const char* url, char* scheme, size_t maxSchemeLen, char* host, size_t maxHostLen, uint16_t* port, char* path, size_t maxPathLen); //Parse URL
         int sendOpcode(uint8_t opcode, char * msg);
         int sendLength(uint32_t len, char * msg);
@@ -139,6 +165,11 @@
 
         int read(char * buf, int len, int min_len = -1);
         int write(char * buf, int len);
+        
+        static char * captureMessage;
+        static bool haveMessage;
+        static bool isConect; 
+        
 };
 
 #endif
diff -r 4567996414a5 -r c9da00db9d33 WebsocketCaptureMonitor.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebsocketCaptureMonitor.cpp	Fri Feb 24 20:06:49 2017 +0000
@@ -0,0 +1,246 @@
+#include "WebsocketCaptureMonitor.h"
+#include "Pmed_reset.h"
+#include "Log.h"
+//#include "Settings.h"
+
+void WebsocketCaptureMonitor::WebsocketCaptureMonitor_Thread(void const *arg)
+{
+    //Log::writeEntry("WebSocket Capture Thread Start");
+    char mensagem[600];
+    CaptureMailbox& mbox = EventDetector::GetMailbox();
+    osEvent evt;
+    while(true){
+        evt = mbox.get();
+        if(evt.status == osEventMail)
+        {
+            //printf("Entrou monitor de captura!!!!\n\n");
+            CaptureEvent* cap = (CaptureEvent*)evt.value.p;
+            
+            //printf("Request=[%s]\n",mensagem);
+            //Websocket::ReceiveMessage(mensagem);
+            //memset(mensagem, 0, 600);
+            //printf("Saiu do monitor de captura!!!!\n\n");
+            
+            //testar porque não funciona, ideia era se o websocket não estiver conectado, abrir um socket e enviar por post direto
+            PrepareMessage(cap, mensagem, true);
+            Websocket::ReceiveMessage(mensagem);
+            
+            //if(Websocket::wsIsConnected()){
+                //PrepareMessage(cap, mensagem, true);
+                //Websocket::ReceiveMessage(mensagem);
+                /*
+                printf("WebSocket conectado para o envio de dados!!!\n");
+                strcpy(tmp, mensagem);
+                strcpy(mensagem, "#*InsertCaptureDB*#");
+                strcat(mensagem, tmp);
+                
+                //memset(tmp,0,600);
+                //alguma forma de tentar conectar o websocket
+                */
+            //}
+            //else
+            //{
+                //TCPSocketConnection sock;
+                //DoPost(sock,Settings::get_networkServer(),cap);
+            //}
+            mbox.free(cap);
+        }
+    }
+}
+
+void WebsocketCaptureMonitor::PrepareMessage(CaptureEvent* dados, char *strfinal, bool isWS){
+    char str[400];
+    char aux[_PRTGMD_SETTINGS_DEFAULT_MAX_HARMONICS_];
+    int i;
+
+    const char *header1 = "POST /Ptgm-Scripts/capture.php HTTP/1.1\r\n";
+                //"Host: 192.168.1.26\r\n"
+                //"Content-Length: "
+                
+    const char *header2 = "\r\n"
+                "Content-Type: application/x-www-form-urlencoded\r\n"
+                "\r\n";
+    
+    //str = (char *) malloc(450);
+    //strfinal = (char *) malloc(450);
+    memset(str,0,400);
+    memset(strfinal,0,500);
+    
+    if(isWS){
+        strcat(strfinal, "#*InsertCaptureDB*#");
+    }
+     
+    strcat(strfinal, header1);    
+    strcat(strfinal, "Host: ");
+    strcat(strfinal, Settings::get_networkServer() );
+    strcat(strfinal, "\r\n");
+    
+    sprintf(aux,"TYPE=0%d",dados->get_Type());
+    strcat(str, aux);
+
+    sprintf(aux,"&OUTLET=%02d",dados->get_OutletNumber());
+    strcat(str, aux);
+    
+    sprintf(aux,"&RFID=%s", dados->get_RFID());
+    strcat(str,aux);
+
+    sprintf(aux,"&OFFSET=%04d",dados->get_Offset());
+    strcat(str,aux);
+    
+    float f = dados->get_Gain();
+    sprintf(aux,"&GAIN=%08X", *(unsigned int*)&f);
+    strcat(str,aux);
+    
+    f = dados->get_RMSValue();
+    sprintf(aux,"&RMS=%08X",*(unsigned int*)&f);
+    strcat(str,aux);
+    
+    f = dados->get_MeanValue();
+    sprintf(aux,"&MV=%08X",*(unsigned int*)&f);
+    strcat(str,aux);        
+    
+    /* Adicionados para alteracao */
+    //printf("MV %f MV2 %f\n", dados->get_MeanValue(), dados->get_MV2());
+    f = dados->get_MV2();
+    sprintf(aux,"&MV2=%08X",*(unsigned int*)&f);
+    strcat(str,aux);        
+    
+    sprintf(aux,"&UNDER=%04d",dados->get_Under());
+    strcat(str,aux);
+    
+    sprintf(aux,"&OVER=%04d",dados->get_Over());
+    strcat(str,aux);
+    
+    sprintf(aux,"&DURATION=%04d",dados->get_Duration());
+    strcat(str,aux);
+    /* Ate Aqui */
+    
+    strcat(str,"&SIN=");
+    for(i=0;i<Settings::get_maxHarmonics();i++)
+    {
+        char s[10];
+        //According to RFC1738,RFC3986 the semicolon is a reserved character and must be encoded
+        f = dados->get_SineValue(i);
+        sprintf(s,"%08X",*(unsigned int*)&f);
+        strcat(str,s);
+        if (i < (Settings::get_maxHarmonics() - 1))
+            strcat(str, "%3B");
+    }
+
+    strcat(str,"&COS=");
+    for(i=0;i<Settings::get_maxHarmonics();i++)
+    {
+        char c[10];
+        //According to RFC1738,RFC3986 the semicolon is a reserved character and must be encoded
+        f = dados->get_CossineValue(i);
+        sprintf(c,"%08X",*(unsigned int*)&f);
+        strcat(str,c);
+        if (i < (Settings::get_maxHarmonics()-1))
+            strcat(str, "%3B");
+    }
+    strcat(str,"\r\n");
+    
+    char len[5];
+    sprintf(len,"%d",strlen(str));        
+    
+    strcat(strfinal, "Content-Length: ");
+    strcat(strfinal, len);
+    strcat(strfinal, header2);
+    strcat(strfinal, str);    
+    strcat(strfinal, "\r\n");
+    
+    //printf("Request=[%s]\n",strfinal);
+    //printf("Tamanho STR %d\n", strlen(str));
+    //printf("Tamanho STRFINAL %d\n", strlen(strfinal));      
+ }
+ 
+ void WebsocketCaptureMonitor::DoPost(TCPSocketConnection sock, char *host, CaptureEvent* dados){
+    char http_cmd[400]; 
+    int escritos, r=-1, i;
+    //FILE *f;
+    
+    //Timer t;
+    //t.start();
+    
+    //printf("HTTP Socket %s:%d\n", host, sock.get_port());
+    //printf("Antes Connect\n");
+    //rs= sock.connect(host, 80);   
+    //printf("%d\n", rs);
+    //printf("Depois Connect "); 
+    
+    //t.stop();
+    //printf("HHTP: The time taken in connection was %d useconds\n", t.read_us());
+           
+    //http_cmd = (char *) malloc(500);
+    memset(http_cmd, 0, 600);
+    PrepareMessage( dados,http_cmd, false );
+    //printf("Fuga\n");
+    //printf("Tamanho do comando %d\n", strlen(http_cmd));
+    //printf("Comando: /* %s */\n", http_cmd);
+    
+    //http_cmd = prepare_POST( dados );
+    
+    //printf("Tamanho comando %d\n", strlen(http_cmd));     
+    //printf("Request \n [%s]\n", http_cmd);     
+
+    
+    for(i=0; i < _PRTGMD_SETTINGS_DEFAULT_TRIES_ ; i++){
+        r = sock.connect(host, 80);        
+        if (r < 0) {
+            printf("Error: Unable to connect to (%s) on port (%d) Try %d\n", host, 80, i);
+            Thread::wait(Settings::get_delayTry());
+        }
+        else
+            break;            
+    }     
+    if (r == 0){
+        for(i=0; i < _PRTGMD_SETTINGS_DEFAULT_TRIES_ ; i++){
+            escritos = sock.send_all(http_cmd, strlen(http_cmd));        
+            if(escritos != strlen(http_cmd)){
+                printf("Erro ao gravar no socket HTTP!! Escritos %d\t Tam %d Try %d\n", escritos, strlen(http_cmd), i);            
+                Thread::wait(Settings::get_delayTry());
+            }
+            else 
+                break;
+        }
+        if ( i != _PRTGMD_SETTINGS_DEFAULT_TRIES_  )
+            Thread::wait(Settings::get_delaySend());
+        else{
+            //printf("Reset\n");
+            /*f = fopen(FILENAMERESET, "a");
+            if (f == NULL)            
+                f = fopen(FILENAMERESET, "w");
+            fprintf(f, "Reset - Connect\n");
+            fclose(f);*/
+                
+            Pmed_reset(PMEDLOG_HTTP_CONNECT);
+        }            
+            
+        //Codigo para buscar o retorno do servidor HTTP
+        /*
+        printf("Vai pegar retorno\n");
+        
+        char buffer[300];
+        int ret;
+        while (true) {
+            ret = sock.receive(buffer, sizeof(buffer)-1);
+            if (ret <= 0)
+                break;
+            buffer[ret] = '\0';
+            printf("Received %d chars from server:\n%s\n", ret, buffer);
+        }
+        */
+    }
+    else{
+        printf("Reset\n");
+        /*f = fopen(FILENAMERESET, "a");
+        if (f == NULL)            
+            f = fopen(FILENAMERESET, "w");
+        fprintf(f, "Reset - Send\n");
+        fclose(f);*/
+            
+        Pmed_reset(PMEDLOG_HTTP_SEND);
+    }
+    
+    sock.close();  
+}
\ No newline at end of file
diff -r 4567996414a5 -r c9da00db9d33 WebsocketCaptureMonitor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebsocketCaptureMonitor.h	Fri Feb 24 20:06:49 2017 +0000
@@ -0,0 +1,34 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "EventDetector.h"
+#include "Websocket.h"
+#include "EthernetInterface.h"
+#include "Settings.h"
+
+extern void WebsocketCaptureMonitor_Thread(void const *arg);
+
+class WebsocketCaptureMonitor
+{
+    public:
+        /**
+        * Thread to start Websocket Capture Monitor
+        *
+        */
+        static void WebsocketCaptureMonitor_Thread(void const *arg);
+        
+        /*
+        * Prepare message get from mailbox
+        *
+        * 
+        */
+        static void PrepareMessage(CaptureEvent* dados,char *strfinal, bool isWS);
+        
+        /*
+        * Send data
+        *
+        * 
+        */
+        
+        static void DoPost(TCPSocketConnection sock, char *host, CaptureEvent* dados);
+    
+};