Go Down

Topic: Arduino + Ethernet Shield + NFC Shield em comunicação de 2 vias com servlet Java (Read 1 time) previous topic - next topic

timrgt

Boa noite!

Bom, tentarei ser o mais sucinto e claro possível na minha dúvida. É o seguinte, estou fazendo um projeto que consiste no Arduino com uma Ethernet Shield e uma NFC Shield ( esta aqui: http://www.seeedstudio.com/wiki/NFC_Shield_V2.0), que deverá ser usada para ler um cartão RFID e enviar a ID do cartão para um servlet em Java para que este execute as operações de banco de dados necessárias. A ideia é fazer com que o servlet retorne um valor inteiro para o Arduino e, de acordo com tal valor, acender um led que será usado para indicar se houve erro ou sucesso na operação. Já consegui fazer com que as duas shields funcionem juntas (ambas usam o pino 10 para SS da comunicação SPI, porém na shield NFC é possível alterar para o pino 9) e envie os dados para o servlet. O grande problema é na hora de receber os dados do servlet. Usei como base a aplicação deste link : http://www.lauridmeyer.com/2012/04/simple-arduino-tcp-client-using-the-ethernetshield-dhcp-and-a-java-server/, porém quando adapto para a minha, não consigo ler os dados enviados pelo servlet corretamente. Aqui vai o código do Arduino (é um tanto extenso)

Code: [Select]

#include <PN532.h>
#include <SPI.h>
#include <Ethernet.h>

/* Define os pinos CS para a Shield NFC e Ethernet */
#define PN532_CS 9
#define ETHNET_CS 10
PN532 nfc(PN532_CS);

/* COnfiguração de rede */
byte mac[] = {
  0x90, 0xA2, 0xDA, 0x0D, 0x3B, 0xB9 }; // MAC
IPAddress ip(192,168,1,110);       // IP do Arduino
IPAddress server(192,168,1,104);  // IP do Servidor
byte netmask[] = {
  255,255,255,0}; // Mascara
EthernetClient client;

/* defino os pinos para os leds */
int redPin =5;
int greenPin = 6;
int bluePin = 7;


/* Rotina para seleção da shield a ser usada */
void spiSelect(int CS) {
  // desativa todas as shields c/ comun. SPI
  pinMode(PN532_CS,OUTPUT);
  pinMode(ETHNET_CS,OUTPUT);
  digitalWrite(PN532_CS,HIGH);
  digitalWrite(ETHNET_CS,HIGH);
  // ativa a shield desejada, através do pino passado por parametro
  digitalWrite(CS,LOW); 
}
/* Rotina que efetua a conexão ao servidor na porta 8080 */
boolean conecta(){
  client.connect(server, 8080);
  Serial.println(client.read());
}



void setup(void) {
  /* Define os pinos dos LEDs como saídas */
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);


  /* Inicia conexão serial */
  Serial.begin(57600);
  Serial.println("Arduino Powered On");

  // desativa o SPI da shield NFC, deixando somente a Ethernet ativa
  spiSelect(ETHNET_CS);
  // ethernet uses the default MSB first so making sure that is set
  SPI.setBitOrder(MSBFIRST);

  /* Inicializa a  rede */

  Ethernet.begin(mac, ip, netmask);
  Serial.print("Arduino IP is ");
  Serial.println(Ethernet.localIP());

  // Desativa o SPI da shield Ethernet, deixando só a NFC ativa
  spiSelect(PN532_CS);
  // NFC uses LSB first so we have to explicitly set that
  SPI.setBitOrder(LSBFIRST);

  /* Inicializa o leitor NFC */
  nfc.begin();
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    digitalWrite(redPin,HIGH); //acende o LED vermelho caso não encontre a shield NFC
    while (1); // halt
  }
  Serial.print("Found chip PN5");
  Serial.println((versiondata>>24) & 0xFF, HEX);
  Serial.print("Firmware ver. ");
  Serial.print((versiondata>>16) & 0xFF, DEC);
  Serial.print('.');
  Serial.println((versiondata>>8) & 0xFF, DEC);
  Serial.print("Supports ");
  Serial.println(versiondata & 0xFF, HEX);
  nfc.SAMConfig();

}

