Due to maintenance work, W&T will be closed on 19.04.2024!

You can reach our technical hotline at:
+49 202/2680-110 or under the emergency number: +49 179/4317651


On Monday 22.04.2024 we will be available as usual.

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 Web-IO digitale dal proprio sito internet con PHP


I modelli Web-IO digitale 4.0 possono essere controllati attraverso richieste HTTP. L’impiego di richieste HTTP per lo scambio di dati viene supportato dalla maggior parte dei linguaggi script e di alto livello. PHP come linguaggio di script è disponibile su quasi tutti i webserver ed è perfetto per gestire la comunicazione con il Web-IO.

L’esempio qui illustrato lavora in due parti. Separa la visualizzazione dinamica degli stati IO mediante HTML, JavaScript e AJAX (sito internet) e la comunicazione con il Web-IO mediante (script) PHP.

La parte fondamentale è lo script PHP webiohttprequest.php che rimane senza elementi di visualizzazione ed esegue esclusivamente lo scambio di dati. Il sito internet, su cui vengono visualizzati gli stati IO, chiama mediante AJAX lo script PHP e richiede lo stato del Web-IO.

Un vantaggio di questa tecnica consiste nel fatto che attraverso lo stesso script PHP, possono essere attivati diversi Web-IO, dove i parametri inviati determinano il Web-IO destinatario. Se i Web-IO e il server PHP sono dietro a un firewall, è necessario solo autorizzare l’accesso al server PHP verso l’esterno.

Controllare Web-IO con AJAX

Il seguente esempio mostra come è strutturato lo script PHP e come si controlla con un semplice sito internet e le funzioni necessarie. La visualizzazione è preparata per il Web-IO digitale 4.0 2x input, 2x output.


Preparativi


Lo script PHP

