/* * beagle_demo.c * * This demo shows how to connect the libiec61850 server stack to a real device. * */ #include "iec61850_server.h" #include "iso_server.h" #include "acse.h" #include "hal_thread.h" #include #include #include #include #include "static_model.h" #include "beaglebone_leds.h" /* import IEC 61850 device model created from SCL-File */ extern IedModel iedModel; static int running = 0; static IedServer iedServer = NULL; static bool automaticOperationMode = true; static ClientConnection controllingClient = NULL; static uint32_t dpcState = 0; void sigint_handler(int signalId) { running = 0; } static void connectionIndicationHandler(IedServer server, ClientConnection connection, bool connected, void* parameter) { const char* clientAddress = ClientConnection_getPeerAddress(connection); if (connected) { printf("BeagleDemoServer: new client connection from %s\n", clientAddress); } else { printf("BeagleDemoServer: client connection from %s closed\n", clientAddress); if (controllingClient == connection) { printf("Controlling client has closed connection -> switch to automatic operation mode\n"); controllingClient = NULL; automaticOperationMode = true; } } } static CheckHandlerResult performCheckHandler(void* parameter, MmsValue* ctlVal, bool test, bool interlockCheck, ClientConnection connection) { if (controllingClient == NULL) { printf("Client takes control -> switch to remote control operation mode\n"); controllingClient = connection; automaticOperationMode = false; } /* test command not accepted if mode is "on" */ if (test) return CONTROL_TEMPORARILY_UNAVAILABLE; /* If there is already another client that controls the device reject the control attempt */ if (controllingClient == connection) return CONTROL_ACCEPTED; else return CONTROL_TEMPORARILY_UNAVAILABLE; } 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); } 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); } 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); } static ControlHandlerResult controlHandlerForBinaryOutput(void* parameter, MmsValue* value, bool test) { if (test) return CONTROL_RESULT_OK; uint64_t timeStamp = Hal_getTimeInMs(); bool newState = MmsValue_getBoolean(value); if (parameter == IEDMODEL_GenericIO_GGIO1_SPCSO1) updateLED1stVal(newState, timeStamp); if (parameter == IEDMODEL_GenericIO_GGIO1_SPCSO2) updateLED2stVal(newState, timeStamp); if (parameter == IEDMODEL_GenericIO_GGIO1_SPCSO3) updateLED3stVal(newState, timeStamp); if (parameter == IEDMODEL_GenericIO_GGIO1_DPCSO1) { /* example for Double Point Control - DPC */ dpcState = 0; /* DPC_STATE_INTERMEDIATE */ IedServer_updateBitStringAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_DPCSO1_stVal, dpcState); IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_DPCSO1_t, timeStamp); if (newState) { flashLED(LED4); Thread_sleep(3000); switchLED(LED4, 1); dpcState = 2; /* DPC_STATE_ON */ } else { flashLED(LED4); Thread_sleep(3000); switchLED(LED4, 0); dpcState = 1; /* DPC_STATE_OFF */ } IedServer_updateBitStringAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_DPCSO1_stVal, dpcState); IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_DPCSO1_t, timeStamp); } 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) { initLEDs(); iedServer = IedServer_create(&iedModel); /* Set control callback handlers */ IedServer_setConnectionIndicationHandler(iedServer, (IedConnectionIndicationHandler) connectionIndicationHandler, NULL); IedServer_setPerformCheckHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1, (ControlPerformCheckHandler) performCheckHandler, IEDMODEL_GenericIO_GGIO1_SPCSO1); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO1); IedServer_setPerformCheckHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2, (ControlPerformCheckHandler) performCheckHandler, IEDMODEL_GenericIO_GGIO1_SPCSO2); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO2); IedServer_setPerformCheckHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3, (ControlPerformCheckHandler) performCheckHandler, IEDMODEL_GenericIO_GGIO1_SPCSO3); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO3); IedServer_setPerformCheckHandler(iedServer, IEDMODEL_GenericIO_GGIO1_DPCSO1, (ControlPerformCheckHandler) performCheckHandler, IEDMODEL_GenericIO_GGIO1_DPCSO1); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_DPCSO1, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_DPCSO1); 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); if (!IedServer_isRunning(iedServer)) { printf("Starting server failed! Exit.\n"); IedServer_destroy(iedServer); exit(-1); } running = 1; signal(SIGINT, sigint_handler); float t = 0.f; bool ledStateValue = false; uint64_t nextLedToggleTime = Hal_getTimeInMs() + 1000; while (running) { uint64_t currentTime = Hal_getTimeInMs(); if (automaticOperationMode) { if (nextLedToggleTime <= currentTime) { 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); } } t += 0.1f; IedServer_lockDataModel(iedServer); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn1_mag_f, sinf(t)); IedServer_updateQuality(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn1_q, QUALITY_VALIDITY_GOOD); IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn1_t, currentTime); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn2_mag_f, sinf(t + 1.f)); IedServer_updateQuality(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn2_q, QUALITY_VALIDITY_GOOD); IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn2_t, currentTime); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn3_mag_f, sinf(t + 2.f)); IedServer_updateQuality(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn3_q, QUALITY_VALIDITY_GOOD); IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn3_t, currentTime); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn4_mag_f, sinf(t + 3.f)); IedServer_updateQuality(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn4_q, QUALITY_VALIDITY_GOOD); IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn4_t, currentTime); IedServer_unlockDataModel(iedServer); Thread_sleep(100); } /* stop MMS server - close TCP server socket and all client sockets */ IedServer_stop(iedServer); /* Cleanup - free all resources */ IedServer_destroy(iedServer); } /* main() */