Sample Machine with Microsoft Silverlight and JavaScript
Microsoft Silverlight is a web-presentation-technology.
Target platform
-Windows XP, XPE, WES
-Windows Vista
-Windows 7
Implementation
-JavaScript
Required Software:
- runtime:
- Microsoft Silverlight 1.0 / 1.1
- developer tools:
- Microsoft Visual Studio 2008 Beta 2
- Microsoft Silverlight Tools Alpha Refresh for Visual Studio (July 2007)
or
- Microsoft Visual Studio 2005
- Microsoft Silverlight 1.0 Software Development Kit
For this sample Microsoft Visual Studio 2005 was used.
- designer tools:
- Expression Blend 2
- others:
- TwinCAT 2.10
- Browser (for example Internet Explorer 7 or Mozilla Firefox 2)
- Microsoft .NET Framework Version 3.0
The first steps...
Step for step you learn to develop a Silverlight-Application and include the TwinCAT ADS Web Service on a sample.
1. Create new Project:
Start the Microsoft Expression Blend 2 and create a new user interface over 'Menu->File -> new Project...' . If the Dialog 'Create New Project' open, now you can edit the type, the name, the location and the language. In this sample choose the type 'Silverlight Application (JavaScript)' and the name 'Machine'.
2. Create user interface:
A few controls are available for the development of the user interfaces in Silverlight applications. You can create a RadioButton with a Textbox and two Ellipses, whitch are grouped into a Canvas. The Progressbar can be created with three Rectangles which are grouped into a separate Canvas again.
The properties of the interface are described in the Page.xaml file.
Note that you can not set the object size to 'Auto'. This may lead to errors later.
You can see the two outputs in the upper left corner. The variable, which counts the work pieces, is placed below. You can change the engine speed with the two RadioButtons on the right side. The displayed steps are equivalent to the number of clocks that are returned to output 1.
3. Add XMLHTTP.JS
In Visual Studio over 'Project → Add Existing Item...' add the file 'XMLHTTP.JS'. This file contains general methods for reading and writing of PLC variables and converting data types.
4. Edit source code
Open the file 'Default.html' in Visual Studio and include the 'XMLHTTP.JS' file into the header.
<scripttype="text/javascript"src="xmlhttp.js"></script>
Add a JavaScript-range in the HEAD-field of the HTML page. You find the following source code in it:
The global variables has to be declared first.
<script type="text/javascript">//enter URL to webservice here:var url = "http://localhost/TcAdsWebService/TcAdsWebService.dll";
//enter netId here:var netId = "172.16.2.63.1.1";
//enter the port here:var port = 811;
//send soap request every x seconds:var refresh = 1000;
var inuse = false;var b64s, success, errors, req;
var vUp, vDown, vProgressbar, vCount, vFast, vSlow;
...
You have to adapt the url of the TcAdsWebService, the netID and the port.
The GUI objects can not be accessed directly. In order to do this the objects will be assigned to already declared variables after the start of the application.
function Load(sender, eventArgs)
{
vUp = sender.findName("pathUp");
vDown = sender.findName("pathDown");
vProgressbar = sender.findName("recProgressbar");
vCount = sender.findName("txbCount");
vFast = sender.findName("ellPointFast");
vSlow = sender.findName("ellPointSlow");
}
The loading method contains the assignation of the variables. For executing the Load method Loaded="Load" has to be added to the Canvas on top of the Page.xaml.
<Canvasxmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="368" Height="256"
x:Name="Page"
Loaded="Load"
>
...
function loop(x)
{
Read(netId, port, '16416', '0', '86'); //send soap read request via xmlhttprequest
window.setTimeout("loop("+x+")", x);
}
Read PLC variable
Read(netId, nPort, indexGroup, indexOffset, cbLen)
- netId: String indicating the AMS-Net-Id of the PLC
- nPort: Port-number of the runtime-system
- indexGroup: IndexGroup of the variables to read
- indexOffset: First byte to read
- ncbLen: Number of bytes to read
function init()
{
b64s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
success = 0;
errors = 0;
loop(refresh); //send request every x seconds
}
Add onload="init()" into <body>, so that the method will be executed during loading.
<body onload="init()" >
The next function reads values and displays them. It is important that the address of the variable in Machine.pro is correctly.
function processReqChange()
{
/*
readyStates:
0 = uninitialized
1 = loading
2 = loaded
3 = interactive
4 = complete
*/ if (req.readyState == 4)
{
// only if "OK"if (req.status == 200)
{
response = req.responseXML.documentElement;
inuse = false;
try//check if there was an error in the request
{
errortext = response.getElementsByTagName('faultstring')[0].firstChild.data;
try
{
errorcode = response.getElementsByTagName('errorcode')[0].firstChild.data;
}
catch (e){errorcode="-";}
alert(errortext + " ("+errorcode+")");
return;
}
catch (e)
{
errorcode=0;
}
var data;
try//if the server returns a <ppData> element decode it, otherwise (write request) do nothing
{
data = response.getElementsByTagName('ppData')[0].firstChild.data;
mode = "read";
}
catch (e)
{
data = "";
mode = "";
}
if (mode=="read")
{
try
{
data = b64t2d(data); //decode result string
steps = toInt(data.substr(1, 2));
bool = toInt(data.substr(5,2));
bool2 = toInt(data.substr(4,2));
count = toInt(data.substr(3, 2));
speed = toInt(data.substr(6, 2));
}
catch (e)
{
alert("Parsing Failed:" + e);
return;
}
vProgressbar.Width = 306.321/100*steps*4;
if (bool2 != "1")
{ vCount.Text = count.toString();}
if (bool == "1")
{ vUp.Opacity=1.0;
vDown.Opacity=0.0; }
else if (bool2 == "1")
{ vUp.Opacity=0.0;
vDown.Opacity=1.0; }
else
{ vUp.Opacity=0.0;
vDown.Opacity=0.0; }
if (speed == "0")
{ vFast.Opacity=1.0;
vSlow.Opacity=0.0; }
else
{ vSlow.Opacity=1.0;
vFast.Opacity=0.0; }
}
}
else alert(req.statusText+" "+req.status); //cannot retrieve xml data
}
}
With the last two methods the PLC variable, which controls the speed of the machine, is set to zero or one.
function Fast_MouseLeftButtonDown(sender, eventArgs)
{
Write(netId, port, '16416', '6', '2', '0', 'int');
}
function Slow_MouseLeftButtonDown(sender, eventArgs)
{
Write(netId, port, '16416', '6', '2', '1', 'int');
}
Write SPS Variables
Write(netId, port, indexGroup, indexOffset, cbLen, pwrData, type)
- netId: String indicating the AMS.Net.Id of the PLC
- nPort: Port-number of the runtime-system
- indexGroup: IndexGroup of the variable
- indexOffset: First byte to write to
- ncbLen: Number of bytes to write
- pwrData: Array containing the data to write
- type: "bool", "int" or "string"
It has to be changed to 'Expression Blend 2' as it has been done with the 'Load' function for declaring the according rows as 'Click' event for both buttons.
<Canvas x:Name="canvasFast" MouseLeftButtonDown="Fast_MouseLeftButtonDown" ...
<Canvas x:Name="canvasSlow" MouseLeftButtonDown="Slow_MouseLeftButtonDown" ...
5. Testing:
By debugging the application you will recognize that it will not work as expected. To prevent this got to 'Build -> Publish'.
Choose the 'Target location' in the dialog window and then 'All project files' under 'Copy'.
If the statusbar says 'Publish succeded', you can run and test the application in the browser.