Code Examples
The following chapter gives you an introduction into the C# manager API via some executable source code examples. Refer to the last section of this chapter for the complete source code of the example.
-
Create a new Manager
Follow the instructions of the chapter Create an C# API manager and delete the source code of the class "Program". Your class should now look as follows:
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");
}
}
}
-
Establish a connection
The following example establishes a connection to a WinCC OA project via given program arguments provided by the command line. Copy the source code into your empty project.
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 goes right into the WinCC OA logviewer
Console.WriteLine("Connection to project established");
return 1;
}
}
}
-
Read an online value from WinCC OA
First example reads an online value using the synchronous version of the GetDpValue() function from the connected WinCC OA project Run the example by copying the code into the class Program and call ReadValuesExample() from the main() function.
// 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 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());
}
}
The second code snippet reads an online value using the asynchronous version of the GetDpValue() function from the connected WinCC OA project. Run the example by copying the code into the class Program and call ReadValuesExampleAsync().Wait() from the main() function.
// 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 a property DpValue from OaDpValue tem
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;
}
-
Write a value to WinCC OA
The following code writes the float value 4.2 on the data point “ExampleDP_Arg1.” Run the example by copying the code into the class Program and call WriteValuesExampleAsync().Wait() from the main() function.
// 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));
}
-
Query value changes
The following example subscribes on value and timestamp changes of the data points “ExampleDP_Arg1.” and “ExampleDP_Arg2.”. Run the example by copying the code into the class Program and call SubscribeOnValueChangesExampleAsync().Wait() from the main() function.
// 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 data points 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();
}
-
Create a data point using ProcessModel
The following code creates a new data point “myNewTestDp”. If the data point already exists, it is automatically deleted. Run the example by copying the code into the class Program and call ModifyDataModelExample().Wait() from the main() function.
// 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");
}
-
Query current alerts using a SELECT statement
This code snippet queries current alerts. Run the example by copying the code into the class Program and call AlertQuerySubscriptionExample().Wait() from the main() function.
// 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();
}
-
Query historical values
The code queries historical values within a specific time range. Run the example by copying the code into the class Program and call QueryHistoricalValuesExample().Wait() from the main() function.
// 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());
}
}
-
Full example
The following example contains the full example 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 shown here as Lambda function or as separate 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();
}
}
}