Hinweise zur Dokumentation

Diese Beschreibung wendet sich ausschließlich an ausgebildetes Fachpersonal der Steuerungs- und Automatisierungstechnik, das mit den geltenden nationalen Normen vertraut ist.
Zur Installation und Inbetriebnahme der Komponenten ist die Beachtung der nachfolgenden Hinweise und Erklärungen unbedingt notwendig.

Das Fachpersonal hat sicherzustellen, dass die Anwendung bzw. der Einsatz der beschriebenen Produkte alle Sicherheitsanforderungen, einschließlich sämtlicher anwendbaren Gesetze, Vorschriften, Bestimmungen und Normen erfüllt.

Disclaimer

Diese Dokumentation wurde sorgfältig erstellt. Die beschriebenen Produkte werden jedoch ständig weiter entwickelt.
Deshalb ist die Dokumentation nicht in jedem Fall vollständig auf die Übereinstimmung mit den beschriebenen Leistungsdaten, Normen oder sonstigen Merkmalen geprüft.
Falls sie technische oder redaktionelle Fehler enthält, behalten wir uns das Recht vor, Änderungen jederzeit und ohne Ankündigung vorzunehmen.
Aus den Angaben, Abbildungen und Beschreibungen in dieser Dokumentation können keine Ansprüche auf Änderung bereits gelieferter Produkte geltend gemacht werden.

Marken

Beckhoff®, TwinCAT®, EtherCAT®, Safety over EtherCAT®, TwinSAFE®, XFC® und XTS® sind eingetragene und lizenzierte Marken der Beckhoff Automation GmbH.
Die Verwendung anderer in dieser Dokumentation enthaltenen Marken oder Kennzeichen durch Dritte kann zu einer Verletzung von Rechten der Inhaber der entsprechenden Bezeichnungen führen.

Patente

Die EtherCAT Technologie ist patentrechtlich geschützt, insbesondere durch folgende Anmeldungen und Patente:
EP1590927, EP1789857, DE102004044764, DE102007017835
mit den entsprechenden Anmeldungen und Eintragungen in verschiedenen anderen Ländern.

Die TwinCAT Technologie ist patentrechtlich geschützt, insbesondere durch folgende Anmeldungen und Patente:
EP0851348, US6167425 mit den entsprechenden Anmeldungen und Eintragungen in verschiedenen anderen Ländern.

Copyright

© Beckhoff Automation GmbH, Deutschland.
Weitergabe sowie Vervielfältigung dieses Dokuments, Verwertung und Mitteilung seines Inhalts sind verboten, soweit nicht ausdrücklich gestattet.
Zuwiderhandlungen verpflichten zu Schadenersatz. Alle Rechte für den Fall der Patent-, Gebrauchsmuster- oder Geschmacksmustereintragung vorbehalten.


Einführung

Ein mit Microsoft Windows XP Media Center Edition ausgestatteter Media Center-PC verbindet die Fähigkeiten von Windows mit der Funktionalität einer modernen Unterhaltungszentrale. Dank des Windows XP Professional-Fundaments steht Ihnen die gesamte Palette der Hard- und Software zur Verfügung. Durch die Erweiterbarkeit der Bedienoberfläche von Windows XP Media Center kann die Leistungsfähigkeit weiter ausgebaut werden.

Dieses Beispiel beschreibt, wie die Bedienoberfläche von Windows XP Media Center um eigene Dialoge erweitert werden kann und wie von diesen Dialogen auf TwinCAT zugegriffen wird. Hiermit lassen sich Automatisierungslösungen sogar am Fernseher per Fernbedienung ansprechen.

Voraussetzungen

Server:

  • .NET-Framework V2.0
  • Microsoft Internet Information Services (IIS)
  • TwinCAT PLC V2.10
  • Microsoft Visual Studio 2005
  • HTML-Editor

Vorkenntnisse:

  • Programmieren unter .NET (speziell WebServices)
  • Erstellung von HTML-Seiten (inklusive CSS und Javascript)
  • Grundlagen Windows XP Media Center SDK
  • SPS-Programmierung unter TwinCAT V2.10

