Merge branch 'v1.5_feature_274' into v1.5

pull/374/head
Michael Zillgith 4 years ago
commit 824c9ad5dd

@ -1,7 +1,7 @@
/*
* IEC61850ServerAPI.cs
*
* Copyright 2016 Michael Zillgith
* Copyright 2016-2022 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -331,12 +331,19 @@ namespace IEC61850
this.parent = parent;
}
internal Dictionary<IntPtr, ReportControlBlock> rcbs = new Dictionary<IntPtr, ReportControlBlock>();
public LogicalNode(string name, LogicalDevice parent)
{
this.parent = parent;
base.self = LogicalNode_create(name, parent.self);
}
internal void AddRcb(ReportControlBlock rcb)
{
rcbs.Add(rcb.self, rcb);
}
}
public enum AccessPolicy {
@ -1301,12 +1308,78 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ReportControlBlock_setPreconfiguredClient(IntPtr self, byte type, [Out] byte[] buf);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern string ReportControlBlock_getName(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ReportControlBlock_getRptEna(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ReportControlBlock_getRptID(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ReportControlBlock_getDataSet(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ReportControlBlock_getConfRev(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ReportControlBlock_getOptFlds(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ReportControlBlock_getBufTm(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 ReportControlBlock_getSqNum(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ReportControlBlock_getTrgOps(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ReportControlBlock_getIntgPd(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ReportControlBlock_getGI(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ReportControlBlock_getPurgeBuf(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ReportControlBlock_getEntryId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt64 ReportControlBlock_getTimeofEntry(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 ReportControlBlock_getResvTms(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ReportControlBlock_getOwner(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Memory_free(IntPtr self);
public IntPtr self = IntPtr.Zero;
private string name = null;
private LogicalNode parent = null;
public ReportControlBlock(string name, LogicalNode parent, string rptId, bool isBuffered,
string dataSetName, uint confRev, byte trgOps, byte options, uint bufTm, uint intgPd)
{
self = ReportControlBlock_create(name, parent.self, rptId, isBuffered, dataSetName, confRev, trgOps, options, bufTm, intgPd);
parent.AddRcb(this);
this.parent = parent;
}
internal ReportControlBlock(IntPtr self, LogicalNode parent)
{
this.parent = parent;
this.self = self;
parent.AddRcb(this);
}
public void SetPreconfiguredClient(byte[] clientAddress)
@ -1316,6 +1389,187 @@ namespace IEC61850
else if (clientAddress.Length == 6)
ReportControlBlock_setPreconfiguredClient(self, 6, clientAddress);
}
public string Name
{
get
{
if (name == null)
{
name = ReportControlBlock_getName(self);
}
return name;
}
}
public LogicalNode Parent
{
get
{
return parent;
}
}
public bool RptEna
{
get
{
return ReportControlBlock_getRptEna(self);
}
}
public string RptID
{
get
{
IntPtr rptIdPtr = ReportControlBlock_getRptID(self);
string rptId = Marshal.PtrToStringAnsi(rptIdPtr);
Memory_free(rptIdPtr);
return rptId;
}
}
public string DataSet
{
get
{
IntPtr dataSetPtr = ReportControlBlock_getDataSet(self);
string dataSet = Marshal.PtrToStringAnsi(dataSetPtr);
Memory_free(dataSetPtr);
return dataSet;
}
}
public UInt32 ConfRev
{
get
{
return ReportControlBlock_getConfRev(self);
}
}
public ReportOptions OptFlds
{
get
{
return (ReportOptions)ReportControlBlock_getOptFlds(self);
}
}
public UInt32 BufTm
{
get
{
return ReportControlBlock_getBufTm(self);
}
}
public UInt16 SqNum
{
get
{
return ReportControlBlock_getSqNum(self);
}
}
public TriggerOptions TrgOps
{
get
{
return (TriggerOptions)ReportControlBlock_getTrgOps(self);
}
}
public UInt32 IntgPd
{
get
{
return ReportControlBlock_getIntgPd(self);
}
}
public bool GI
{
get
{
return ReportControlBlock_getGI(self);
}
}
public bool PurgeBuf
{
get
{
return ReportControlBlock_getPurgeBuf(self);
}
}
public byte[] EntryID
{
get
{
IntPtr entryIdPtr = ReportControlBlock_getEntryId(self);
if (entryIdPtr != IntPtr.Zero)
{
byte[] entryId = null;
MmsValue octetStringVal = new MmsValue(entryIdPtr, true);
entryId = octetStringVal.getOctetString();
return entryId;
}
else
return null;
}
}
public UInt64 TimeofEntry
{
get
{
return ReportControlBlock_getTimeofEntry(self);
}
}
public UInt16 ResvTms
{
get
{
return ReportControlBlock_getResvTms(self);
}
}
public byte[] Owner
{
get
{
IntPtr mmsValuePtr = ReportControlBlock_getOwner(self);
if (mmsValuePtr != IntPtr.Zero)
{
byte[] owner = null;
MmsValue octetStringVal = new MmsValue(mmsValuePtr, true);
owner = octetStringVal.getOctetString();
return owner;
}
else
return null;
}
}
}
/// <summary>
@ -1691,6 +1945,47 @@ namespace IEC61850
public delegate void GoCBEventHandler(MmsGooseControlBlock goCB, int cbEvent, object parameter);
/// <summary>
/// Report control block event types
/// </summary>
public enum RCBEventType
{
/// <summary>
/// parameter read by client (not implemented).
/// </summary>
GET_PARAMETER = 0,
/// <summary>
/// parameter set by client.
/// </summary>
SET_PARAMETER = 1,
/// <summary>
/// reservation canceled.
/// </summary>
UNRESERVED = 2,
/// <summary>
/// reservation
/// </summary>
RESERVED = 3,
/// <summary>
/// RCB enabled
/// </summary>
ENABLED = 4,
/// <summary>
/// RCB disabled
/// </summary>
DISABLED = 5,
/// <summary>
/// GI report triggered
/// </summary>
GI = 6,
/// <summary>
/// Purge buffer procedure executed
/// </summary>
PURGEBUF = 7
}
public delegate void RCBEventHandler(object parameter, ReportControlBlock rcb, ClientConnection con, RCBEventType eventType, string parameterName, MmsDataAccessError serviceError);
public delegate MmsDataAccessError WriteAccessHandler (DataAttribute dataAttr, MmsValue value,
ClientConnection connection, object parameter);
@ -1917,6 +2212,12 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_setGoCBHandler(IntPtr self, InternalGoCBEventHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalRCBEventHandler(IntPtr paramter, IntPtr rcb, IntPtr connection, int eventType, string parameterName, int serviceError);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_setRCBEventHandler(IntPtr self, InternalRCBEventHandler handler, IntPtr parameter);
private IntPtr self = IntPtr.Zero;
private InternalControlHandler internalControlHandlerRef = null;
@ -2561,6 +2862,70 @@ namespace IEC61850
}
}
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ReportControlBlock_getParent(IntPtr self);
private RCBEventHandler rcbEventHandler = null;
private object rcbEventHandlerParameter = null;
private InternalRCBEventHandler internalRCBEventHandler = null;
private void InternalRCBEventHandlerImplementation(IntPtr parameter, IntPtr rcb, IntPtr connection, int eventType, string parameterName, int serviceError)
{
if (rcbEventHandler != null)
{
ClientConnection con = null;
if (connection != IntPtr.Zero)
{
this.clientConnections.TryGetValue(connection, out con);
}
ReportControlBlock reportControlBlock = null;
if (rcb != IntPtr.Zero)
{
IntPtr lnPtr = ReportControlBlock_getParent(rcb);
if (lnPtr != IntPtr.Zero)
{
ModelNode lnModelNode = iedModel.GetModelNodeFromNodeRef(lnPtr);
if (lnModelNode != null)
{
LogicalNode ln = lnModelNode as LogicalNode;
if (ln.rcbs.TryGetValue(rcb, out reportControlBlock) == false)
{
reportControlBlock = new ReportControlBlock(rcb, ln);
}
}
}
}
rcbEventHandler.Invoke(rcbEventHandlerParameter, reportControlBlock, con, (RCBEventType)eventType, parameterName, (MmsDataAccessError)serviceError);
}
}
/// <summary>
/// Set a callback handler for RCB events
/// </summary>
/// <param name="handler">the callback handler</param>
/// <param name="parameter">user provided parameter that is passed to the callback handler</param>
public void SetRCBEventHandler(RCBEventHandler handler, object parameter)
{
rcbEventHandler = handler;
rcbEventHandlerParameter = parameter;
if (internalRCBEventHandler == null)
{
internalRCBEventHandler = new InternalRCBEventHandler(InternalRCBEventHandlerImplementation);
IedServer_setRCBEventHandler(self, internalRCBEventHandler, IntPtr.Zero);
}
}
}
}

@ -67,6 +67,25 @@ namespace server1
}, null);
iedServer.SetRCBEventHandler(delegate (object parameter, ReportControlBlock rcb, ClientConnection con, RCBEventType eventType, string parameterName, MmsDataAccessError serviceError)
{
Console.WriteLine("RCB: " + rcb.Parent.GetObjectReference() + "." + rcb.Name + " event: " + eventType.ToString());
if (eventType == RCBEventType.ENABLED)
{
//Console.WriteLine(" RptID: " + rcb.RptID);
//Console.WriteLine(" DatSet: " + rcb.DataSet);
Console.WriteLine(" TrgOps: " + rcb.TrgOps.ToString());
}
if ((eventType == RCBEventType.SET_PARAMETER) || (eventType == RCBEventType.GET_PARAMETER))
{
Console.WriteLine(" param: " + parameterName);
Console.WriteLine(" result: " + serviceError.ToString());
}
}, null);
iedServer.Start(102);
if (iedServer.IsRunning())

@ -79,6 +79,27 @@ connectionHandler (IedServer self, ClientConnection connection, bool connected,
printf("Connection closed\n");
}
static void
rcbEventHandler(void* parameter, ReportControlBlock* rcb, ClientConnection connection, IedServer_RCBEventType event, const char* parameterName, MmsDataAccessError serviceError)
{
printf("RCB: %s event: %i\n", ReportControlBlock_getName(rcb), event);
if ((event == RCB_EVENT_SET_PARAMETER) || (event == RCB_EVENT_GET_PARAMETER)) {
printf(" param: %s\n", parameterName);
printf(" result: %i\n", serviceError);
}
if (event == RCB_EVENT_ENABLE) {
char* rptId = ReportControlBlock_getRptID(rcb);
printf(" rptID: %s\n", rptId);
char* dataSet = ReportControlBlock_getDataSet(rcb);
printf(" datSet: %s\n", dataSet);
free(rptId);
free(dataSet);
}
}
int
main(int argc, char** argv)
{
@ -136,6 +157,8 @@ main(int argc, char** argv)
IedServer_setConnectionIndicationHandler(iedServer, (IedConnectionIndicationHandler) connectionHandler, NULL);
IedServer_setRCBEventHandler(iedServer, rcbEventHandler, NULL);
/* By default access to variables with FC=DC and FC=CF is not allowed.
* This allow to write to simpleIOGenericIO/GGIO1.NamPlt.vendor variable used
* by iec61850_client_example1.

@ -1,7 +1,7 @@
/*
* iec61850_common.c
*
* Copyright 2013-2020 Michael Zillgith
* Copyright 2013-2022 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -70,6 +70,20 @@ Quality_fromMmsValue(const MmsValue* mmsValue)
return (Quality) MmsValue_getBitStringAsInteger(mmsValue);
}
MmsValue*
Quality_toMmsValue(Quality* self, MmsValue* mmsValue)
{
if (mmsValue == NULL) {
mmsValue = MmsValue_newBitString(13);
}
if (mmsValue) {
MmsValue_setBitStringFromInteger(mmsValue, *self);
}
return mmsValue;
}
Dbpos
Dbpos_fromMmsValue(const MmsValue* mmsValue)
{
@ -491,6 +505,25 @@ Timestamp_toMmsValue(Timestamp* self, MmsValue* mmsValue)
return convertedValue;
}
Timestamp*
Timestamp_fromMmsValue(Timestamp* self, MmsValue* mmsValue)
{
if (mmsValue->type == MMS_UTC_TIME) {
if (self == NULL)
self = Timestamp_create();
if (self) {
memcpy(self->val, mmsValue->value.utcTime, 8);
}
return self;
}
else {
return NULL;
}
}
char*
MmsMapping_getMmsDomainFromObjectReference(const char* objectReference, char* buffer)
{

@ -370,6 +370,9 @@ Quality_isFlagSet(Quality* self, int flag);
LIB61850_API Quality
Quality_fromMmsValue(const MmsValue* mmsValue);
LIB61850_API MmsValue*
Quality_toMmsValue(Quality* self, MmsValue* mmsValue);
/** @} */
/**
@ -515,6 +518,17 @@ Timestamp_setByMmsUtcTime(Timestamp* self, const MmsValue* mmsValue);
LIB61850_API MmsValue*
Timestamp_toMmsValue(Timestamp* self, MmsValue* mmsValue);
/**
* \brief Get the Timestamp value from an MmsValue instance of type MMS_UTC_TIME
*
* \param self the Timestamp instance or NULL to create a new instance
* \param mmsValue the mmsValue instance of type MMS_UTC_TIME
*
* \return the updated Timestamp value or NULL in case of an error
*/
LIB61850_API Timestamp*
Timestamp_fromMmsValue(Timestamp* self, MmsValue* mmsValue);
/**
* \brief Get the version of the library as string
*

@ -211,6 +211,83 @@ ReportControlBlock_create(const char* name, LogicalNode* parent, const char* rpt
LIB61850_API void
ReportControlBlock_setPreconfiguredClient(ReportControlBlock* self, uint8_t clientType, const uint8_t* clientAddress);
/**
* \brief Get the name of the RCB instance
*
* NOTE: the returned string is only valid during the lifetime of the ReportControlBlock instance!
*
* \param self the RCB instance
*
* \return the RCB instance name
*/
LIB61850_API const char*
ReportControlBlock_getName(ReportControlBlock* self);
/**
* \brief Is the RCB buffered or unbuffered?
*
* \param self the RCB instance
*
* \return true, in case of a buffered RCB, false otherwise
*/
LIB61850_API bool
ReportControlBlock_isBuffered(ReportControlBlock* self);
/**
* \brief Get the parent (LogicalNode) of the RCB instance
*
* \param self the RCB instance
*
* \return the parent (LogicalNode) of the RCB instance
*/
LIB61850_API LogicalNode*
ReportControlBlock_getParent(ReportControlBlock* self);
LIB61850_API char*
ReportControlBlock_getRptID(ReportControlBlock* self);
LIB61850_API int
ReportControlBlock_getRptEna(ReportControlBlock* self);
LIB61850_API char*
ReportControlBlock_getDataSet(ReportControlBlock* self);
LIB61850_API uint32_t
ReportControlBlock_getConfRev(ReportControlBlock* self);
LIB61850_API uint32_t
ReportControlBlock_getOptFlds(ReportControlBlock* self);
LIB61850_API uint32_t
ReportControlBlock_getBufTm(ReportControlBlock* self);
LIB61850_API uint16_t
ReportControlBlock_getSqNum(ReportControlBlock* self);
LIB61850_API uint32_t
ReportControlBlock_getTrgOps(ReportControlBlock* self);
LIB61850_API uint32_t
ReportControlBlock_getIntgPd(ReportControlBlock* self);
LIB61850_API bool
ReportControlBlock_getGI(ReportControlBlock* self);
LIB61850_API bool
ReportControlBlock_getPurgeBuf(ReportControlBlock* self);
LIB61850_API MmsValue*
ReportControlBlock_getEntryId(ReportControlBlock* self);
LIB61850_API uint64_t
ReportControlBlock_getTimeofEntry(ReportControlBlock* self);
LIB61850_API int16_t
ReportControlBlock_getResvTms(ReportControlBlock* self);
LIB61850_API MmsValue*
ReportControlBlock_getOwner(ReportControlBlock* self);
/**
* \brief create a new log control block (LCB)
*

@ -269,7 +269,9 @@ struct sReportControlBlock {
type can be one of (0 - no reservation, 4 - IPv4 client, 6 - IPv6 client) */
uint8_t clientReservation[17];
ReportControlBlock* sibling; /* next control block in list or NULL if this is the last entry */
ReportControlBlock* sibling; /* next control block in list or NULL if this is the last entry
* at runtime reuse as pointer to ReportControl instance!
**/
};
struct sLogControlBlock {

@ -3,7 +3,7 @@
*
* IEC 61850 server API for libiec61850.
*
* Copyright 2013-2020 Michael Zillgith
* Copyright 2013-2022 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -1534,6 +1534,47 @@ IedServer_updateCtlModel(IedServer self, DataObject* ctlObject, ControlModel val
/**@}*/
/**
* @defgroup IEC61850_SERVER_RCB Server side report control block (RCB) handling
*
* @{
*/
typedef enum {
RCB_EVENT_GET_PARAMETER, /* << parameter read by client (not implemented) */
RCB_EVENT_SET_PARAMETER, /* << parameter set by client */
RCB_EVENT_UNRESERVED, /* << RCB reservation canceled */
RCB_EVENT_RESERVED, /* << RCB reserved */
RCB_EVENT_ENABLE, /* << RCB enabled */
RCB_EVENT_DISABLE, /* << RCB disabled */
RCB_EVENT_GI, /* << GI report triggered */
RCB_EVENT_PURGEBUF /* << Purge buffer procedure executed */
} IedServer_RCBEventType;
/**
* \brief Callback that is called in case of RCB event
*
* \param parameter user provided parameter
* \param rcb affected report control block
* \param connection client connection that is involved
* \param event event type
* \param parameterName name of the parameter in case of RCB_EVENT_SET_PARAMETER
* \param serviceError service error in case of RCB_EVENT_SET_PARAMETER
*/
typedef void (*IedServer_RCBEventHandler) (void* parameter, ReportControlBlock* rcb, ClientConnection connection, IedServer_RCBEventType event, const char* parameterName, MmsDataAccessError serviceError);
/**
* \brief Set a handler for report control block (RCB) events
*
* \param self the instance of IedServer to operate on.
* \param handler the event handler to be used
* \param parameter a user provided parameter that is passed to the handler.
*/
LIB61850_API void
IedServer_setRCBEventHandler(IedServer self, IedServer_RCBEventHandler handler, void* parameter);
/**@}*/
/**
* @defgroup IEC61850_SERVER_SVCB Server side sampled values control block (SVCB) handling
*

@ -1,7 +1,7 @@
/*
* mms_mapping_internal.h
*
* Copyright 2013-2020 Michael Zillgith
* Copyright 2013-2022 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -328,6 +328,9 @@ struct sMmsMapping {
IedConnectionIndicationHandler connectionIndicationHandler;
void* connectionIndicationHandlerParameter;
IedServer_RCBEventHandler rcbEventHandler;
void* rcbEventHandlerParameter;
};
#endif /* MMS_MAPPING_INTERNAL_H_ */

@ -53,8 +53,12 @@ typedef struct {
LogicalNode* parentLN;
MmsValue* rcbValues;
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore rcbValuesLock;
#endif
MmsValue* inclusionField;
MmsValue* confRev;
DataSet* dataSet;
bool isDynamicDataSet;
@ -107,6 +111,7 @@ typedef struct {
MmsValue* timeOfEntry;
ReportControlBlock* rcb;
ReportControlBlock* sibling; /* backup sibling field of original ReportControlBlock */
IedServer server;
} ReportControl;
@ -136,7 +141,7 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
MmsServerConnection connection);
LIB61850_INTERNAL void
ReportControl_readAccess(ReportControl* rc, MmsMapping* mmsMapping, char* elementName);
ReportControl_readAccess(ReportControl* rc, MmsMapping* mmsMapping, MmsServerConnection connection, char* elementName);
LIB61850_INTERNAL void
Reporting_activateBufferedReports(MmsMapping* self);

@ -584,6 +584,13 @@ IedServer_createWithTlsSupport(IedModel* dataModel, TLSConfiguration tlsConfigur
return IedServer_createWithConfig(dataModel, tlsConfiguration, NULL);
}
void
IedServer_setRCBEventHandler(IedServer self, IedServer_RCBEventHandler handler, void* parameter)
{
self->mmsMapping->rcbEventHandler = handler;
self->mmsMapping->rcbEventHandlerParameter = parameter;
}
void
IedServer_destroy(IedServer self)
{

@ -2034,6 +2034,24 @@ MmsMapping_create(IedModel* model, IedServer iedServer)
MmsMapping_destroy(self);
self = NULL;
}
else {
LinkedList rcElem = LinkedList_getNext(self->reportControls);
while (rcElem) {
ReportControl* rc = (ReportControl*)LinkedList_getData(rcElem);
/* backup original sibling of ReportControlBlock */;
rc->sibling = rc->rcb->sibling;
/* reuse ReportControlBlock.sibling as reference to runtime information (ReportControl) */
rc->rcb->sibling = (ReportControlBlock*)rc;
/* set runtime mode flag (indicate that sibling field contains now runtime information reference!) */
rc->rcb->trgOps |= 64;
rcElem = LinkedList_getNext(rcElem);
}
}
return self;
}
@ -3075,15 +3093,28 @@ mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerCo
char* elementName = MmsMapping_getNextNameElement(reportName);
ReportControl_readAccess(rc, self, elementName);
ReportControl_readAccess(rc, self, connection, elementName);
MmsValue* value = NULL;
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(rc->rcbValuesLock);
#endif
if (elementName != NULL)
value = ReportControl_getRCBValue(rc, elementName);
else
value = rc->rcbValues;
if (value) {
value = MmsValue_clone(value);
MmsValue_setDeletableRecursive(value);
}
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(rc->rcbValuesLock);
#endif
retValue = value;
goto exit_function;

File diff suppressed because it is too large Load Diff

@ -383,6 +383,24 @@ ReportControlBlock_setPreconfiguredClient(ReportControlBlock* self, uint8_t clie
}
}
const char*
ReportControlBlock_getName(ReportControlBlock* self)
{
return self->name;
}
LogicalNode*
ReportControlBlock_getParent(ReportControlBlock* self)
{
return self->parent;
}
bool
ReportControlBlock_isBuffered(ReportControlBlock* self)
{
return self->buffered;
}
#if (CONFIG_IEC61850_SETTING_GROUPS == 1)
static void
LogicalNode_addSettingGroupControlBlock(LogicalNode* self, SettingGroupControlBlock* sgcb)

