- added function LogicalNode_getDataSet
This commit is contained in:
parent
7eeac08551
commit
bbccffb65a
12 changed files with 112 additions and 34 deletions
|
@ -10,7 +10,7 @@
|
|||
#define STACK_CONFIG_H_
|
||||
|
||||
/* include asserts if set to 1 */
|
||||
#define DEBUG 1
|
||||
#define DEBUG 0
|
||||
|
||||
/* print debugging information with printf if set to 1 */
|
||||
#define DEBUG_SOCKET 0
|
||||
|
@ -21,7 +21,7 @@
|
|||
#define DEBUG_IED_CLIENT 0
|
||||
#define DEBUG_MMS_CLIENT 0
|
||||
#define DEBUG_MMS_SERVER 0
|
||||
#define DEBUG_GOOSE_SUBSCRIBER 1
|
||||
#define DEBUG_GOOSE_SUBSCRIBER 0
|
||||
#define DEBUG_GOOSE_PUBLISHER 0
|
||||
|
||||
/* Maximum MMS PDU SIZE - default is 65000 */
|
||||
|
@ -136,7 +136,7 @@
|
|||
#define CONFIG_IEC61850_SETTING_GROUPS 1
|
||||
|
||||
/* 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 */
|
||||
#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com"
|
||||
|
|
|
@ -376,6 +376,11 @@ GoosePublisher_publish(GoosePublisher self, LinkedList dataSet)
|
|||
if (DEBUG_GOOSE_PUBLISHER)
|
||||
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);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -612,6 +612,13 @@ exit_with_fault:
|
|||
static void
|
||||
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;
|
||||
bool subscriberFound = false;
|
||||
uint8_t* buffer = self->buffer;
|
||||
|
|
|
@ -416,6 +416,17 @@ LogicalNode_hasBufferedReports(LogicalNode* node);
|
|||
bool
|
||||
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
|
||||
DataObject_hasFCData(DataObject* dataObject, FunctionalConstraint fc);
|
||||
|
||||
|
|
|
@ -960,11 +960,12 @@ IedServer_observeDataAttribute(IedServer self, DataAttribute* dataAttribute,
|
|||
* \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 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.
|
||||
*/
|
||||
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.
|
||||
|
@ -979,10 +980,11 @@ typedef MmsDataAccessError
|
|||
* \param dataAttribute the data attribute to monitor
|
||||
* \param handler the callback function that is invoked if a client tries to write to
|
||||
* the monitored data attribute.
|
||||
* \param parameter a user provided parameter that is passed to the WriteAccessHandler when called.
|
||||
*/
|
||||
void
|
||||
IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute,
|
||||
WriteAccessHandler handler);
|
||||
WriteAccessHandler handler, void* parameter);
|
||||
|
||||
typedef enum {
|
||||
ACCESS_POLICY_ALLOW,
|
||||
|
|
|
@ -139,7 +139,7 @@ void
|
|||
MmsMapping_setConnectionIndicationHandler(MmsMapping* self, IedConnectionIndicationHandler handler, void* parameter);
|
||||
|
||||
void
|
||||
MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler);
|
||||
MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter);
|
||||
|
||||
MmsDataAccessError
|
||||
Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
|
||||
|
|
|
@ -476,7 +476,7 @@ singleThreadedServerThread(void* parameter)
|
|||
|
||||
while (running) {
|
||||
|
||||
if (IedServer_waitReady(self, 100) > 0) {
|
||||
if (IedServer_waitReady(self, 25) > 0) {
|
||||
MmsServer_handleIncomingMessages(self->mmsServer);
|
||||
IedServer_performPeriodicTasks(self);
|
||||
}
|
||||
|
@ -770,26 +770,26 @@ checkForChangedTriggers(IedServer self, DataAttribute* dataAttribute)
|
|||
#if (CONFIG_IEC61850_REPORT_SERVICE == 1) || (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
|
||||
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)
|
||||
MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue,
|
||||
REPORT_CONTROL_VALUE_CHANGED);
|
||||
#endif
|
||||
|
||||
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
|
||||
MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue);
|
||||
#endif
|
||||
}
|
||||
|
||||
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)
|
||||
MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue,
|
||||
REPORT_CONTROL_QUALITY_CHANGED);
|
||||
#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) */
|
||||
|
||||
|
@ -916,9 +916,16 @@ IedServer_updateBooleanAttributeValue(IedServer self, DataAttribute* dataAttribu
|
|||
bool currentValue = MmsValue_getBoolean(dataAttribute->mmsValue);
|
||||
|
||||
if (currentValue == value) {
|
||||
|
||||
checkForUpdateTrigger(self, dataAttribute);
|
||||
}
|
||||
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);
|
||||
|
||||
checkForChangedTriggers(self, dataAttribute);
|
||||
|
@ -993,15 +1000,15 @@ IedServer_updateQuality(IedServer self, DataAttribute* dataAttribute, Quality qu
|
|||
if (oldQuality != (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 (dataAttribute->triggerOptions & TRG_OPT_QUALITY_CHANGED)
|
||||
MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue,
|
||||
REPORT_CONTROL_QUALITY_CHANGED);
|
||||
#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
|
||||
IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute, WriteAccessHandler handler)
|
||||
IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter)
|
||||
{
|
||||
if (dataAttribute == NULL)
|
||||
*((int*) NULL) = 1;
|
||||
|
||||
MmsMapping_installWriteAccessHandler(self->mmsMapping, dataAttribute, handler);
|
||||
MmsMapping_installWriteAccessHandler(self->mmsMapping, dataAttribute, handler, parameter);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -169,7 +169,6 @@ MmsGooseControlBlock_enable(MmsGooseControlBlock self)
|
|||
|
||||
if (!MmsGooseControlBlock_isEnabled(self)) {
|
||||
|
||||
|
||||
if (self->dataSetRef != NULL) {
|
||||
GLOBAL_FREEMEM(self->dataSetRef);
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ typedef struct
|
|||
{
|
||||
DataAttribute* attribute;
|
||||
WriteAccessHandler handler;
|
||||
void* parameter;
|
||||
} AttributeAccessHandler;
|
||||
|
||||
|
||||
|
@ -1759,6 +1760,8 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
|
|||
sg->editSgConfirmedHandler(sg->editSgConfirmedHandlerParameter, sg->sgcb,
|
||||
sg->sgcb->editSG);
|
||||
|
||||
unselectSettingGroup(sg);
|
||||
|
||||
return DATA_ACCESS_ERROR_SUCCESS;
|
||||
}
|
||||
else
|
||||
|
@ -1826,7 +1829,8 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
|
|||
|
||||
if (matchingValue != NULL) {
|
||||
MmsDataAccessError handlerResult =
|
||||
accessHandler->handler(dataAttribute, matchingValue, (ClientConnection) connection);
|
||||
accessHandler->handler(dataAttribute, matchingValue, (ClientConnection) connection,
|
||||
accessHandler->parameter);
|
||||
|
||||
if (handlerResult == DATA_ACCESS_ERROR_SUCCESS)
|
||||
handlerFound = true;
|
||||
|
@ -1838,8 +1842,8 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
|
|||
else { /* if ACCESS_POLICY_DENY only allow direct access to handled data attribute */
|
||||
if (dataAttribute->mmsValue == cachedValue) {
|
||||
MmsDataAccessError handlerResult =
|
||||
accessHandler->handler(dataAttribute, value, (ClientConnection) connection);
|
||||
|
||||
accessHandler->handler(dataAttribute, value, (ClientConnection) connection,
|
||||
accessHandler->parameter);
|
||||
|
||||
if (handlerResult == DATA_ACCESS_ERROR_SUCCESS) {
|
||||
handlerFound = true;
|
||||
|
@ -1923,7 +1927,7 @@ getAccessHandlerForAttribute(MmsMapping* self, DataAttribute* dataAttribute)
|
|||
}
|
||||
|
||||
void
|
||||
MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler)
|
||||
MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter)
|
||||
{
|
||||
AttributeAccessHandler* accessHandler = getAccessHandlerForAttribute(self, dataAttribute);
|
||||
|
||||
|
@ -1931,6 +1935,7 @@ MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttrib
|
|||
accessHandler = (AttributeAccessHandler*) GLOBAL_MALLOC(sizeof(AttributeAccessHandler));
|
||||
|
||||
accessHandler->attribute = dataAttribute;
|
||||
accessHandler->parameter = parameter;
|
||||
LinkedList_add(self->attributeAccessHandlers, (void*) accessHandler);
|
||||
}
|
||||
|
||||
|
|
|
@ -345,6 +345,46 @@ LogicalNode_hasFCData(LogicalNode* node, FunctionalConstraint fc)
|
|||
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
|
||||
LogicalDevice_getLogicalNodeCount(LogicalDevice* logicalDevice)
|
||||
{
|
||||
|
|
|
@ -103,12 +103,19 @@ encodeStructuredAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool
|
|||
int
|
||||
mmsServer_encodeAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool encode)
|
||||
{
|
||||
if (value == NULL) // TODO report internal error
|
||||
return 0;
|
||||
// if (value == NULL) // TODO report internal error
|
||||
// return 0;
|
||||
|
||||
int size;
|
||||
|
||||
switch (value->type) {
|
||||
case MMS_BOOLEAN:
|
||||
if (encode)
|
||||
bufPos = BerEncoder_encodeBoolean(0x83, value->value.boolean, buffer, bufPos);
|
||||
else
|
||||
size = 3;
|
||||
break;
|
||||
|
||||
case MMS_STRUCTURE:
|
||||
if (encode)
|
||||
bufPos = encodeStructuredAccessResult(value, buffer, bufPos, true);
|
||||
|
@ -166,12 +173,7 @@ mmsServer_encodeAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool
|
|||
else
|
||||
size = BerEncoder_determineEncodedBitStringSize(value->value.bitString.size);
|
||||
break;
|
||||
case MMS_BOOLEAN:
|
||||
if (encode)
|
||||
bufPos = BerEncoder_encodeBoolean(0x83, value->value.boolean, buffer, bufPos);
|
||||
else
|
||||
size = 3;
|
||||
break;
|
||||
|
||||
case MMS_BINARY_TIME:
|
||||
if (encode)
|
||||
bufPos = BerEncoder_encodeOctetString(0x8c, value->value.binaryTime.buf,
|
||||
|
|
Binary file not shown.
Loading…
Add table
Reference in a new issue