Code-Beispiele
Dieses Kapitel beschreibt wie WinCC OA C# Manager API verwendet werden kann. Das Kapitel enthält Executable Code-Beispiele. Den vollständigen Sourcecode des Beispiels finden Sie im letzten Abschnitt dieses Kapitels.
1. Neuen Manager erstellen
Folgen Sie den Anweisungen des Kapitels C# API-Manager erstellen und löschen Sie den Code der Klasse "Samples". Die Klasse sollte wie folgt aussehen:
using System;
using System.Threading.Tasks;
using ETM.WCCOA;
namespace GettingStarted
{
class Samples
{
static OaManager _managerInstance = null;
public Samples()
{
PrintSampleUsage();
}
public void PrintSampleUsage()
{
Console.Clear();
Console.WriteLine("Press key 1 - 9 to run sample code:");
Console.WriteLine("1 Create a new Manager");
Console.WriteLine("2 Establish a connection");
Console.WriteLine("3 Read an online value from WinCC OA sync + async");
Console.WriteLine("4 Write a value to WinCC OA async");
Console.WriteLine("5 Query value changes");
Console.WriteLine("6 Create a data point using ProcessModel");
Console.WriteLine("7 Query current alerts using a SELECT statement");
Console.WriteLine("8 Query historical values");
Console.WriteLine("9 Complete sample");
Console.WriteLine("ESC Exit sample");
}
}
}
2. Verbindung aufbauen
Bauen Sie eine Verbindung zu einem WinCC OA-Projekt über die Programmargumente (über die Kommandozeilenoptionen) auf. Kopieren Sie den Sourcecode in Ihr leeres Projekt.
class Program
using System;
using System.Threading.Tasks;
using ETM.WCCOA;
namespace GettingStarted
{
class Samples
{
static OaManager _managerInstance = null;
public Samples()
{
PrintSampleUsage();
}
public void PrintSampleUsage()
{
Console.Clear();
Console.WriteLine("Press key 1 - 9 to run sample code:");
Console.WriteLine("1 Create a new Manager");
Console.WriteLine("2 Establish a connection");
Console.WriteLine("3 Read an online value from WinCC OA sync + async");
Console.WriteLine("4 Write a value to WinCC OA async");
Console.WriteLine("5 Query value changes");
Console.WriteLine("6 Create a data point using ProcessModel");
Console.WriteLine("7 Query current alerts using a SELECT statement");
Console.WriteLine("8 Query historical values");
Console.WriteLine("9 Complete sample");
Console.WriteLine("ESC Exist sample");
}
// SAMPLE 1: Create a Manager object
public OaManager ManagerInstance
{
get
{
// Singleton design pattern - ensure that only one manager object is created
if (_managerInstance == null)
_managerInstance = OaSdk.CreateManager();
return _managerInstance;
}
}
// SAMPLE 2: Establish connection to the WinCC OA project
public async Task<int>EstablishConection(string[] args)
{
// Initialize manager configuration
ManagerInstance.Init(ManagerSettings.DefaultApiSettings, args);
// Start the manager
await ManagerInstance.StartAsync();
// Inform about the connection. Console output is shown in the WinCC OA logviewer
Console.WriteLine("Connection to project established");
return 1;
}
}
}
3. Lesen Sie einen Online-Wert aus WinCC OA
Das erste Beispiel liest einen Online-Wert über die synchrone Version der Funktion GetDpValue() aus dem WinCC OA-Projekt. Führen Sie das Beispiel aus indem Sie den Code in die Program-Klasse kopieren und ReadValuesExample() aus der main()-Funktion aufrufen:.
// SAMPLE 3: Read an online value from WinCC OA
public void ReadValuesExample()
{
// Get access to the ProcessValues
OaProcessValues valueAccess = ManagerInstance.ProcessValues;
// Calling GetDpValue via an "Access" object
OaDpValueItem myFloatItem = valueAccess.GetDpValue("ExampleDP_Arg1.");
// Read a property DpValue from an OaDpValue item
double myFloatVal1 = myFloatItem.DpValue;
// This could also be done in one line with
double myFloatVal2 = valueAccess.GetDpValue("ExampleDP_Arg1.").DpValue;
// Read more than one value
string[] myValuesToRead = { "ExampleDP_Arg1.", "ExampleDP_AlertHdl1." };
var myResultCollection = valueAccess.GetDpValue(myValuesToRead);
// Go through the answer collection
foreach (var item in myResultCollection)
{
Console.WriteLine(item.DpValue.ToString());
}
}
Das Beispiel liest einen Onlinewert über die asynchrone Version GetDpValueAsync() aus dem WinCC OA-Projekt. Führen Sie das Beispiel aus indem Sie den Code in die Program-Klasse kopieren und ReadValuesExampleAsync().Wait() aus der main()-Funktion aufrufen:.
// SAMPLE 3b: Read an online value from WinCC OA async
public async Task ReadValuesExampleAsync()
{
// Get access to the ProcessValues
OaProcessValues valueAccess = ManagerInstance.ProcessValues;
// Calling GetDpValue via an "Access" object
OaDpValueItem myFloatItem = await valueAccess.GetDpValueAsync("ExampleDP_Arg1.");
// Read property DpValue from OaDpValue item
double myFloatVal1 = myFloatItem.DpValue;
// Without await, the async value returns a Task object which could be awaited later on
Task<OaDpValueItem> myTaskToWait = valueAccess.GetDpValueAsync("ExampleDP_Arg1.");
// Do some work in between
Console.WriteLine("Do some work while waiting for value");
// Wait for the result and get a result value directly
var myFloatIVal2 = (await myTaskToWait).DpValue;
}
4. Schreibe einen Wert auf einen Datenpunkt.
Das folgende Beispiel schreibt den Float-Wert 4.2 auf den Datenpunkt “ExampleDP_Arg1.” Führen Sie das Beispiel aus indem Sie den Code in die Program-Klasse kopieren und WriteValuesExampleAsync().Wait() aus der main()-Funktion aufrufen:.
// SAMPLE 4. Write a value to WinCC OA
public async Task WriteValuesExampleAsync()
{
// Get access to the ProcessValues
OaProcessValues valueAccess = ManagerInstance.ProcessValues;
// Calling SetDpValue via an "Access" object. SetDpValue waits for an answer from
// the Event Manager
await valueAccess.SetDpValueAsync("ExampleDP_Arg1.", 4.2);
// Calling FireDpValue. FireDpValue does not wait for the answer from the Event Manager
// (therefore an async variant is not necessary)
valueAccess.FireDpValue("ExampleDP_Arg1.", 77.2);
// Set a collection of values with a specific time
await valueAccess.SetDpValueAsync(DateTime.Now.AddSeconds(2),
new Tuple<string, OaVariant>("ExampleDP_Arg1.", (double)7.7),
new Tuple<string, OaVariant>("ExampleDP_AlertHdl1.", (bool)false));
}
5. Abfrage von Wertänderungen
Das folgende Beispiel fragt Wert- und Zeitstempel-Änderungen der Datenpunkte “ExampleDP_Arg1.” und “ExampleDP_Arg2.” ab. Führen Sie das Beispiel aus indem Sie den Code in die Program-Klasse kopieren und SubscribeOnValueChangesExampleAsync().Wait() aus der main()-Funktion aufrufen:.
// SAMPLE 5: Query value changes
public async Task SubscribeOnValueChangesExampleAsync()
{
// Get access to the ProcessValues
OaProcessValues valueAccess = ManagerInstance.ProcessValues;
// Create "Subscription"-object
OaDpValueSubscription mySubscription = valueAccess.CreateDpValueSubscription();
// Append datapoints to subscribe to
mySubscription.AddDp("ExampleDP_Arg1.");
mySubscription.AddDp("ExampleDP_Arg1.:_online.._stime");
mySubscription.AddDp("ExampleDP_Arg2.");
mySubscription.AddDp("ExampleDP_Arg2.:_online.._stime");
// Define delegate function for value changed event. Can be done as shown here.
//Either as a Lambda function or as a separate function
mySubscription.SingleValueChanged += (vcsender, vce) =>
{
if (vce.IsAnswer)
Console.WriteLine("FirstAnswer: " + vce.Value.DpValue.ToString());
else
Console.WriteLine("ValueChange: " + vce.Value.DpValue.ToString());
};
// If FireChangedEventForAnswer is set to true, the ValueChangedEvent is also fired for the first answer
mySubscription.FireChangedEventForAnswer = true;
// Start the subscription and as an additional option wait for the first answer as result value
var FirstAnswerItem = await mySubscription.StartAsync();
// Change the value of one DPE to trigger the subscription event
await valueAccess.SetDpValueAsync("ExampleDP_Arg1.", 100.1);
await mySubscription.StopAsync();
}
6. Erstelle einen Datenpunkt über das ProcessModel
Der folgende Code erstellt einen neuen Datenpunkt “myNewTestDp”. Wenn der Datenpunkt bereits existiert, wird dieser automatisch gelöscht. Führen Sie das Beispiel aus indem Sie den Code in die Program-Klasse kopieren und ModifyDataModelExample().Wait() aus der main()-Funktion aufrufen:.
// SAMPLE 6: Create a data point by using ProcessModel
public async Task ModifyDataModelExample()
{
// Get access to the ProcessModel
OaProcessModel dataModel = ManagerInstance.ProcessModel;
// Check if data point "myNewTestDp" already exists and delete it in that case
if (await dataModel.IsDpPathExistingAsync("myNewTestDp"))
await dataModel.DeleteDpAsync("myNewTestDp");
// Create "myNewTestDp"
await dataModel.CreateDpAsync("myNewTestDp", "ExampleDP_Float");
}
7. Abfrage der aktuellen Alarme über eine SELECT-Abfrage
Das Beispiel fragt aktuelle Alarme ab. Führen Sie das Beispiel aus indem Sie den Code in die Program-Klasse kopieren und AlertQuerySubscriptionExample().Wait() aus der main()-Funktion aufrufen:.
// SAMPLE 7: Query current alerts using a SELECT statement
EventHandler<OaQuerySubscriptionChangedEventArgs> myAlertChangedEvent = delegate (object sender, OaQuerySubscriptionChangedEventArgs args)
{
for (int iLoop = 0; iLoop < args.Result.GetRecordCount(); iLoop++)
{
var atime = args.Result.GetData(iLoop, 1);
var avalue = args.Result.GetData(iLoop, 2);
Console.WriteLine("Record " + iLoop + ": alertTime: " + atime.ToString() + "value: " + avalue.ToString());
}
};
public async Task AlertQuerySubscriptionExample()
{
// Get access to Alerts
var alerts = ManagerInstance.Alerts;
// Create an AlertQuerySubscription
var alertSubscription = alerts.CreateAlertQuerySubscription();
// Configure AlertQuerySubscription;
// Set AlertChangedEvent by assigning the SystemEventHandler;
alertSubscription.ValueChanged += myAlertChangedEvent;
// Trigger a ChangedEvent also for first answer
alertSubscription.FireChangedEventForAnswer = true;
// Set the query-string
alertSubscription.SetQuery("SELECT ALERT '_alert_hdl.._value' FROM '*.**'");
// start AlertQuerySubscription
await alertSubscription.StartAsync();
}
8. Historische Werte abfragen
Der Code fragt historische Werte eines spezifischen Zeitbereiches ab. Führen Sie das Beispiel aus indem Sie den Code in die Program-Klasse kopieren und QueryHistoricalValuesExample().Wait() aus der main()-Funktion aufrufen:.
// SAMPLE 8: Query historical values
public async Task QueryHistoricalValuesExample()
{
// Get access to ValueHistory
var histAccess = ManagerInstance.ValueHistory;
DateTime tStart = DateTime.Now; // remember the start time
// Simulate 5 values using SetValue
for (int i = 1; i <= 5; i++)
{
// using ProcessValues directly without temporary variable
ManagerInstance.ProcessValues.SetDpValue("ExampleDP_Rpt1.", (double)i);
}
DateTime tEnd = DateTime.Now; // remember the end time
// Query the historical data
var myResult = await histAccess.GetDpValuePeriodAsync(tStart, tEnd, "ExampleDP_Rpt1.");
foreach (var TimedValue in myResult)
{
Console.WriteLine("Received: " + TimedValue.DpName.ToString() +
" Value: " + TimedValue.DpValue.ToString() +
" Timestamp: " + TimedValue.SourceTime.ToString());
}
}
9. Vollständiges Beispiel
Das folgende Beispiel enthält den vollständigen Beispiel-Code:
// SAMPLE 9: Complete sample
public void CompleteSample(string[] args)
{
// get a local reference to the Manager object
OaManager myManager = ManagerInstance;
// Initialize Manager Configuration
myManager.Init(ManagerSettings.DefaultApiSettings, args);
// Start the Manager and Connect to the OA project with the given configuration
myManager.Start();
// Read from config File Section myCsTest.
// ReadString(section, key, defaultval)
OaConfigurationFile file = new OaConfigurationFile();
string dpNameSet = file.ReadString("myCsTest", "dpNameSet", "ExampleDP_Arg2.");
string dpNameConnect = file.ReadString("myCsTest", "dpNameConnect", "ExampleDP_Arg1.");
// Get Access to the ProcessValues
var valueAccess = myManager.ProcessValues;
// Create Subscription object
var mySubscription = valueAccess.CreateDpValueSubscription();
// Append Datapoints to subcribe on
mySubscription.AddDp(dpNameConnect);
// Define Lambda function for value changed event. Can be done as shon here as Lambda function or as seperate function
mySubscription.SingleValueChanged += (vcsender, vce) =>
{
// vce.Value can be null in error case
if (vce.Value == null)
return;
Console.WriteLine("Received value: " + vce.Value.DpValue.ToString() + " for DPE: " + vce.Value.DpName.ToString());
//Set received value on DPE dpNameSet
valueAccess.SetDpValue(dpNameSet, vce.Value.DpValue.ToDouble());
Console.WriteLine("Set value: " + vce.Value.DpValue.ToString() + " also on DPE: " + dpNameSet);
};
// If FireChangedEventForAnswer is set to true, the ValueChanged Event is also fired for the first answer
mySubscription.FireChangedEventForAnswer = true;
// Start the subscription and as an additional option wait for the first answer as a result value
mySubscription.StartAsync();
}
}
}