LogServies API added

v1.6
Maxson Ramon dos Anjos Medeiros 2 months ago
parent c69b958134
commit 4a8245caf3

@ -1,9 +1,16 @@
Changes to version 1.6.1
------------------------
-.NET Tools: in the Tools folder you can find the .net project to generate Static and Dynamic Models
New features and improvements:
- .NET API: IEC61850ServerAPI -> LogStorage function wrapper added.
- .NET API: MmsValue -> MmsValue_encodeMmsData and MmsValue_decodeMmsData added.
- .NET API: Fixed issue of not printing log entries in log_client and log_server examples.
- .NET Tools: in the Tools folder you can find the .net project to generate Static and Dynamic Models
- SCLParser: also available on tools, you can load your SCL model and use it with our library
Changes to version 1.6.0
------------------------

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("IEC61850 API for C#")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("MZ Automation GmbH")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Michael Zillgith")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,56 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C35D624E-5506-4560-8074-1728F1FA1A4D}</ProjectGuid>
<TargetFramework>netstandard2.0</TargetFramework>
<OutputType>Library</OutputType>
<RootNamespace>iec61850dotnet</RootNamespace>
<AssemblyName>iec61850dotnet</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkProfile />
<AssemblyTitle>IEC61850 API for C#</AssemblyTitle>
<Company>MZ Automation GmbH</Company>
<Copyright>Michael Zillgith</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="MmsValue.cs" />
<Compile Include="DataSet.cs" />
<Compile Include="ReportControlBlock.cs" />
<Compile Include="IEC61850ClientAPI.cs" />
<Compile Include="Reporting.cs" />
<Compile Include="Control.cs" />
<Compile Include="IsoConnectionParameters.cs" />
<Compile Include="MmsVariableSpecification.cs" />
<Compile Include="IEC61850ServerAPI.cs" />
<Compile Include="IEC61850CommonAPI.cs" />
<Compile Include="TLS.cs" />
<Compile Include="SampledValuesControlBlock.cs" />
<Compile Include="GooseControlBlock.cs" />
<Compile Include="GooseSubscriber.cs" />
<Compile Include="SampledValuesSubscriber.cs" />
<Compile Include="IedServerConfig.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

