WebServer SD

Salve a tutti, vi scrivo per chiedervi una mano, da poco mi sto dilettando sulla configurazione di un Arduino Uno per la domotica.
Ho iniziato con il WebServer seguente …

#include <Ethernet.h>


byte mac[] = { 0x54, 0x55, 0x58, 0x10, 0x05, 0x24 };
byte ip[]  = { 192, 168, ***, *** };                  // IP-Adresse
byte gateway[] = { 192, 168, ***, *** };                // Gateway
byte subnet[]  = { 255, 255, ***, *** };

Server server(80);

int Pin2 = 2;
int Pin3 = 3;
int Pin4 = 4;
int Pin5 = 5;

String readString = String(100);

void setup(){
Ethernet.begin(mac, ip, gateway, subnet);
server.begin();
pinMode(Pin2, OUTPUT);
pinMode(Pin3, OUTPUT);
pinMode(Pin4, OUTPUT);
pinMode(Pin5, OUTPUT);

Serial.begin(9600); }

void loop(){

Client client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();

if (readString.length() < 100) {

readString = readString + c;
}

Serial.print(c);

if (c == '\n') {

if(readString.indexOf("2=On+%2F+Off") > -1) {
digitalWrite(Pin2, HIGH);
delay(100);
digitalWrite(Pin2, LOW);
Pin2ON = true;

}

if(readString.indexOf("3=On+%2F+Off") > -1) {
digitalWrite(Pin3, HIGH);
delay(100);
digitalWrite(Pin3, LOW);
Pin3ON = true;
}
if(readString.indexOf("4=On+%2F+Off") > -1) {
digitalWrite(Pin4, HIGH);
delay(100);
digitalWrite(Pin4, LOW);
Pin4ON = true;
}
if(readString.indexOf("5=On+%2F+Off") > -1) {
digitalWrite(Pin5, HIGH);
delay(100);
digitalWrite(Pin5, LOW);
Pin5ON = true;
}

if(readString.indexOf("all=Spegni") > -1){
digitalWrite(Pin2, HIGH);
digitalWrite(Pin3, HIGH);
digitalWrite(Pin4, HIGH);
digitalWrite(Pin5, HIGH);
delay(100);
digitalWrite(Pin2, LOW);
digitalWrite(Pin3, LOW);
digitalWrite(Pin4, LOW);
digitalWrite(Pin5, LOW);

}
//--------------------------HTML------------------------
client.println("HTTP/1.1 200 OK");

client.println("Content-Type: text/html");

client.println();

client.print("<html><head>");

client.print("<title>Arduino Webserver</title>");

client.println("</head>");

client.print("<body>");

client.println("<div style='width:240px; height:320px;'>"); //risoluzione per nokia e66 240x320

client.println("<center><font color='#2076CD'>ARDUINO</font color></center>");

client.println("
");

client.println("<table><tr>");

client.println("<td><font face='Verdana' size='2'>Controllo n1</font></td>");

client.println("<td><form method=get><input type=submit name=4 value='On / Off'></form></td>");

client.println("</tr><tr><td><font face='Verdana' size='2'>Controllo n2</font></td>");

client.println("<td><form method=get><input type=submit name=2 value='On / Off'></form></td>");

client.println("</tr><tr><td><font face='Verdana' size='2'>Controllo n3</font></td>");

client.println("<td><form method=get><input type=submit name=3 value='On / Off'></form></td>");

client.println("</tr><tr><td><font face='Verdana' size='2'>Controllo n4
</font></td>");

client.println("<td><form method=get><input type=submit name=5 value='On / Off'></form></td>");

client.println("</tr><tr><td><font face='Verdana' size='2'>Spegni tutto</font></td><td><form method=get><input type=submit name=all value='Spegni'></form></td>");

client.println("</tr><table></div></body></html>");

readString="";

client.stop();
}}}}}


Ora avendo una conoscenza medio-alta di html e css ho pensato di migliorarne l’aspetto grafico.
Quindi ho realizzato un sito più complesso composto da un index dal quale raggiungere altre pagine con i pulsanti per controllare i relè ,con immagini il tutto gestito dai css … non ho ancora realizzato il client … però ora sorge il “problema” del caricare i vari file .html il .css e le 5 immagini sull’SD.
Ho trovato TinyWebServer che non ho compreso, potete spiegarmi come funziona la mia conoscenza del C è basilare!

