I had the opportunity recently to work for a client who wanted to extract log data from a Siemens WinAC PLC using a C# .NET client. The application was archiving software that would run when another software component encountered an error. Log data was assembled from a variety of sources in the system stack, including the Siemens PLC. In order to keep the PLC's Step 7 code independent of this diagnostic logging, I used the Siemens WinAC ODK.
The WinAC API exposes two interfaces, IPLC and IFeature, which can be used to extract logging information from the PLC. The WinAC ODK User Manual, available for download from Siemens, explains how to add two assemblies, S7WCUIFX and S7WCUFPX, to a C# project. Note that 32-bit regsvr32.exe must be run without the /i switch to register these assemblies on all systems upon which the extractor will execute. After doing so, two type libraries will be available for use in your project. Adding these as references will create an interoperation assembly for each of the Siemens assemblies. Lastly, set the Embed Interop Types option of each type library in your project to false to avoid compiler errors.
The WinAC ODK includes some sample programs which can be used as templates when extracting log data from the PLC. The first step is to find your target PLC on the network. To do that, resolve the name of the computer hosting the Step 7 controller, and pass that as the single string in a string array to the IPLC.Browse method. This should be able to find PLCs on your local network. If you want to find the PLC on your local machine, pass an empty string array to the Browse method. The Browse method will return two objects that can be passed to the IPLC.Connect method, which will in turn return an object implementing IFeature.
IFeature can be used to enumerate all of the "features" of the PLC. Features are objects exposing PLC functionality to clients of the WinAC API. In our case, we are interested in the DiagnosticLanguage and Diagnostic features. Both must be present to extract logging data from the PLC. The DiagnosticLanguage feature specifies the language in which the PLC data will be returned, while the Diagnostic feature exposes the PLC logs themselves. First get the DiagnosticLanguage feature using IFeature.GetFeature, then manipulate its return objects as shown below to obtain the Diagnostic feature. Once the diagnostic feature has been obtained, it is short work to list all of the diagnostic events in the PLC log and extract those of interest.
Here is the tricky code needed to populate all of the diagnostic events when obtaining the Diagnostic feature.
object
oAttributeNames =
null
;
object
oAttributeValues =
null
;
_Feature.GetFeature(
"DiagnosticLanguage"
,
ref
oAttributeNames,
ref
oAttributeValues,
ref
errorId);
// check for errors
if
(errorId != 0)
{
throw
new
Exception(
"Getting feature language failed."
);
}
// get the returned arrays
string
[] attributeNames = (
string
[])oAttributeNames;
Array attributeValues = (Array)oAttributeValues;
int
i = 0;
foreach
(var attributeValue
in
attributeValues)
{
if
(attributeValue.ToString() ==
"ENGLISH"
)
{
attributeNames[i] =
"Language"
;
// This denotes English as the language in which the diagnostic data will be returned
}
++i;
}
_Feature.GetFeature(
"Diagnostic"
,
ref
oAttributeNames,
ref
oAttributeValues,
ref
errorId);
Learn more about DMC's manufacturing automation and intelligence services.