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 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 - SCLParser: also available on tools, you can load your SCL model and use it with our library
Changes to version 1.6.0 Changes to version 1.6.0
------------------------ ------------------------

@ -1,24 +1,8 @@
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; 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: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [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, // The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing. // if desired. See the Mono documentation for more information about signing.

@ -1,56 +1,23 @@
<?xml version="1.0" encoding="utf-8"?> <Project Sdk="Microsoft.NET.Sdk">
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <TargetFramework>netstandard2.0</TargetFramework>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C35D624E-5506-4560-8074-1728F1FA1A4D}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RootNamespace>iec61850dotnet</RootNamespace> <RootNamespace>iec61850dotnet</RootNamespace>
<AssemblyName>iec61850dotnet</AssemblyName> <AssemblyName>iec61850dotnet</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion> <AssemblyTitle>IEC61850 API for C#</AssemblyTitle>
<TargetFrameworkProfile /> <Company>MZ Automation GmbH</Company>
<Copyright>Michael Zillgith</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath> <OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants> <DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType> <DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath> <OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </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> </Project>

@ -22,9 +22,11 @@
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using IEC61850.Common; using IEC61850.Common;
using IEC61850.TLS; using IEC61850.TLS;
using static IEC61850.Client.IedConnection;
// IEC 61850 API for the libiec61850 .NET wrapper library // IEC 61850 API for the libiec61850 .NET wrapper library
namespace IEC61850 namespace IEC61850
@ -2186,6 +2188,22 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int LogStorage_getMaxLogEntries(IntPtr self); 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)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void LogStorage_destroy(IntPtr self); static extern void LogStorage_destroy(IntPtr self);
@ -2210,6 +2228,21 @@ namespace IEC61850
{ {
return LogStorage_getMaxLogEntries(self); 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> /// <summary>
/// The maximum allowed number of log entries in the log storage /// The maximum allowed number of log entries in the log storage
@ -2315,6 +2348,12 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedServer_getFunctionalConstrainedData(IntPtr self, IntPtr dataObject, int fc); 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)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int InternalControlPerformCheckHandler (IntPtr action, IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test, [MarshalAs(UnmanagedType.I1)] bool interlockCheck); 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 Dictionary<IntPtr, WriteAccessHandlerInfo> writeAccessHandlers = new Dictionary<IntPtr, WriteAccessHandlerInfo> ();
private void ConnectionIndicationHandlerImpl (IntPtr iedServer, IntPtr clientConnection, bool connected, IntPtr parameter) private void ConnectionIndicationHandlerImpl (IntPtr iedServer, IntPtr clientConnection, bool connected, IntPtr parameter)

@ -208,6 +208,12 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [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)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_clone(IntPtr self); static extern IntPtr MmsValue_clone(IntPtr self);
@ -221,6 +227,17 @@ namespace IEC61850
this.responsableForDeletion = false; this.responsableForDeletion = false;
} }
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) internal MmsValue (IntPtr value, bool responsableForDeletion)
{ {
valueReference = value; valueReference = value;

@ -47,12 +47,14 @@ namespace log_client
Console.WriteLine("LD: " + deviceName); Console.WriteLine("LD: " + deviceName);
List<string> deviceDirectory = con.GetLogicalDeviceDirectory(deviceName); List<string> deviceDirectory = con.GetLogicalDeviceDirectory(deviceName);
foreach (string lnName in deviceDirectory) { foreach (string lnName in deviceDirectory)
{
Console.WriteLine(" LN: " + lnName); Console.WriteLine(" LN: " + lnName);
List<string> lcbs = con.GetLogicalNodeDirectory(deviceName + "/" + lnName, IEC61850.Common.ACSIClass.ACSI_CLASS_LCB); 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); Console.WriteLine(" LCB: " + lcbName);
MmsValue lcbValues = con.ReadValue(deviceName + "/" + lnName + "." + lcbName, FunctionalConstraint.LG); 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); 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); Console.WriteLine(" LOG: " + logName);
} }
} }
@ -72,6 +75,9 @@ namespace log_client
Console.WriteLine("\nQueryLogAfter:"); Console.WriteLine("\nQueryLogAfter:");
Console.WriteLine(DateTime.UtcNow);
List<MmsJournalEntry> journalEntries = con.QueryLogAfter("simpleIOGenericIO/LLN0$EventLog", List<MmsJournalEntry> journalEntries = con.QueryLogAfter("simpleIOGenericIO/LLN0$EventLog",
new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0, out moreFollows); new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0, out moreFollows);

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

@ -2,10 +2,15 @@
using IEC61850.Server; using IEC61850.Server;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Common;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using static IEC61850.Server.IedServer;
using static IEC61850.Server.LogStorage;
namespace log_server namespace log_server
{ {
@ -13,6 +18,25 @@ namespace log_server
{ {
public static void Main(string[] args) 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; bool running = true;
/* run until Ctrl-C is pressed */ /* run until Ctrl-C is pressed */
@ -41,7 +65,37 @@ namespace log_server
iedServer.SetLogStorage("GenericIO/LLN0$EventLog", statusLog); 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()) if (iedServer.IsRunning())
{ {
@ -67,7 +121,11 @@ namespace log_server
stVal = !stVal; stVal = !stVal;
iedServer.LockDataModel(); 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.UpdateTimestampAttributeValue(ggio1AnIn1T, ts);
iedServer.UpdateFloatAttributeValue(ggio1AnIn1magF, floatVal); iedServer.UpdateFloatAttributeValue(ggio1AnIn1magF, floatVal);
iedServer.UpdateTimestampAttributeValue(ggio1Spcso1T, ts); iedServer.UpdateTimestampAttributeValue(ggio1Spcso1T, ts);
@ -86,6 +144,7 @@ namespace log_server
} }
iedServer.Destroy(); iedServer.Destroy();
statusLog.Dispose();
} }
} }
} }

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

@ -3,7 +3,7 @@
# Typical usage: # Typical usage:
# *) install cross compiler: `sudo apt-get install mingw-w64` # *) install cross compiler: `sudo apt-get install mingw-w64`
# *) cd build # *) 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. # This is free and unencumbered software released into the public domain.
set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_SYSTEM_NAME Windows)

Loading…
Cancel
Save