@ -1,7 +1,7 @@
/*
* mms_server_libinternal.h
*
* Copyright 2013-2020 Michael Zillgith
* Copyright 2013-2022 Michael Zillgith
*
* This file is part of libIEC61850.
*

@ -1,7 +1,7 @@
/*
* mms_read_service.c
*
* Copyright 2013-2018 Michael Zillgith
* Copyright 2013-2022 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -98,10 +98,9 @@ addComplexValueToResultList(MmsVariableSpecification* namedVariable,
LinkedList typedValues, MmsServerConnection connection,
MmsDomain* domain, char* nameIdStr)
{
MmsValue* value = addNamedVariableValue(namedVariable, connection, domain, nameIdStr);
if (value != NULL)
if (value)
LinkedList_add(typedValues, value);
}
@ -109,9 +108,8 @@ addComplexValueToResultList(MmsVariableSpecification* namedVariable,
static void
appendValueToResultList(MmsValue* value, LinkedList values)
{
if (value != NULL )
LinkedList_add(values, value);
if (value)
LinkedList_add(values, value);
}
static void
@ -126,15 +124,15 @@ deleteValueList(LinkedList values)
{
LinkedList value = LinkedList_getNext(values);
while (value != NULL ) {
MmsValue* typedValue = (MmsValue*) (value->data);
while (value) {
MmsValue* typedValue = (MmsValue*) (value->data);
MmsValue_deleteConditional(typedValue);
MmsValue_deleteConditional(typedValue);
value = LinkedList_getNext(value);
}
value = LinkedList_getNext(value);
}
LinkedList_destroyStatic(values);
LinkedList_destroyStatic(values);
}
static bool

Loading…
Cancel
Save