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
Applicazione relativa al Web-IO digitale:

Web-IO digitali - visualizzazione nel browser con AJAX

Il browser Internet è oggi parte integrante di tutti i moderni sistemi operativi. Che si tratti di Internet Explorer, Firefox, Opera, Netscape o Safari, nella navigazione in Internet il browser viene apprezzato come strumento di visualizzazione versatile.

Ajax e Web-IO digitale

Con AJAX e con i Web-IO W&T il browser ora può essere utilizzato anche come elemento di visualizzazione e controllo per applicazioni tecniche dinamiche.

AJAX è l’abbreviazione di Asynchronous JavaScript and XML, dove la funzionalità chiave di AJAX consiste nel continuare a comunicare con il server anche dopo il caricamento di una pagina web nel browser. Le pagine web con struttura HTML standard possono essere caricate di nuovo per l’aggiornamento solo in modo completo. I JavaScript basati su AJAX possono al contrario sostituire o modificare successivamente singoli elementi di visualizzazione.

Confronto tecnica Ajax e HTTP standard

L’applicazione AJAX descritta di seguito mostra ad esempio l’interazione di AJAX e Web-IO.

Preparativi

Collocazione dei diversi elementi di comando e oggetti di visualizzazione nella pagina web

Elementi di comando AJAX

