diff --git a/CHANGELOG b/CHANGELOG index 9b7a70c8..250f33e6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ Changes to version 0.8.7 ------------------------ +- extended beoglebone demo (write access to GAPC settings, ...) +- File service: support for wildcard character ('*') in requests - server: changed signature of WriteAccessHandler: Handler now return MmsDataAccessError instead of boolean value! - server: added function IedModel_setIedNameForDynamicModel diff --git a/config/stack_config.h b/config/stack_config.h index 91322e99..e3b0b2d0 100644 --- a/config/stack_config.h +++ b/config/stack_config.h @@ -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 @@ -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" diff --git a/demos/beaglebone/beagle_demo.c b/demos/beaglebone/beagle_demo.c index 31cc3c6a..82c1ac05 100644 --- a/demos/beaglebone/beagle_demo.c +++ b/demos/beaglebone/beagle_demo.c @@ -77,27 +77,27 @@ static void updateLED1stVal(bool newLedState, uint64_t timeStamp) { switchLED(LED1, newLedState); + IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1_t, timeStamp); IedServer_updateBooleanAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1_stVal, newLedState); IedServer_updateQuality(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1_q, QUALITY_VALIDITY_GOOD | QUALITY_SOURCE_SUBSTITUTED); - IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1_t, timeStamp); } static void updateLED2stVal(bool newLedState, uint64_t timeStamp) { switchLED(LED2, newLedState); + IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2_t, timeStamp); IedServer_updateBooleanAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2_stVal, newLedState); IedServer_updateQuality(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2_q, QUALITY_VALIDITY_QUESTIONABLE | QUALITY_DETAIL_OSCILLATORY); - IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2_t, timeStamp); } static void updateLED3stVal(bool newLedState, uint64_t timeStamp) { switchLED(LED3, newLedState); + IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3_t, timeStamp); IedServer_updateBooleanAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3_stVal, newLedState); IedServer_updateQuality(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3_q, QUALITY_VALIDITY_GOOD); - IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3_t, timeStamp); } static ControlHandlerResult @@ -146,6 +146,62 @@ controlHandlerForBinaryOutput(void* parameter, MmsValue* value, bool test) return CONTROL_RESULT_OK; } +static int ledOnTimeMs = 1000; +static int ledOffTimeMs = 1000; +static int32_t opCnt = 0; + +static ControlHandlerResult +controlHandlerForInt32Controls(void* parameter, MmsValue* value, bool test) +{ + if (test) + return CONTROL_RESULT_OK; + + if (parameter == IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs) { + int32_t newValue = MmsValue_toInt32(value); + + opCnt = newValue; + + uint64_t currentTime = Hal_getTimeInMs(); + + IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_t, currentTime); + IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_stVal, opCnt); + } + + return CONTROL_RESULT_OK; +} + + + +static MmsDataAccessError +int32WriteAccessHandler (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection, void* parameter) +{ + int newValue = MmsValue_toInt32(value); + + /* Check if value is inside of valid range */ + if (newValue < 0) + return DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID; + + if (dataAttribute == IEDMODEL_GenericIO_TIM_GAPC1_OpDlTmms_setVal) { + + printf("New value for TIM_GAPC1.OpDlTmms.setVal = %i\n", newValue); + + ledOffTimeMs = newValue; + + return DATA_ACCESS_ERROR_SUCCESS; + } + + if (dataAttribute == IEDMODEL_GenericIO_TIM_GAPC1_RsDlTmms_setVal) { + + printf("New value for TIM_GAPC1.RsDlTmms.setVal = %i\n", newValue); + + ledOnTimeMs = newValue; + + return DATA_ACCESS_ERROR_SUCCESS; + } + + return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; +} + int main(int argc, char** argv) { @@ -153,7 +209,7 @@ int main(int argc, char** argv) { iedServer = IedServer_create(&iedModel); - /* Set callback handlers */ + /* Set control callback handlers */ IedServer_setConnectionIndicationHandler(iedServer, (IedConnectionIndicationHandler) connectionIndicationHandler, NULL); IedServer_setPerformCheckHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1, @@ -181,11 +237,22 @@ int main(int argc, char** argv) { IEDMODEL_GenericIO_GGIO1_DPCSO1); - /* Initialize process values */ + IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs, (ControlHandler) controlHandlerForInt32Controls, + IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs); + /* Initialize process values */ MmsValue* DPCSO1_stVal = IedServer_getAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_DPCSO1_stVal); MmsValue_setBitStringFromInteger(DPCSO1_stVal, 1); /* set DPC to OFF */ + /* Intitalize setting values */ + IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_GenericIO_TIM_GAPC1_OpDlTmms_setVal, ledOffTimeMs); + IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_GenericIO_TIM_GAPC1_RsDlTmms_setVal, ledOnTimeMs); + + /* Set callback handler for settings */ + IedServer_handleWriteAccess(iedServer, IEDMODEL_GenericIO_TIM_GAPC1_OpDlTmms_setVal, int32WriteAccessHandler, NULL); + IedServer_handleWriteAccess(iedServer, IEDMODEL_GenericIO_TIM_GAPC1_RsDlTmms_setVal, int32WriteAccessHandler, NULL); + + /* MMS server will be instructed to start listening to client connections. */ IedServer_start(iedServer, 102); @@ -210,10 +277,21 @@ int main(int argc, char** argv) { if (automaticOperationMode) { if (nextLedToggleTime <= currentTime) { - nextLedToggleTime = currentTime + 1000; + + + if (ledStateValue) + nextLedToggleTime = currentTime + ledOffTimeMs; + else + nextLedToggleTime = currentTime + ledOnTimeMs; ledStateValue = !ledStateValue; + if (ledStateValue) { + opCnt++; + IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_t, currentTime); + IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_stVal, opCnt); + } + updateLED1stVal(ledStateValue, currentTime); updateLED2stVal(ledStateValue, currentTime); updateLED3stVal(ledStateValue, currentTime); diff --git a/demos/beaglebone/beagle_demo.icd b/demos/beaglebone/beagle_demo.icd index 6169c814..259c21f5 100644 --- a/demos/beaglebone/beagle_demo.icd +++ b/demos/beaglebone/beagle_demo.icd @@ -72,6 +72,7 @@ + @@ -99,6 +100,9 @@ + + + @@ -106,20 +110,22 @@ - - - + + + + - + + - - - + + + @@ -134,17 +140,65 @@ - + + + + + + + + + + + + + + + + + + EXT:2015 + + + + + + + + + + - + + + direct-with-normal-security + - - - - + + + + + + + + + + + + + + + + + + + + status-only + + @@ -152,24 +206,29 @@ + + + + + @@ -177,11 +236,13 @@ + + @@ -189,6 +250,7 @@ + @@ -198,6 +260,7 @@ + @@ -205,13 +268,33 @@ + + + + + + + + + + + + + + + + + + + + @@ -228,6 +311,21 @@ + + + on + blocked + test + test/blocked + off + + + + unknown + forward + backward + both + status-only @@ -236,6 +334,7 @@ direct-with-enhanced-security sbo-with-enhanced-security + not-supported bay-control diff --git a/demos/beaglebone/beaglebone_leds.h b/demos/beaglebone/beaglebone_leds.h index 2bcfa0d9..61a396c7 100644 --- a/demos/beaglebone/beaglebone_leds.h +++ b/demos/beaglebone/beaglebone_leds.h @@ -9,6 +9,9 @@ /* set to 1 if you want to run the demo on a PC */ //#define SIMULATED 1 + + +/* select correct file paths to access LEDs - depends on beaglebones linux distro/version */ #if 0 #define LED1 "/sys/class/leds/beaglebone::usr0" #define LED2 "/sys/class/leds/beaglebone::usr1" diff --git a/demos/beaglebone/static_model.c b/demos/beaglebone/static_model.c index 9d2b861b..993db3ec 100644 --- a/demos/beaglebone/static_model.c +++ b/demos/beaglebone/static_model.c @@ -76,36 +76,36 @@ LogicalNode iedModel_GenericIO_LLN0 = { "LLN0", (ModelNode*) &iedModel_GenericIO, (ModelNode*) &iedModel_GenericIO_LPHD1, - (ModelNode*) &iedModel_GenericIO_LLN0_Mod, + (ModelNode*) &iedModel_GenericIO_LLN0_Beh, }; -DataObject iedModel_GenericIO_LLN0_Mod = { +DataObject iedModel_GenericIO_LLN0_Beh = { DataObjectModelType, - "Mod", + "Beh", (ModelNode*) &iedModel_GenericIO_LLN0, - (ModelNode*) &iedModel_GenericIO_LLN0_Beh, - (ModelNode*) &iedModel_GenericIO_LLN0_Mod_stVal, + (ModelNode*) &iedModel_GenericIO_LLN0_Mod, + (ModelNode*) &iedModel_GenericIO_LLN0_Beh_stVal, 0 }; -DataAttribute iedModel_GenericIO_LLN0_Mod_stVal = { +DataAttribute iedModel_GenericIO_LLN0_Beh_stVal = { DataAttributeModelType, "stVal", - (ModelNode*) &iedModel_GenericIO_LLN0_Mod, - (ModelNode*) &iedModel_GenericIO_LLN0_Mod_q, + (ModelNode*) &iedModel_GenericIO_LLN0_Beh, + (ModelNode*) &iedModel_GenericIO_LLN0_Beh_q, NULL, 0, IEC61850_FC_ST, - INT32, + ENUMERATED, 0 + TRG_OPT_DATA_CHANGED, NULL, 0}; -DataAttribute iedModel_GenericIO_LLN0_Mod_q = { +DataAttribute iedModel_GenericIO_LLN0_Beh_q = { DataAttributeModelType, "q", - (ModelNode*) &iedModel_GenericIO_LLN0_Mod, - (ModelNode*) &iedModel_GenericIO_LLN0_Mod_t, + (ModelNode*) &iedModel_GenericIO_LLN0_Beh, + (ModelNode*) &iedModel_GenericIO_LLN0_Beh_t, NULL, 0, IEC61850_FC_ST, @@ -114,11 +114,11 @@ DataAttribute iedModel_GenericIO_LLN0_Mod_q = { NULL, 0}; -DataAttribute iedModel_GenericIO_LLN0_Mod_t = { +DataAttribute iedModel_GenericIO_LLN0_Beh_t = { DataAttributeModelType, "t", - (ModelNode*) &iedModel_GenericIO_LLN0_Mod, - (ModelNode*) &iedModel_GenericIO_LLN0_Mod_ctlModel, + (ModelNode*) &iedModel_GenericIO_LLN0_Beh, + NULL, NULL, 0, IEC61850_FC_ST, @@ -127,46 +127,33 @@ DataAttribute iedModel_GenericIO_LLN0_Mod_t = { NULL, 0}; -DataAttribute iedModel_GenericIO_LLN0_Mod_ctlModel = { - DataAttributeModelType, - "ctlModel", - (ModelNode*) &iedModel_GenericIO_LLN0_Mod, - NULL, - NULL, - 0, - IEC61850_FC_CF, - ENUMERATED, - 0, - NULL, - 0}; - -DataObject iedModel_GenericIO_LLN0_Beh = { +DataObject iedModel_GenericIO_LLN0_Mod = { DataObjectModelType, - "Beh", + "Mod", (ModelNode*) &iedModel_GenericIO_LLN0, (ModelNode*) &iedModel_GenericIO_LLN0_Health, - (ModelNode*) &iedModel_GenericIO_LLN0_Beh_stVal, + (ModelNode*) &iedModel_GenericIO_LLN0_Mod_stVal, 0 }; -DataAttribute iedModel_GenericIO_LLN0_Beh_stVal = { +DataAttribute iedModel_GenericIO_LLN0_Mod_stVal = { DataAttributeModelType, "stVal", - (ModelNode*) &iedModel_GenericIO_LLN0_Beh, - (ModelNode*) &iedModel_GenericIO_LLN0_Beh_q, + (ModelNode*) &iedModel_GenericIO_LLN0_Mod, + (ModelNode*) &iedModel_GenericIO_LLN0_Mod_q, NULL, 0, IEC61850_FC_ST, - INT32, + ENUMERATED, 0 + TRG_OPT_DATA_CHANGED, NULL, 0}; -DataAttribute iedModel_GenericIO_LLN0_Beh_q = { +DataAttribute iedModel_GenericIO_LLN0_Mod_q = { DataAttributeModelType, "q", - (ModelNode*) &iedModel_GenericIO_LLN0_Beh, - (ModelNode*) &iedModel_GenericIO_LLN0_Beh_t, + (ModelNode*) &iedModel_GenericIO_LLN0_Mod, + (ModelNode*) &iedModel_GenericIO_LLN0_Mod_t, NULL, 0, IEC61850_FC_ST, @@ -175,11 +162,11 @@ DataAttribute iedModel_GenericIO_LLN0_Beh_q = { NULL, 0}; -DataAttribute iedModel_GenericIO_LLN0_Beh_t = { +DataAttribute iedModel_GenericIO_LLN0_Mod_t = { DataAttributeModelType, "t", - (ModelNode*) &iedModel_GenericIO_LLN0_Beh, - NULL, + (ModelNode*) &iedModel_GenericIO_LLN0_Mod, + (ModelNode*) &iedModel_GenericIO_LLN0_Mod_ctlModel, NULL, 0, IEC61850_FC_ST, @@ -188,6 +175,19 @@ DataAttribute iedModel_GenericIO_LLN0_Beh_t = { NULL, 0}; +DataAttribute iedModel_GenericIO_LLN0_Mod_ctlModel = { + DataAttributeModelType, + "ctlModel", + (ModelNode*) &iedModel_GenericIO_LLN0_Mod, + NULL, + NULL, + 0, + IEC61850_FC_CF, + ENUMERATED, + 0, + NULL, + 0}; + DataObject iedModel_GenericIO_LLN0_Health = { DataObjectModelType, "Health", @@ -205,7 +205,7 @@ DataAttribute iedModel_GenericIO_LLN0_Health_stVal = { NULL, 0, IEC61850_FC_ST, - INT32, + ENUMERATED, 0 + TRG_OPT_DATA_CHANGED, NULL, 0}; @@ -357,7 +357,7 @@ DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_stVal = { NULL, 0, IEC61850_FC_ST, - INT32, + ENUMERATED, 0 + TRG_OPT_DATA_CHANGED, NULL, 0}; @@ -440,85 +440,85 @@ LogicalNode iedModel_GenericIO_GGIO1 = { LogicalNodeModelType, "GGIO1", (ModelNode*) &iedModel_GenericIO, - NULL, - (ModelNode*) &iedModel_GenericIO_GGIO1_Mod, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1, + (ModelNode*) &iedModel_GenericIO_GGIO1_Beh, }; -DataObject iedModel_GenericIO_GGIO1_Mod = { +DataObject iedModel_GenericIO_GGIO1_Beh = { DataObjectModelType, - "Mod", + "Beh", (ModelNode*) &iedModel_GenericIO_GGIO1, - (ModelNode*) &iedModel_GenericIO_GGIO1_Beh, - (ModelNode*) &iedModel_GenericIO_GGIO1_Mod_q, + (ModelNode*) &iedModel_GenericIO_GGIO1_Mod, + (ModelNode*) &iedModel_GenericIO_GGIO1_Beh_stVal, 0 }; -DataAttribute iedModel_GenericIO_GGIO1_Mod_q = { +DataAttribute iedModel_GenericIO_GGIO1_Beh_stVal = { DataAttributeModelType, - "q", - (ModelNode*) &iedModel_GenericIO_GGIO1_Mod, - (ModelNode*) &iedModel_GenericIO_GGIO1_Mod_t, + "stVal", + (ModelNode*) &iedModel_GenericIO_GGIO1_Beh, + (ModelNode*) &iedModel_GenericIO_GGIO1_Beh_q, NULL, 0, IEC61850_FC_ST, - QUALITY, - 0 + TRG_OPT_QUALITY_CHANGED, + ENUMERATED, + 0 + TRG_OPT_DATA_CHANGED, NULL, 0}; -DataAttribute iedModel_GenericIO_GGIO1_Mod_t = { +DataAttribute iedModel_GenericIO_GGIO1_Beh_q = { DataAttributeModelType, - "t", - (ModelNode*) &iedModel_GenericIO_GGIO1_Mod, - (ModelNode*) &iedModel_GenericIO_GGIO1_Mod_ctlModel, + "q", + (ModelNode*) &iedModel_GenericIO_GGIO1_Beh, + (ModelNode*) &iedModel_GenericIO_GGIO1_Beh_t, NULL, 0, IEC61850_FC_ST, - TIMESTAMP, - 0, + QUALITY, + 0 + TRG_OPT_QUALITY_CHANGED, NULL, 0}; -DataAttribute iedModel_GenericIO_GGIO1_Mod_ctlModel = { +DataAttribute iedModel_GenericIO_GGIO1_Beh_t = { DataAttributeModelType, - "ctlModel", - (ModelNode*) &iedModel_GenericIO_GGIO1_Mod, + "t", + (ModelNode*) &iedModel_GenericIO_GGIO1_Beh, NULL, NULL, 0, - IEC61850_FC_CF, - ENUMERATED, + IEC61850_FC_ST, + TIMESTAMP, 0, NULL, 0}; -DataObject iedModel_GenericIO_GGIO1_Beh = { +DataObject iedModel_GenericIO_GGIO1_Mod = { DataObjectModelType, - "Beh", + "Mod", (ModelNode*) &iedModel_GenericIO_GGIO1, (ModelNode*) &iedModel_GenericIO_GGIO1_Health, - (ModelNode*) &iedModel_GenericIO_GGIO1_Beh_stVal, + (ModelNode*) &iedModel_GenericIO_GGIO1_Mod_stVal, 0 }; -DataAttribute iedModel_GenericIO_GGIO1_Beh_stVal = { +DataAttribute iedModel_GenericIO_GGIO1_Mod_stVal = { DataAttributeModelType, "stVal", - (ModelNode*) &iedModel_GenericIO_GGIO1_Beh, - (ModelNode*) &iedModel_GenericIO_GGIO1_Beh_q, + (ModelNode*) &iedModel_GenericIO_GGIO1_Mod, + (ModelNode*) &iedModel_GenericIO_GGIO1_Mod_q, NULL, 0, IEC61850_FC_ST, - INT32, + ENUMERATED, 0 + TRG_OPT_DATA_CHANGED, NULL, 0}; -DataAttribute iedModel_GenericIO_GGIO1_Beh_q = { +DataAttribute iedModel_GenericIO_GGIO1_Mod_q = { DataAttributeModelType, "q", - (ModelNode*) &iedModel_GenericIO_GGIO1_Beh, - (ModelNode*) &iedModel_GenericIO_GGIO1_Beh_t, + (ModelNode*) &iedModel_GenericIO_GGIO1_Mod, + (ModelNode*) &iedModel_GenericIO_GGIO1_Mod_t, NULL, 0, IEC61850_FC_ST, @@ -527,11 +527,11 @@ DataAttribute iedModel_GenericIO_GGIO1_Beh_q = { NULL, 0}; -DataAttribute iedModel_GenericIO_GGIO1_Beh_t = { +DataAttribute iedModel_GenericIO_GGIO1_Mod_t = { DataAttributeModelType, "t", - (ModelNode*) &iedModel_GenericIO_GGIO1_Beh, - NULL, + (ModelNode*) &iedModel_GenericIO_GGIO1_Mod, + (ModelNode*) &iedModel_GenericIO_GGIO1_Mod_ctlModel, NULL, 0, IEC61850_FC_ST, @@ -540,6 +540,19 @@ DataAttribute iedModel_GenericIO_GGIO1_Beh_t = { NULL, 0}; +DataAttribute iedModel_GenericIO_GGIO1_Mod_ctlModel = { + DataAttributeModelType, + "ctlModel", + (ModelNode*) &iedModel_GenericIO_GGIO1_Mod, + NULL, + NULL, + 0, + IEC61850_FC_CF, + ENUMERATED, + 0, + NULL, + 0}; + DataObject iedModel_GenericIO_GGIO1_Health = { DataObjectModelType, "Health", @@ -557,7 +570,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Health_stVal = { NULL, 0, IEC61850_FC_ST, - INT32, + ENUMERATED, 0 + TRG_OPT_DATA_CHANGED, NULL, 0}; @@ -1901,44 +1914,526 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind4_t = { NULL, 0}; -extern ReportControlBlock iedModel_GenericIO_LLN0_report0; -extern ReportControlBlock iedModel_GenericIO_LLN0_report1; -extern ReportControlBlock iedModel_GenericIO_LLN0_report2; -extern ReportControlBlock iedModel_GenericIO_LLN0_report3; -extern ReportControlBlock iedModel_GenericIO_LLN0_report4; - -ReportControlBlock iedModel_GenericIO_LLN0_report0 = {&iedModel_GenericIO_LLN0, "EventsRCB01", "Events1", false, "Events", 1, 8, 111, 50, 1000, &iedModel_GenericIO_LLN0_report1}; -ReportControlBlock iedModel_GenericIO_LLN0_report1 = {&iedModel_GenericIO_LLN0, "EventsRCB02", "Events1", false, "Events", 1, 8, 111, 50, 1000, &iedModel_GenericIO_LLN0_report2}; -ReportControlBlock iedModel_GenericIO_LLN0_report2 = {&iedModel_GenericIO_LLN0, "EventsRCB03", "Events1", false, "Events", 1, 8, 111, 50, 1000, &iedModel_GenericIO_LLN0_report3}; -ReportControlBlock iedModel_GenericIO_LLN0_report3 = {&iedModel_GenericIO_LLN0, "EventsRCB04", "Events1", false, "Events", 1, 8, 111, 50, 1000, &iedModel_GenericIO_LLN0_report4}; -ReportControlBlock iedModel_GenericIO_LLN0_report4 = {&iedModel_GenericIO_LLN0, "EventsRCB05", "Events1", false, "Events", 1, 8, 111, 50, 1000, NULL}; - +LogicalNode iedModel_GenericIO_TIM_GAPC1 = { + LogicalNodeModelType, + "TIM_GAPC1", + (ModelNode*) &iedModel_GenericIO, + NULL, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Beh, +}; +DataObject iedModel_GenericIO_TIM_GAPC1_Beh = { + DataObjectModelType, + "Beh", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Mod, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Beh_stVal, + 0 +}; +DataAttribute iedModel_GenericIO_TIM_GAPC1_Beh_stVal = { + DataAttributeModelType, + "stVal", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Beh, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Beh_q, + NULL, + 0, + IEC61850_FC_ST, + ENUMERATED, + 0 + TRG_OPT_DATA_CHANGED, + NULL, + 0}; -IedModel iedModel = { - "beagle", - &iedModel_GenericIO, - &iedModelds_GenericIO_LLN0_Events, - &iedModel_GenericIO_LLN0_report0, +DataAttribute iedModel_GenericIO_TIM_GAPC1_Beh_q = { + DataAttributeModelType, + "q", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Beh, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Beh_t, NULL, + 0, + IEC61850_FC_ST, + QUALITY, + 0 + TRG_OPT_QUALITY_CHANGED, NULL, - initializeValues -}; + 0}; -static void -initializeValues() -{ +DataAttribute iedModel_GenericIO_TIM_GAPC1_Beh_t = { + DataAttributeModelType, + "t", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Beh, + NULL, + NULL, + 0, + IEC61850_FC_ST, + TIMESTAMP, + 0, + NULL, + 0}; -iedModel_GenericIO_LLN0_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0); +DataObject iedModel_GenericIO_TIM_GAPC1_Mod = { + DataObjectModelType, + "Mod", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Str, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Mod_stVal, + 0 +}; -iedModel_GenericIO_GGIO1_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0); +DataAttribute iedModel_GenericIO_TIM_GAPC1_Mod_stVal = { + DataAttributeModelType, + "stVal", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Mod, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Mod_q, + NULL, + 0, + IEC61850_FC_ST, + ENUMERATED, + 0 + TRG_OPT_DATA_CHANGED, + NULL, + 0}; -iedModel_GenericIO_GGIO1_SPCSO1_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(1); +DataAttribute iedModel_GenericIO_TIM_GAPC1_Mod_q = { + DataAttributeModelType, + "q", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Mod, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Mod_t, + NULL, + 0, + IEC61850_FC_ST, + QUALITY, + 0 + TRG_OPT_QUALITY_CHANGED, + NULL, + 0}; -iedModel_GenericIO_GGIO1_SPCSO2_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(2); +DataAttribute iedModel_GenericIO_TIM_GAPC1_Mod_t = { + DataAttributeModelType, + "t", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Mod, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Mod_ctlModel, + NULL, + 0, + IEC61850_FC_ST, + TIMESTAMP, + 0, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_Mod_ctlModel = { + DataAttributeModelType, + "ctlModel", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Mod, + NULL, + NULL, + 0, + IEC61850_FC_CF, + ENUMERATED, + 0, + NULL, + 0}; + +DataObject iedModel_GenericIO_TIM_GAPC1_Str = { + DataObjectModelType, + "Str", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Op, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Str_general, + 0 +}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_Str_general = { + DataAttributeModelType, + "general", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Str, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Str_dirGeneral, + NULL, + 0, + IEC61850_FC_ST, + BOOLEAN, + 0 + TRG_OPT_DATA_CHANGED, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_Str_dirGeneral = { + DataAttributeModelType, + "dirGeneral", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Str, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Str_q, + NULL, + 0, + IEC61850_FC_ST, + ENUMERATED, + 0 + TRG_OPT_DATA_CHANGED, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_Str_q = { + DataAttributeModelType, + "q", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Str, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Str_t, + NULL, + 0, + IEC61850_FC_ST, + QUALITY, + 0 + TRG_OPT_QUALITY_CHANGED, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_Str_t = { + DataAttributeModelType, + "t", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Str, + NULL, + NULL, + 0, + IEC61850_FC_ST, + TIMESTAMP, + 0, + NULL, + 0}; + +DataObject iedModel_GenericIO_TIM_GAPC1_Op = { + DataObjectModelType, + "Op", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpDlTmms, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Op_general, + 0 +}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_Op_general = { + DataAttributeModelType, + "general", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Op, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Op_q, + NULL, + 0, + IEC61850_FC_ST, + BOOLEAN, + 0 + TRG_OPT_DATA_CHANGED, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_Op_q = { + DataAttributeModelType, + "q", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Op, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Op_t, + NULL, + 0, + IEC61850_FC_ST, + QUALITY, + 0 + TRG_OPT_QUALITY_CHANGED, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_Op_t = { + DataAttributeModelType, + "t", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_Op, + NULL, + NULL, + 0, + IEC61850_FC_ST, + TIMESTAMP, + 0, + NULL, + 0}; + +DataObject iedModel_GenericIO_TIM_GAPC1_OpDlTmms = { + DataObjectModelType, + "OpDlTmms", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_RsDlTmms, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpDlTmms_setVal, + 0 +}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpDlTmms_setVal = { + DataAttributeModelType, + "setVal", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpDlTmms, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpDlTmms_dataNs, + NULL, + 0, + IEC61850_FC_SP, + INT32, + 0 + TRG_OPT_DATA_CHANGED, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpDlTmms_dataNs = { + DataAttributeModelType, + "dataNs", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpDlTmms, + NULL, + NULL, + 0, + IEC61850_FC_EX, + VISIBLE_STRING_255, + 0, + NULL, + 0}; + +DataObject iedModel_GenericIO_TIM_GAPC1_RsDlTmms = { + DataObjectModelType, + "RsDlTmms", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_RsDlTmms_setVal, + 0 +}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_RsDlTmms_setVal = { + DataAttributeModelType, + "setVal", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_RsDlTmms, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_RsDlTmms_dataNs, + NULL, + 0, + IEC61850_FC_SP, + INT32, + 0 + TRG_OPT_DATA_CHANGED, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_RsDlTmms_dataNs = { + DataAttributeModelType, + "dataNs", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_RsDlTmms, + NULL, + NULL, + 0, + IEC61850_FC_EX, + VISIBLE_STRING_255, + 0, + NULL, + 0}; + +DataObject iedModel_GenericIO_TIM_GAPC1_OpCntRs = { + DataObjectModelType, + "OpCntRs", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1, + NULL, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_stVal, + 0 +}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_stVal = { + DataAttributeModelType, + "stVal", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_q, + NULL, + 0, + IEC61850_FC_ST, + INT32, + 0 + TRG_OPT_DATA_CHANGED, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_q = { + DataAttributeModelType, + "q", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_t, + NULL, + 0, + IEC61850_FC_ST, + QUALITY, + 0 + TRG_OPT_QUALITY_CHANGED, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_t = { + DataAttributeModelType, + "t", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper, + NULL, + 0, + IEC61850_FC_ST, + TIMESTAMP, + 0, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper = { + DataAttributeModelType, + "Oper", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_ctlModel, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_ctlVal, + 0, + IEC61850_FC_CO, + CONSTRUCTED, + 0, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_ctlVal = { + DataAttributeModelType, + "ctlVal", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin, + NULL, + 0, + IEC61850_FC_CO, + BOOLEAN, + 0, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin = { + DataAttributeModelType, + "origin", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_ctlNum, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin_orCat, + 0, + IEC61850_FC_CO, + CONSTRUCTED, + 0, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin_orCat = { + DataAttributeModelType, + "orCat", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin_orIdent, + NULL, + 0, + IEC61850_FC_CO, + ENUMERATED, + 0, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin_orIdent = { + DataAttributeModelType, + "orIdent", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin, + NULL, + NULL, + 0, + IEC61850_FC_CO, + OCTET_STRING_64, + 0, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_ctlNum = { + DataAttributeModelType, + "ctlNum", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_T, + NULL, + 0, + IEC61850_FC_CO, + INT8U, + 0, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_T = { + DataAttributeModelType, + "T", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_Test, + NULL, + 0, + IEC61850_FC_CO, + TIMESTAMP, + 0, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_Test = { + DataAttributeModelType, + "Test", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper, + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_Check, + NULL, + 0, + IEC61850_FC_CO, + BOOLEAN, + 0, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_Check = { + DataAttributeModelType, + "Check", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper, + NULL, + NULL, + 0, + IEC61850_FC_CO, + CHECK, + 0, + NULL, + 0}; + +DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_ctlModel = { + DataAttributeModelType, + "ctlModel", + (ModelNode*) &iedModel_GenericIO_TIM_GAPC1_OpCntRs, + NULL, + NULL, + 0, + IEC61850_FC_CF, + ENUMERATED, + 0, + NULL, + 0}; + +extern ReportControlBlock iedModel_GenericIO_LLN0_report0; +extern ReportControlBlock iedModel_GenericIO_LLN0_report1; +extern ReportControlBlock iedModel_GenericIO_LLN0_report2; +extern ReportControlBlock iedModel_GenericIO_LLN0_report3; +extern ReportControlBlock iedModel_GenericIO_LLN0_report4; + +ReportControlBlock iedModel_GenericIO_LLN0_report0 = {&iedModel_GenericIO_LLN0, "EventsRCB01", "Events1", false, "Events", 1, 24, 111, 50, 1000, &iedModel_GenericIO_LLN0_report1}; +ReportControlBlock iedModel_GenericIO_LLN0_report1 = {&iedModel_GenericIO_LLN0, "EventsRCB02", "Events1", false, "Events", 1, 24, 111, 50, 1000, &iedModel_GenericIO_LLN0_report2}; +ReportControlBlock iedModel_GenericIO_LLN0_report2 = {&iedModel_GenericIO_LLN0, "EventsRCB03", "Events1", false, "Events", 1, 24, 111, 50, 1000, &iedModel_GenericIO_LLN0_report3}; +ReportControlBlock iedModel_GenericIO_LLN0_report3 = {&iedModel_GenericIO_LLN0, "EventsRCB04", "Events1", false, "Events", 1, 24, 111, 50, 1000, &iedModel_GenericIO_LLN0_report4}; +ReportControlBlock iedModel_GenericIO_LLN0_report4 = {&iedModel_GenericIO_LLN0, "EventsRCB05", "Events1", false, "Events", 1, 24, 111, 50, 1000, NULL}; + + + + +IedModel iedModel = { + "beagle", + &iedModel_GenericIO, + &iedModelds_GenericIO_LLN0_Events, + &iedModel_GenericIO_LLN0_report0, + NULL, + NULL, + initializeValues +}; + +static void +initializeValues() +{ + +iedModel_GenericIO_LLN0_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0); + +iedModel_GenericIO_GGIO1_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0); + +iedModel_GenericIO_GGIO1_SPCSO1_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(1); + +iedModel_GenericIO_GGIO1_SPCSO2_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(2); iedModel_GenericIO_GGIO1_SPCSO3_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(1); iedModel_GenericIO_GGIO1_DPCSO1_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(3); + +iedModel_GenericIO_TIM_GAPC1_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0); + +iedModel_GenericIO_TIM_GAPC1_OpDlTmms_dataNs.mmsValue = MmsValue_newVisibleString("EXT:2015"); + +iedModel_GenericIO_TIM_GAPC1_RsDlTmms_dataNs.mmsValue = MmsValue_newVisibleString("EXT:2015"); + +iedModel_GenericIO_TIM_GAPC1_OpCntRs_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(1); } diff --git a/demos/beaglebone/static_model.h b/demos/beaglebone/static_model.h index 36a7e0f7..a50ade81 100644 --- a/demos/beaglebone/static_model.h +++ b/demos/beaglebone/static_model.h @@ -13,15 +13,15 @@ extern IedModel iedModel; extern LogicalDevice iedModel_GenericIO; extern LogicalNode iedModel_GenericIO_LLN0; +extern DataObject iedModel_GenericIO_LLN0_Beh; +extern DataAttribute iedModel_GenericIO_LLN0_Beh_stVal; +extern DataAttribute iedModel_GenericIO_LLN0_Beh_q; +extern DataAttribute iedModel_GenericIO_LLN0_Beh_t; extern DataObject iedModel_GenericIO_LLN0_Mod; extern DataAttribute iedModel_GenericIO_LLN0_Mod_stVal; extern DataAttribute iedModel_GenericIO_LLN0_Mod_q; extern DataAttribute iedModel_GenericIO_LLN0_Mod_t; extern DataAttribute iedModel_GenericIO_LLN0_Mod_ctlModel; -extern DataObject iedModel_GenericIO_LLN0_Beh; -extern DataAttribute iedModel_GenericIO_LLN0_Beh_stVal; -extern DataAttribute iedModel_GenericIO_LLN0_Beh_q; -extern DataAttribute iedModel_GenericIO_LLN0_Beh_t; extern DataObject iedModel_GenericIO_LLN0_Health; extern DataAttribute iedModel_GenericIO_LLN0_Health_stVal; extern DataAttribute iedModel_GenericIO_LLN0_Health_q; @@ -44,14 +44,15 @@ extern DataAttribute iedModel_GenericIO_LPHD1_Proxy_stVal; extern DataAttribute iedModel_GenericIO_LPHD1_Proxy_q; extern DataAttribute iedModel_GenericIO_LPHD1_Proxy_t; extern LogicalNode iedModel_GenericIO_GGIO1; -extern DataObject iedModel_GenericIO_GGIO1_Mod; -extern DataAttribute iedModel_GenericIO_GGIO1_Mod_q; -extern DataAttribute iedModel_GenericIO_GGIO1_Mod_t; -extern DataAttribute iedModel_GenericIO_GGIO1_Mod_ctlModel; extern DataObject iedModel_GenericIO_GGIO1_Beh; extern DataAttribute iedModel_GenericIO_GGIO1_Beh_stVal; extern DataAttribute iedModel_GenericIO_GGIO1_Beh_q; extern DataAttribute iedModel_GenericIO_GGIO1_Beh_t; +extern DataObject iedModel_GenericIO_GGIO1_Mod; +extern DataAttribute iedModel_GenericIO_GGIO1_Mod_stVal; +extern DataAttribute iedModel_GenericIO_GGIO1_Mod_q; +extern DataAttribute iedModel_GenericIO_GGIO1_Mod_t; +extern DataAttribute iedModel_GenericIO_GGIO1_Mod_ctlModel; extern DataObject iedModel_GenericIO_GGIO1_Health; extern DataAttribute iedModel_GenericIO_GGIO1_Health_stVal; extern DataAttribute iedModel_GenericIO_GGIO1_Health_q; @@ -161,20 +162,59 @@ extern DataObject iedModel_GenericIO_GGIO1_Ind4; extern DataAttribute iedModel_GenericIO_GGIO1_Ind4_stVal; extern DataAttribute iedModel_GenericIO_GGIO1_Ind4_q; extern DataAttribute iedModel_GenericIO_GGIO1_Ind4_t; +extern LogicalNode iedModel_GenericIO_TIM_GAPC1; +extern DataObject iedModel_GenericIO_TIM_GAPC1_Beh; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Beh_stVal; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Beh_q; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Beh_t; +extern DataObject iedModel_GenericIO_TIM_GAPC1_Mod; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Mod_stVal; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Mod_q; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Mod_t; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Mod_ctlModel; +extern DataObject iedModel_GenericIO_TIM_GAPC1_Str; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Str_general; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Str_dirGeneral; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Str_q; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Str_t; +extern DataObject iedModel_GenericIO_TIM_GAPC1_Op; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Op_general; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Op_q; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_Op_t; +extern DataObject iedModel_GenericIO_TIM_GAPC1_OpDlTmms; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpDlTmms_setVal; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpDlTmms_dataNs; +extern DataObject iedModel_GenericIO_TIM_GAPC1_RsDlTmms; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_RsDlTmms_setVal; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_RsDlTmms_dataNs; +extern DataObject iedModel_GenericIO_TIM_GAPC1_OpCntRs; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_stVal; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_q; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_t; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_ctlVal; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin_orCat; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin_orIdent; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_ctlNum; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_T; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_Test; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_Check; +extern DataAttribute iedModel_GenericIO_TIM_GAPC1_OpCntRs_ctlModel; #define IEDMODEL_GenericIO (&iedModel_GenericIO) #define IEDMODEL_GenericIO_LLN0 (&iedModel_GenericIO_LLN0) +#define IEDMODEL_GenericIO_LLN0_Beh (&iedModel_GenericIO_LLN0_Beh) +#define IEDMODEL_GenericIO_LLN0_Beh_stVal (&iedModel_GenericIO_LLN0_Beh_stVal) +#define IEDMODEL_GenericIO_LLN0_Beh_q (&iedModel_GenericIO_LLN0_Beh_q) +#define IEDMODEL_GenericIO_LLN0_Beh_t (&iedModel_GenericIO_LLN0_Beh_t) #define IEDMODEL_GenericIO_LLN0_Mod (&iedModel_GenericIO_LLN0_Mod) #define IEDMODEL_GenericIO_LLN0_Mod_stVal (&iedModel_GenericIO_LLN0_Mod_stVal) #define IEDMODEL_GenericIO_LLN0_Mod_q (&iedModel_GenericIO_LLN0_Mod_q) #define IEDMODEL_GenericIO_LLN0_Mod_t (&iedModel_GenericIO_LLN0_Mod_t) #define IEDMODEL_GenericIO_LLN0_Mod_ctlModel (&iedModel_GenericIO_LLN0_Mod_ctlModel) -#define IEDMODEL_GenericIO_LLN0_Beh (&iedModel_GenericIO_LLN0_Beh) -#define IEDMODEL_GenericIO_LLN0_Beh_stVal (&iedModel_GenericIO_LLN0_Beh_stVal) -#define IEDMODEL_GenericIO_LLN0_Beh_q (&iedModel_GenericIO_LLN0_Beh_q) -#define IEDMODEL_GenericIO_LLN0_Beh_t (&iedModel_GenericIO_LLN0_Beh_t) #define IEDMODEL_GenericIO_LLN0_Health (&iedModel_GenericIO_LLN0_Health) #define IEDMODEL_GenericIO_LLN0_Health_stVal (&iedModel_GenericIO_LLN0_Health_stVal) #define IEDMODEL_GenericIO_LLN0_Health_q (&iedModel_GenericIO_LLN0_Health_q) @@ -197,14 +237,15 @@ extern DataAttribute iedModel_GenericIO_GGIO1_Ind4_t; #define IEDMODEL_GenericIO_LPHD1_Proxy_q (&iedModel_GenericIO_LPHD1_Proxy_q) #define IEDMODEL_GenericIO_LPHD1_Proxy_t (&iedModel_GenericIO_LPHD1_Proxy_t) #define IEDMODEL_GenericIO_GGIO1 (&iedModel_GenericIO_GGIO1) -#define IEDMODEL_GenericIO_GGIO1_Mod (&iedModel_GenericIO_GGIO1_Mod) -#define IEDMODEL_GenericIO_GGIO1_Mod_q (&iedModel_GenericIO_GGIO1_Mod_q) -#define IEDMODEL_GenericIO_GGIO1_Mod_t (&iedModel_GenericIO_GGIO1_Mod_t) -#define IEDMODEL_GenericIO_GGIO1_Mod_ctlModel (&iedModel_GenericIO_GGIO1_Mod_ctlModel) #define IEDMODEL_GenericIO_GGIO1_Beh (&iedModel_GenericIO_GGIO1_Beh) #define IEDMODEL_GenericIO_GGIO1_Beh_stVal (&iedModel_GenericIO_GGIO1_Beh_stVal) #define IEDMODEL_GenericIO_GGIO1_Beh_q (&iedModel_GenericIO_GGIO1_Beh_q) #define IEDMODEL_GenericIO_GGIO1_Beh_t (&iedModel_GenericIO_GGIO1_Beh_t) +#define IEDMODEL_GenericIO_GGIO1_Mod (&iedModel_GenericIO_GGIO1_Mod) +#define IEDMODEL_GenericIO_GGIO1_Mod_stVal (&iedModel_GenericIO_GGIO1_Mod_stVal) +#define IEDMODEL_GenericIO_GGIO1_Mod_q (&iedModel_GenericIO_GGIO1_Mod_q) +#define IEDMODEL_GenericIO_GGIO1_Mod_t (&iedModel_GenericIO_GGIO1_Mod_t) +#define IEDMODEL_GenericIO_GGIO1_Mod_ctlModel (&iedModel_GenericIO_GGIO1_Mod_ctlModel) #define IEDMODEL_GenericIO_GGIO1_Health (&iedModel_GenericIO_GGIO1_Health) #define IEDMODEL_GenericIO_GGIO1_Health_stVal (&iedModel_GenericIO_GGIO1_Health_stVal) #define IEDMODEL_GenericIO_GGIO1_Health_q (&iedModel_GenericIO_GGIO1_Health_q) @@ -314,6 +355,45 @@ extern DataAttribute iedModel_GenericIO_GGIO1_Ind4_t; #define IEDMODEL_GenericIO_GGIO1_Ind4_stVal (&iedModel_GenericIO_GGIO1_Ind4_stVal) #define IEDMODEL_GenericIO_GGIO1_Ind4_q (&iedModel_GenericIO_GGIO1_Ind4_q) #define IEDMODEL_GenericIO_GGIO1_Ind4_t (&iedModel_GenericIO_GGIO1_Ind4_t) +#define IEDMODEL_GenericIO_TIM_GAPC1 (&iedModel_GenericIO_TIM_GAPC1) +#define IEDMODEL_GenericIO_TIM_GAPC1_Beh (&iedModel_GenericIO_TIM_GAPC1_Beh) +#define IEDMODEL_GenericIO_TIM_GAPC1_Beh_stVal (&iedModel_GenericIO_TIM_GAPC1_Beh_stVal) +#define IEDMODEL_GenericIO_TIM_GAPC1_Beh_q (&iedModel_GenericIO_TIM_GAPC1_Beh_q) +#define IEDMODEL_GenericIO_TIM_GAPC1_Beh_t (&iedModel_GenericIO_TIM_GAPC1_Beh_t) +#define IEDMODEL_GenericIO_TIM_GAPC1_Mod (&iedModel_GenericIO_TIM_GAPC1_Mod) +#define IEDMODEL_GenericIO_TIM_GAPC1_Mod_stVal (&iedModel_GenericIO_TIM_GAPC1_Mod_stVal) +#define IEDMODEL_GenericIO_TIM_GAPC1_Mod_q (&iedModel_GenericIO_TIM_GAPC1_Mod_q) +#define IEDMODEL_GenericIO_TIM_GAPC1_Mod_t (&iedModel_GenericIO_TIM_GAPC1_Mod_t) +#define IEDMODEL_GenericIO_TIM_GAPC1_Mod_ctlModel (&iedModel_GenericIO_TIM_GAPC1_Mod_ctlModel) +#define IEDMODEL_GenericIO_TIM_GAPC1_Str (&iedModel_GenericIO_TIM_GAPC1_Str) +#define IEDMODEL_GenericIO_TIM_GAPC1_Str_general (&iedModel_GenericIO_TIM_GAPC1_Str_general) +#define IEDMODEL_GenericIO_TIM_GAPC1_Str_dirGeneral (&iedModel_GenericIO_TIM_GAPC1_Str_dirGeneral) +#define IEDMODEL_GenericIO_TIM_GAPC1_Str_q (&iedModel_GenericIO_TIM_GAPC1_Str_q) +#define IEDMODEL_GenericIO_TIM_GAPC1_Str_t (&iedModel_GenericIO_TIM_GAPC1_Str_t) +#define IEDMODEL_GenericIO_TIM_GAPC1_Op (&iedModel_GenericIO_TIM_GAPC1_Op) +#define IEDMODEL_GenericIO_TIM_GAPC1_Op_general (&iedModel_GenericIO_TIM_GAPC1_Op_general) +#define IEDMODEL_GenericIO_TIM_GAPC1_Op_q (&iedModel_GenericIO_TIM_GAPC1_Op_q) +#define IEDMODEL_GenericIO_TIM_GAPC1_Op_t (&iedModel_GenericIO_TIM_GAPC1_Op_t) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpDlTmms (&iedModel_GenericIO_TIM_GAPC1_OpDlTmms) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpDlTmms_setVal (&iedModel_GenericIO_TIM_GAPC1_OpDlTmms_setVal) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpDlTmms_dataNs (&iedModel_GenericIO_TIM_GAPC1_OpDlTmms_dataNs) +#define IEDMODEL_GenericIO_TIM_GAPC1_RsDlTmms (&iedModel_GenericIO_TIM_GAPC1_RsDlTmms) +#define IEDMODEL_GenericIO_TIM_GAPC1_RsDlTmms_setVal (&iedModel_GenericIO_TIM_GAPC1_RsDlTmms_setVal) +#define IEDMODEL_GenericIO_TIM_GAPC1_RsDlTmms_dataNs (&iedModel_GenericIO_TIM_GAPC1_RsDlTmms_dataNs) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs (&iedModel_GenericIO_TIM_GAPC1_OpCntRs) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_stVal (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_stVal) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_q (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_q) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_t (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_t) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_Oper (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_Oper_ctlVal (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_ctlVal) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin_orCat (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin_orCat) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin_orIdent (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_origin_orIdent) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_Oper_ctlNum (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_ctlNum) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_Oper_T (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_T) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_Oper_Test (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_Test) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_Oper_Check (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_Oper_Check) +#define IEDMODEL_GenericIO_TIM_GAPC1_OpCntRs_ctlModel (&iedModel_GenericIO_TIM_GAPC1_OpCntRs_ctlModel) #endif /* STATIC_MODEL_H_ */ diff --git a/examples/server_example5/server_example5.c b/examples/server_example5/server_example5.c index 21f5207a..1d6d90ee 100644 --- a/examples/server_example5/server_example5.c +++ b/examples/server_example5/server_example5.c @@ -22,7 +22,7 @@ void sigint_handler(int signalId) } static MmsDataAccessError -writeAccessHandler (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection) +writeAccessHandler (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection, void* parameter) { if (dataAttribute == IEDMODEL_Inverter_ZINV1_OutVarSet_setMag_f) { @@ -54,7 +54,7 @@ int main(int argc, char** argv) { /* Instruct the server that we will be informed if a clients writes to a * certain variables we are interested in. */ - IedServer_handleWriteAccess(iedServer, IEDMODEL_Inverter_ZINV1_OutVarSet_setMag_f, writeAccessHandler); + IedServer_handleWriteAccess(iedServer, IEDMODEL_Inverter_ZINV1_OutVarSet_setMag_f, writeAccessHandler, NULL); if (!IedServer_isRunning(iedServer)) { printf("Starting server failed! Exit.\n"); diff --git a/src/goose/goose_publisher.c b/src/goose/goose_publisher.c index cc453865..47b85995 100644 --- a/src/goose/goose_publisher.c +++ b/src/goose/goose_publisher.c @@ -201,6 +201,7 @@ prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char* int bufPos = 12; +#if 1 /* Priority tag - IEEE 802.1Q */ self->buffer[bufPos++] = 0x81; self->buffer[bufPos++] = 0x00; @@ -212,6 +213,7 @@ prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char* self->buffer[bufPos++] = tci1; /* Priority + VLAN-ID */ self->buffer[bufPos++] = tci2; /* VLAN-ID */ +#endif /* EtherType GOOSE */ self->buffer[bufPos++] = 0x88; @@ -374,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; diff --git a/src/goose/goose_receiver.c b/src/goose/goose_receiver.c index 44595d97..201fcf93 100644 --- a/src/goose/goose_receiver.c +++ b/src/goose/goose_receiver.c @@ -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; @@ -752,7 +759,6 @@ GooseReceiver_destroy(GooseReceiver self) void GooseReceiver_startThreadless(GooseReceiver self) { - if (self->interfaceId == NULL) self->ethSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, NULL); else diff --git a/src/hal/filesystem/linux/file_provider_linux.c b/src/hal/filesystem/linux/file_provider_linux.c index f95cff5c..c973dd2a 100644 --- a/src/hal/filesystem/linux/file_provider_linux.c +++ b/src/hal/filesystem/linux/file_provider_linux.c @@ -123,7 +123,7 @@ FileSystem_getFileInfo(char* filename, uint32_t* fileSize, uint64_t* lastModific { struct stat fileStats; - char fullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 255]; + char fullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256]; createFullPathFromFileName(fullPath, filename); @@ -131,8 +131,8 @@ FileSystem_getFileInfo(char* filename, uint32_t* fileSize, uint64_t* lastModific return false; if (lastModificationTimestamp != NULL) - *lastModificationTimestamp = fileStats.st_mtime * 1000; - // does not work on older systems --> *lastModificationTimestamp = fileStats.st_ctim.tv_sec * 1000; + *lastModificationTimestamp = (uint64_t) (fileStats.st_mtime) * 1000LL; + // does not work on older systems --> *lastModificationTimestamp = (uint64_t) (fileStats.st_ctim.tv_sec) * 1000LL; if (fileSize != NULL) *fileSize = fileStats.st_size; diff --git a/src/hal/filesystem/win32/file_provider_win32.c b/src/hal/filesystem/win32/file_provider_win32.c index 662f5439..8df94e58 100644 --- a/src/hal/filesystem/win32/file_provider_win32.c +++ b/src/hal/filesystem/win32/file_provider_win32.c @@ -96,7 +96,7 @@ FileSystem_closeFile(FileHandle handle) bool FileSystem_getFileInfo(char* filename, uint32_t* fileSize, uint64_t* lastModificationTimestamp) { - char fullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 255]; + char fullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256]; createFullPathFromFileName(fullPath, filename); diff --git a/src/hal/inc/hal_filesystem.h b/src/hal/inc/hal_filesystem.h index 10272958..f18f6745 100644 --- a/src/hal/inc/hal_filesystem.h +++ b/src/hal/inc/hal_filesystem.h @@ -133,6 +133,10 @@ FileSystem_openDirectory(char* directoryName); /** * \brief read the next directory entry * + * This function returns the next directory entry. The entry is only a valid pointer as long as the + * FileSystem_closeDirectory or another FileSystem_readDirectory function is not called for the given + * DirectoryHandle. + * * \param directory the handle to identify the directory * \param isDirectory return value that indicates if the directory entry is itself a directory (true) * diff --git a/src/iec61850/client/client_report_control.c b/src/iec61850/client/client_report_control.c index 9ed5f615..933a9378 100644 --- a/src/iec61850/client/client_report_control.c +++ b/src/iec61850/client/client_report_control.c @@ -611,7 +611,7 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo if (!isBuffered) goto error_invalid_parameter; - strcpy(itemId + itemIdLen, "$TimeOfEntry"); + strcpy(itemId + itemIdLen, "$TimeofEntry"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->timeOfEntry); diff --git a/src/iec61850/inc/iec61850_model.h b/src/iec61850/inc/iec61850_model.h index f8d36e63..665a2491 100644 --- a/src/iec61850/inc/iec61850_model.h +++ b/src/iec61850/inc/iec61850_model.h @@ -407,6 +407,9 @@ IedModel_getLogicalDeviceCount(IedModel* iedModel); int LogicalDevice_getLogicalNodeCount(LogicalDevice* logicalDevice); +ModelNode* +LogicalDevice_getChildByMmsVariableName(LogicalDevice* logicalDevice, const char* mmsVariableName); + bool LogicalNode_hasFCData(LogicalNode* node, FunctionalConstraint fc); @@ -416,6 +419,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); diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index 263f6f52..834a4673 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -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, diff --git a/src/iec61850/inc_private/mms_mapping.h b/src/iec61850/inc_private/mms_mapping.h index 527a72c9..11e7a778 100644 --- a/src/iec61850/inc_private/mms_mapping.h +++ b/src/iec61850/inc_private/mms_mapping.h @@ -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, diff --git a/src/iec61850/inc_private/reporting.h b/src/iec61850/inc_private/reporting.h index 1f4b1bc2..739bdf22 100644 --- a/src/iec61850/inc_private/reporting.h +++ b/src/iec61850/inc_private/reporting.h @@ -29,6 +29,7 @@ typedef struct sReportBufferEntry ReportBufferEntry; struct sReportBufferEntry { uint8_t entryId[8]; uint8_t flags; /* bit 0 (1 = isIntegrityReport), bit 1 (1 = isGiReport) */ + uint64_t timeOfEntry; int entryLength; ReportBufferEntry* next; }; diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index d630087f..5f418cf6 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -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 + } + + else if (dataAttribute->triggerOptions & TRG_OPT_QUALITY_CHANGED) { #if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue); #endif - } - - else if (dataAttribute->triggerOptions & TRG_OPT_QUALITY_CHANGED) { #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,6 +916,7 @@ IedServer_updateBooleanAttributeValue(IedServer self, DataAttribute* dataAttribu bool currentValue = MmsValue_getBoolean(dataAttribute->mmsValue); if (currentValue == value) { + checkForUpdateTrigger(self, dataAttribute); } else { @@ -993,15 +994,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 +1080,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 diff --git a/src/iec61850/server/mms_mapping/mms_goose.c b/src/iec61850/server/mms_mapping/mms_goose.c index e4c0678c..8b9d723f 100644 --- a/src/iec61850/server/mms_mapping/mms_goose.c +++ b/src/iec61850/server/mms_mapping/mms_goose.c @@ -169,7 +169,6 @@ MmsGooseControlBlock_enable(MmsGooseControlBlock self) if (!MmsGooseControlBlock_isEnabled(self)) { - if (self->dataSetRef != NULL) { GLOBAL_FREEMEM(self->dataSetRef); diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index c82eed03..78fb5dea 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -50,6 +50,7 @@ typedef struct { DataAttribute* attribute; WriteAccessHandler handler; + void* parameter; } AttributeAccessHandler; @@ -1761,6 +1762,8 @@ mmsWriteHandler(void* parameter, MmsDomain* domain, sg->editSgConfirmedHandler(sg->editSgConfirmedHandlerParameter, sg->sgcb, sg->sgcb->editSG); + unselectSettingGroup(sg); + return DATA_ACCESS_ERROR_SUCCESS; } else @@ -1828,7 +1831,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; @@ -1840,8 +1844,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; @@ -1925,7 +1929,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); @@ -1933,6 +1937,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); } diff --git a/src/iec61850/server/mms_mapping/reporting.c b/src/iec61850/server/mms_mapping/reporting.c index 8763d9b3..b3513b0f 100644 --- a/src/iec61850/server/mms_mapping/reporting.c +++ b/src/iec61850/server/mms_mapping/reporting.c @@ -214,7 +214,7 @@ ReportControl_getRCBValue(ReportControl* rc, char* elementName) return MmsValue_getElement(rc->rcbValues, 10); else if (strcmp(elementName, "EntryID") == 0) return MmsValue_getElement(rc->rcbValues, 11); - else if (strcmp(elementName, "TimeOfEntry") == 0) + else if (strcmp(elementName, "TimeofEntry") == 0) return MmsValue_getElement(rc->rcbValues, 12); else if (strcmp(elementName, "ResvTms") == 0) return MmsValue_getElement(rc->rcbValues, 13); @@ -949,7 +949,7 @@ createBufferedReportControlBlock(ReportControlBlock* reportControlBlock, mmsValue->value.structure.components[11] = MmsValue_newOctetString(8, 8); namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); - namedVariable->name = copyString("TimeOfEntry"); + namedVariable->name = copyString("TimeofEntry"); namedVariable->type = MMS_BINARY_TIME; namedVariable->typeSpec.binaryTime = 6; rcb->typeSpec.structure.elements[12] = namedVariable; @@ -1420,7 +1420,6 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme if (rcbValue != NULL) MmsValue_update(rcbValue, value); else { - printf("AAAAAA\n"); retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID; goto exit_function; } @@ -1520,7 +1519,7 @@ printReportId(ReportBufferEntry* report) #endif static void -enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI) +enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_t timeOfEntry) { if (DEBUG_IED_SERVER) printf("IED_SERVER: enqueueReport: RCB name: %s (SQN:%u) enabled:%i buffered:%i buffering:%i intg:%i GI:%i\n", reportControl->name, (unsigned) reportControl->sqNum, reportControl->enabled, @@ -1746,15 +1745,17 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI) ReportBufferEntry* entry = (ReportBufferEntry*) entryBufPos; /* ENTRY_ID is set to system time in ms! */ - uint64_t timestamp = Hal_getTimeInMs(); + uint64_t entryId = timeOfEntry; - if (timestamp <= reportControl->lastEntryId) - timestamp = reportControl->lastEntryId + 1; + if (entryId <= reportControl->lastEntryId) + entryId = reportControl->lastEntryId + 1; + + entry->timeOfEntry = entryId; #if (ORDER_LITTLE_ENDIAN == 1) - memcpyReverseByteOrder(entry->entryId, (uint8_t*) ×tamp, 8); + memcpyReverseByteOrder(entry->entryId, (uint8_t*) &entryId, 8); #else - memcpy (entry->entryId, (uint8_t*) ×tamp, 8); + memcpy (entry->entryId, (uint8_t*) &entryId, 8); #endif #if (DEBUG_IED_SERVER == 1) @@ -1844,7 +1845,7 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI) if (buffer->oldestReport == NULL) buffer->oldestReport = buffer->lastEnqueuedReport; - reportControl->lastEntryId = timestamp; + reportControl->lastEntryId = entryId; } static void @@ -1924,7 +1925,15 @@ sendNextReportEntry(ReportControl* self) goto return_out_of_memory; if (MmsValue_getBitStringBit(optFlds, 2)) { /* report time stamp */ - if (MemAllocLinkedList_add(reportElements, self->timeOfEntry) == NULL) + MmsValue* timeOfEntry = (MmsValue*) MemoryAllocator_allocate(&ma, sizeof(MmsValue)); + + if (timeOfEntry == NULL) goto return_out_of_memory; + + timeOfEntry->deleteValue = 0; + timeOfEntry->type = MMS_UTC_TIME; + MmsValue_setUtcTimeMs(timeOfEntry, report->timeOfEntry); + + if (MemAllocLinkedList_add(reportElements, timeOfEntry) == NULL) goto return_out_of_memory; } @@ -2010,7 +2019,7 @@ sendNextReportEntry(ReportControl* self) + ldNameLength + variableNameLength + 1; - char* dataReference = (char*) MemoryAllocator_allocate(&ma, refLen); + char* dataReference = (char*) MemoryAllocator_allocate(&ma, refLen + 1); if (dataReference == NULL) goto return_out_of_memory; @@ -2214,7 +2223,7 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs) /* send current events in event buffer before GI report */ if (rc->triggered) { if (rc->buffered) - enqueueReport(rc, false, false); + enqueueReport(rc, false, false, currentTimeInMs); else sendReport(rc, false, false); @@ -2224,7 +2233,7 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs) updateTimeOfEntry(rc, currentTimeInMs); if (rc->buffered) - enqueueReport(rc, false, true); + enqueueReport(rc, false, true, currentTimeInMs); else sendReport(rc, false, true); @@ -2242,7 +2251,7 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs) /* send current events in event buffer before integrity report */ if (rc->triggered) { if (rc->buffered) - enqueueReport(rc, false, false); + enqueueReport(rc, false, false, currentTimeInMs); else sendReport(rc, false, false); @@ -2253,7 +2262,7 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs) updateTimeOfEntry(rc, currentTimeInMs); if (rc->buffered) - enqueueReport(rc, true, false); + enqueueReport(rc, true, false, currentTimeInMs); else sendReport(rc, true, false); @@ -2266,7 +2275,7 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs) if (currentTimeInMs >= rc->reportTime) { if (rc->buffered) - enqueueReport(rc, false, false); + enqueueReport(rc, false, false, currentTimeInMs); else sendReport(rc, false, false); diff --git a/src/iec61850/server/model/model.c b/src/iec61850/server/model/model.c index ad1bd598..6e752faa 100644 --- a/src/iec61850/server/model/model.c +++ b/src/iec61850/server/model/model.c @@ -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) { @@ -360,6 +400,54 @@ LogicalDevice_getLogicalNodeCount(LogicalDevice* logicalDevice) return lnCount; } +ModelNode* +LogicalDevice_getChildByMmsVariableName(LogicalDevice* logicalDevice, const char* mmsVariableName) +{ + + + char fcString[3]; + char nameRef[65]; + + char* separator = strchr(mmsVariableName,'$'); + + if (separator == NULL) + return NULL; + + if (strlen(separator) > 4) { + fcString[0] = separator[1]; + fcString[1] = separator[2]; + fcString[2] = 0; + + const char* strpos = mmsVariableName; + + int targetPos = 0; + + while (strpos < separator) { + nameRef[targetPos++] = strpos[0]; + strpos++; + } + + nameRef[targetPos++] = '.'; + + strpos = separator + 4; + + while (strpos[0] != 0) { + nameRef[targetPos++] = strpos[0]; + strpos++; + } + + nameRef[targetPos++] = 0; + + StringUtils_replace(nameRef, '$', '.'); + + FunctionalConstraint fc = FunctionalConstraint_fromString(fcString); + + return ModelNode_getChildWithFc((ModelNode*) logicalDevice, nameRef, fc); + } + + return NULL; +} + static int createObjectReference(ModelNode* node, char* objectReference) { diff --git a/src/mms/iso_mms/client/mms_client_connection.c b/src/mms/iso_mms/client/mms_client_connection.c index 90455d98..c91005cd 100644 --- a/src/mms/iso_mms/client/mms_client_connection.c +++ b/src/mms/iso_mms/client/mms_client_connection.c @@ -1058,11 +1058,12 @@ mmsClient_getNameListSingleRequest( ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload); - - if (responseMessage != NULL) moreFollows = mmsClient_parseGetNameListResponse(nameList, self->lastResponse, NULL); + if (self->lastResponseError != MMS_ERROR_NONE) + *mmsError = self->lastResponseError; + releaseResponse(self); if (self->associationState == MMS_STATE_CLOSED) diff --git a/src/mms/iso_mms/server/mms_access_result.c b/src/mms/iso_mms/server/mms_access_result.c index 3b4f033c..59d52ab6 100644 --- a/src/mms/iso_mms/server/mms_access_result.c +++ b/src/mms/iso_mms/server/mms_access_result.c @@ -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, diff --git a/src/mms/iso_mms/server/mms_file_service.c b/src/mms/iso_mms/server/mms_file_service.c index 03618b45..d0780fb3 100644 --- a/src/mms/iso_mms/server/mms_file_service.c +++ b/src/mms/iso_mms/server/mms_file_service.c @@ -214,11 +214,11 @@ mmsServer_handleFileDeleteRequest( filename[length] = 0; if (DEBUG_MMS_SERVER) - printf("mms_file_service.c: Delete file (%s)\n", filename); + printf("MMS_SERVER: mms_file_service.c: Delete file (%s)\n", filename); if (!FileSystem_getFileInfo(filename, NULL, NULL)) { if (DEBUG_MMS_SERVER) - printf("mms_file_service.c: File (%s) not found\n", filename); + printf("MMS_SERVER: mms_file_service.c: File (%s) not found\n", filename); mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); return; @@ -226,7 +226,7 @@ mmsServer_handleFileDeleteRequest( if (!FileSystem_deleteFile(filename)) { if (DEBUG_MMS_SERVER) - printf("mms_file_service.c: Delete file (%s) failed\n", filename); + printf("MMS_SERVER: mms_file_service.c: Delete file (%s) failed\n", filename); mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_ACCESS_DENIED); return; @@ -381,7 +381,7 @@ mmsServer_handleFileReadRequest( int32_t frsmId = (int32_t) BerDecoder_decodeUint32(buffer, maxBufPos - bufPos, bufPos); if (DEBUG_MMS_SERVER) - printf("mmsServer_handleFileReadRequest read request for frsmId: %i\n", frsmId); + printf("MMS_SERVER: mmsServer_handleFileReadRequest read request for frsmId: %i\n", frsmId); MmsFileReadStateMachine* frsm = getFrsm(connection, frsmId); @@ -436,104 +436,105 @@ encodeFileSpecification(uint8_t tag, char* fileSpecification, uint8_t* buffer, i } } - - -static void -createFileDirectoryResponse(uint32_t invokeId, ByteBuffer* response, char* directoryName, char* continueAfterFileName) +static int +addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* directoryName, char* continueAfterFileName, bool* moreFollows) { - int maxSize = response->maxSize - 3; /* reserve space for moreFollows */ - uint8_t* buffer = response->buffer; - - bool moreFollows = false; - - int tempStartPos = 30; /* estimated header part with safety margin */ - int tempCurPos = tempStartPos; - int tempEncoded = 0; - - char extendedFileName[300]; + int directoryNameLength = strlen(directoryName); DirectoryHandle directory = FileSystem_openDirectory(directoryName); - if (continueAfterFileName != NULL) { - if (strlen(continueAfterFileName) == 0) - continueAfterFileName = NULL; - } - if (directory != NULL) { bool isDirectory; char* fileName = FileSystem_readDirectory(directory, &isDirectory); while (fileName != NULL) { - if (isDirectory) { - strcpy(extendedFileName, fileName); - strcat(extendedFileName, "/"); - - fileName = extendedFileName; - } - - if (continueAfterFileName != NULL) { - if (strcmp(continueAfterFileName, fileName) == 0) - continueAfterFileName = NULL; - } - else { - uint64_t msTime; + directoryName[directoryNameLength] = 0; - char fullPath[CONFIG_MMS_FILE_SERVICE_MAX_FILENAME_LENGTH]; + if (directoryNameLength > 0) + strcat(directoryName, "/"); - if (directoryName != NULL) { - int directoryLen = strlen(directoryName); + strcat(directoryName, fileName); - strcpy(fullPath, directoryName); + if (isDirectory) { + bufPos = addFileEntriesToResponse(buffer, bufPos, maxBufSize, directoryName, continueAfterFileName, moreFollows); - if (directoryName[directoryLen - 1] != CONFIG_SYSTEM_FILE_SEPARATOR) { - fullPath[directoryLen] = CONFIG_SYSTEM_FILE_SEPARATOR; - fullPath[directoryLen + 1] = 0; - } + if (*moreFollows == true) + break; + } + else { + if (continueAfterFileName != NULL) { + if (strcmp(continueAfterFileName, directoryName) == 0) + continueAfterFileName = NULL; + } + else { + uint64_t msTime; - strcat(fullPath, fileName); - } - else { - strncpy(fullPath, fileName, CONFIG_MMS_FILE_SERVICE_MAX_FILENAME_LENGTH - 1); - fullPath[CONFIG_MMS_FILE_SERVICE_MAX_FILENAME_LENGTH - 1] = 0; - } + uint32_t fileSize; - uint32_t fileSize; + FileSystem_getFileInfo(directoryName, &fileSize, &msTime); - FileSystem_getFileInfo(fullPath, &fileSize, &msTime); + char gtString[30]; - char gtString[30]; + Conversions_msTimeToGeneralizedTime(msTime, (uint8_t*) gtString); - Conversions_msTimeToGeneralizedTime(msTime, (uint8_t*) gtString); + int fileAttributesSize = encodeFileAttributes(0xa1, fileSize, gtString, NULL, 0); - int fileAttributesSize = encodeFileAttributes(0xa1, fileSize, gtString, NULL, 0); + int filenameSize = encodeFileSpecification(0xa0, directoryName, NULL, 0); - int filenameSize = encodeFileSpecification(0xa0, fileName, NULL, 0); + int dirEntrySize = 2 + fileAttributesSize + filenameSize; - int dirEntrySize = 2 + fileAttributesSize + filenameSize; + int overallEntrySize = 1 + BerEncoder_determineLengthSize(dirEntrySize) + dirEntrySize; - int overallEntrySize = 1 + BerEncoder_determineLengthSize(dirEntrySize) + dirEntrySize; + int bufferSpaceLeft = maxBufSize - bufPos; - int bufferSpaceLeft = maxSize - tempCurPos; + if (overallEntrySize > bufferSpaceLeft) { + *moreFollows = true; + break; + } - if (overallEntrySize > bufferSpaceLeft) { - moreFollows = true; - break; - } + bufPos = BerEncoder_encodeTL(0x30, dirEntrySize, buffer, bufPos); /* SEQUENCE (DirectoryEntry) */ + bufPos = encodeFileSpecification(0xa0, directoryName, buffer, bufPos); /* fileName */ + bufPos = encodeFileAttributes(0xa1, fileSize, gtString, buffer, bufPos); /* file attributes */ - tempCurPos = BerEncoder_encodeTL(0x30, dirEntrySize, buffer, tempCurPos); /* SEQUENCE (DirectoryEntry) */ - tempCurPos = encodeFileSpecification(0xa0, fileName, buffer, tempCurPos); /* fileName */ - tempCurPos = encodeFileAttributes(0xa1, fileSize, gtString, buffer, tempCurPos); /* file attributes */ + } } + fileName = FileSystem_readDirectory(directory, &isDirectory); } FileSystem_closeDirectory(directory); } - else { + + directoryName[directoryNameLength] = 0; + + return bufPos; +} + +static void +createFileDirectoryResponse(uint32_t invokeId, ByteBuffer* response, char* directoryName, char* continueAfterFileName) +{ + int maxSize = response->maxSize - 3; /* reserve space for moreFollows */ + uint8_t* buffer = response->buffer; + + bool moreFollows = false; + + int tempStartPos = 30; /* estimated header part with safety margin */ + int tempCurPos = tempStartPos; + int tempEncoded = 0; + + if (continueAfterFileName != NULL) { + if (strlen(continueAfterFileName) == 0) + continueAfterFileName = NULL; + } + + tempCurPos = addFileEntriesToResponse(buffer, tempCurPos, maxSize, directoryName, continueAfterFileName, &moreFollows); + + if (tempCurPos < 0) { + if (DEBUG_MMS_SERVER) - printf("Error opening directory!\n"); + printf("MMS_SERVER: Error opening directory!\n"); mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); @@ -608,7 +609,7 @@ mmsServer_handleFileRenameRequest( return; if (DEBUG_MMS_SERVER) - printf("currentFileName: (%s)\n", currentFileName); + printf("MMS_SERVER: currentFileName: (%s)\n", currentFileName); break; @@ -617,12 +618,12 @@ mmsServer_handleFileRenameRequest( return; if (DEBUG_MMS_SERVER) - printf("newFileName: (%s)\n", newFileName); + printf("MMS_SERVER: newFileName: (%s)\n", newFileName); break; default: /* ignore unknown tag */ if (DEBUG_MMS_SERVER) - printf("unknown tag: (%02x)\n", tag); + printf("MMS_SERVER: unknown tag: (%02x)\n", tag); bufPos += length; break; @@ -637,7 +638,7 @@ mmsServer_handleFileRenameRequest( else { if (DEBUG_MMS_SERVER) - printf("rename file failed!\n"); + printf("MMS_SERVER: rename file failed!\n"); mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_FILE_OTHER); } @@ -655,7 +656,7 @@ mmsServer_handleFileDirectoryRequest( ByteBuffer* response) { if (DEBUG_MMS_SERVER) - printf("handleFileDirectoryRequest bufPos:%i, maxBufPus:%i\n", bufPos, maxBufPos); + printf("MMS_SERVER: handleFileDirectoryRequest bufPos:%i, maxBufPus:%i\n", bufPos, maxBufPos); char filename[256] = ""; @@ -678,6 +679,11 @@ mmsServer_handleFileDirectoryRequest( case 0xa0: /* filename */ if (!parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response)) return; + + /* check for wildcard character(*) */ + if ((strcmp(filename, "*") == 0) || (strcmp(filename, "/") == 0) || (strcmp(filename, "\\") == 0)) + filename[0] = 0; + break; case 0xa1: /* continue-after */ @@ -690,7 +696,7 @@ mmsServer_handleFileDirectoryRequest( default: /* unrecognized parameter */ if (DEBUG_MMS_SERVER) - printf("handleFileDirectoryRequest: unrecognized parameter\n"); + printf("MMS_SERVER: handleFileDirectoryRequest: unrecognized parameter\n"); mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response); return; } diff --git a/src/vs/libiec61850-wo-goose.def b/src/vs/libiec61850-wo-goose.def index 09c2cdab..54cabdeb 100644 --- a/src/vs/libiec61850-wo-goose.def +++ b/src/vs/libiec61850-wo-goose.def @@ -492,4 +492,5 @@ EXPORTS IedModel_setIedNameForDynamicModel ControlObjectClient_useConstantT ControlObjectClient_setOrigin - + LogicalDevice_getChildByMmsVariableName + LogicalNode_getDataset diff --git a/src/vs/libiec61850.def b/src/vs/libiec61850.def index 9682ddad..73d532e7 100644 --- a/src/vs/libiec61850.def +++ b/src/vs/libiec61850.def @@ -516,3 +516,5 @@ EXPORTS IedModel_setIedNameForDynamicModel ControlObjectClient_useConstantT ControlObjectClient_setOrigin + LogicalDevice_getChildByMmsVariableName + LogicalNode_getDataset diff --git a/tools/model_generator/genconfig.jar b/tools/model_generator/genconfig.jar index 75df96c9..3a36f546 100644 Binary files a/tools/model_generator/genconfig.jar and b/tools/model_generator/genconfig.jar differ diff --git a/tools/model_generator/genmodel.jar b/tools/model_generator/genmodel.jar index 84d30c65..28621fac 100644 Binary files a/tools/model_generator/genmodel.jar and b/tools/model_generator/genmodel.jar differ diff --git a/tools/model_generator/src/com/libiec61850/scl/model/DataAttribute.java b/tools/model_generator/src/com/libiec61850/scl/model/DataAttribute.java index 573183f2..44193d78 100644 --- a/tools/model_generator/src/com/libiec61850/scl/model/DataAttribute.java +++ b/tools/model_generator/src/com/libiec61850/scl/model/DataAttribute.java @@ -62,6 +62,9 @@ public class DataAttribute implements DataModelNode { if (this.fc == null) this.fc = fc; + if (fc != null) + this.fc = fc; + if ((parent != null) && (parent instanceof DataAttribute)) this.triggerOptions = ((DataAttribute) parent).getTriggerOptions(); else diff --git a/tools/model_generator/src/com/libiec61850/scl/model/DataObject.java b/tools/model_generator/src/com/libiec61850/scl/model/DataObject.java index 13a373e0..7a861767 100644 --- a/tools/model_generator/src/com/libiec61850/scl/model/DataObject.java +++ b/tools/model_generator/src/com/libiec61850/scl/model/DataObject.java @@ -81,7 +81,16 @@ public class DataObject implements DataModelNode { daDefinitions = ((DataAttributeType) sclType).getSubDataAttributes(); for (DataAttributeDefinition daDefinition : daDefinitions) { + + if (daDefinition.getFc() == FunctionalConstraint.SE) { + + System.out.println("Add SG DA for corresponding SE DA: "); + this.dataAttributes.add(new DataAttribute(daDefinition, typeDeclarations, FunctionalConstraint.SG, this)); + } + this.dataAttributes.add(new DataAttribute(daDefinition, typeDeclarations, null, this)); + + } }