Beispieldateien

Sämtliche Beispieldateien befinden sich in dem Archiv TcMCE_Sample.zip. Diese werden für die folgenden Erläuterungen benötigt. Kopieren Sie diese bitte auf den Server.

Inhalt

  • Schritt 1: Erstellen des SPS-Programmes
  • Schritt 2: Erstellen einer Media Center kompatiblen Oberfläche
  • Schritt 3: Erstellen des WebServices
  • Schritt 4: Einbinden der Zugriffsmöglichkeit von der Media Center Oberfläche auf den WebService
  • Schritt 5: Einrichten der Visualisierung


Schritt 1: Erstellen des SPS-Programmes

Das SPS-Programm des Beispiels ist bewusst einfach gehalten. Es werden 3 globale Variablen angelegt:

Globale Variablen

VAR_GLOBAL
   bLight1  : BOOL;
   bLight2  : BOOL;
   nCounter : INT;
END_VAR

bLight1 & bLight2 sind einfache boolsche Variablen, welche hier als Status für Lampen dienen.
nCounter ist ein Zählvariable, die ebenfalls ausgelesen werden soll.

"MAIN"-Programm

Im "MAIN"-Programm wird nur eine Programmzeile hinzugefügt, welche nCounter hochzählen lässt:

nCounter := nCounter + 1;

Fahren Sie nun bitte mit Schritt 2 fort.


Schritt 2: Erstellen einer Windows XP Media Center kompatiblen Oberfläche

Windows XP Media Center kann Visualisierungen durch speziell formatierte HTML-Seiten darstellen. Diese Seiten können ebenfalls im Internet Explorer betrachtet werden. Somit ist es auch ohne Windows XP Media Center möglich, auf die Visualisierung zuzugreifen.

Generell gelten beim Erstellen der Seiten die selben Regeln wie bei herkömmlichen HTML-Seiten. Es wird daher hierbei nur auf die besonderen Einstellungen eingegangen, die für die Media-Center-Kompatiblität notwendig sind.

Notwendige Implementationen

  • Sie benötigen im selben Verzeichnis wie die HTML-Seite(n) die Dateien "BasicFunctions.js", "Hilite.htc", "Hilite.js" und "MoveFocus.js". Diese Dateien entnehmen Sie bitte dem Beispiel oder den HTML-Samples des Media Center SDKs. Um diese Dateien einzubinden fügen Sie bitte folgende Zeilen dem Head hinzu:
    <script src="BasicFunctions.js" type="text/javascript"></script>