Allo script PHP webiohttprequest.php devono essere trasmessi vari parametri all’apertura che vengono trasmessi come componenti della richiesta HTTP.

  • HTTPS
    HTTPS=0 - la richiesta viene inviata come richiesta HTTP
    HTTPS=1 - la richiesta viene inviata crittografata come richiesta HTTPS

  • IP
    IP=<indirizzo IP del Web-IO>

  • PORT
    PORT=<porta HTTP(s) del Web-IO>

  • PW
    PW=<password del Web-IO>

  • COMMAND
    COMMAND=<comando che deve essere inviato al Web-IO>
    comandi possibili: input, output, counter, outputaccess, single

  • STATE (solo con comando outputaccess)
    STATE=<schema di bit degli stati di attivazione nei quali devono essere attivati gli output come numero esadecimale>

  • MASK (solo con comando outputaccess
    MASK=<schema di bit degli output, che devono essere attivati come numero esadecimale>

I comandi e parametri da trasmettere con COMMAND corrispondono ai comandi di base delle richieste HTTP.

Per l’invio delle richieste HTTP il PHP-Script utilizza la biblioteca funzionale PHP CURL.

							
<?php
  $PROTO="http://";
  $PORT="80";
  if (!isset($_GET[’COMMAND’])) {die( ’ERROR command’ );} else {$COMMAND=$_GET[’COMMAND’];}
  if (!isset($_GET[’IP’])) {die( ’ERROR ip’ );} else {$IP=$_GET[’IP’];}
  if (!isset($_GET[’HTTPS’])) {$PROTO=’http://’;}
  else
  { if ($_GET[’HTTPS’] == 1)
    { $PROTO=’https://’;
      $PORT=’443’;
    }
  }
  if (isset($_GET[’PORT’])) {$PORT=$_GET[’PORT’];}
  if (!isset($_GET[’PW’])) {$PW="";} else {$PW=$_GET[’PW’];}
  if (!isset($_GET[’MASK’])) {$MASK="0FFF";} else {$MASK=$_GET[’MASK’];}
  if (!isset($_GET[’STATE’]))
  { $STATE="0000";
    $MASK="0000";
  }
  else $STATE=$_GET[’STATE’];
  { if ($COMMAND == "outputaccess")
    { $URL=$PROTO.$IP.":".$PORT."/".$COMMAND."?PW=".$PW."&Mask=".$MASK."&State=".$STATE."&";
    }
    else
    { if (substr($COMMAND,0,6) == "single")
      { $URL=$PROTO.$IP.":".$PORT."/".$COMMAND;
      }
      else
      { $URL=$PROTO.$IP.":".$PORT."/".$COMMAND."?PW=".$PW."&";
      }
    }
    $ch = curl_init();
    $options = array(
      CURLOPT_URL            => $URL,
      CURLOPT_RETURNTRANSFER => true,     // return web page
      CURLOPT_HEADER         => false,    // don’t return headers
      CURLOPT_ENCODING       => "",       // handle all encodings
      CURLOPT_USERAGENT      => "webio",  // who am i
      CURLOPT_CONNECTTIMEOUT => 20,      // timeout on connect
      CURLOPT_TIMEOUT        => 20,      // timeout on response
      CURLOPT_MAXREDIRS      => 1,        // stop after 10 redirects
      CURLOPT_SSL_VERIFYHOST => false,
      CURLOPT_SSL_VERIFYPEER => false,
    );
    curl_setopt_array( $ch, $options );
    $data = curl_exec($ch);
    if ($data==false)
    { die(’ERROR ’.$URL);
    }
    else
    { $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
      if ($http_status==200)
      { echo $data;
      }
      else
      { die(’ERROR ’.$URL.’ status ’.$http_status);
      }
    }
    curl_close($ch);
  }
?>
							
						

Struttura di base del sito internet

Pagina internet Cross-Origin

L’impalcatura di base HTML di questa pagina è la seguente:

							
<!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 e sulle informazioni style. I contenuti dell’area script vengono descritti in seguito. Sono importanti nell’area 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 modificare le 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 WebioPort = [’80’, ’80’];
var ApplicationStep = 0;
var Interval = 250;

// 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;
}
							
						

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

							
// Sending command lines to Web-IO and receiving IO State
function DataRequest(WebioNo, SendString)
{ var xmlHttp;
  if( window.ActiveXObject )       // Internet Explorer
  { xmlHttp = new ActiveXObject( "Microsoft.XMLHTTP" );
  }
  else if(window.XMLHttpRequest )  // Mozilla, Opera und Safari
  { xmlHttp = new XMLHttpRequest();
  }
  if (xmlHttp)
  { xmlHttp.onreadystatechange = function()
    { if (xmlHttp.readyState == 4)
      { if (xmlHttp.status == 200)
        { if (xmlHttp.responseText.length > 0)
          { updateDisplay(WebioNo, xmlHttp.responseText);
          }
          xmlHttp=null;
        }
      }
    }
    xmlHttp.open("GET", SendString, true);
    xmlHttp.setRequestHeader("If-Modified-Since", "Thu, 1 Jan 1970 00:00:00 GMT");
    xmlHttp.send(null);
  }
}
								
							

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 SendString viene quindi inviata al server e al Web-IO, dal quale la pagina web è stata anche caricata. La risposta, ovvero la HTTP-reply viene quindi trasferita alla funzione UpdateDisplay.

Richiesta ciclica di input, output e counter

								
// Preparing command lines for cycle sending
function CommandLoop()
{ var Command =’’;
  var CommandString =’’;
  var WebioNo = 0;
  ApplicationStep++;
  switch(ApplicationStep)
  { case 1:
      Command = ’input’;
    break;
    case 2:
      Command = ’input’;
      WebioNo = 1;
    break;
    case 3:
      Command = ’output’;
    break;
    case 4:
      Command = ’output’;
      WebioNo = 1;
    break;
    case 5:
      Command = ’counter’;
    break;
    case 6:
      Command = ’counter’;
      WebioNo = 1;
      ApplicationStep = 0;
    break;
  }
  var IOPassword = document.getElementById(’webio’+WebioNo+’pw’).value;
  CommandString = ’webiohttprequest.php?IP=’+WebioIP[WebioNo]+’&PORT=’+WebioPort[WebioNo]+’&COMMAND=’+Command+’&PW=’+ IOPassword;
  if (WebioPort[WebioNo] == ’443’)
  { CommandString = CommandSting + ’&HTTPS=1’
  }
  DataRequest(WebioNo, CommandString);
  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 = ’webiohttprequest.php?IP=’+WebioIP[WebioNo]+’&PORT=’+WebioPort[WebioNo]+’&COMMAND=outputaccess&PW=’+ IOPassword+’&MASK=’+(2**OutNo).toString(16);
  if(OutVal>0)
  { CommandString = CommandString + ’&STATE=0fff’;
  }
  else
  { CommandString = CommandString + ’&STATE=0’;
  }
  if (WebioPort[WebioNo] == ’443’)
  { CommandString = CommandSting + ’&HTTPS=1’
  }
  DataRequest(WebioNo, CommandString);
}
							
						

Cliccando sui relativi tasti si apre la funzione setOutput e viene trasmesso il numero del Web-IO, dell’output e lo 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;
  var CommandString = ’webiohttprequest.php?IP=’+WebioIP[WebioNo]+’&PORT=’+WebioPort[WebioNo]+’&COMMAND=counterclear’+CounterNo+’&PW=’+ IOPassword;
  if (WebioPort[WebioNo] == ’443’)
  { CommandString = CommandSting + ’&HTTPS=1’
  }
	DataRequest(WebioNo, CommandString);
}
							
						

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. Il PHP-Script trasmette la risposta del Web-IO in modo identico.

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 UND 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.


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