/* Main program loop */
void loop(void) {


  // disable the ethernet SPI here so just NFC is active
  spiSelect(PN532_CS);
  // NFC uses LSB first so we have to explicitly set that
  SPI.setBitOrder(LSBFIRST);

  /* look for MiFare type cards */
  uint32_t id;
  id = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);
  if (id != 0) {
    Serial.print("Read card #");
    Serial.println(id);
    //delay(5000);   
    /* Acende o LED verde quando ler o cartão e depois de 2s apaga e acende apenas o LED azul */
    digitalWrite(bluePin,LOW);
    digitalWrite(greenPin,HIGH);
    delay(2000);
    digitalWrite(greenPin,LOW);
    digitalWrite(bluePin,HIGH);
  }

  // disable the NFC SPI here so just network is active
  spiSelect(ETHNET_CS);
  // ethernet uses the default MSB first so we need to switch back
  SPI.setBitOrder(MSBFIRST);


  // check ethernet is still working
  Serial.print("Arduino IP is ");
  Serial.println(Ethernet.localIP());
  if (id != 0) { //se a ID lida pela shield NFC for diferente de zero
    if (conecta()) { //se houver a conexão com o servidor


      Serial.println("\n");
      //se houver conexão com o servidor, o led azul é ativado
      Serial.println("Conectado ao servidor");
      Serial.println(client.read()); //lê os dados enviados do servidor, usado apenas para verificação pois não foi enviado nada ainda p/ o Arduino
      digitalWrite(bluePin, HIGH);   

      boolean currentLineIsBlank = true;
      /* Inicialmente estava enviando os dados como num formulário, mantive desta maneira*/
      client.print("GET /TG/inserePresenca?id_tag=="); //envia o texto
      Serial.print("GET /TG/inserePresenca?id_tag=="); //replica para a Serial
      Serial.println(client.read()); //lê os dados enviados do servidor, usado apenas para verificação pois não foi enviado nada ainda p/ o Arduino
      client.print(id); //envia a ID lida
      Serial.print(id); //replica para a Serial
      Serial.println(client.read()); //lê os dados enviados do servidor, nesse momento já deveria mostrar o que o servidor enviou
      Serial.println();

      Serial.println();
      /* mantém o LED verde apagado e o azul aceso */
      digitalWrite(greenPin,LOW);
      digitalWrite(bluePin,HIGH);
      client.stop(); //interrompe a conexão
      /* aqui deveria exibir corretamente o que o servidor enviou, idem acima */
      Serial.println("e o que ele leu eh");

    }
    /* se não houver conexão, o led vermelho fica piscando */
    else{
      digitalWrite(bluePin,LOW);
      while(true){
        digitalWrite(redPin,HIGH);
        delay(250);
        digitalWrite(redPin,LOW);
      }
    }

  }
}




E aqui o código do Servlet. Estou usando o do link que mostrei anteriormente, por hora só estou testnado o envio dos dados do servlet para o Arduino:

Code: [Select]

import java.io.*;
import java.net.*;

public class Server {

    //defining the Port on which the Server runs
    private static final int port=8080;
    private static int i=0;

    public static void main(String argv[]) throws Exception
    {
       String clientMsg;//incoming Message from Client
       ServerSocket mySocket = new ServerSocket(port);//the socket
   
       System.out.println("TCP-Server started");

       while(true)
       {
           Socket connectionSocket = mySocket.accept();//aceitando conexões de entrada
           //Bufferedreader para ler o que o cliente envia
     
           BufferedReader clientInput = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
           //Outputstream para enviar as mensagens ao cliente
           DataOutputStream clientOutput = new DataOutputStream(connectionSocket.getOutputStream());
           clientMsg = clientInput.readLine();//reading the Message that was just recieved
           System.out.println(i+"--Client says: " + clientMsg);//print that message
           clientMsg="";
         
            clientMsg+=i;
         
            System.out.println(clientMsg);
         clientOutput.writeBytes(clientMsg);
           i++;
       }
    }
}