<script src="MoveFocus.js" type="text/javascript"></script>
  • Sie benötigen eine spezielle CSS-Datei (siehe unten) (in diesem Beispiel trägt sie den Namen "mediacenter.css" und ist im Beispiel enthalten).
    Dieser Stylesheet bestimmt das Aussehen und das Verhalten der Seite und einzelner Elemente darin.
    Diese Datei binden Sie ebenfalls wie folgt im Head ein:
    <link href="mediacenter.css" type="text/css" rel="stylesheet" />
  • Fügen Sie dem Head einen Javascript-Teil hinzu. Dieser enthält die onLoad-Methode
    function Loader()
{
   setBGColor("#0B5EBB");
   checkSVP();
   setArray();
   startFocus();
}
    Der Name der Funktion kann frei gewählt werden. Die vier Funktionsaufrufe können um eigene ergänzt werden. Die genaue Bedeutung der Funktionen wird in den HTML-Samples des Media Center SDKs genauer beschrieben.
  • Des weiteren wird in diesen Script-Teil die "doSelect"-Funktion zum Eventhandling implementiert.
    function doSelect()
{
   switch(oCurFocus.id)
   {
      ...
   }
}
    Diese Funktion wird bei einem Klick oder einem Drücken der Okay-Taste aufgerufen. Tragen Sie die ID der Elemente als case ein, bei denen daraufhin ein Effekt bzw. Methodenaufruf stattfinden soll. Diese Befehle sind innerhalb des Cases einzutragen.

    Beispiel:

    function doSelect()
{
   switch(oCurFocus.id)
   {
      case "btnLight1Toggle":
         ToggleLight_Request(1);
         break;

      case "btnLight2Toggle":
         ToggleLight_Request(2);
         break;

      case "btnCounterReset":
         ResetCounter_Request();
         break;
   }
}

  • der "body"-tag benötigt zusätzliche Attribute:
    • onload="" : Tragen Sie hier den Namen der onLoad-Methode ein.
    • MCFocusStart="" : Tragen Sie hier die ID des Elementes ein, welches bei Seitenaufruf den Fokus haben soll.
    • onkeydown="onRemoteEvent(window.event.keyCode) : Dieses Attribut wird für die Steuerung per Fernbedienung benötigt.
  • Fokussierbare oder wichtige Elemente sollten als SPAN deklariert werden. Diese benötigen zudem noch folgende Attribute:
    • id="" : Tragen Sie hier einen eindeutigen Namen für das Element ein, über dass es angesprochen und erkannt wird.
    • class="" : Tragen Sie hier den Namen des Styles (aus der CSS-Datei) ein, den das Element haben soll.
    • MCFocusable="" : Tragen Sie "true" ein, wenn das Element fokussierbar sein solll, ansonsten "false".
  • Soll die Seite die Funktion eines "shared view ports" unterstützen, muss Folgendes dem body hinzugefügt werden (Wichtig: Verändern Sie diesen Inhalt nicht, da sonst die Funktionalität verloren geht):
    <table><tr><td><span id="SVP" MCFocusable="true" /></td></tr></table>
    Der "shared view port" ist ein kleines Fenster-Element in der unteren linken Ecke des Bildschirms, der weiterhin Zugriff auf ein laufendes Medium erlaubt.

Die HTML-Seite

<html>
<head>
<title>Connecting TwinCAT with Windows XP Media Center Edition</title>

<link href="mediacenter.css" type="text/css" rel="stylesheet" />
<script src="BasicFunctions.js" type="text/javascript"></script>
<script src="MoveFocus.js" type="text/javascript"></script>

<script type="text/javascript">
function Loader()
{
   setBGColor("#0B5EBB");
   checkSVP();
   setArray();
   startFocus();
}

function doSelect()
{
   switch(oCurFocus.id)
   {
      case "btnLight1Toggle":
         break;

      case "btnLight2Toggle":
         break;

      case "btnCounterReset":
         break;
   }
}
</script>
</head>

<body id="body" class="body" MCFocusStart="btnLight1Toggle" onload="Loader()" onkeydown="onRemoteEvent(window.event.keyCode)">
<span id="headback" class="headback">BECKHOFF</span>
<span id="headfront" class="headfront">Connecting TwinCAT with Windows XP Media Center Edition</span>
<table><tr><td><span id="SVP" MCFocusable="true" /></td></tr></table>

<span id="leftmenu" class="leftmenu">
   <table>
      <tr>
         <td>
            <img src="../images/logo_beckhoff.gif" width="250" height="72"/>
         </td>
      </tr>
   </table>
</span>

<span id="navmenu" class="navmenu">
   <table align="center">
      <tr>
         <td>
            <span id="lblLight1Text" class="navlabel" MCFocusable="false">Light 1 :</span>
            <span id="lblLight1Value" class="navlabel" MCFocusable="false">???</span>
            <span id="btnLight1Toggle" class="navbutton" MCFocusable="true">toggle</span>
         </td>
      </tr>
      <tr>
         <td>
            <span id="lblLight2Text" class="navlabel" MCFocusable="false">Light 2 :</span>
            <span id="lblLight2Value" class="navlabel" MCFocusable="false">???</span>
            <span id="btnLight2Toggle" class="navbutton" MCFocusable="true">toggle</span>
         </td>
      </tr>
      <tr>
         <td>
            <span id="lblCounterText" class="navlabel" MCFocusable="false">Counter :</span>
            <span id="lblCounterValue" class="navlabel" MCFocusable="false">???</span>
            <span id="btnCounterReset" class="navbutton" MCFocusable="true">reset</span>
         </td>
      </tr>
   </table>
