Ian Bolfarini
/
APS_SO
APS_SO
main.cpp
- Committer:
- ianwillianb
- Date:
- 2017-12-15
- Revision:
- 2:27a7a42b2bae
- Parent:
- 1:3da12598c635
File content as of revision 2:27a7a42b2bae:
#include "mbed.h" #include "rtos.h" #include "Rtc_Ds1307.h" #include "EthernetInterface.h" #include "Websocket.h" #include <iostream> #include <string> //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); //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, 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 ) { gSerial.printf("\nInsira a hora(HH MM SS): "); gSerial.scanf("%d %d %d", &hora, &min, &seg); if( (hora < 24 && hora>=0) && (min>=0 && min <60) && (seg>=0 && seg <60)) { rtc.getTime(alarm_time); alarm_time.hour = hora; alarm_time.min = min; alarm_time.sec = seg; 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); } else gSerial.printf("Entrada Incorreta.\n"); } if(opt==2 || opt ==3) { 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; rtc.setTime(alarm_time, true, false); rtc.getTime(alarm_time); gSerial.printf("\nData Ajustada: %2d/%02d/%d \n",alarm_time.date,alarm_time.mon,alarm_time.year); } else gSerial.printf("Entrada Incorreta.\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", ð); //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 } //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); } 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); } } //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 } //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); } } 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); }