@ -22,9 +22,11 @@
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using IEC61850.Common;
using IEC61850.TLS;
using static IEC61850.Client.IedConnection;
// IEC 61850 API for the libiec61850 .NET wrapper library
namespace IEC61850
@ -2186,6 +2188,22 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int LogStorage_getMaxLogEntries(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int LogStorage_addEntry(IntPtr self, long time);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool LogStorage_addEntryData(IntPtr self, int entryID, string dataRef, byte[] data, int dataSize, int reasonCode);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool LogEntryCallback(IntPtr self, long timeStamp, long entryID, bool moreFollows);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool LogEntryDataCallback(IntPtr self, string dataRef, byte[] data, int dataSize, int reasonCode, bool moreFollows);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool LogStorage_getEntries(IntPtr self, long startingTime, long endingTime, LogEntryCallback entryCallback, LogEntryDataCallback entryDataCallback, object parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void LogStorage_destroy(IntPtr self);
@ -2210,6 +2228,21 @@ namespace IEC61850
{
return LogStorage_getMaxLogEntries(self);
}
public int AddEntry(long time)
{
return LogStorage_addEntry(self, time);
}
public bool AddEntryData(int entryID, string dataRef, byte[] data, int dataSize, int reasonCode)
{
return LogStorage_addEntryData(self, entryID, dataRef, data, dataSize, reasonCode);
}
public bool GetEntries(long startingTime, long endingTime, LogEntryCallback entryCallback, LogEntryDataCallback entryDataCallback, object parameter)
{
return LogStorage_getEntries(self, startingTime, endingTime, entryCallback, entryDataCallback, parameter);
}
/// <summary>
/// The maximum allowed number of log entries in the log storage
@ -2315,6 +2348,12 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedServer_getFunctionalConstrainedData(IntPtr self, IntPtr dataObject, int fc);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
public static extern void IedServer_setListObjectsAccessHandler(IntPtr self, IedServer_ListObjectsAccessHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool IedServer_ListObjectsAccessHandler(IntPtr parameter, ClientConnection connection, ACSIClass acsiClass, LogicalDevice ld, LogicalNode ln, string objectName, string subObjectName, FunctionalConstraint fc);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int InternalControlPerformCheckHandler (IntPtr action, IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test, [MarshalAs(UnmanagedType.I1)] bool interlockCheck);
@ -2538,6 +2577,11 @@ namespace IEC61850
}
}
public void SetListObjectsAccessHandler(IedServer_ListObjectsAccessHandler handler, System.IntPtr parameter)
{
IedServer_setListObjectsAccessHandler(self, handler, parameter);
}
private Dictionary<IntPtr, WriteAccessHandlerInfo> writeAccessHandlers = new Dictionary<IntPtr, WriteAccessHandlerInfo> ();
private void ConnectionIndicationHandlerImpl (IntPtr iedServer, IntPtr clientConnection, bool connected, IntPtr parameter)

@ -206,7 +206,13 @@ namespace IEC61850
static extern void MmsValue_setElement(IntPtr complexValue, int index, IntPtr elementValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsVariableSpecification_getChildValue(IntPtr self, IntPtr value, string childId);
static extern IntPtr MmsVariableSpecification_getChildValue(IntPtr self, IntPtr value, string childId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsValue_encodeMmsData(IntPtr self, byte[] buffer, int bufPos, bool encode);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsValue_decodeMmsData(IntPtr self, int bufPos, int bufferLength, IntPtr endBufPo);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_clone(IntPtr self);
@ -220,8 +226,19 @@ namespace IEC61850
valueReference = value;
this.responsableForDeletion = false;
}
internal MmsValue (IntPtr value, bool responsableForDeletion)
public int EncodeMmsData(byte[] buffer, int bufPos, bool encode)
{
return MmsValue_encodeMmsData(this.valueReference, buffer, bufPos, encode);
}
public int DecodeMmsData(int bufPos, int bufferLength, IntPtr endBufPo)
{
return MmsValue_decodeMmsData(this.valueReference, bufPos, bufferLength, endBufPo);
}
internal MmsValue (IntPtr value, bool responsableForDeletion)
{
valueReference = value;
this.responsableForDeletion = responsableForDeletion;

@ -10,7 +10,7 @@ namespace log_client
private static void PrintJournalEntries(List<MmsJournalEntry> journalEntries) {
foreach (MmsJournalEntry entry in journalEntries) {
Console.WriteLine("EntryID: " + BitConverter.ToString(entry.GetEntryID()));
Console.WriteLine(" occurence time: " + MmsValue.MsTimeToDateTimeOffset(entry.GetOccurenceTime()).ToString());
Console.WriteLine(" occurence time: " + MmsValue.MsTimeToDateTimeOffset(entry.GetOccurenceTime()).ToString());
foreach (MmsJournalVariable variable in entry.GetJournalVariables()) {
Console.WriteLine(" variable: " + variable.GetTag());
Console.WriteLine(" value: " + variable.GetValue().ToString());
@ -47,12 +47,14 @@ namespace log_client
Console.WriteLine("LD: " + deviceName);
List<string> deviceDirectory = con.GetLogicalDeviceDirectory(deviceName);
foreach (string lnName in deviceDirectory) {
foreach (string lnName in deviceDirectory)
{
Console.WriteLine(" LN: " + lnName);
List<string> lcbs = con.GetLogicalNodeDirectory(deviceName + "/" + lnName, IEC61850.Common.ACSIClass.ACSI_CLASS_LCB);
foreach(string lcbName in lcbs) {
foreach (string lcbName in lcbs)
{
Console.WriteLine(" LCB: " + lcbName);
MmsValue lcbValues = con.ReadValue(deviceName + "/" + lnName + "." + lcbName, FunctionalConstraint.LG);
@ -62,7 +64,8 @@ namespace log_client
List<string> logs = con.GetLogicalNodeDirectory(deviceName + "/" + lnName, IEC61850.Common.ACSIClass.ACSI_CLASS_LOG);
foreach(string logName in logs) {
foreach (string logName in logs)
{
Console.WriteLine(" LOG: " + logName);
}
}
@ -72,7 +75,10 @@ namespace log_client
Console.WriteLine("\nQueryLogAfter:");
List<MmsJournalEntry> journalEntries = con.QueryLogAfter("simpleIOGenericIO/LLN0$EventLog",
Console.WriteLine(DateTime.UtcNow);
List<MmsJournalEntry> journalEntries = con.QueryLogAfter("simpleIOGenericIO/LLN0$EventLog",
new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0, out moreFollows);
PrintJournalEntries(journalEntries);

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8.1" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>
</configuration>

@ -2,10 +2,15 @@
using IEC61850.Server;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Common;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static IEC61850.Server.IedServer;
using static IEC61850.Server.LogStorage;
namespace log_server
{
@ -13,6 +18,25 @@ namespace log_server
{
public static void Main(string[] args)
{
bool entryCallback(System.IntPtr self, long timestamp, long entryID1, bool moreFollow)
{
if (moreFollow)
Console.WriteLine($"Found entry ID:{entryID1} timestamp:{timestamp}");
return true;
}
bool entryDataCallback(System.IntPtr self, string dataRef, byte[] data, int dataSize, int reasonCode, bool moreFollow)
{
if (moreFollow)
{
Console.WriteLine($"EntryData: ref: {dataRef}\n");
}
return true;
}
bool running = true;
/* run until Ctrl-C is pressed */
@ -41,7 +65,37 @@ namespace log_server
iedServer.SetLogStorage("GenericIO/LLN0$EventLog", statusLog);
iedServer.Start(10002);
long time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
int entryID = statusLog.AddEntry(time);
MmsValue value = new MmsValue(123);
byte[] blob = new byte[256];
int blobSize = value.EncodeMmsData(blob, 0, true);
bool restun = statusLog.AddEntryData(entryID, "GenericIO/GGIO1.SPCSO1$stVal", blob, blobSize, 0);
value.Dispose();
ulong unixTimeMs = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
entryID = statusLog.AddEntry((long)unixTimeMs);
value = MmsValue.NewUtcTime(unixTimeMs);
blob = new byte[256];
blobSize = value.EncodeMmsData(blob, 0, true);
value.Dispose();
bool restun1 = statusLog.AddEntryData(entryID, "simpleIOGenerioIO/GPIO1$ST$SPCSO1$t", blob, blobSize, 0);
bool return3 = statusLog.GetEntries(0, DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), (LogEntryCallback)entryCallback, (LogEntryDataCallback)entryDataCallback, (System.IntPtr)null);
iedServer.Start(102);
if (iedServer.IsRunning())
{
@ -67,7 +121,11 @@ namespace log_server
stVal = !stVal;
iedServer.LockDataModel();
var ts = new Timestamp(DateTime.Now);
long unixSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
DateTime utcTime = DateTimeOffset.FromUnixTimeSeconds(unixSeconds).UtcDateTime;
var ts = new Timestamp(utcTime);
iedServer.UpdateTimestampAttributeValue(ggio1AnIn1T, ts);
iedServer.UpdateFloatAttributeValue(ggio1AnIn1magF, floatVal);
iedServer.UpdateTimestampAttributeValue(ggio1Spcso1T, ts);
@ -86,6 +144,7 @@ namespace log_server
}
iedServer.Destroy();
statusLog.Dispose();
}
}
}

@ -8,7 +8,7 @@
<OutputType>Exe</OutputType>
<RootNamespace>log_server</RootNamespace>
<AssemblyName>log_server</AssemblyName>
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
@ -27,6 +27,7 @@
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>

@ -3,7 +3,7 @@
# Typical usage:
# *) install cross compiler: `sudo apt-get install mingw-w64`
# *) cd build
# *) cmake -DCMAKE_TOOLCHAIN_FILE=~/mingw-w64-x86_64.cmake ..
# *) cmake -DCMAKE_TOOLCHAIN_FILE=../mingw-w64-x86_64.cmake ..
# This is free and unencumbered software released into the public domain.
set(CMAKE_SYSTEM_NAME Windows)

Loading…
Cancel
Save