se non erro carichi i file direttamente su SD, e la libreria fa il resto. Il file "di ingreeso" è l'index.html

Ho utilizzato il seguente esempio presente nell’archivio del TinyWebServer “BlinkLed”

// -*- c++ -*-
//
// Copyright 2010 Ovidiu Predescu <ovidiu@gmail.com>
// Date: December 2010
//

#include <SPI.h>
#include <Ethernet.h>
#include <Flash.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <TinyWebServer.h>

// The LED attached in PIN 13 on an Arduino board.
const int ledPin = 7;

// The initial state of the LED
int ledState = LOW;

void setLedEnabled(boolean state) {
  ledState = state;
  digitalWrite(ledPin, ledState);
}

inline boolean getLedState() { return ledState; }

boolean file_handler(TinyWebServer& web_server);
boolean blink_led_handler(TinyWebServer& web_server);
boolean led_status_handler(TinyWebServer& web_server);
boolean index_handler(TinyWebServer& web_server);

TinyWebServer::PathHandler handlers[] = {
  // Work around Arduino's IDE preprocessor bug in handling /* inside
  // strings.
  //
  // `put_handler' is defined in TinyWebServer
  {"/", TinyWebServer::GET, &index_handler },
  {"/upload/" "*", TinyWebServer::PUT, &TinyWebPutHandler::put_handler },
  {"/blinkled", TinyWebServer::POST, &blink_led_handler },
  {"/ledstatus" "*", TinyWebServer::GET, &led_status_handler },
  {"/" "*", TinyWebServer::GET, &file_handler },
  {NULL},
};

const char* headers[] = {
  "Content-Length",
  NULL
};

TinyWebServer web = TinyWebServer(handlers, headers);

boolean has_filesystem = true;
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

static uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// Don't forget to modify the IP to an available one on your home network
byte ip[]  = { 192, 168, *** , *** };                  // IP-Adresse
byte gateway[] = { 192, 168, ***, *** };                // Gateway
byte subnet[]  = { 255, 255, ***, *** };

void send_file_name(TinyWebServer& web_server, const char* filename) {
  if (!filename) {
    web_server.send_error_code(404);
    web_server << F("Could not parse URL");
  } else {
    TinyWebServer::MimeType mime_type
      = TinyWebServer::get_mime_type_from_filename(filename);
    web_server.send_error_code(200);
    web_server.send_content_type(mime_type);
    web_server.end_headers();
    if (file.open(&root, filename, O_READ)) {
      Serial << F("Read file "); Serial.println(filename);
      web_server.send_file(file);
      file.close();
    } else {
      web_server << F("Could not find file: ") << filename << "\n";
    }
  }
}

boolean file_handler(TinyWebServer& web_server) {
  char* filename = TinyWebServer::get_file_from_path(web_server.get_path());
  send_file_name(web_server, filename);
  free(filename);
  return true;
}

boolean blink_led_handler(TinyWebServer& web_server) {
  web_server.send_error_code(200);
  web_server.send_content_type("text/plain");
  web_server.end_headers();
  // Reverse the state of the LED.
  setLedEnabled(!getLedState());
  Client& client = web_server.get_client();
  if (client.available()) {
    char ch = (char)client.read();
    if (ch == '0') {
      setLedEnabled(false);
    } else if (ch == '1') {
      setLedEnabled(true);
    }
  }
}

boolean led_status_handler(TinyWebServer& web_server) {
  web_server.send_error_code(200);
  web_server.send_content_type("text/plain");
  web_server.end_headers();
  Client& client = web_server.get_client();
  client.println(getLedState(), DEC);
}

boolean index_handler(TinyWebServer& web_server) {
  send_file_name(web_server, "INDEX.HTM");
  return true;
}

