- added function LogicalNode_getDataSet

This commit is contained in:
Michael Zillgith 2015-07-20 10:37:40 +02:00
parent 7eeac08551
commit bbccffb65a
12 changed files with 112 additions and 34 deletions

View file

@ -10,7 +10,7 @@
#define STACK_CONFIG_H_ #define STACK_CONFIG_H_
/* include asserts if set to 1 */ /* include asserts if set to 1 */
#define DEBUG 1 #define DEBUG 0
/* print debugging information with printf if set to 1 */ /* print debugging information with printf if set to 1 */
#define DEBUG_SOCKET 0 #define DEBUG_SOCKET 0
@ -21,7 +21,7 @@
#define DEBUG_IED_CLIENT 0 #define DEBUG_IED_CLIENT 0
#define DEBUG_MMS_CLIENT 0 #define DEBUG_MMS_CLIENT 0
#define DEBUG_MMS_SERVER 0 #define DEBUG_MMS_SERVER 0
#define DEBUG_GOOSE_SUBSCRIBER 1 #define DEBUG_GOOSE_SUBSCRIBER 0
#define DEBUG_GOOSE_PUBLISHER 0 #define DEBUG_GOOSE_PUBLISHER 0
/* Maximum MMS PDU SIZE - default is 65000 */ /* Maximum MMS PDU SIZE - default is 65000 */
@ -136,7 +136,7 @@
#define CONFIG_IEC61850_SETTING_GROUPS 1 #define CONFIG_IEC61850_SETTING_GROUPS 1
/* default reservation time of a setting group control block in s */ /* default reservation time of a setting group control block in s */
#define CONFIG_IEC61850_SG_RESVTMS 10 #define CONFIG_IEC61850_SG_RESVTMS 300
/* default results for MMS identify service */ /* default results for MMS identify service */
#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" #define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com"

View file

@ -376,6 +376,11 @@ GoosePublisher_publish(GoosePublisher self, LinkedList dataSet)
if (DEBUG_GOOSE_PUBLISHER) if (DEBUG_GOOSE_PUBLISHER)
printf("GOOSE_PUBLISHER: send GOOSE message\n"); printf("GOOSE_PUBLISHER: send GOOSE message\n");
struct timeval tv;
gettimeofday(&tv,NULL/*&tz*/);
printf("GOOSE SEND: %ld %ld\n",tv.tv_sec, tv.tv_usec);
Ethernet_sendPacket(self->ethernetSocket, self->buffer, self->payloadStart + payloadLength); Ethernet_sendPacket(self->ethernetSocket, self->buffer, self->payloadStart + payloadLength);
return 0; return 0;

View file

