- .NET API: GooseSubscriber - added GetGoId, GetGoCbRef, GetFataSet

methods
- .NET API: GooseReceiver - store references to all added
GooseSubscribers to prevent garbage collection
- update documentation comments for GooseSubscriber API
pull/341/head
Michael Zillgith 4 years ago
parent 2ace50b712
commit bb64d9d8fe

@ -22,6 +22,7 @@
*/ */
using System; using System;
using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using IEC61850.Common; using IEC61850.Common;
@ -69,6 +70,8 @@ namespace IEC61850
private bool isDisposed = false; private bool isDisposed = false;
private List<GooseSubscriber> subscribers = new List<GooseSubscriber>();
public GooseReceiver() public GooseReceiver()
{ {
self = GooseReceiver_create (); self = GooseReceiver_create ();
@ -79,14 +82,29 @@ namespace IEC61850
GooseReceiver_setInterfaceId (self, interfaceId); GooseReceiver_setInterfaceId (self, interfaceId);
} }
/// <summary>
/// Add the subscriber to be handled by this receiver instance
/// </summary>
/// <remarks>A GooseSubscriber can only be added to one GooseReceiver!</remarks>
/// <param name="subscriber"></param>
public void AddSubscriber(GooseSubscriber subscriber) public void AddSubscriber(GooseSubscriber subscriber)
{ {
GooseReceiver_addSubscriber (self, subscriber.self); if (subscriber.attachedToReceiver == false)
{
subscriber.attachedToReceiver = true;
GooseReceiver_addSubscriber(self, subscriber.self);
subscribers.Add(subscriber);
}
} }
public void RemoveSubscriber(GooseSubscriber subscriber) public void RemoveSubscriber(GooseSubscriber subscriber)
{ {
GooseReceiver_removeSubscriber (self, subscriber.self); if (subscriber.attachedToReceiver)
{
GooseReceiver_removeSubscriber(self, subscriber.self);
subscribers.Remove(subscriber);
subscriber.attachedToReceiver = false;
}
} }
public void Start() public void Start()
@ -175,10 +193,22 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseSubscriber_setListener (IntPtr self, InternalGooseListener listener, IntPtr parameter); private static extern void GooseSubscriber_setListener (IntPtr self, InternalGooseListener listener, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getGoId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getGoCbRef(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getDataSet(IntPtr self);
internal IntPtr self; internal IntPtr self;
private bool isDisposed = false; private bool isDisposed = false;
// don't call native destructor when attached to a receiver
internal bool attachedToReceiver = false;
private GooseListener listener = null; private GooseListener listener = null;
private object listenerParameter = null; private object listenerParameter = null;
@ -214,7 +244,6 @@ namespace IEC61850
return GooseSubscriber_isValid (self); return GooseSubscriber_isValid (self);
} }
public void SetListener(GooseListener listener, object parameter) public void SetListener(GooseListener listener, object parameter)
{ {
this.listener = listener; this.listener = listener;
@ -227,6 +256,21 @@ namespace IEC61850
} }
} }
public string GetGoId()
{
return Marshal.PtrToStringAnsi(GooseSubscriber_getGoId(self));
}
public string GetGoCbRef()
{
return Marshal.PtrToStringAnsi(GooseSubscriber_getGoCbRef(self));
}
public string GetDataSet()
{
return Marshal.PtrToStringAnsi(GooseSubscriber_getDataSet(self));
}
public UInt32 GetStNum() public UInt32 GetStNum()
{ {
return GooseSubscriber_getStNum (self); return GooseSubscriber_getStNum (self);
@ -300,12 +344,20 @@ namespace IEC61850
{ {
if (isDisposed == false) { if (isDisposed == false) {
isDisposed = true; isDisposed = true;
GooseSubscriber_destroy (self);
if (attachedToReceiver == false)
GooseSubscriber_destroy (self);
self = IntPtr.Zero; self = IntPtr.Zero;
} }
} }
} ~GooseSubscriber()
{
Dispose();
}
}
} }

