W&T collega
Adattatori per TCP/IP, Ethernet, RS-232, RS-485, USB, 20 mA, Fibra ottica di vetro e plastica, http, SNMP, OPC, Modbus TCP, I/O digitale, I/O analogico, ISA, PCI

Tutorial al Web-IO digitale:

Controllare più Web-IO digitali da un sito internet


Esistono casi applicativi che richiedono che vengano monitorati e controllati dinamicamente più Web-IO da un sito internet comune. Come mostrato nell’esempio Controllare Web-IO digitale da un sito internet proprio con AJAX Fondamentalmente non è difficile programmare siti internet che aggiornano i contenuti della pagina mediante richieste HTTP successive.

Tuttavia i browser attuali per motivi di sicurezza permettono solo alle richieste HTTP inviate con la tecnica AJAX di raggiungere il server, dal quale è stata effettivamente caricata la pagina web.

Esempio: Se da un Web-IO si apre la pagina utente La mia pagina internet, si possono visualizzare dinamicamente qui solo gli stati IO di questo Web-IO.

Cross-Origin-Requests

Si si cerca di caricare contenuti del server B da un sito internet che è stato caricato dal server A, la richiesta HTTP necessaria a questo viene definita Cross-Origin-Request. Come già descritto, i contenuti del browser forniti dopo queste richieste vengono respinti dal browser per motivi di sicurezza.

Affinché il browser accetti ed elabori nonostante tutto questi contenuti, il terzo server interrogato deve inviare nella sua risposta una dichiarazione di Allow-Cross-Origin.

Controllare Web-IO con AJAX

Web-IO e Cross Origin Requests

Gli apparecchi integrati come il Web-IO possono essere configurati in modo tale che venga inviato Allow-Cross-Origin all’inizio dell’HTTP della risposta HTTP. A tal scopo occorre indicare l’URL del Web-server dal quale è stata caricata la pagina web che mandava inizialmente la richiesta - per la combinazione mostrata, quindi p. es. http://<url von Web-IO 0>. In alternativa è possibile inserire un * come wildcard, il che fa si che il browser accetti la risposta indipendentemente da dove venga caricata la pagina web originale.

Il prossimo esempio mostra come si utilizza Cross-Origin nella pratica e come si deve strutturare un rispettivo sito internet per il Web-IO digitale 4.0 2x input, 2x output e il relativo JavaScript.


Preparativi


Struttura di base del proprio sito internet

Pagina internet Cross-Origin