Durante a execução, a saída de console do servlet é esta:
Quote

TCP-Server started
0--Client says: GET /TG/inserePresenca?id_tag==1538968478
0
1--Client says: GET /TG/inserePresenca?id_tag==1538968478
1


e a saída de console do Arduino é:
Quote

Arduino Powered On
Arduino IP is 192.168.1.110
Found chip PN532
Firmware ver. 1.6
Supports 7
Arduino IP is 192.168.1.110
Arduino IP is 192.168.1.110
Found 1 tags
Sens Response: 0x4
Sel Response: 0x8
0x5B 0xBA 0xCB 0x9ERead card #1538968478
Arduino IP is 192.168.1.110
-1


Conectado ao servidor
-1
GET /TG/inserePresenca?id_tag==-1
1538968478-1


e o que ele leu eh ______
Arduino IP is 192.168.1.110



O que marquei em negrito é o que ele teoricamente lê do servidor. Reparem que em todos obtenho a leitura -1, mesmo antes de enviar a ID do cartão, e no último (marcado com ___ ) não é recebido nada.

Verificando com o Wireshark, pude constatar que quando o servlet envia a resposta, a conexão TCP foi fechada pelo Arduino, mesmo antes de chegar no client.stop(); no código

Alguém sabe me ajudar a resolver isso?

É meu primeiro post aqui, então já peço desculpas de antemão caso não tenha sido claro o suficiente

Obrigado!



Ok... há algo que não percebi...

Code: [Select]

      Serial.println();
      /* mantém o LED verde apagado e o azul aceso */
      digitalWrite(greenPin,LOW);
      digitalWrite(bluePin,HIGH);
      client.stop(); //interrompe a conexão
      /* aqui deveria exibir corretamente o que o servidor enviou, idem acima */
      Serial.println("e o que ele leu eh");



Tu aqui fazes stop antes de fazeres o print do "e o que ele leu"... depois dessa frase, não tens nada a mandar para a serial a dizer o que ele teria lido... então porque esperas ver algo no Serial Monitor? :|

Os -1 que tu vês é a resposta dos teus client.read()... basicamente a dizer-te que não chegou nada.

Já fizeste um ping do teu servidor ao Arduino? Provavelmente, como está na mesma rede vai dizer-te que um ping demora 1ms ou menos que isso... mas ainda assim o Arduino é um bichinho que mexe rápido e pode não estar disposto a ouvir quando chegam lá os dados.

Porque não experimentas algo como um timeout?
Code: [Select]

boolean currentLineIsBlank = true;
      /* Inicialmente estava enviando os dados como num formulário, mantive desta maneira*/
      client.print("GET /TG/inserePresenca?id_tag=="); //envia o texto
      Serial.print("GET /TG/inserePresenca?id_tag=="); //replica para a Serial
      Serial.println(client.available()); //lê os dados enviados do servidor, usado apenas para verificação pois não foi enviado nada ainda p/ o Arduino
      client.println(id); //envia a ID lida    //manda aqui uma NewLine só por causa das coisas...

unsigned long now = millis();
    Serial.println("testa timeout");
    while ((c = client.available()) <= 0)  {
        if (millis() - now >= 1000)  {  //um segundo para teste... isto é demasiado, mas por agora terá de servir.
            Serial.println("timed out");
            break; //sai daqui para fora
        } //end if
    }  //end while

      Serial.print(id); //replica para a Serial
      while (client.available() >0) {
          Serial.println(client.read()); //lê os dados enviados do servidor, nesse momento já deveria mostrar o que o servidor enviou
      }
      Serial.println();
      Serial.println();
      /* mantém o LED verde apagado e o azul aceso */
      digitalWrite(greenPin,LOW);
      digitalWrite(bluePin,HIGH);
      client.stop(); //interrompe a conexão