@ -886,7 +886,7 @@ namespace IEC61850
/// Creates a new SampledValuesControlBlock instance. /// Creates a new SampledValuesControlBlock instance.
/// </summary> /// </summary>
/// <returns>The new GoCB instance</returns> /// <returns>The new GoCB instance</returns>
/// <param name="gocbObjectReference">The object reference of the GoCB</param> /// <param name="gocbObjectReference">The object reference of the GoCB (e.g. "simpleIOGenericIO/LLN0.gcbAnalogValues")</param>
public GooseControlBlock GetGooseControlBlock(string gocbObjectReference) public GooseControlBlock GetGooseControlBlock(string gocbObjectReference)
{ {
return new GooseControlBlock(gocbObjectReference, connection); return new GooseControlBlock(gocbObjectReference, connection);

@ -86,9 +86,9 @@ namespace IEC61850
public UInt16 vlanId; public UInt16 vlanId;
public UInt16 appId; public UInt16 appId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=6)] [MarshalAs(UnmanagedType.ByValArray, SizeConst=6)]
public byte[] dstAddress = new byte[6]; public byte[] dstAddress = new byte[6];
} }
/// <summary> /// <summary>
/// MMS data access error for MmsValue type MMS_DATA_ACCESS_ERROR /// MMS data access error for MmsValue type MMS_DATA_ACCESS_ERROR

