APS SO

Dependencies:   WebSocketClient mbed

Fork of APS_SO by Ian Bolfarini

Revision:
2:27a7a42b2bae
Parent:
1:3da12598c635
--- a/main.cpp	Sat Oct 28 22:45:10 2017 +0000
+++ b/main.cpp	Fri Dec 15 20:07:49 2017 +0000
@@ -1,27 +1,49 @@
 #include "mbed.h"
+#include "rtos.h"
 #include "Rtc_Ds1307.h"
+#include "EthernetInterface.h"
+#include "Websocket.h"
+#include <iostream>   
+#include <string>     
 
 
-//Inicialização do Led RGB
-DigitalOut led(LED_BLUE);
+//Objeto da ethernet
+EthernetInterface eth;
 //Inicialização do RTC
 Rtc_Ds1307 rtc(D14,D15);
 //Estrutura responsável por armazenar os dados do RTC
 Rtc_Ds1307::Time_rtc alarm_time ; 
+//Estrutura responsável por armazenar a data/hora de ativação do alarme
+Rtc_Ds1307::Time_rtc a_time_start ;
+Rtc_Ds1307::Time_rtc a_time_end ; 
+int range = 3; // uma flag mantida em "1" caso o tempo atual lido do rtc esteja dentro do intervalo de funcionamento do alarme e, caso contrário, setada para "0".
 //Estabelece comunicação serial para DEBUG
 Serial gSerial(USBTX, USBRX);