void file_uploader_handler(TinyWebServer& web_server,
			   TinyWebPutHandler::PutAction action,
			   char* buffer, int size) {
  static uint32_t start_time;
  static uint32_t total_size;

  switch (action) {
  case TinyWebPutHandler::START:
    start_time = millis();
    total_size = 0;
    if (!file.isOpen()) {
      // File is not opened, create it. First obtain the desired name
      // from the request path.
      char* fname = web_server.get_file_from_path(web_server.get_path());
      if (fname) {
	Serial << F("Creating ") << fname << "\n";
	file.open(&root, fname, O_CREAT | O_WRITE | O_TRUNC);
	free(fname);
      }
    }
    break;

  case TinyWebPutHandler::WRITE:
    if (file.isOpen()) {
      file.write(buffer, size);
      total_size += size;
    }
    break;

  case TinyWebPutHandler::END:
    file.sync();
    Serial << F("Wrote ") << file.fileSize() << F(" bytes in ")
	   << millis() - start_time << F(" millis (received ")
           << total_size << F(" bytes)\n");
    file.close();
  }
}

void setup() {
  Serial.begin(115200);
  Serial << F("Free RAM: ") << FreeRam() << "\n";

  pinMode(ledPin, OUTPUT);
  setLedEnabled(false);

  // initialize the SD card
  Serial << F("Setting up SD card...\n");
  pinMode(10, OUTPUT); // set the SS pin as an output (necessary!)
  digitalWrite(10, HIGH); // but turn off the W5100 chip!
  if (!card.init(SPI_FULL_SPEED, 4)) {
    Serial << F("card failed\n");
    has_filesystem = false;
  }
  // initialize a FAT volume
  if (!volume.init(&card)) {
    Serial << F("vol.init failed!\n");
    has_filesystem = false;
  }
  if (!root.openRoot(&volume)) {
    Serial << F("openRoot failed");
    has_filesystem = false;
  }

  if (has_filesystem) {
    // Assign our function to `upload_handler_fn'.
    TinyWebPutHandler::put_handler_fn = file_uploader_handler;
  }

  Serial << F("Setting up the Ethernet card...\n");
  Ethernet.begin(mac, ip);

  // Start the web server.
  Serial << F("Web server starting...\n");
  web.begin();

  Serial << F("Ready to accept HTTP requests.\n");
}

void loop() {
  if (has_filesystem) {
    web.process();
  }
}

Ha funzionato riesco a vedere le pagine caricate sull’SD
adesso dovrei inserire il client per farlo interagire con la pagina web?
per esempio come nel mio primo CODE?

Client client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();

if (readString.length() < 100) {

readString = readString + c;
}

Serial.print(c);

if (c == '\n') {

if(readString.indexOf("2=On+%2F+Off") > -1) {
digitalWrite(Pin2, HIGH);
delay(100);
digitalWrite(Pin2, LOW);
Pin2ON = true;

}

giusepperomano: Salve a tutti, vi scrivo per chiedervi una mano, da poco mi sto dilettando sulla configurazione di un Arduino Uno per la domotica. Ho iniziato con il WebServer seguente ...

Ciao,

io sono ancora un passo indietro e ho provato a studiare il tuo sketch iniziale, che non capisco..... Mi sembra che le variabili Pin2ON (etc...) non siano state dichiarate (infatti mi da errore)...inoltre non capisco questi cicli IF

if(readString.indexOf("3=On+%2F+Off") > -1) { digitalWrite(Pin3, HIGH); delay(100); digitalWrite(Pin3, LOW); Pin3ON = true;

Prima accendi a poi spegni? non manca qualcosa?

Grazie, Andrea.

lesto: se non erro carichi i file direttamente su SD, e la libreria fa il resto. Il file "di ingreeso" è l'index.html

Scusa se ti correggo ma index va scritta in formato DOS 8+3, altrimenti non funziona.

Quindi: index.htm

BaBBuino:

lesto: se non erro carichi i file direttamente su SD, e la libreria fa il resto. Il file "di ingreeso" è l'index.html

Scusa se ti correggo ma index va scritta in formato DOS 8+3, altrimenti non funziona.

Quindi: index.htm

felice di essere corretto :-)

Ragà ma ogni 2 giorni, anzi no, un giorno si e l'altro anche, c'è un post sul WebServer-Arduino.

Ma non sarebbe il caso di farci una sotto-sezione per mega-sviluppi?

una sul networking in effetti ci sta tutta

Ragà ma ogni 2 giorni, anzi no, un giorno si e l'altro anche, c'è un post sul WebServer-Arduino.

Ma non sarebbe il caso di farci una sotto-sezione per mega-sviluppi?

sezioni o sottosezioni a parte (tema che in questi giorni va di moda), un buon punto di partenza sarebbe sfogliare qualche pagina o che so, fare una ricerca (in alto a sx, oppure con google), prima di aprire un altro post. Personalissima opinione :zipper_mouth_face: (e soprattutto non diretta a chi ha aperto il thread, è generale)

per quello che riguarda il tinywebserver è molto più semplice di quello che credi.

{"/upload/" "", TinyWebServer::PUT, &TinyWebPutHandler::put_handler }, questa e la relativa funzione void file_uploader_handler(TinyWebServer& web_server, TinyWebPutHandler::PutAction action, char buffer, int size)

la puoi anche eliminare non è necessaria al funzionamento tantomeno per capire come funziona, serve per fare gli upload dei file, il creatore di questo sketch lo utilizzava con un file batch su windows oppure con un curl da php per fare l'upload dei file verso la sd perchè si era stufato di metterla e toglierla

le uniche funzioni che devi capire sono queste 2. e tutto gira qui tutto il resto non va toccato che serve per gestire il caricamento dei vari file da parte del client (download del client da sd)

questa riceve i dati dal client POST {"/blinkled", TinyWebServer::POST, &blink_led_handler }, .......richiama il void blink_led_handler(.....)

questa invia i dati al client con GET {"/ledstatus" "*", TinyWebServer::GET, &led_status_handler },............richiama il void led_status_handler (......)

ciao

Buongiorno, ho letto questo topik ed approfitto per chiedere una informazione, ho usato il progetto messo all'inizio (modificando l'ip, le righe riferite al server con EthernetServer e dichiarando i vari PinXON come boolean), tutto funziona tranne una cosa che non mi è per nulla chiara... Al momento che premo il pulsante mi fa accende il led corretto ma subito dopo lo spegne e non capisco il perchè. Alla fine i vari miei progetti web mi danno lo stesso risultato, un lampeggio al posto di una accensione effettiva. Dato che e il 3° progetto che trovo, copio e testo dandomi lo stesso problema, non capisco quale sia la causa.