Nella denominazione dei singoli oggetti o delle funzioni da richiamare è utile utilizzare nomi che ne riprendono il significato.

  • 1. Struttura di base HTML della pagina web Collocazione degli elementi di comando e visualizzazione

    Per una migliore strutturazione i singoli elementi vengono sistemati in tabelle e il tutto indicato come modulo. Il tag <user.htm> non appartiene alla sintassi HTML standard e serve al Web-IO per l’identificazione della pagina web. Il tag viene filtrato nel browser prima dell’upload.

    
    <user.htm>
    	<html>
    		<head>
    			<title>Web-IO AJAX-Client</title>
    			<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    			<STYLE type=text/css>
    				TD {
    				COLOR: #000000;
    				FONT-FAMILY: Verdana,Arial,Helvetica;
    				FONT-SIZE: 10pt;
    					}
    			</STYLE>
    		</head>
    		<body bgcolor="#FFFFFF" text="#000000" link="#000000">
    			<form name="ioform">
    				<table width="500" border="1" height="144" bgcolor="#CCCCCC">
    					<tr>
    						<td>
    							<table width="500">
    								<tr>
    									<td colspan="6">
    										<b>Input/Output Control &lt;/b>
    									</td>
    								</tr>
    								<tr>
    									<td width="100">
    										<input type="checkbox" name="cb_output" onclick="setOutput(0)">Output 0
    									</td>
    									<td width="100">
    										<input type="checkbox" name="cb_input">Input 0
    									</td>
    									<td width="100">
    										<div align="right">Counter 0 </div>
    									</td>
    									<td width="*" bgcolor="#FFFFFF" id="counter0">
    									</td>
    									<td width="55">
    										<input type="button" value="Read" onclick="getCounter(0)">
    									</td>
    									<td width="55">
    										<input type="button" value="Clear" onclick="clearCounter(0)">
    									</td>
    								</tr>
    								<tr>
    									<td width="100">
    										<input type="checkbox" name="cb_output" onclick="setOutput(1)"> Output 1
    									</td>
    									<td width="100">
    										<input type="checkbox" name="cb_input"> Input 1
    									</td>
    									<td width="100">
    										<div align="right">Counter 1 </div>
    									</td>
    									<td width="*" bgcolor="#FFFFFF" id="counter1">
    									</td>
    									<td width="55">
    										<input type="button" value="Read" onclick="getCounter(1)">
    									</td>
    									<td width="55">
    										<input type="button" value="Clear" onclick="clearCounter(1)">
    									</td>
    								</tr>
    								<tr>
    									<td width="100" height="29">
    										<input type="button" value="Read all" onclick="getOutputs()">
    									</td>
    									<td width="100" height="29">
    										<input type="button" value="Read all" onclick="getInputs()">
    									</td>
    									<td width="100" height="29">
    										<div align="right">Counter all &lt;/div>
    									</td>
    									<td width="*" height="29">
    									</td>
    									<td width="55" height="29">
    										<input type="button" value="Read" onclick="getCounter()">
    									</td>
    									<td width="55" height="29">
    										<input type="button" value="Clear" onclick="clearCounter()">
    									</td>
    								</tr>
    								<tr>
    									<td width="100">
    										<input type="checkbox" name="cb_output_polling">Polling
    									</td>
    									<td width="100">
    										<input type="checkbox" name="cb_input_polling"> Polling
    									</td>
    									<td width="100">
    										<div align="right">
    										<input type="button" value="Set Interval" onclick="setPolInterval()">
    										</div>
    									</td>
    									<td width="*" >
    										<input type="text" name="ed_interval" value="500" maxlength="6" size="9">
    									</td>
    									<td colspan="2">
    										<input type="checkbox" name="cb_counter_polling"> Polling
    									</td>
    								</tr>
    							</table>
    						</td>
    					</tr>
    				</table>
    				<table width="500" border="1" bgcolor="#CCCCCC" >
    					<tr>
    						<td height="35">
    							<table width="500">
    								<tr>
    									<td width="78">Password</td>
    									<td width="410">
    										<input type="text" name="ed_password">
    									</td>
    								</tr>
    							</table>
    						</td>
    					</tr>
    				</table>
    			</form>
    	....
  • 2. Dichiarazioni JavaScript globali Variabili e funzioni generali

    Sebbene la pagina web sia costruita per il Web-IO 2x input digitale, 2x output digitale, i JavaScript sono stati predisposti per i Web-IO con più IO. Pertanto anche la funzione HexToInt che converte le stringhe esadecimali in numeri interi.

    La variabile SendString viene utilizzata successivamente per l’invio di dati al Web-IO.

    ...
    var MAXIO=2;
    var SendString;
    
    function HexToInt(HexStr)
    	{
    	var TempVal;
    	var HexVal=0;
    	for( 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;
    	}
  • 3. Elaborazione dell’utilizzo da parte dell’utente

    In base all’elemento di comando della pagina web su cui ha fatto clic o che ha modificato l’utente, la variabile SendString viene riempita con il corrispondente comando.

    Impostazione degli output

    L’impostazione degli output è resa possibile all’utente da due caselle di spunta cb_output. Al richiamo della funzione viene fornito il n. dell’output.

    La funzione DataRequest, che viene richiamata alla fine, serve allo scambio di dati con il Web-IO e più avanti è descritta dettagliatamente.

    
    			function setOutput(OutputNr)
    				{
    				if (ioform.cb_output[OutputNr].checked==true)
    					{
    					SendString=’outputaccess’+OutputNr+’?PW=’+ioform.ed_password.value+’&State=ON&’;
    					}
    				else
    					{
    					SendString=’outputaccess’+OutputNr+’?PW=’+ioform.ed_password.value+’&State=OFF&’;
    					}
    				DataRequest(SendString);
    				}
    Interrogazione dello stato degli output/input

    L’utente può richiedere lo stato degli output e degli input facendo clic sul relativo pulsante.

    
    			function getOutputs()
    				{
    				DataRequest(’output?PW=’+ioform.ed_password.value+’&’);
    				}
    
    			function getInputs()
    				{
    				DataRequest(’Input?PW=’+ioform.ed_password.value+’&’);
    				}
    Interrogazione/cancellazione dei counter

    È possibile interrogare o cancellare anche gli stati dei counter degli input. Come parametro viene fornito il n. del counter che deve essere letto o cancellato. Se non viene fornito alcun parametro, il Web-IO legge o cancella tutti i counter.

    
    			function getCounter(CounterNr)
    				{
    				if (CounterNr==undefined)
    					{
    					DataRequest(’counter?PW=’+ioform.ed_password.value+’&’);
    					}
    					else
    					{
    					DataRequest(’counter’+CounterNr+’?PW=’+ioform.ed_password.value+’&’);
    					}
    				}
    
    			function clearCounter(CounterNr)
    				{
    				if (CounterNr==undefined)
    					{
    					DataRequest(’counterclear?PW=’+ioform.ed_password.value+’&’);
    					}
    				else
    					{
    					DataRequest(’counterclear’+CounterNr+’?PW=’+ioform.ed_password.value+’&’);
    					}
    				}
  • 4. Comunicazione con il Web-IO

    Scambio di dati con il Web-IO e aggiornamento della pagina web dopo il suo caricamento.

    • La funzione qui presentata contiene ciò che costituisce AJAX.
    • La funzione DataRequest invia al Web-IO, senza che ciò sia visibile per l’utente, i comandi selezionati e forniti in SendString. La funzione integrata DataReceived riceve le risposte del Web-IO.
    • Le risposte del Web-IO hanno una struttura specifica in base al tipo.
    • Per gli output: output;<valore binario dello stato degli output in formato esadecimale>
    • Per gli input: input;<valore binario dello stato degli input in formato esadecimale>
    • Per i counter: counterx;<stato del conteggio decimale>
    • oppure counter;<stato del conteggio decimale 0 >; <stato del conteggio decimale 0 >; ... se tutti i counter devono essere letti in un’unica volta.
    • In base alla risposta ricevuta la funzione di ricezione si ramifica corrispondentemente e aggiorna la visualizzazione degli oggetti nella finestra del browser.
    
    	function DataRequest(SendString)
    		{
    		var xmlHttp;
    		try
    			{// Internet Explorer
    			if( window.ActiveXObject )
    				{
    				xmlHttp = new ActiveXObject("Microsoft.XMLHTTP" );
    				}
    			// Mozilla, Opera und Safari
    			else if(window.XMLHttpRequest)
    				{
    				xmlHttp = new XMLHttpRequest();
    				}
    			}
    		// loading of xmlhttp object failed
    		catch( excNotLoadable )
    			{
    			xmlHttp = false;
    			alert("no knowen browser");
    			}
    		if (xmlHttp)
    			{ xmlHttp.onreadystatechange = DataReceived;
    			xmlHttp.open("GET", SendString, true);
    			xmlHttp.setRequestHeader("Cache-Control", "no-store, no-cache, must-revalidate");
    			xmlHttp.setRequestHeader("Expires", "Sat, 05 Nov 2005 00:00:00 GMT");
    			xmlHttp.setRequestHeader("Pragma","no-cache");
    			xmlHttp.send(null);
    			}
    	function DataReceived()
    		{
    		var HexVal;
    		var ReceiveStr;
    		if (xmlHttp.readyState == 4)
    			{
    			if (xmlHttp.status == 200)
    				{
    				ReceiveStr = xmlHttp.responseText;
    				//Input handling
    				if (ReceiveStr.substring(0,5)==’input’)
    					{
    					HexVal=HexToInt(ReceiveStr.substring(6,10));
    					for (i=0;i<MAXIO;i++)
    						{
    						if ((HexVal & Math.pow(2,i)) == Math.pow(2,i))
    							{
    							ioform.cb_input[i].checked = true;
    							}
    						else
    							{
    							ioform.cb_input[i].checked = false;
    							}
    						}
    					}
    				//Output handling
    				if (ReceiveStr.substring(0,6)==’output’)
    					{
    					HexVal=HexToInt(ReceiveStr.substring(7,11));
    					for (i=0;i<MAXIO;i++)
    						{
    						if ((HexVal & Math.pow(2,i)) == Math.pow(2,i))
    							{
    							ioform.cb_output[i].checked = true;
    							}
    							else
    							{
    							ioform.cb_output[i].checked = false;
    							}
    						}
    					}
    				//Counter handling
    				if (ReceiveStr.substring(0,7)==’counter’)
    					{
    					var slength=ReceiveStr.length;
    					if (ReceiveStr.substring(7,8)==’;’)
    						{
    						countervalue=ReceiveStr.split(’;’);
    						for (i=0;i<MAXIO;i++)
    							{
    							document.getElementById(’counter’+i).innerHTML = ’<a>’+countervalue[i+1]+’<\/a>’;
    							}
    						}
    					else
    						{
    						if (ReceiveStr.substring(9,10)==’;’)
    							{
    							i=(ReceiveStr.substring(7,9));
    							document.getElementById(’counter’+i).innerHTML = ’<a>’+ReceiveStr.substring(10,slength)+’<\/a>’;
    							}
    							else
    							{
    							i=(ReceiveStr.substring(7,8));
    							document.getElementById(’counter’+i).innerHTML = ’<a>’+ReceiveStr.substring(9,slength)+’<\/a>’;
    							}
    						}
    					}
    				}
    			}
    		}
    }

    Anche se l’esempio mostrato è improntato per il Web-IO 2x input digitale, 2x output digitale, la funzione DataRequest è predisposta anche per il Web-IO con più IO.

  • 5. Polling

    Interrogazione ciclica di determinati valori - Per rendere possibile anche un aggiornamento completamente automatico della visualizzazione viene utilizzata la funzione JavaScript Interval. In base alle caselle di spunta per il polling degli output, degli input e dei counter le corrispondenti informazioni vengono interrogate dal Web-IO nell’intervallo impostato.

    
    var pollingtimer = window.setInterval("Polling()", 500);
    function Polling()
    	{
    	if (ioform.cb_output_polling.checked==true)
    		{
    		DataRequest(’output?PW=’+ioform.ed_password.value+’&’);
    		}
    	if (ioform.cb_input_polling.checked==true)
    		{
    		DataRequest(’input?PW=’+ioform.ed_password.value+’&’);
    		}
    	if (ioform.cb_counter_polling.checked==true)
    		{
    		DataRequest(’counter?PW=’+ioform.ed_password.value+’&’);
    		}
    	} 

    L’intervallo desiderato può essere immesso nel corrispondente campo di testo e viene adattato facendo clic sul pulsante Set Interval.

    
    function setPolInterval()
    	{
    	var intervaltime=parseInt(ioform.ed_interval.value)
    	clearInterval(pollingtimer);
    	pollingtimer = window.setInterval("Polling()", intervaltime);
    	} 

Installazione della pagina web nel Web-IO

Le pagine web che si basano su AJAX funzionano soltanto se i dati per l’aggiornamento provengono dallo stesso server da cui proviene la pagina web. Non è possibile caricare la pagina web dal server A e interrogare i dati dal server B.

Se la programmazione della pagina web è conclusa, questa deve essere caricata nel Web-IO. Ciò avviene comodamente con alcuni clic del mouse sull’interfaccia web del Web-IO:

Upload di Ajax nel Web-IO

L’esempio supporta tutte le funzioni comuni del Web-IO, ottimizzato per il Web-IO 2x Digital Input, 2x Digital Output PoE Per gli altri modelli di Web-IO devono essere eventualmente apportati adattamenti alla pagina web esempio. Ulteriori esempi di programma per la programmazione socket sono riportati nelle pagine dei tool relative al Web-IO. Una descrizione dettagliata relativa ai comandi dei modelli Web-IO digitali è riportata nel manuale di riferimento.

Download esempio di programma

Non disponete ancora di un Web-IO e desiderate semplicemente provarne il funzionamento come nell’esempio illustrato?

Nessun problema: vi mettiamo a disposizione gratuitamente per 30 giorni il Web-IO digitale 2x input, 2x output. Non dovete far altro che compilare l’ordinazione del campione e vi forniremo il Web-IO in prova in conto aperto. Se ci restituite l’apparecchio entro 30 giorni, vi accreditiamo completamente la fattura.

All’ordinazione del campione