-                
- //Ajuste da hora atraves da interface serial               
+//variavel de estado do alarme: 0 - desarmado devido ao horario, 1 - armado, 2 - disparando, 3- desarmado pelo usuario
+int state = 0; //incia em zero desarmado, é ajustado na thread de controle caso o horario esteja no range de alarme ativado
+DigitalIn enable(D8); //a variável enable lê o sinal do sensor de presença, que está conectado na entrada D8. Variável enable será true ou false conforme haja sinal ou não do sensor.
+DigitalOut led_red(LED_RED); //led vermelho
+DigitalOut led_green(LED_GREEN); //led verde
+DigitalOut led_blue(LED_BLUE); //led azul
+DigitalOut buzzer(D9); //buzzer
+
+
+//Declaracao das Threads
+Thread *RtcRead; //le o RTC e atualiza a estrutura 
+Thread *SetRange; //Verifica se está dentro do range - entre tempo de inicio e tempo de fim
+Thread *LedThread; //controla leds de status e buzzer
+Thread *SetState; //verifica e ajusta os estados - armado, desarmado, disparando, desarmado forçado 
+Thread *PrintRange; //imprime valores de estado e range e hora atual - para debug
+Thread *SocketThread; //thread das sockets
+
+//Ajuste da hora atraves da interface serial, so para ajuste do relogio              
  void set_time_serial()
  {
-    int hora, min, seg, dia, mes, ano, opt;
+    int hora, min, seg, dia, mes, ano, opt, d_sem;
     
     gSerial.printf("\n1-Ajuste de Hora, 2-Ajuste de Data, 3-Ajuste de Data/Hora: ");
     gSerial.scanf("%d",&opt);
-   /* if(opt >=1 && opt <=3){
-        
-        
-                }  */
+   
     
     if(opt == 1 || opt ==3 ) {
                     
@@ -35,9 +57,6 @@
                    alarm_time.hour = hora;
                    alarm_time.min = min;
                    alarm_time.sec = seg;      
-                   //alarm_time.date = 28;
-                   //alarm_time.mon = 10;
-                   //alarm_time.year = 2017;
                    rtc.setTime(alarm_time, true, false);
                    rtc.getTime(alarm_time);
                    gSerial.printf("\nHora Ajustada: %2d:%02d:%02d \n",alarm_time.hour,alarm_time.min,alarm_time.sec);
@@ -54,13 +73,14 @@
           if(opt==2 || opt ==3)
              {
                  
-                gSerial.printf("Insira a data(DIA MES ANO): ");
-                gSerial.scanf("%d %d %d", &dia, &mes, &ano);
-                if((dia < 32 && dia >0 && mes<13 && mes>0  && ano>2000) && !(mes == 2 && dia >=29 ) && !((mes == 4 || mes == 6 || mes == 9 || mes == 11)  && dia >30))
+                gSerial.printf("Insira a data(DIA MES ANO DIA-SEMANA(1-7)): ");
+                gSerial.scanf("%d %d %d %d", &dia, &mes, &ano, &d_sem);
+                if((dia < 32 && dia >0 && mes<13 && mes>0  && ano>2000) && !(mes == 2 && dia >=29 ) && !((mes == 4 || mes == 6 || mes == 9 || mes == 11)  && dia >30) && (d_sem>0 &&d_sem<8))
                 {
                  
                     
                    rtc.getTime(alarm_time);
+                   alarm_time.wday = d_sem;
                    alarm_time.date = dia;
                    alarm_time.mon = mes;
                    alarm_time.year = ano;      
@@ -75,57 +95,436 @@
                  
             } 
             
-            else gSerial.printf("Opcao Invalida!.\n");
+            else gSerial.printf("Opcao Invalida!.\n");         
+
              
+ }     
+ 
+ void set_range () {
+     
+    while(1) {
+        /* pode-se ter 3 situações: 
+        //  a hora de início da ativação do alarme é numericamente menor que a hora do encerramento
+        //  a hora de início da ativação é igual à hora de fim
+        //  a hora de início da ativação é numericamente maior que a hora de fim
+        */
+        if (a_time_start.hour < a_time_end.hour) { // Neste caso, o range está contido todo dentro de um dia (entre 0:00 e 23:59) mas as horas de início e fim do alarme são diferentes.
+            if (a_time_start.hour < alarm_time.hour && alarm_time.hour < a_time_end.hour)  {// Neste caso o valor do RTC está entre o horário de ligada e o de desligada
+                printf("muda range = 1\n");
+                range = 1;  
+                }
+            else if (a_time_start.hour == alarm_time.hour) { // Neste caso a hora do RTC é igual à de um dos extremos (início do range)
+                if (a_time_start.min <= alarm_time.min)
+                    range = 1;
+                else range = 0;    
+            }
+            else if (a_time_end.hour == alarm_time.hour) { // Neste caso a hora do RTC é igual à do último extremo (fim do range)
+                if (a_time_end.min >= alarm_time.min)
+                    range = 1;
+                else range = 0;    
+            }
+            else range = 0;
+        }
+        
+        else if (a_time_start.hour == a_time_end.hour) { // Neste caso a hora de ativamento e de desarme do alarme é a mesma. Mas o caso específico será destrinchado nos "ifs" aninhados
+            if (a_time_start.min < a_time_end.min) {
+                if (alarm_time.hour == a_time_start.hour) {
+                    if (a_time_start.min <= alarm_time.min && alarm_time.min <= a_time_end.min)
+                        range = 1;
+                    else range = 0;    
+                }
+                else range = 0;
+            }
+            else if (a_time_start.min > a_time_end.min) {
+                if (alarm_time.hour == a_time_end.hour) {
+                    if (a_time_start.min > alarm_time.min && alarm_time.min > a_time_end.min)
+                        range = 0;
+                    else range = 1;    
+                }
+                else range = 1;
+            }
+            else if(a_time_start.min == a_time_end.min) range = 0;
+        }
+        
+        else if (a_time_start.hour > a_time_end.hour) { // Neste caso, o range está contido em um período que compreende dois dias - alarme permanece ativado na transição de 23:59 para 0:00. As horas de início e fim do alarme são diferentes.
+            if (a_time_start.hour > alarm_time.hour && alarm_time.hour > a_time_end.hour)
+                range = 0;  
+            else if (a_time_end.hour == alarm_time.hour) {
+                if (a_time_end.min < alarm_time.min)
+                    range = 0;
+                else range = 1;    
+            } 
+            else if (a_time_start.hour == alarm_time.hour) {
+                if (a_time_start.min > alarm_time.min)
+                    range = 0;
+                else range = 1;    
+            } 
+            else range = 1;
+        }
+                
+    }
+        
+}      
 
+ void set_state () {
+ 
+    while (1) {
+        
+        if (state != 3) { //se estado é 3 o alarme foi desabilitado pelo usuario, logo não são necessarios teste
+            if (range == 0 && state == 1) state = 0; //se nao esta no range e estado =1(armado), desarma automatico 
+            if (range == 1 && state == 0) state = 1; //se esta no range mas estado = 0 (desarmado), arma automatico 
+            if (range == 1 && state == 1) { //estado armado e no range
+                if (enable) state = 2;  //se o sensor pir mandar um sinal em alto, manda para o estado 2 (armado)
+            }
+        }    
+         
+         
+
+         
+    }    
+ 
+ }
+
+ //thread resposavel por verificar a hora
+ void rtc_read (){
+ 
+ while(1){
+        rtc.getTime(alarm_time);
+        }
+        
+ 
+ }
+ 
+void led_thread()
+{
+    //apaga todos os leds antes de acender os leds desejados
+    led_blue=1;
+    led_green=1;
+    led_blue =1;
+    
+    
+ while(true){   
+    
+if(state == 0 || state==3) { //neste caso o alarme não está ativo - estado desarmado ou desarmado forçado
+    
+    
+    led_green = 1;
+    led_blue = 1;
+    led_red =0;
+       
+    
+    }    
+    
+    
+    if(state == 1) //se estiver armado só liga o led verde
+    
+    {
+    
+    led_green = 0; 
+    led_blue = 1;
+    led_red =1;    
+        
+        
+        
+    }
+    
+    
+    if(state == 2) //estado disparado: acionamento dos leds vermelho e azul alternado em 0.5s, buzzer é ativo junto com os leds na mesma frequência
+    
+    {   //desliga todos os leds para assegurar que somente os desejados estarão ligados neste estado
+        led_red=1;
+        led_blue=1;
+        led_green =1;
+        
+        led_red =0; //liga o led vermelho
+        buzzer = 0;  //liga o buzzer, ativo em 0 devido ao transistor PNP
+        wait(0.5); //aguarda meio segundo
+        led_red = 1; //desliga o led vermelho
+        led_blue = 0; //liga o led azul
+        buzzer = 1; //desliga o buzzer 
+        wait(0.5);  //aguarda 0.5s
+        led_blue=1; //desliga o led azul    
+        
+        
+        
+        }
+    
+    }
+    
+    
+}
+
+//thread para estabelecer comunicação via sockets
+void socket_thread(){
+    
+        //inicia um comunicação via socket com o seguinte servidor
+        Websocket ws("ws://192.168.2.2:8555/ws", &eth);
+        //conecta
+        int connect_error = ws.connect();
+        //wait para o sensor exibir mensagem de comunicação
+        wait(1);
+
+
+    
+//buffer de entrada, guarda dados do servidor
+char buf_in[20];
+//ponteiro usado na função strtok_r
+char *token;
+//char para o codigo para indicar que o servidor deve exibir o menu
+char menu_return[2];
+
+
+        
+        
+   //loop da thread     
+   while(true){     
+   
+        
+
+          //se receber dados via socket     
+         if (ws.read(buf_in)) {
+             //cria uma cópia do buffer para ser "thread safe"
+             char *rest = buf_in;
+             //corta a string entre espaços
+             token = strtok_r(rest, " ", &rest);
+             //converte o primeiro dado para int. opt indica qual operação sera realiza, é sempre o primeiro dado da string recebida
+             int opt = atoi(token); 
+             //se for 1, realiza a modificação do horario de inicio e fim de operação do alarme 
+             if(opt ==1){
+            //divide a string e converte os dados para int   
+             token = strtok_r(rest, " ", &rest);
+             int start_hour = atoi(token);
+             token = strtok_r(rest, " ", &rest);
+             int start_min = atoi(token);
+             token = strtok_r(rest, " ", &rest);
+             int start_sec = atoi(token);
+            token = strtok_r(rest, " ", &rest);
+             int end_hour = atoi(token);
+             token = strtok_r(rest, " ", &rest);
+             int end_min = atoi(token);
+             token = strtok_r(rest, " ", &rest);
+             int end_sec = atoi(token); 
+             //faz atribuições
+             a_time_start.hour  = start_hour;
+             a_time_start.min  = start_min;
+             a_time_start.sec  = start_sec;
+             a_time_end.hour  = end_hour;
+             a_time_end.min  = end_min;
+             a_time_end.sec  = end_sec;
+
+            
+            sprintf (menu_return, "99"); //codigo de retorno ao menu para a aplicação no pc
+            ws.send(menu_return); //envia código indicando que a operação foi finalizada e aplicação deve retornar ao menu
+            
+            
+            
+             }
              
              
-                
- }               
- 
-void ajus_data_hora()
-    
-{
-
-   char hadj;
-   gSerial.printf("Deseja ajustar a hora? - Caso sim digite s: ");
-   gSerial.scanf("%c",&hadj);
-   if(hadj=='s')
-   {
-    set_time_serial();
-    
-    }
-
-}
-  
+             //opção 2 usuario habilita ou desabilita o alarme mesmo que esteja dentro do range de tempo de funcionamento
+             if(opt == 2)
+             {
+                 char en_dis[25];
+                 //se o estado for diferente de 3 (desarmado pelo usuario), seta em 3
+                 if(state!=3){
+                  
+                 printf("opt: %d\n",opt);
+                 state =3;
+                 
+                 printf("state: %d\n",state);
+                  //envia feedback para a aplicação
+                    sprintf (en_dis, "Sistema Desabilitado");        
+                    ws.send(en_dis);
+                 
+                 }
+                 //caso for 3 habilita o alarme
+                 else if(state==3){
+                     
+                 printf("opt: %d\n",opt);
+                 state =0;
+                 
+                  //envia feedback para a aplicação
+                 sprintf (en_dis, "Sistema Habilitado");        
+                 ws.send(en_dis);
                 
 
 
-int main()
-{   
+                     
+                     }
+                    wait(1);
+                    sprintf (menu_return, "99"); //codigo de retorno ao menu
+                    ws.send(menu_return);
+             }
+             
+            // envia para a aplicação feedback de seu status
+             if(opt == 3) 
+             {  char state_text[60];
+                
+                if(state == 0){
+                    sprintf (state_text, "Alarme Desabilitado - Fora do Periodo de Funcionamento");        
+                    ws.send(state_text);
+                    }
+                if(state == 1){
+                    sprintf (state_text, "Alarme Habilitado");        
+                    ws.send(state_text);
+                    }
+                if(state == 2){
+                    sprintf (state_text, "Alarme Disparado!!!");        
+                    ws.send(state_text);
+                    }
+                if(state == 3){
+                    sprintf (state_text, "Alarme Desabilitido pelo Usuario");        
+                    ws.send(state_text);
+                    }       
+                                wait(1);
+                                sprintf (menu_return, "99"); //codigo de retorno ao menu
+                                ws.send(menu_return);
+                 
+            }  //fim do opt==3
+             
+                
+                 
+                //informa para a aplicação, que deve voltar ao menu principal       
+                 if(opt == 8 || opt == 6)
+                     
+                     {
+                         char back_to_menu1[2];
+                         sprintf(back_to_menu1,"99");
+                        ws.send(back_to_menu1);
+                         
+                         
+                     }
+
 
-   char hadj; //opcao do ajuste do rtc
-   gSerial.printf("Deseja ajustar a hora? - Caso sim digite s: ");
-   gSerial.scanf("%c",&hadj);
-   if(hadj=='s') //caso seja digitado s exibe as opcoes de ajuste 
-   {
-    set_time_serial();
+         }
+         
+         //caso dispare
+         if(state==2){
+                        //buffer de entrada
+                        char state_2[1];
+                        //para sair do loop
+                        int input =1; 
+                        //manda código para a apicação informando que o alarme disparou
+                        char disp[2];
+                        //int resposavel por armazenar a resposta da aplicação
+                        int state_20;
+                        sprintf(disp,"88"); //codigo 88 alarme disparado
+                        ws.send(disp);
+                        //loop para receber a resposta
+                        while(input){
+                            //se receber dados da aplicação
+                            if(ws.read(state_2)){ 
+                            
+                            
+                            //converte para int o dado recebido
+                            state_20 = atoi(state_2);
+                            
+                      
+                            
+                            }
+                            
+                                //se for 9 (indica que o usuario desabilitou o alarme)
+                                if(state_20 == 9) {
+                                
+                                
+                                 //alarme desabilitado, volta para 0, deixa para a thread set_state decidir o proximo estado
+                                state = 0;
+                               //condicao para sair do loop
+                               input = 0;
+
+                               
+                               }
+                                
+                            
+                         
+                            }//fim do while do state 2
+                        
+
+             
+         }//fim do if state=2
+        
+        
+        
+                
+              }//fim do while
+                
+            
+            
+            
+
+    
     
     }
 
 
-  
-    while (true) {
+//thread explicitamente usada para debug, nao realiza trabalho útil. É dispensável para o funcionamento do sistema
+void print_range(){
+
+while(true){
+
+//hora do rtc
+gSerial.printf("Hora: %2d:%02d:%02d \n",alarm_time.hour,alarm_time.min,alarm_time.sec);  
+//valor do range
+gSerial.printf("Valor Range: %d\n", range);
+//valor de hora de inicio e fim da ativação ajustado via aplicação
+gSerial.printf("para a estrutura: start_hour: %d start_min: %d start_sec: %d end_hour: %d end_min: %d end_sec: %d \n",a_time_start.hour,a_time_start.min,a_time_start.sec,a_time_end.hour,a_time_end.min,a_time_end.sec);  
+
+wait(1);
+
+
+
+}
+
+
+}
+
+
 
-        rtc.getTime(alarm_time);
-        led = !led;  
-        gSerial.printf("\r");
-        gSerial.printf("Hora: %2d:%02d:%02d \n",alarm_time.hour,alarm_time.min,alarm_time.sec);  
-        wait(1);      
-                }
-                
-                
-            
-            
-            
-} 
\ No newline at end of file
+ 
+ int main()
+ {       
+         buzzer = 1; //desativa o buzzer. Como usamos um transistor pnp para chavear o buzzer, a lógica é inversa. O buzzer deve ser desativado pois a saida default da porta é 0
+         enable.mode(PullDown); //coloca na entrada um resistor de pull-down para ler 0, a não ser que exista uma entrada em 1 vindo do sensor PIR    
+          
+        int x = eth.set_dhcp(true); //ativa dhcp
+        int i=eth.connect(); //conecta
+        //verifica conexão para debug apenas
+        gSerial.printf("DHCP status: %i \r\n",x);
+        gSerial.printf("connect status: %i \r\n",i);
+        gSerial.printf("IP Address is %s\n\r", eth.get_ip_address());
+        
+
+        
+        
+         
+        //Iniciando o alarme com valor default inicial
+        a_time_start.hour = 0;
+        a_time_start.min = 10;
+        
+        //Iniciando o alarme com valor default final
+        a_time_end.hour = 6;
+        a_time_end.min = 50;        
+  
+
+           
+        wait(2); //aguarda 2s para o sensor PIR gerar uma saida consistente   
+        
+        //Inicialização das Threads
+         SetRange = new Thread(set_range);
+         RtcRead = new Thread(rtc_read);
+         PrintRange = new Thread(print_range);
+         SetState = new Thread(set_state);
+         LedThread = new Thread(led_thread); 
+         SocketThread = new Thread(socket_thread);
+        
+  
+   
+         
+         
+
+}
+ 
+
+
+
+