Ad ogni modo io uso una mega 2560 con shield ethernet, forse sarà questa la causa??

Ringrazio in anticipo... Saluti Max

ora ho provato anche con un arduino UNO SMD... stesso problema, lampeggia ma non resta acceso fisso...

Non è un problema di arduino se mega o uno, io utilizzo tinywebserver, ovviamente moolto modificato e stravolto completamente, sinceramente non ho provato lo sketch postato su questo treadth anche perchè dubito che funzioni sulla 1.0.

Considera che questo progetto (tinywebserver) lavora su webserver persistente con socket, nel senso che un informazione viene inviata e ricevuta 2 volte al secondo circa, in continuazione e all'infinito con jquery, pertanto nel tuo caso 99/100 si tratta di informazioni sbagliate tra client e server

Domanda: che IDE usi 1.0 o precedenti? Parli del primo sketch postato o del terzo post? perchè sono un po' differenti

ciao

Grazie per la celere risposta,
io uso il primo sketch postato, modificato come gia scritto…

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

byte mac[] = { 0x54, 0x55, 0x58, 0x10, 0x05, 0x24 };
byte ip[]  = { 192, 168, 10, 25 };                  // IP-Adresse
byte gateway[] = { 192, 168, 10, 1 };                // Gateway
byte subnet[]  = { 255, 255, 255, 0 };

EthernetServer server(80);
boolean Pin2ON  = false;
boolean Pin5ON  = false;
boolean Pin3ON  = false;
boolean Pin4ON  = false;
int Pin2 = 7;
int Pin3 = 8;
int Pin4 = 9;
int Pin5 = 5;

String readString = String(100);

void setup(){
Ethernet.begin(mac, ip, gateway, subnet);
server.begin();
pinMode(Pin2, OUTPUT);
pinMode(Pin3, OUTPUT);
pinMode(Pin4, OUTPUT);
pinMode(Pin5, OUTPUT);

Serial.begin(9600); }