Nota também que existe um método chamado available... eu acho que deverias usar o available em vez do read para detectar se chegou algo...
Também acho que devias mandar algo mais interessante que um único caracter... por exemplo, um OK X em que X é o número de série ou algo assim... o zero é algo esquisito de mandar e não sei o que acontece, se o 0 é convertido para ASCII ou enviado como inteiro...

Testaste a tua servlet com um telnet de outro computador por exemplo?
Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

timrgt

Então, depois do stop dei um read para ver se haveria alguma diferença entre o que foi recebido antes. Coloquei ali só para teste mesmo

O ping realmente fica nessa casa, não imaginei que o Arduino fosse tão "impaciente" assim. Testei este código de timeout que você postou e agora estou conseguindo fazer com que o Arduino leia os dados! Constatei via Wireshark que o Arduino só encerra a conexão depois que o servidor envia a resposta, assim ele é capaz de ler o que o servidor envia. O timeout então faz com que o Arduino aguarde alguma resposta durante o tempo definido (1s no caso) antes de 'ir para frente' na execução do programa, correto?

Sobre o available e o read, tenho uma pequena dúvida: o available verifica se há algum dado a ser lido apenas, enquanto o read lê esse dado. Estou certo?

Enviei um número apenas para teste (como você deve ter visto no servlet, o número enviado conta quantas vezes foi feita aquela iteração no servlet), na minha aplicação real irei fazer diferente. Modifiquei um pouco a mensagem ,adicionando um texto "Deu certo" e realmente está chegando tudo, porém o Arduino lê como ASCII mesmo (coloquei os traços apenas para demarcar as linhas):
Quote

Found 1 tags
Sens Response: 0x4
Sel Response: 0x8
0x5B 0xBA 0xCB 0x9ERead card #1538968478
Arduino IP is 192.168.1.110
-1


Conectado ao servidor
-1
GET /TG/inserePresenca?id_tag==0
testa timeout
1538968478e o que ele leu eh
-------
68-------
69-------
85-------
32-------
67-------
69-------
82-------
84-------
79-------
49



De qualquer modo, já foi um grande progresso, ao menos agora consigo fazer com que haja uma troca de mensagens efetivas em ambos os sentidos. Basta agora eu tratar essa informação recebida (converter para String, basicamente) e fazer as ações necessárias. Vou programar tanto o servlet quando o Arduino para fazerem o que desejo e voltarei a postar quando tiver com mais resultados. Desde já muitíssimo obrigado pela ajuda e atenção!




O ping realmente fica nessa casa, não imaginei que o Arduino fosse tão "impaciente" assim. Testei este código de timeout que você postou e agora estou conseguindo fazer com que o Arduino leia os dados! Constatei via Wireshark que o Arduino só encerra a conexão depois que o servidor envia a resposta, assim ele é capaz de ler o que o servidor envia. O timeout então faz com que o Arduino aguarde alguma resposta durante o tempo definido (1s no caso) antes de 'ir para frente' na execução do programa, correto?

Sim. É isso... o programa bloqueia ali até receber algo ou passar 1s sem receber nada.
Podes alterar o timeout... mas não vejo necessidade. Também podes alterar o código para ver quanto tempo demora a receber uma resposta.


Sobre o available e o read, tenho uma pequena dúvida: o available verifica se há algum dado a ser lido apenas, enquanto o read lê esse dado. Estou certo?


Não. Tu apenas podes executar uma funcão de cada vez... o Serial ou o client, têm um buffer onde são guardados os dados recebidos pelo interface onde estão ligados.
O available diz-te o numero de bytes que podem ser lidos nesse instante.
O read, lê um caracter e se não houver nada, envia um -1 para indicar que o buffer está vazio.

Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

mayso

cara estou com mesmo problema

consigo enviar a tag lida
mais nao consigo receber a resposta, sempre leio o -1


Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy