Comandare Arduino da web esterno tramite POST Jquery

Salve a tutti.

Chiedo a qualcuno di voi una mano a risolvere il problema (simile un altra segnalazione Ethernet + Javascript - Networking, Protocols, and Devices - Arduino Forum)

Ho la necessità di inviare dei "messaggi" da un sito esterno verso un WebServer caricato su Arduino usando un POST in Ajax

Di seguito il pezzo di codice che invia il post (all'interno di una pagina html)

 function send() {

$(document).ready(function(){
 $.ajax({
       type: "POST",
       data: "Start",
       dataType: "text/html",
	   url: "http://xx.xxx.xx.xxx",
	   success: function( r ){
	   $( "#result" ).html(r);
		 },
       error: function(){
		$( "#result" ).html("Error")},
	 });
	 
   });
   
   };

il primo problema è che eseguendo il post arriva sul webserver arduino un messaggio di post senza nessun dato collegato (che secondo il codice dovrebbe essere "Start")

Quindi riesco a vedere il post su Arduino "POST / HTTP/1.1HTTP/1.1 "ma nessuna traccia del dato che ho inviato ("Start")

Per completezza: il post lo leggo attraverso la stringa che compongo leggendo carattereXcarattere la "client.read()"

Qualcuno riesce ad aiutarmi a capire dove sbaglio?

Grazie

a parte che la scritta "POST / HTTP/1.1HTTP/1.1 " è sbagliata, dovrebbe essere seguita dagli header, poi dopo dovresti leggere una volta a capo, i dati inviati, e poi 2 volte a capo.
Quindi direi che l'errore è sia nella creazione della stringa post, che nella lettura da parte di arduino. Quindi posta il codice del testbed (un test apposito che legge solo la post su arduino) e la stringa che viene letta

Scusa ma temo di non capire cos'è il testbed...

provo a mettere il codice di arduino (è praticamente l'esempio del webServer dove v'è la sezione per intercettare il POST

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 10, 172, 80, 203 };           // ip in lan

EthernetServer server(80);
char buffer[64];

void setup()
{
    Ethernet.begin(mac, ip);
    Serial.begin(9600);
  server.begin();
  if (!SD.begin(4)) { return; }

}

void loop()
{
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      while(client.available()) {
        char c = client.read();
        
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
           client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          client.println("Server Up & Running");
                  
          String s = buffer;
          
          if (s.startsWith("GET")) {
            Serial.println("Intercettato GET");
         Serial.println(buffer);
            } 
          
          if (s.startsWith("POST")) { 
              Serial.println("Intercettato POST");
             Serial.println(buffer); //in questo caso il contenuto di Buffer è : POST / HTTP/1.1
              }
  
        client.stop();
        }
        else if (c == '\r') {
          // you're starting a new line
          currentLineIsBlank = true;
          buffer[index]='\0';
          index=0;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
          buffer[index++] = c;
        }
         
        
      }
    }
    Serial.println("Client disconnected.");
  }

  
    
}

spero di non aver scritto/detto troppe bestialità :wink:

l'errore è if (c == '\n' && currentLineIsBlank) {

tu quì ad ogni "a capo" invi l'header 200: peccato che come detto prima dovrebbe arrivare dopo un DOPPIO a capo.

Grazie per la dritta.
ci sto lavorando ma per ora ottengo, aggiungendo altri "a capo" altre info non utili
ecco cosa:
POST / HTTP/1.1
Host: xx.xxx.xx.xxx
User-Agent: Mozilla/5.0 (Wiows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: /
Accept-Language: it
Accept-Encoding: gzip, deflate
Connection: keep-alive

per ora accetti un "a capo", che però è preceduto da scritte.
il post è fatto più o meno così:

POST / HTTP/1.1
Host: xx.xxx.xx.xxx
User-Agent: Mozilla/5.0 (Wiows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: */*
Accept-Language: it
Accept-Encoding: gzip, deflate
Connection: keep-alive

dati vari

notare 1 riga vuota tra header e dati, e 2 linee vuote dopo i dati, segnale di fine POST, valido anche per le GET. In effetti il codice di esempio dell'IDE è errato, se non gestisce correttamente questi casi.

Da dove mandi i dati? sicuro sia un server? o una pagina html costruita su un pc remoto? c'è differenza, dovresti avere file PHP se usi un server quindi in ambiente php usi header o curl per spedire pacchetti
Se stai facendo una pagina html con script jquery ajax e usi firefox te lo puoi scordare ..... non si può fare il pacchetto non arriva

perchè usi:
dataType: "text/html", ... ad arduino non mandi codici html
dovresti usare dataType: "text",

ciao

pablos, se riceve parte dell'header la comunicazione è instaurata con successo, quindi non è quello il problema. Il problema e di come legge l'input con arduino.

Non funziona siamo stati in 3 una settimana a provarci in questo forum, ora non ricordo il treadh se lo trovo lo posto.
Firefox blocca le le risposte di arduino. L'header arriva si, ma il dato no.

Quello che gli ho chiesto se il lavoro che sta facendo è su una pag html o su un server, inoltre se lo sta facendo con Firefox
Ripeto FIREFOX NON FUNZIONA CON AJAX

http://blog.endpoint.com/2012/02/jquery-async-ajax-interrupts-ie-not.html

.ajax is not working in firefox - jQuery Forum

http://kodemaniak.de/?p=62

usa la funzione JSON http://usejquery.com/posts/the-jquery-cross-domain-ajax-guide

oppure quello che hai fatto provalo su IE, se non ci sono errori di codice funzionerà, il browser ti chiederà di sbloccare le richieste col classico menu' a tendina, sbloccalo e riceverai i messaggi, solo che lo devi fare ogni volta

ciao

uhmmm, permettere la connessione ma non i dati? mi sembra alquanto strano. Per questo, anche se non ho mai usato ajax, farò il suo avvocato.
Avete controllato l'output con un programma apposito sniffer come snort o simili?
Ho letto che firefox + ajax non permette connessioni se si esce dalla lan... quindi tutto con url locali. Da questo punto di vista tutti e 3 i link che proponi sembrano tentare di uscire all'esterno. Io ti propongo questo (vecchio) link, a vi chiedo.. errori dalla consolle di ajax/firefox??

Sono rimasto basito anch'io qui ci sono varie prove e sniff se hai tempo dacci un occhio ciao

http://arduino.cc/forum/index.php/topic,92140.0.html dalla pag 2 in poi

Ciao,

come dicevate il problema e' di sicurezza, per cui sono bloccati gli scambi di dati cross-domain (anche se i dati vengono inviati, questi vengono semplicemente ignorati dopo la prima riga di intestazione ad esempio HTTP 200 OK.

Oltre alla soluzione di realizzare un proxy server in PHP citata in precedenza, vi sono altre opportunita', ad esempio una alternativa, ancora in evoluzione, presente nei browser piu' recenti sono gli HTML5 Websockets.
I Websockets promettono inoltre di avere bassi tempi di latenza.

Qualcuno ha gia' implementato la cosa facendo delle librerie per Arduino.

Alcune librerie che implementano i websockets per Arduino:

Arduino Websocket server
https://github.com/ejeklint/Arduino-Websocket-Server
e
Arduino Websocket Client

Altro approccio, per chi vuole utilizzare il linguaggio javascript come server, e' quello di utilizzare node.js (nodejs.org) per gestire le connessioni in entrata e i procket i/o per controllareArduino via porta seriale (o via shield Ethernet).

Ciao,
Marco.

Su questo problema c'ho sbattuto la testa anch'io diverso tempo fa. E come vedo sembra essere un problema diffuso.
Fortunatamente si risolve facilmente tramite l'uso delle socket. Io (e ho visto anche altri) ho adottato questa soluzione e non ho avuto problemi con nessun tipo di passaggio dei dati (textplain, json, xml).
In pratica, il succo della faccenda è questo: per realizzare la chiamata AJAX dal server verso Arduino occorre un file .php che faccia da "ponte" tra i due sistemi (una socket, appunto), in modo tale che i dati di ritorno dalla chiamata Ajax siano a loro volta postati da un file .php alla parte client della comunicazione.
Il file potrebbe essere molto simile a questo:

    <?
      // FILE "PONTE" di nome "sock.php"
      $command = $_GET['command'];  // comando da passare ad Arduino
      
      $ip_arduino = "IP_Arduino";
      $port = 62;
      // apre socket con Arduino (30 secondi di timeout)
      $fp = fsockopen ($ip_arduino, $port, $errno, $errstr, 30);
      if (!$fp) {
          echo "$errstr ($errno)
\n";
      } 
      else {
        // inoltra un comando di GET per il recupero dei dati
        fputs ($fp, "GET /?$command HTTP/1.0\r\n\r\n");
        
        //preleva dati di risposta e li invia come risposta alla chiamata AJAX
        header("Content-Type: text/xml");
        while (!feof($fp)) {
            echo fgets($fp, 128);
        }
        fclose ($fp);
      }
    ?>

Nell'esempio io faccio restituire ad Arduino dei dati in formato xml come ad esempio:

  <controllo_luci>
    <linea1>1</linea1>
    <linea2>0</linea2>
    ..... altri dati .....
  </controllo_luci>

ma potrebbe essere usato un qualunque altro formato di dati (come json ad esempio)
il socket legge la risposta, aggiunge l'adeguata intestazione (vedi: header("Content-Type: text/xml"); ), e invia tutto al client Ajax, che poi è quello che ha fatto la chiamata, ad esempio:

      // invia un comando ad Arduino
       function sendArduino(command) {
        // chiamata Ajax al file "PONTE" per contattare Arduino
        $.ajax({
          type      : "GET",
          url       : "sock.php",
          data      : {"command": command},
          dataType  : "xml",         
          
          success: function(xml){
            // recupero dei dati ricevuti...
            var dato1 = $(xml).find('linea1').text();
            var dato2 = $(xml).find('linea2').text();
            // etc...
          },
          error: function(data){
            alert("Errore chiamata Ajax");
          }
        });        
      }

Ovviamente le variabili dato1 e dato2 saranno usate per scrivere i dati nella pagina, nel consueto stile della comunicazione Ajax.
Nell'esempio ho usato JQuery perchè lo trovo un framework incredibilmente efficiente e comodo, ma anche con il "semplice" linguaggio javascript non cambierebbe assolutamente nulla (provato!)

Io non so se ci sono altri modi di risolvere questa faccenda, ma questo metodo funziona...e anche alla grande :slight_smile:

Grazie a tutti per i contributi.
La soluzione mi sembra abbastanza articolata (per non dire incasinata).
Peso che per ora opterò per un workaround molto più grezzo: inserisco nell'url del POST i parametri che voglio passare e poi faccio parsing su Arduino

Grazie

Ma su Internet explorer funziona. Fai come ti aggrada :slight_smile: ..... ciao

Non mi funziona per niente su IE8 (ovviamente dopo aver attivato il blocco Ajax)...rispetto a Firefox e Chrome non arriva assolutamente niente su Arduino.
Ho provato a ridurre i livelli di sicurezza del browser ma niente.
Probabilemente dovrei perderci un po' di tempo ma poi mi ritrovo con una roba che funziona solo su IE...e non lo posso accettare :wink:

Probabilemente dovrei perderci un po' di tempo ma poi mi ritrovo con una roba che funziona solo su IE...e non lo posso accettare :wink:

Hai ragione nemmeno io posso accettare una roba che funziona solo su IE :slight_smile:

@Marco Benini
@dalubar
Attualmente carico la pagina da SD di arduino, quindi su firefox jquery - ajax POST e GET funzionano benissimo, comunque mi interessano anche altre strade, grazie per gli esempi e i link me li studierò

Ciao

MatteoBeginner:
Peso che per ora opterò per un workaround molto più grezzo: inserisco nell'url del POST i parametri che voglio passare e poi faccio parsing su Arduino

Grazie

quindi una get....

hai ragione..grazie

ora devo combattere con i caratteri speciali che mi arrivano nella stringa (%3 ecc.)

Prova con paraimpu, non ho letto i dettagli del tuo problema ma potrebbe aiutarti. Guarda su paraimpu.crs4.it :wink:

MatteoBeginner:
Salve a tutti.

Chiedo a qualcuno di voi una mano a risolvere il problema (simile un altra segnalazione Ethernet + Javascript - Networking, Protocols, and Devices - Arduino Forum)

Ho la necessità di inviare dei "messaggi" da un sito esterno verso un WebServer caricato su Arduino usando un POST in Ajax

Di seguito il pezzo di codice che invia il post (all'interno di una pagina html)

 function send() {

$(document).ready(function(){
$.ajax({
      type: "POST",
      data: "Start",
      dataType: "text/html",
  url: "http://xx.xxx.xx.xxx",
  success: function( r ){
  $( "#result" ).html(r);
},
      error: function(){
$( "#result" ).html("Error")},
});

});
 
  };




il primo problema è che eseguendo il post arriva sul webserver arduino un messaggio di post senza nessun dato collegato (che secondo il codice dovrebbe essere "Start")

Quindi riesco a vedere il post su Arduino "POST / HTTP/1.1HTTP/1.1 "ma nessuna traccia del dato che ho inviato ("Start")

Per completezza: il post lo leggo attraverso la stringa che compongo leggendo carattereXcarattere la "client.read()"

Qualcuno riesce ad aiutarmi a capire dove sbaglio?

Grazie