void loop(){

EthernetClient client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();

if (readString.length() < 100) {

readString = readString + c;
}

Serial.print(c);

if (c == '\n') {

if(readString.indexOf("2=On+%2F+Off") > -1) {
digitalWrite(Pin2, HIGH);
delay(100);
digitalWrite(Pin2, LOW);
Pin2ON = true;

}

if(readString.indexOf("3=On+%2F+Off") > -1) {
digitalWrite(Pin3, HIGH);
delay(100);
digitalWrite(Pin3, LOW);
Pin3ON = true;
}
if(readString.indexOf("4=On+%2F+Off") > -1) {
digitalWrite(Pin4, HIGH);
delay(100);
digitalWrite(Pin4, LOW);
Pin4ON = true;
}
if(readString.indexOf("5=On+%2F+Off") > -1) {
digitalWrite(Pin5, HIGH);
delay(100);
digitalWrite(Pin5, LOW);
Pin5ON = true;
}

if(readString.indexOf("all=Spegni") > -1){
digitalWrite(Pin2, HIGH);
digitalWrite(Pin3, HIGH);
digitalWrite(Pin4, HIGH);
digitalWrite(Pin5, HIGH);
delay(100);
digitalWrite(Pin2, LOW);
digitalWrite(Pin3, LOW);
digitalWrite(Pin4, LOW);
digitalWrite(Pin5, LOW);

}
//--------------------------HTML------------------------
client.println("HTTP/1.1 200 OK");

client.println("Content-Type: text/html");

client.println();

client.print("<html><head>");

client.print("<title>Arduino Webserver</title>");

client.println("</head>");

client.print("<body>");

client.println("<div style='width:240px; height:320px;'>"); //risoluzione per nokia e66 240x320

client.println("<center><font color='#2076CD'>ARDUINO</font color></center>");

client.println("
");

client.println("<table><tr>");

client.println("<td><font face='Verdana' size='2'>Controllo n1</font></td>");

client.println("<td><form method=get><input type=submit name=4 value='On / Off'></form></td>");

client.println("</tr><tr><td><font face='Verdana' size='2'>Controllo n2</font></td>");

client.println("<td><form method=get><input type=submit name=2 value='On / Off'></form></td>");

client.println("</tr><tr><td><font face='Verdana' size='2'>Controllo n3</font></td>");

client.println("<td><form method=get><input type=submit name=3 value='On / Off'></form></td>");

client.println("</tr><tr><td><font face='Verdana' size='2'>Controllo n4
</font></td>");

client.println("<td><form method=get><input type=submit name=5 value='On / Off'></form></td>");

client.println("</tr><tr><td><font face='Verdana' size='2'>Spegni tutto</font></td><td><form method=get><input type=submit name=all value='Spegni'></form></td>");

client.println("</tr><table></div></body></html>");

readString="";

client.stop();
}}}}}

mentre per la versione dell’ ide e la 1.00.
ora ho provato a scaricare la 0023 vediamo se con questa risolvo anche se la 1.00 non mi dava problemi (tranne i noti)

p.s. il tinywebserver non l’ho provato ancora, ho provato 2 guide distinte per realizzare il comando con il web ma il risultato era lo stesso quindi mi sono bloccato…

Grazie :wink:

ciao @medimax, non so cosa devi fare ma il tuo codice, se non sbaglio, mette ad HIGH il relativo pin aspetta 100msec e poi lo mette a LOW. Questo si traduce se hai un led collegato ad una accessione e allo spegnimento quasi immediato. Probabilmente devi controllare la variabile di stato associata ad ogni led se vuoi spegnere/accendere. Ad esempio per il Pin2:

if(readString.indexOf("2=On+%2F+Off") > -1) {
  if(Pin2ON) { //se ON lo spegne
    digitalWrite(Pin2, LOW);
    Pin2ON=false;
  } else { //se OFF lo accende
    digitalWrite(Pin2, HIGH);
    Pin2ON = true;
  }
}

Però tutto dipende da cosa devi fare.

Ciao Critical,

il mio scopo futuro e l domotica e quindi interfacciare il pin con un relè ed accendere (sia tramite un pulsante che tramite interfaccia web) tenendo accesa la luce per poi temporizzarla e spegerla.

ad ogni modo non riesco (per ignoranza) a capire dove gli scrivo di spegnersi dopo 100msec, immagino qui:

"2=On+%2F+Off") > -1

cortesemente mi spieghi come funziona e quale soluzione adottare??

io ho usato anche questo:

"ImpLamSalSX=1") > 0 come variante in un altro progetto simile (ovviamente altro sketch completamente diverso preso da un'altro sito) dove ImpLamSalSX equivale al link per l'accensione ma non capisco l'utilità del =1 dato che se e 1 si accende e se e 0 si spegne...

comunque restiamo sullo sketch attuale, poi mi adatto io...

Allora, per quanto riguarda il relè io mi chiamo fuori... sono newbie newbie :P. Per quanto riguarda il codice invece: readString.indexOf("2=On+%2F+Off") > -1 indexOf è una funzione che ritorna -1 se non trova il parametro della funzione (in questo caso: 2=On+%2F+Off) nel valore della variabile readString http://arduino.cc/en/Reference/StringIndexOf.

Nel tuo caso le righe che spengono il pin dopo 100msec sono: delay(100); digitalWrite(Pin2, LOW); http://arduino.cc/en/Reference/delay http://arduino.cc/en/Reference/digitalWrite.

Cavoli, sono 2 giorni che mi scervello sull'altro sketch che quando ho usato questo, e mi ha dato lo stesso problema, non mi sono accorto del delay e spegnimento successivo... non ho parole che newbie che sono... sta sera provo...

per il relè l'ho già messo in opera su un'altro sketch, è più facile rispetto a gestire l'Arduino da una pagina web.

per la dritta su

readString.indexOf("2=On+%2F+Off") > -1

indexOf è una funzione che ritorna -1

ora mi spiego tante cose, forse e il parametro -1 che mi restituisce che ri-spegne il circuito.

grazie mille per la mia svista..

Non so cosa tu voglia dire con:

ora mi spiego tante cose, forse e il parametro -1 che mi restituisce che ri-spegne il circuito.

ma quello che accende e subito spegne il circuito è il seguente pezzo di codice:

{   digitalWrite(Pin2, HIGH);
    delay(100);
    digitalWrite(Pin2, LOW);
    Pin2ON = true;
}

ossia le istruzioni all'interno dell'if:

if(readString.indexOf("2=On+%2F+Off") > -1)

cioè se la variabile readString contiene: "2=On+%2F+Off" allora la condizione > -1 è vera e l'esecuzione entra nel ramo then eseguendo quindi le 4 istruzioni all'interno delle graffe che sono nell'ordine:

1- accendo il Pin2; 2- aspetto 100msec; 3- spengo il Pin2; 4- metto a true la variabile Pin2ON (che se non sbaglio all'interno del tuo sketch non è mai utilizzata)

Il valore di ritorno della funzione indexOf è utilizzato solo per confrontarla con il "> -1". Se quello che vuoi fare è accendere o spegnere un led (giusto per cominciare per gradi) utilizzando i bottoni del form allora dovresti utilizzare il codice che ti ho postato la prima volta. Consiglio mio è di metterti anche un print della variabile readString fuori dall'if scritto sopra così ti assicuri del suo valore.

Spero di non aver frainteso quanto hai scritto. Ciao.

Ok, tutto giusto e ti ho capito bene..

un'ultima domanda

if(readString.indexOf("2=On+%2F+Off") > -1)

in questo codice mi spieghi il significato lettera per lettera di questo pezzo??

2=On+%2F+Off

e solo perchè ho copiato il codice per poter partire da una base e capire la procedura ma non riesco a spiegarmelo.

2=On+%2F+Off

è la stringa che viene prodotta quando premi il pulsante sulla tabella. Se vuoi fare una prova estrapola il codice HTML che trovi dopo il commento //--------------------------HTML------------------------ (dal tag HTML in poi, senza i client.println :)) salvalo su un file e aprilo con un browser. Quando premi un bottone guarda sulla barra degli indirizzi, la stringa che vedi dopo il ? è '2=On+%2F+Off' (o altro dipende dal bottone che premi ;)) che sarà il valore la variabile readString sulla quale poi sarà invocata la funzione indexOf. In maggior dettaglio: 2 è il valore dell'attributo 'name' del tag input, On+%2F+Off è il valore dell'attributo 'value' ('+' rappresenta lo spazio, %2F è la stringa che identifica il '/') sempre del tag input, = è il carattere che separa il nome della variabile (in questo caso 2) dal suo valore (in questo caso On+%2F+Off) ed è lo standard per richieste GET (form method=get).

Spero di essere stato chiaro.

Ciao