@ -4,6 +4,9 @@ using IEC61850.GOOSE.Subscriber;
using System.Threading; using System.Threading;
using IEC61850.Common; using IEC61850.Common;
/// <summary>
/// This example is intended to be
/// </summary>
namespace goose_subscriber namespace goose_subscriber
{ {
class MainClass class MainClass
@ -11,9 +14,10 @@ namespace goose_subscriber
private static void gooseListener (GooseSubscriber subscriber, object parameter) private static void gooseListener (GooseSubscriber subscriber, object parameter)
{ {
Console.WriteLine ("Received GOOSE message:\n-------------------------"); Console.WriteLine ("Received GOOSE message:\n-------------------------");
Console.WriteLine (" GoID: " + subscriber.GetGoId());
Console.WriteLine (" GoCbRef: " + subscriber.GetGoCbRef());
Console.WriteLine (" DatSet: " + subscriber.GetDataSet());
Console.WriteLine (" stNum: " + subscriber.GetStNum ()); Console.WriteLine (" stNum: " + subscriber.GetStNum ());
Console.WriteLine (" sqNum: " + subscriber.GetSqNum ()); Console.WriteLine (" sqNum: " + subscriber.GetSqNum ());
@ -33,17 +37,27 @@ namespace goose_subscriber
GooseReceiver receiver = new GooseReceiver (); GooseReceiver receiver = new GooseReceiver ();
receiver.SetInterfaceId ("eth0"); receiver.SetInterfaceId ("eth0");
//receiver.SetInterfaceId("0"); // on windows use the interface index starting with 0
GooseSubscriber subscriber = new GooseSubscriber ("simpleIOGenericIO/LLN0$GO$gcbAnalogValues"); GooseSubscriber subscriber = new GooseSubscriber ("simpleIOGenericIO/LLN0$GO$gcbAnalogValues");
subscriber.SetAppId(1000); // APP-ID has to match the APP-ID of the publisher
subscriber.SetAppId(4096);
subscriber.SetListener (gooseListener, null); subscriber.SetListener (gooseListener, null);
receiver.AddSubscriber (subscriber); receiver.AddSubscriber (subscriber);
GooseSubscriber subscriber2 = new GooseSubscriber("simpleIOGenericIO/LLN0$GO$gcbEvents");
subscriber2.SetAppId(4096);
subscriber2.SetListener(gooseListener, null);
receiver.AddSubscriber(subscriber2);
receiver.Start (); receiver.Start ();
subscriber = null;
if (receiver.IsRunning ()) { if (receiver.IsRunning ()) {
bool running = true; bool running = true;

@ -1,7 +1,7 @@
/* /*
* goose_subscriber.h * goose_subscriber.h
* *
* Copyright 2013-2018 Michael Zillgith * Copyright 2013-2021 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -82,12 +82,27 @@ typedef void (*GooseListener)(GooseSubscriber subscriber, void* parameter);
LIB61850_API GooseSubscriber LIB61850_API GooseSubscriber
GooseSubscriber_create(char* goCbRef, MmsValue* dataSetValues); GooseSubscriber_create(char* goCbRef, MmsValue* dataSetValues);
/**
* \brief Get the GoId value of the received GOOSE message
*
* \param self GooseSubscriber instance to operate on.
*/
LIB61850_API char* LIB61850_API char*
GooseSubscriber_getGoId(GooseSubscriber self); GooseSubscriber_getGoId(GooseSubscriber self);
/**
* \brief Get the GOOSE Control Block reference value of the received GOOSE message
*
* \param self GooseSubscriber instance to operate on.
*/
LIB61850_API char* LIB61850_API char*
GooseSubscriber_getGoCbRef(GooseSubscriber self); GooseSubscriber_getGoCbRef(GooseSubscriber self);
/**
* \brief Get the DatSet value of the received GOOSE message
*
* \param self GooseSubscriber instance to operate on.
*/
LIB61850_API char* LIB61850_API char*
GooseSubscriber_getDataSet(GooseSubscriber self); GooseSubscriber_getDataSet(GooseSubscriber self);
@ -133,6 +148,14 @@ GooseSubscriber_isValid(GooseSubscriber self);
LIB61850_API GooseParseError LIB61850_API GooseParseError
GooseSubscriber_getParseError(GooseSubscriber self); GooseSubscriber_getParseError(GooseSubscriber self);
/**
* \brief Destroy the GooseSubscriber instance
*
* Do not call this function when the GooseSubscriber instance was added to a GooseReceiver.
* The GooseReceiver will call the destructor when \ref GooseReceiver_destroy is called!
*
* \param self GooseSubscriber instance to operate on.
*/
LIB61850_API void LIB61850_API void
GooseSubscriber_destroy(GooseSubscriber self); GooseSubscriber_destroy(GooseSubscriber self);
@ -146,14 +169,32 @@ GooseSubscriber_destroy(GooseSubscriber self);
LIB61850_API void LIB61850_API void
GooseSubscriber_setListener(GooseSubscriber self, GooseListener listener, void* parameter); GooseSubscriber_setListener(GooseSubscriber self, GooseListener listener, void* parameter);
/**
* \brief Get the APPID value of the received GOOSE message
*
* \param self GooseSubscriber instance to operate on.
*/
LIB61850_API int32_t LIB61850_API int32_t
GooseSubscriber_getAppId(GooseSubscriber self); GooseSubscriber_getAppId(GooseSubscriber self);
/**
* \brief Get the source MAC address of the received GOOSE message
*
* \param self GooseSubscriber instance to operate on.
* \param buffer buffer to store the MAC address (at least 6 byte)
*/
LIB61850_API void LIB61850_API void
GooseSubscriber_getSrcMac(GooseSubscriber self, uint8_t *buffer); GooseSubscriber_getSrcMac(GooseSubscriber self, uint8_t* buffer);
/**
* \brief Get the destination MAC address of the received GOOSE message
*
* \param self GooseSubscriber instance to operate on.
* \param buffer buffer to store the MAC address (at least 6 byte)
*/
LIB61850_API void LIB61850_API void
GooseSubscriber_getDstMac(GooseSubscriber self, uint8_t *buffer); GooseSubscriber_getDstMac(GooseSubscriber self, uint8_t* buffer);
/** /**
* \brief return the state number (stNum) of the last received GOOSE message. * \brief return the state number (stNum) of the last received GOOSE message.
* *

Loading…
Cancel
Save