@ -612,6 +612,13 @@ exit_with_fault:
static void static void
parseGooseMessage(GooseReceiver self, int numbytes) parseGooseMessage(GooseReceiver self, int numbytes)
{ {
struct timeval tv;
gettimeofday(&tv,NULL/*&tz*/);
printf("RCVD GOOSE: %ld %ld\n",tv.tv_sec, tv.tv_usec);
int bufPos; int bufPos;
bool subscriberFound = false; bool subscriberFound = false;
uint8_t* buffer = self->buffer; uint8_t* buffer = self->buffer;

View file

@ -416,6 +416,17 @@ LogicalNode_hasBufferedReports(LogicalNode* node);
bool bool
LogicalNode_hasUnbufferedReports(LogicalNode* node); LogicalNode_hasUnbufferedReports(LogicalNode* node);
/**
* \brief get a data set instance
*
* \param self the logical node instance of the data set
* \param dataSetName the name of the data set
*
* \return the data set instance or NULL if the data set does not exist
*/
DataSet*
LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName);
bool bool
DataObject_hasFCData(DataObject* dataObject, FunctionalConstraint fc); DataObject_hasFCData(DataObject* dataObject, FunctionalConstraint fc);

View file

@ -960,11 +960,12 @@ IedServer_observeDataAttribute(IedServer self, DataAttribute* dataAttribute,
* \param the data attribute that has been written by an MMS client. * \param the data attribute that has been written by an MMS client.
* \param the value the client want to write to the data attribute * \param the value the client want to write to the data attribute
* \param connection the connection object of the client connection that invoked the write operation * \param connection the connection object of the client connection that invoked the write operation
* \param parameter the user provided parameter
* *
* \return true if access is accepted, false if access is denied. * \return true if access is accepted, false if access is denied.
*/ */
typedef MmsDataAccessError typedef MmsDataAccessError
(*WriteAccessHandler) (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection); (*WriteAccessHandler) (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection, void* parameter);
/** /**
* \brief Install a WriteAccessHandler for a data attribute. * \brief Install a WriteAccessHandler for a data attribute.
@ -979,10 +980,11 @@ typedef MmsDataAccessError
* \param dataAttribute the data attribute to monitor * \param dataAttribute the data attribute to monitor
* \param handler the callback function that is invoked if a client tries to write to * \param handler the callback function that is invoked if a client tries to write to
* the monitored data attribute. * the monitored data attribute.
* \param parameter a user provided parameter that is passed to the WriteAccessHandler when called.
*/ */
void void
IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute, IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute,
WriteAccessHandler handler); WriteAccessHandler handler, void* parameter);
typedef enum { typedef enum {
ACCESS_POLICY_ALLOW, ACCESS_POLICY_ALLOW,

View file

@ -139,7 +139,7 @@ void
MmsMapping_setConnectionIndicationHandler(MmsMapping* self, IedConnectionIndicationHandler handler, void* parameter); MmsMapping_setConnectionIndicationHandler(MmsMapping* self, IedConnectionIndicationHandler handler, void* parameter);
void void
MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler); MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter);
MmsDataAccessError MmsDataAccessError
Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* variableIdOrig, Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,

View file

@ -476,7 +476,7 @@ singleThreadedServerThread(void* parameter)
while (running) { while (running) {
if (IedServer_waitReady(self, 100) > 0) { if (IedServer_waitReady(self, 25) > 0) {
MmsServer_handleIncomingMessages(self->mmsServer); MmsServer_handleIncomingMessages(self->mmsServer);
IedServer_performPeriodicTasks(self); IedServer_performPeriodicTasks(self);
} }
@ -770,26 +770,26 @@ checkForChangedTriggers(IedServer self, DataAttribute* dataAttribute)
#if (CONFIG_IEC61850_REPORT_SERVICE == 1) || (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) #if (CONFIG_IEC61850_REPORT_SERVICE == 1) || (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
if (dataAttribute->triggerOptions & TRG_OPT_DATA_CHANGED) { if (dataAttribute->triggerOptions & TRG_OPT_DATA_CHANGED) {
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue);
#endif
#if (CONFIG_IEC61850_REPORT_SERVICE == 1) #if (CONFIG_IEC61850_REPORT_SERVICE == 1)
MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue, MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue,
REPORT_CONTROL_VALUE_CHANGED); REPORT_CONTROL_VALUE_CHANGED);
#endif #endif
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue);
#endif
} }
else if (dataAttribute->triggerOptions & TRG_OPT_QUALITY_CHANGED) { else if (dataAttribute->triggerOptions & TRG_OPT_QUALITY_CHANGED) {
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue);
#endif
#if (CONFIG_IEC61850_REPORT_SERVICE == 1) #if (CONFIG_IEC61850_REPORT_SERVICE == 1)
MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue, MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue,
REPORT_CONTROL_QUALITY_CHANGED); REPORT_CONTROL_QUALITY_CHANGED);
#endif #endif
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue);
#endif
} }
#endif /* (CONFIG_IEC61850_REPORT_SERVICE== 1) || (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */ #endif /* (CONFIG_IEC61850_REPORT_SERVICE== 1) || (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
@ -916,9 +916,16 @@ IedServer_updateBooleanAttributeValue(IedServer self, DataAttribute* dataAttribu
bool currentValue = MmsValue_getBoolean(dataAttribute->mmsValue); bool currentValue = MmsValue_getBoolean(dataAttribute->mmsValue);
if (currentValue == value) { if (currentValue == value) {
checkForUpdateTrigger(self, dataAttribute); checkForUpdateTrigger(self, dataAttribute);
} }
else { else {
// struct timeval tv;
//
// gettimeofday(&tv,NULL/*&tz*/);
// printf("UPDATE BOOL: %ld %ld\n",tv.tv_sec, tv.tv_usec);
MmsValue_setBoolean(dataAttribute->mmsValue, value); MmsValue_setBoolean(dataAttribute->mmsValue, value);
checkForChangedTriggers(self, dataAttribute); checkForChangedTriggers(self, dataAttribute);
@ -993,15 +1000,15 @@ IedServer_updateQuality(IedServer self, DataAttribute* dataAttribute, Quality qu
if (oldQuality != (uint32_t) quality) { if (oldQuality != (uint32_t) quality) {
MmsValue_setBitStringFromInteger(dataAttribute->mmsValue, (uint32_t) quality); MmsValue_setBitStringFromInteger(dataAttribute->mmsValue, (uint32_t) quality);
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue);
#endif
#if (CONFIG_IEC61850_REPORT_SERVICE == 1) #if (CONFIG_IEC61850_REPORT_SERVICE == 1)
if (dataAttribute->triggerOptions & TRG_OPT_QUALITY_CHANGED) if (dataAttribute->triggerOptions & TRG_OPT_QUALITY_CHANGED)
MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue, MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue,
REPORT_CONTROL_QUALITY_CHANGED); REPORT_CONTROL_QUALITY_CHANGED);
#endif #endif
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue);
#endif
} }
@ -1079,12 +1086,12 @@ IedServer_setWriteAccessPolicy(IedServer self, FunctionalConstraint fc, AccessPo
} }
void void
IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute, WriteAccessHandler handler) IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter)
{ {
if (dataAttribute == NULL) if (dataAttribute == NULL)
*((int*) NULL) = 1; *((int*) NULL) = 1;
MmsMapping_installWriteAccessHandler(self->mmsMapping, dataAttribute, handler); MmsMapping_installWriteAccessHandler(self->mmsMapping, dataAttribute, handler, parameter);
} }
void void