L’impalcatura di base HTML di questa pagina è così:

							
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1250">
<title>Web-IO Digital, Cross Origin</title>
<style type="text/css">
* { font-family:arial; }
table { font-size:14px; text-align:center; padding-left:5px; padding-right:5px;}
.borderLeft { border-left:1px solid #000000; }
.button { font-size:9px; width:40px; }
.name { font-size:20px; font-weight:bold; text-align:center }
.table { background-color:#d6e8ff; border-collapse:collapse; border:1px solid #000000; }
.whiteBack { background-color:#ffffff; }
</style>
<script language="JavaScript" type="text/javascript">

  ........
  ........

</script>
</head>
<body onload="CommandLoop()">
  <form>
    <div align="center">
      <h2>Web-IO 0</h2>
      <span>Password: </span>
      <input id="webio0pw" type="password" maxlength="31" size="20"">
    </div>
  </form>
  <table align="center" class="table">
    <tr>
      <td>input 0</td>
      <td id="webio0input0">OFF</td>
      <td id="webio0counter0">0</td>
      <td>
        <input class="button" onclick="clearCounter(0,0);" type="button" value="Clear">
      </td>
      <td class="borderLeft">output 0</td>
      <td id="webio0output0">OFF</td>
      <td>
        <input class="button" onclick="setOutput(0,0,1);" type="button" value="ON">
        <input class="button" onclick="setOutput(0,0,0);" type="button" value="OFF">
      </td>
    </tr>
    <tr class="whiteBack">
      <td>input 1</td>
      <td id="webio0input1">OFF</td>
      <td id="webio0counter1">0</td>
      <td>
        <input class="button" onclick="clearCounter(0,1);" type="button" value="Clear">
      </td>
      <td class="borderLeft">output 1</td>
      <td id="webio0output1">OFF</td>
      <td>
        <input class="button" onclick="setOutput(0,1,1);" type="button" value="ON">
        <input class="button" onclick="setOutput(0,1,0);" type="button" value="OFF">
      </td>
    </tr>
  </table>
  <br />
  <form>
    <div align="center">
      <h2>Web-IO 1</h2>
      <span>Password: </span>
      <input id="webio1pw" type="password" maxlength="31" size="20"">
    </div>
  </form>
  <table align="center" class="table">
    <tr>
      <td>input 0</td>
      <td id="webio1input0">OFF</td>
      <td id="webio1counter0">0</td>
      <td>
        <input class="button" onclick="clearCounter(1,0);" type="button" value="Clear">
      </td>
      <td class="borderLeft">output 0</td>
      <td id="webio1output0">OFF</td>
      <td>
        <input class="button" onclick="setOutput(1,0,1);" type="button" value="ON">
        <input class="button" onclick="setOutput(1,0,0);" type="button" value="OFF">
      </td>
    </tr>
    <tr class="whiteBack">
      <td>input 1</td>
      <td id="webio1input1">OFF</td>
      <td id="webio1counter1">0</td>
      <td>
        <input class="button" onclick="clearCounter(1,1);" type="button" value="Clear">
      </td>
      <td class="borderLeft">output 1</td>
      <td id="webio1output1">OFF</td>
      <td>
        <input class="button" onclick="setOutput(1,1,1);" type="button" value="ON">
        <input class="button" onclick="setOutput(1,1,0);" type="button" value="OFF">
      </td>
    </tr>
  </table>
</body>
</html>
							
						

qui non vogliamo dilungarci oltre sull’area head qui addentrarci in dettaglio sull’area head e sulle informazioni style. Nel seguito verranno descritti i contenuti dell’ script area. Sono importanti nel body le denominazioni id sulle quali nelle funzioni JavaScript vengono attivati gli oggetti e le celle delle tabelle. Attraverso onclick viene fissata la funzione da aprire ai tasti. Come parametro viene trasferito il numero del Web-IO, seguito dal numero del counter e degli output. Negli output il secondo parametro indica lo stato (0=OFF, 1=ON).

Mantenendo questa sistematica si può adattare l’esempio, senza modifica delle funzioni JavaScript aggiungendo ulteriori righe delle tabelle ad altri modelli Web-IO.

Variabili e funzioni globali nel JavaScript

Innanzitutto è necessario dichiarare alcune variabili globali.

							
var MaxI = 2;
var MaxO = 2;
var WebioIP = [’192.168.0.25’, ’192.168.0.26’]
var ApplicationStep = 0;
var Interval = 500;

// Converting hexadecimal string to Integer
function HexToInt(HexStr)
{ var TempVal;
  var HexVal=0;
  for( var i=0; i<HexStr.length;i++)
  { if (HexStr.charCodeAt(i) > 57)
    { TempVal = HexStr.charCodeAt(i) - 55;
    }
    else
    { TempVal = HexStr.charCodeAt(i) - 48;
    }
    HexVal=HexVal+TempVal*Math.pow(16, HexStr.length-i-1);
  }
  return HexVal;
}
            

È importante inserire nel campo delle variabili WebioIP gli indirizzi IP dei Web-IO interessati.

Inviare richieste HTTP (requests) e ricevere risposte HTTP (reply)


// Sending command lines to Web-IO and receiving IO state
function DataRequest(WebioNo, CommandString)
{ var cor;
  if(window.XDomainRequest)
  { cor = new XDomainRequest();
    if(cor)
    { cor.onload = function()
      { alert( "received: " + cor.responseText);
      }
    }
    else
    { alert(’Your Browser does not support Cross Origin Request’);
    }
  }
  else
  { cor = new XMLHttpRequest();
    cor.onreadystatechange = function()
    { if(cor.readyState == 4)
        updateDisplay(WebioNo, cor.responseText);
    }
  }
  cor.open(’GET’, ’http://’+WebioIP[WebioNo]+’/’+CommandString);
  cor.send();
}
								
							

La gestione delle richieste HTTP e delle risposte HTTP è realizzata dalla funzione DataRequest. Purtroppo Internet Explorer utilizza per l’elaborazione di richieste HTTP altri meccanismi rispetto agli altri browser. Per questo la funzione verifica innanzitutto in quale browser viene eseguito il sito web. La richiesta HTTP trasmessa come CommandString viene inviata al Web-IO, il cui indirizzo IP nel campo variabile WebioIP è inserito al numero WebioNo assegnato. La risposta, quindi l’HTTP-Reply viene quindi trasferita insieme al numero del Web-IO richiesto alla funzione UpdateDisplay.

Richiesta ciclica di input, output e counter

								
// Preparing command lines for cycle sending
function CommandLoop()
{	var CommandString =’’;
  ApplicationStep++;
  switch(ApplicationStep)
  { case 1:
      CommandString = ’input’;
    break;
    case 2:
      CommandString = ’output’;
    break;
    case 3:
      CommandString = ’counter’;
      ApplicationStep = 0;
    break;
  }
  DataRequest(0, CommandString + ’?PW=’ + document.getElementById(’webio0pw’).value + ’&’);
  DataRequest(1, CommandString + ’?PW=’ + document.getElementById(’webio1pw’).value + ’&’);
  maintimer = setTimeout("CommandLoop()", Interval);
}
								
							

La funzione CommandLoop viene avviata attraverso il parametro onload nel tag body, non appena il sito internet è completamente caricato. La funzione invia attraverso la funzione DataRequest Alternatamente le richieste HTTP per la richiesta di input, output e counter ai Web-IO e si riapre autonomamente in modo ritardato. In questo modo vengono aggiornati continuamente a intervalli fissi gli stati IO.

Collegamento degli output

								
// Set Output to ON (requested from User)
function setOutput(WebioNo, OutNo, OutVal)
{ var iopassword = document.getElementById(’webio’+WebioNo+’pw’).value;
  var CommandString = ’outputaccess’+OutNo+’?PW=’+iopassword+’&State=OFF&’;
  if(OutVal>0)
  { CommandString = ’outputaccess’+OutNo+’?PW=’+iopassword+’&State=ON&’;
  }
  DataRequest(WebioNo, CommandString);
}
								
							

Cliccando sui relativi tasti si apre la funzione setOutput e vengono trasmessi i numeri del Web-IO, dell’output e dello stato da attivare. Attraverso la funzione DataRequest viene inviata la necessaria richiesta HTTP al Web-IO.

Cancellazione dei counter

								
// Set Counter to 0 (requested from display)
function clearCounter(WebioNo, CounterNo)
{ var iopassword = document.getElementById(’webio’+WebioNo+’pw’).value;
  DataRequest(WebioNo, ’counterclear’+CounterNo+’?PW=’+iopassword+’&’);
}
							
						

Cliccando sui relativi tasti si apre la funzione clearCounter e viene trasmesso il numero del Web-IO e dell’input.

Aggiornamento dei contenuti delle pagine web

							
// Dynamic update of the display depending on IO state
function updateDisplay(WebioNo, ReceiveStr)
{ var HexVal;
  var state;
  var ReceiveData = ReceiveStr.split(’;’)
  // Display Intput state
  if (ReceiveData[ReceiveData.length - 2].substring(0, 1) == ’i’)
  { HexVal = HexToInt(ReceiveData[ReceiveData.length - 1]);
    for (var i = 0; i < MaxI; i++)
    { state = false;
      if ((HexVal & Math.pow(2, i)) == Math.pow(2, i))
      { state = true;
      }
      document.getElementById(’webio’+WebioNo+’input’+i).firstChild.data = ( !state ) ? ’OFF’ : ’ON’;
    }
  }
  // Display Output state
  if (ReceiveData[ReceiveData.length - 2].substring(0, 1) == ’o’)
  { HexVal = HexToInt(ReceiveData[ReceiveData.length - 1]);
    for (var i = 0; i < MaxO; i++)
    { state = false;
    if ((HexVal & Math.pow(2, i)) == Math.pow(2, i))
    { state = true;
    }
      document.getElementById(’webio’+WebioNo+’output’+i).firstChild.data = ( !state ) ? ’OFF’ : ’ON’;
    }
  }
  //Display Counter
  if (ReceiveData.length - MaxI - 1 >= 0)
  { if (ReceiveData[ReceiveData.length - MaxI - 1].substring(0, 1) == ’c’)
    { for (var i = 0; i < MaxI; i++)
      {
        document.getElementById(’webio’+WebioNo+’counter’ + i).innerHTML = ReceiveData[ReceiveData.length - MaxI + i]
      }
    }
  }
  //Display cleared Counter
  if (ReceiveData[ReceiveData.length - 2].substring(0, 1) == ’c’)
  { document.getElementById(’webio’+WebioNo+’counter’+ ReceiveData[ReceiveData.length - 2].substring(7, ReceiveData[ReceiveData.length - 2].length)).innerHTML = ReceiveData[ReceiveData.length - 1];
  }
}
							
						

Come risposta a una richiesta HTTP il Web-IO invia sempre il comando effettivo e uno o più parametri separati da punto e virgola.

Per un’interrogazione dell’input p. es. input;1

La funzione UpdateDisplay scompone per mezzo di split la stringa trasmessa in una serie di stringhe. Per l’esempio input si genera una serie con le prime variabili del campo input e le seconde 1. Attraverso le prime lettere delle prime variabili del campo si constata se la risposta interessa un input, output o i counter.

La seconda variabile del campo contiene per input e output il campione bit per lo stato di attivazione degli IO (Bit0=input=, Bit1=input1,...). Dal momento che viene trasmesso il valore in scrittura esadecimale deve essere trasformato innanzitutto attraverso la funzione HexToInt in un numero decimale

Attraverso un collegamento AND del valore dell’input con la potenza alla seconda che corrisponde al valore di bit dei singoli input e Output, si constata se il rispettivo input (output) è uguale a 0 o 1, quindi OFF o ON. Ciò avviene in una serie che scorrerà in funzione del numero di IO.

Mediante la funzione JavaScript document.getElementById l’oggetto di visualizzazione da aggiornare viene identificato e adattato in funzione dello stato di attivazione attuale.

Gli stessi meccanismi vengono utilizzati per l’aggiornamento dei counter, laddove viene meno la conversione da esadecimali a decimali perché gli stati dei counter trasmetteranno in decimali.

Consiglio: Naturalmente un sito internet realizzato in questo modo può anche essere avviato dal disco rigido del PC locale. In questo caso è obbligatorio inserire come URL per Cross-Origin nel Web-IO * Perché il browser del disco rigido non può assegnare nessuna origine IP!


Il esempio supporta le funzioni più importanti del Web-IO, disponibili mediante richieste HTTP, ottimizzate per Web-IO digitale 4.0 2x input, 2x output. Per gli altri modelli Web-IO si devono effettuare eventualmente la modifica della struttura del sito internet e della parte di JavaScript. Una descrizione dettagliata dell’impiego delle richieste HTTP per i modelli digitali Web-IO è disponibile in lista di comandi richieste o nel manuale di programmazione sul Web-IO.

Download esempio di programma

Prodotti