W&T connects
Interfaces for TCP/IP, Ethernet, RS-232, RS-485, USB, 20mA, glass and plastic fiber optic cable, http, SNMP, OPC, Modbus TCP, I/O digital, I/O analog, ISA, PCI

Tutorial for the Web-IO Digital:

Control several Web-IO Ditial from a web page


There are applications that require dynamic monitoring and control of several Web-IOs from a common web page. As shown in the example "Control Web-IO Digital from your own web page using AJAX", it is basically not difficult to program web pages that refresh page contents using subsequent HTTP requests.

On the other hand, for security reasons current browsers do not permit such HTTP requests that are sent using AJAX except to the server from which the actual web page was loaded.

Example: If from a Web-IO you open the user page My Web Page, only the IO states of this Web-IO can be dynamically displayed.

Cross-origin requests

If you try to reload the contents of Server B from a web page that was loaded from Server A, the necessary HTTP request is called a cross-origin request. As already noted, the contents returned following such requests are rejected by the browser for reasons of security.

To allow the browser to accept and process the contents, the queried third-party server must include in its reply an Allow-Cross-Origin statement.

Controlling Web-IO using AJAX

Web-IO and cross-origin requests

Embedded devices such as the Web-IO can be configured such that Allow-Cross-Origin is included in the HTTP header of the HTTP reply. This requires that the URL of the web server from which the original requesting web page was loaded be indicated - for the constellation shown for example http://<url von Web-IO 0>. Alternately an * can be entered as a wildcard, which results in the browser accepting the reply regardless of from where the original web page was loaded.

The following example shows how Cross Origin is used in practice and how a corresponding web page for the Web-IO Digital 4.0 2xIn, 2xOut and the associated Java Script must be constructed.


Preparations


Basic construction of your own web page

Webpage Cross-Origin

The HTML basic structure of this page looks as follows:

							
<!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>
							
						

The head area and style information will not be covered here. The contents of the script area are described in the following. Important in the body area are the id nomenclatures by means of which the objects and table cells are accessed in the JavaScript functions. Using onclick the function assigned to the buttons is determined. As a parameter the number of the Web-IO followed by the number of counters and outputs is transmitted. For the outputs the second parameter indicates the status (0=OFF, 1=ON).

By maintaining this system the example can be adapted to other Web-IO models without changing the JavaScript functions simply by adding additional table lines.

Global variables and functions in JavaScript

First a few global variables need to be declared.

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

It is important to enter WebioIP the IP addresses of the Web-IOs involved in the variable field.

Sending HTTP requests and receiving HTTP replies


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

Processing of HTTP Request and HTTP Reply is handled by the function DataRequest. Unfortunately Internet Explorer uses different mechanisms for processing HTTP requests than other browsers. Therefore the function first checks in which browser the web page is being opened in. The HTTP Request sent as CommandString is then sent to the Web-IO whose IP address is entered in the variable field WebioIP under the number passed with WebioNo. The HTTP Reply is then passed together with the number of the queried Web-IO to the UpdateDisplay function.

Cyclical querying of inputs, outputs and counters

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

The CommandLoop function is started using the parameter onload in the body tag as soon as the web page is fully loaded. The function using the DataRequest function to alternatingly send the HTTP Requests to the Web-IOs for querying inputs, outputs and counters and calls itself again after a time delay. In this way the IO states are continually refreshed at a fixed interval.

Switching outputs

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

Clicking on the corresponding buttons calls the setOutput function and passes the number of the Web-IO, the output, as well as the state to be switched. Using the DataRequest function the necessary HTTP Request is sent to the Web-IO.

Clearing the counters

								
// 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+’&’);
}
							
						

Clicking on the corresponding buttons calls the clearCounter function and sends the number of the Web-IO and the input number.

Refreshing the web page contents

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

In reply to an HTTP Request the Web-IO always sends the actual command and, separated by a semicolon, one or more parameters.

For an input query for example input;1

The function UpdateDisplay uses split to break down the passed string into a string array. For the input example the result is an array with the first field variable input and the second 1. The first letter of the first field variable determines whether the reply affects an input, output or the counters.

The second field variable contains for input and output the bit pattern for the switching state of the IOs (Bit0=Input0, Bit1=Input1, .....). Since the value is sent in hexadecimal format, it must first be converted using the function HexToInt into a decimal number.

Using an AND operation on the input value with the power of 2, which corresponds to the bit value of the individual inputs and outputs, the determination is made whether the affected input (output) is 0 or 1, i.e. OFF or ON. This is done in a loop which runs depending on the number of IOs.

Using the JavaScript function document.getElementById the display object to be refreshed is identified and adjusted correspondingly to the current switching state.

The same mechanisms are used for refreshing the counters, except that there is no hex to decimal conversion since the counter states are already passed in decimal format.

Tip: Of course a web page created in this way can also be started directly from the hard drive of the local PC. In this case you must enter * as the URL for cross-origin in the Web-IO, since the browser cannot associate an IP origin with the hard drive!


The example supports the most important functions of the Web-IO which are available using HTTP requests, optimized for the Web-IO Digital 4.0 2xIn, 2xOut. For the other Web-IO models you may have to make changes to the structure of the web page and in the JavaScript section. A detailed description for using HTTP requests for the Web-IO Digital models can be found in the Request command overview or in the programming manual for the Web-IO.

Download program example

Products