View file

@ -169,7 +169,6 @@ MmsGooseControlBlock_enable(MmsGooseControlBlock self)
if (!MmsGooseControlBlock_isEnabled(self)) { if (!MmsGooseControlBlock_isEnabled(self)) {
if (self->dataSetRef != NULL) { if (self->dataSetRef != NULL) {
GLOBAL_FREEMEM(self->dataSetRef); GLOBAL_FREEMEM(self->dataSetRef);

View file

@ -50,6 +50,7 @@ typedef struct
{ {
DataAttribute* attribute; DataAttribute* attribute;
WriteAccessHandler handler; WriteAccessHandler handler;
void* parameter;
} AttributeAccessHandler; } AttributeAccessHandler;
@ -1759,6 +1760,8 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
sg->editSgConfirmedHandler(sg->editSgConfirmedHandlerParameter, sg->sgcb, sg->editSgConfirmedHandler(sg->editSgConfirmedHandlerParameter, sg->sgcb,
sg->sgcb->editSG); sg->sgcb->editSG);
unselectSettingGroup(sg);
return DATA_ACCESS_ERROR_SUCCESS; return DATA_ACCESS_ERROR_SUCCESS;
} }
else else
@ -1826,7 +1829,8 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
if (matchingValue != NULL) { if (matchingValue != NULL) {
MmsDataAccessError handlerResult = MmsDataAccessError handlerResult =
accessHandler->handler(dataAttribute, matchingValue, (ClientConnection) connection); accessHandler->handler(dataAttribute, matchingValue, (ClientConnection) connection,
accessHandler->parameter);
if (handlerResult == DATA_ACCESS_ERROR_SUCCESS) if (handlerResult == DATA_ACCESS_ERROR_SUCCESS)
handlerFound = true; handlerFound = true;
@ -1838,8 +1842,8 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
else { /* if ACCESS_POLICY_DENY only allow direct access to handled data attribute */ else { /* if ACCESS_POLICY_DENY only allow direct access to handled data attribute */
if (dataAttribute->mmsValue == cachedValue) { if (dataAttribute->mmsValue == cachedValue) {
MmsDataAccessError handlerResult = MmsDataAccessError handlerResult =
accessHandler->handler(dataAttribute, value, (ClientConnection) connection); accessHandler->handler(dataAttribute, value, (ClientConnection) connection,
accessHandler->parameter);
if (handlerResult == DATA_ACCESS_ERROR_SUCCESS) { if (handlerResult == DATA_ACCESS_ERROR_SUCCESS) {
handlerFound = true; handlerFound = true;
@ -1923,7 +1927,7 @@ getAccessHandlerForAttribute(MmsMapping* self, DataAttribute* dataAttribute)
} }
void void
MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler) MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter)
{ {
AttributeAccessHandler* accessHandler = getAccessHandlerForAttribute(self, dataAttribute); AttributeAccessHandler* accessHandler = getAccessHandlerForAttribute(self, dataAttribute);
@ -1931,6 +1935,7 @@ MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttrib
accessHandler = (AttributeAccessHandler*) GLOBAL_MALLOC(sizeof(AttributeAccessHandler)); accessHandler = (AttributeAccessHandler*) GLOBAL_MALLOC(sizeof(AttributeAccessHandler));
accessHandler->attribute = dataAttribute; accessHandler->attribute = dataAttribute;
accessHandler->parameter = parameter;
LinkedList_add(self->attributeAccessHandlers, (void*) accessHandler); LinkedList_add(self->attributeAccessHandlers, (void*) accessHandler);
} }

View file

@ -345,6 +345,46 @@ LogicalNode_hasFCData(LogicalNode* node, FunctionalConstraint fc)
return false; return false;
} }
DataSet*
LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName)
{
assert(self->modelType == LogicalNodeModelType);
assert(dataSetName != NULL);
char dsName[66];
LogicalDevice* ld = (LogicalDevice*) self->parent;
if (strlen(dataSetName) > 32) {
if (DEBUG_IED_SERVER) {
printf("IED_SERVER: LogicalNode_getDataSet - data set name %s too long!\n", dataSetName);
}
goto exit_error;
}
StringUtils_createStringInBuffer(dsName, 3, self->name, "$", dataSetName);
IedModel* iedModel = (IedModel*) ld->parent;
DataSet* ds = iedModel->dataSets;
while (ds != NULL) {
if (strcmp(ds->logicalDeviceName, ld->name) == 0) {
if (strcmp(ds->name, dsName) == 0) {
return ds;
}
}
ds = ds->sibling;
}
exit_error:
return NULL;
}
int int
LogicalDevice_getLogicalNodeCount(LogicalDevice* logicalDevice) LogicalDevice_getLogicalNodeCount(LogicalDevice* logicalDevice)
{ {

View file

@ -103,12 +103,19 @@ encodeStructuredAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool
int int
mmsServer_encodeAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool encode) mmsServer_encodeAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool encode)
{ {
if (value == NULL) // TODO report internal error // if (value == NULL) // TODO report internal error
return 0; // return 0;
int size; int size;
switch (value->type) { switch (value->type) {
case MMS_BOOLEAN:
if (encode)
bufPos = BerEncoder_encodeBoolean(0x83, value->value.boolean, buffer, bufPos);
else
size = 3;
break;
case MMS_STRUCTURE: case MMS_STRUCTURE:
if (encode) if (encode)
bufPos = encodeStructuredAccessResult(value, buffer, bufPos, true); bufPos = encodeStructuredAccessResult(value, buffer, bufPos, true);
@ -166,12 +173,7 @@ mmsServer_encodeAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool
else else
size = BerEncoder_determineEncodedBitStringSize(value->value.bitString.size); size = BerEncoder_determineEncodedBitStringSize(value->value.bitString.size);
break; break;
case MMS_BOOLEAN:
if (encode)
bufPos = BerEncoder_encodeBoolean(0x83, value->value.boolean, buffer, bufPos);
else
size = 3;
break;
case MMS_BINARY_TIME: case MMS_BINARY_TIME:
if (encode) if (encode)
bufPos = BerEncoder_encodeOctetString(0x8c, value->value.binaryTime.buf, bufPos = BerEncoder_encodeOctetString(0x8c, value->value.binaryTime.buf,

Binary file not shown.