</span>

</body>
</html>

Die CSS-Datei (hier: "mediacenter.css")

Genauere Informationen zum Erstellen der CSS-Datei entnehmen Sie bitte den HTML-Samples des Media Center SDKs.

body
{
   background-color: "#0B5eBB";
   background-image: url(../images/background.jpg);
   background-repeat: no-repeat;
}

td
{
   position: relative;
}

.headback
{
   filter: alpha(opacity=10);
   position: absolute;
   left: -5px;
   top: 30px;
   color: White;
   font-family: Arial;
   font-size: 150px;
   text-align: left;
   font-weight: bold;
}

.headfront
{
   position: absolute;
   top: 125px;
   left: 105px;
   color: White;
   font-family: Arial;
   font-size: 25px;
   text-align: left;
   font-weight: bolder;
}

.leftmenu
{
   position: absolute;
   top: 200;
   left: 20;
   color: White;
   font-family: Arial;
   font-size: 20pt;
   font-weight: bold;
   font-size: 20pt;
   text-align: center;
   padding-top: 10px;
}

.navmenu
{
   position: absolute;
   top: 200;
   left: 280;
   height: 63%;
   width: 72%;
   overflow: hidden;
}

.navlabel
{
   color: White;
   width: 150px;
   height: 50px;
   font-family: Arial;
   font-size: 20pt;
   font-weight: bold;
   text-align: center;
   padding-top: 10px;
}

.navbutton
{
   behavior:url(Hilite.htc);
   color: White;
   background-image: url(../images/navbutton.gif);
   background-repeat: no-repeat;
   width: 250px;
   height: 50px;
   font-family: Arial;
   font-size: 20pt;
   font-weight: bold;
   text-align: center;
   padding-top: 10px;
   cursor: hand;
}

.navbutton_hilite
{
   behavior: url(Hilite.htc);
   color: White;
   background-image: url(../images/navbutton_hilite.gif);
   background-repeat: no-repeat;
   width: 250px;
   height: 50px;
   font-family: Arial;
   font-size: 20pt;
   font-weight: bold;
   text-align: center;
   padding-top: 10px;
   cursor: hand;
}

Fahren Sie nun mit Schritt 3 fort.


Schritt 3: Erstellen des WebServices

WebServices dienen dazu, per HTTP-Request bestimmte serverseitige Funktionen aufzurufen, welche auf den kompletten Funktionsumfang des .NET-Frameworks zurückgreifen können.

Hinweis: Für die Erstellung des WebServices wird dringend die Verwendung des Microsoft Visual Studio empfohlen.

Die ASMX-Seite

Bei einem Anlegen eines neuen WebSite-Projektes im Visual Studio wird die ASMX-Seite automatisch mitgeneriert, es ist jedoch möglich Veränderungen vorzunehmen.
Die Parameter dieser Datei haben folgende Bedeutung:
Language : Steht für die in der Quellcode-Datei verwendete Programmiersprache
CodeBehind : Gibt den Pfad der Quellcode-Datei an
Class : Steht für den Namen der Klasse in der Quellcode-Datei, welche von System.Web.Services.WebService erbt

Beispiel:

<%@ WebService Language="C#" CodeBehind="~/App_Code/TcMCE_Sample.cs" Class="TcMCE_Sample" %>

Die Quellcode-Datei

Diese Datei enthält den eigentlichen Quelltext. Um eine Klasse als WebService zu deklarieren, muss sie von System.Web.Services.WebService erben.
Außerdem muss Sie public sein und ihr die Zeile "[WebService()]" vorangestellt werden.

Um auf eine Funktion in dieser Klasse von außen über den WebService zuzugreifen, muss diese ebenfalls public sein und ihr "[WebMethod]" vorangestallt werden.
Diese Methoden können durchaus mehrere Eingabeparameter besitzen.
Wollen Sie mehr Daten zurücksenden, als es der Rückgabewert erlaubt, so sind Referenz-Parameter zu verwenden.

Beispiel:

public int ToggleLight(int nNumber, ref bool bValue)

Der Zugriff auf die SPS lässt sich nun per TwinCAT Ads.NET-Komponente, Ads-DLL oder Ads-OCX realisieren. Die Einbindung und Funktionsweise dieser Bibliotheken entnehmen Sie bitte den entsprechenden Dokumentationen im Beckhoff Information System.

Beispiel (in C#) :

using System;
using System.Web.Services;
using TwinCAT.Ads;

[WebService()]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class TcMCE_Sample : WebService
{
   TcAdsClient adsClient;
   int hLight1;
   int hLight2;
   int hCounter;

   public TcMCE_Sample()
   {
      adsClient = new TcAdsClient();
      adsClient.Connect(801);

      hLight1 = adsClient.CreateVariableHandle(".bLight1");
      hLight2 = adsClient.CreateVariableHandle(".bLight2");
      hCounter = adsClient.CreateVariableHandle(".nCounter");
   }

   ~TcMCE_Sample()
   {
      adsClient.DeleteVariableHandle(hLight1);
      adsClient.DeleteVariableHandle(hLight2);
      adsClient.DeleteVariableHandle(hCounter);
      adsClient.Dispose();
   }

   [WebMethod]
   public bool GetValues(ref bool[] arrLightValues, ref int nCounterValue)
   {
      try
      {
         arrLightValues = new bool[2];
         arrLightValues[0] = Convert.ToBoolean(adsClient.ReadAny(hLight1, typeof(bool)));
         arrLightValues[1] = Convert.ToBoolean(adsClient.ReadAny(hLight2, typeof(bool)));
         nCounterValue = Convert.ToInt32(adsClient.ReadAny(hCounter, typeof(int)));
         return true;
      }
      catch(Exception)
      {
         return false;
      }
   }

   [WebMethod]
   public int ToggleLight(int nNumber, ref bool bValue)
   {
      try
      {
         AdsStream adsStream = new AdsStream(1);
         AdsBinaryWriter adsWriter = new AdsBinaryWriter(adsStream);

         switch(nNumber)
         {
            case 1:
               bValue = !(Convert.ToBoolean(adsClient.ReadAny(hLight1, typeof(bool))));
               adsWriter.Write(bValue);
               adsClient.Write(hLight1, adsStream);
               return 1;
            case 2:
               bValue = !(Convert.ToBoolean(adsClient.ReadAny(hLight2, typeof(bool))));
               adsWriter.Write(bValue);
               adsClient.Write(hLight2, adsStream);
               return 2;
            default:
               return 0;
         }
      }
      catch(Exception)
      {
         return 0;
      }
   }

   [WebMethod]
   public bool ResetCounter()
   {
      try
      {
         AdsStream adsStream = new AdsStream(2);
         AdsBinaryWriter adsWriter = new AdsBinaryWriter(adsStream);
         adsWriter.Write((Int16)0);
         adsClient.Write(hCounter, adsStream);
         return true;
      }
      catch(Exception)
      {
         return false;
      }
   }
}

Nun muss dieser WebService per Javascript von der HTML-Seite aus angesprochen werden. Dies wird in Schritt 4 erklärt.


Schritt 4: Einbinden der Zugriffsmöglichkeit von der Media Center Oberfläche auf den WebService

Dieser Abschnitt beschreibt, wie die Media-Center-HTML-Seite per Javascript auf den zuvor erstellten WebService zugreifen kann.

Hierfür benötigen Sie die Datei "webservice.htc" aus dem Beispiel oder von Microsoft im MSDN. Diese kopieren Sie bitte in das Verzeichnis der in Schritt 2 erstellten HTML-Seite.

Notwendige Implementationen

  • Fügen Sie die der CSS-Datei dem "body" folgende Zeile hinzu:
    behavior:url(webservice.htc);

  • Fügen Sie der onLoad-Methode folgende Zeilen hinzu:
    body.onserviceavailable = enableServiceCall();
body.useService("...","...");
    Fügen Sie beim ersten Parameter der "useService"-Methode die URL der WSDL-Darstellung des WebServices ein.
    Der zweite Parameter steht für den Namen, über den Sie zukünftig die WebService-Funktionalität aufrufen wollen.

    Beispiel:

    body.useService("../TcMCE_Sample.asmx?wsdl","WebServiceSample");

  • Fügen Sie in Script-Teil der Seite folgende Zeile ein:
    function enableServiceCall(){}

Asynchroner Aufruf eines WebServices

Eine WebService-Funktion kann mit folgender Script-Zeile aufgerufen werden (wobei "WebServiceSample" durch den Namen ersetzt werden muss, den man bei Parameter 2 der "useService" -Funktion angegeben hat):
iCallID = body.Parameter2derUseServiceMethode.callService(... , "...", "...");
Parameter 1 beinhaltet den Namen der Funktion, die die Antwort des WebServices abfängt.
Parameter 2 steht für den Namen, den die aufzurufende Funktion des WebService hat.
Benötigt die die aufzurufende Funktion Eingabeparameter, so werden dafür die Parameter 3 und folgende verwendet.

Beispiel:

iCallID = body.WebServiceSample.callService(ToggleLight_Result, "ToggleLight", nNumber);

Abfangen der WebService-Antwort

Die Abfang-Methode muss einen Eingabeparameter "res" aufweisen.
Mit Hilfe des Aufrufs "res.value["AufgerufeneWebServiceMethodeResult"]" kann auf den Rückgabewert der Funktion zugegriffen werden.
Besitzt die Funktion Ausgangsparameter, so so lassen sich deren Werte mit dem Aufruf "res.value["ParameterName"]" aufrufen.
Beispiel:

function GetValues_Result(res)
{
   if(res.value["GetValuesResult"] == true)
   {
      lblLight1Value.innerText = res.value["arrLightValues"][0];
      lblLight2Value.innerText = res.value["arrLightValues"][1];
      lblCounterValue.innerText = res.value["nCounterValue"];
   }
}
Wie in diesem Beispiel zu sehen, ist sogar das Auslesen von Arrays möglich.

Um zu gewährleisten, dass die Werte konstant ausgelesen werden, muss eine Schleife in das Script eingebaut werden, welche die Werte kontinuierlich neu ausliest. Achten Sie dabei darauf, den Timeout nicht zu gering einzustellen, da sonst der Server (gerade bei vielen Benutzern) stark beansprucht wird.

Für die Schleife bietet sich die "window.setTimeout()"-Methode an."

Um mehr über das Auslesen von WebServices mit Javascript zu erfahren, lesen Sie bitte die entsprechenden Artikel im Mircosoft MSDN.

Wie man eine solche Implementierung im konkreten Beispiel realisieren kann, entnehmen Sie bitte dem Beispiel.

Sie besitzen nun alle Kenntnisse um selbst TwinCAT-Zugriffe über Media Center realisieren zu können.

Um die Visualisierung einzurichten lesen Sie bitte Schritt 5.


Schritt 5: Einrichten der Visualisierung

  • Spielen Sie das SPS-Programm auf die von Ihnen gewünschte SPS und Laufzeit. Passen Sie ggf. Ihren WebService hinsichtlich der AMS-Net-Id und des Ports an.
  • Legen Sie den WebService zusammen mit der HTML-Seite und den Script-Dateien auf dem Server im IIS in ein neues virtuelles Verzeichnis und gewähren Sie ausreichende Script-Ausführ- und Zugriffsrechte.

  • Die Visualisierung lässt sich nun mit Hilfe einer "MCL"-Datei und/oder einer speziellen Installation ins Media Center einpflegen bzw. darin aufrufen.
    Genauere Informationen hierzu entnehmen Sie bitte dem Media Center SDK.

    Beispiel für eine MCL-Datei:

    <application
   url="http://VisuServer/TcMCE_Sample/HTML/TcMCE_Sample.html"
   name="Connecting TwinCAT with Media Center"
   ThumbnailImage = "http://VisuServer/TcMCE_Sample/images/thumbnail.jpg"
/>