int main(int argc, char** argv) { MmsValue* dataSetValues = MmsValue_createEmtpyArray(4); int i; for (i = 0; i < 4; i++) { MmsValue* dataSetEntry = MmsValue_newBoolean(false); MmsValue_setElement(dataSetValues, i, dataSetEntry); } // GooseSubscriber subscriber = GooseSubscriber_create("simpleIOGenericIO/LLN0$GO$gcbEvents", dataSetValues); GooseSubscriber subscriber = GooseSubscriber_create("simpleIOGenericIO/LLN0$GO$gcbAnalogValues", NULL); if (argc > 1) { printf("Set interface id: %s\n", argv[1]); GooseSubscriber_setInterfaceId(subscriber, argv[1]); } GooseSubscriber_setAppId(subscriber, 1000); GooseSubscriber_setListener(subscriber, gooseListener, NULL); GooseSubscriber_subscribe(subscriber); signal(SIGINT, sigint_handler); while (running) { Thread_sleep(100); } GooseSubscriber_destroy(subscriber); }
// only required for multi-threaded server! static void isoServerThread(void* isoServerParam) { IsoServer self = (IsoServer) isoServerParam; if (!setupIsoServer(self)) { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: starting server failed!\n"); goto cleanUp; } if (DEBUG_ISO_SERVER) printf("ISO_SERVER: isoServerThread %p started\n", &isoServerParam); while (self->state == ISO_SVR_STATE_RUNNING) { handleIsoConnections(self); Thread_sleep(1); } self->state = ISO_SVR_STATE_STOPPED; cleanUp: self->serverSocket = NULL; if (DEBUG_ISO_SERVER) printf("ISO_SERVER: isoServerThread %p stopped\n", &isoServerParam); }
static void singleThreadedServerThread(void* parameter) { IedServer self = (IedServer) parameter; MmsMapping* mmsMapping = self->mmsMapping; bool running = true; mmsMapping->reportThreadFinished = false; mmsMapping->reportThreadRunning = true; if (DEBUG_IED_SERVER) printf("IED_SERVER: server thread started!\n"); while (running) { MmsServer_handleIncomingMessages(self->mmsServer); IedServer_performPeriodicTasks(self); Thread_sleep(1); running = mmsMapping->reportThreadRunning; } if (DEBUG_IED_SERVER) printf("IED_SERVER: server thread finished!\n"); mmsMapping->reportThreadFinished = true; }
void IsoServer_startListening(IsoServer self) { if (self->state == ISO_SVR_STATE_RUNNING) { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: server already in RUNNING state!\n"); goto exit_function; } self->state = ISO_SVR_STATE_IDLE; self->serverThread = Thread_create((ThreadExecutionFunction) isoServerThread, self, false); Thread_start(self->serverThread); /* wait until server is up */ while (self->state == ISO_SVR_STATE_IDLE) Thread_sleep(1); if (DEBUG_ISO_SERVER) printf("ISO_SERVER: new iso server thread started\n"); exit_function: return; }
int main(int argc, char** argv) { IedServer iedServer = IedServer_create(&iedModel); /* Activate authentication */ AcseAuthenticationParameter auth = (AcseAuthenticationParameter) calloc(1, sizeof(struct sAcseAuthenticationParameter)); auth->mechanism = AUTH_PASSWORD; auth->value.password.string = "testpw"; IsoServer isoServer = IedServer_getIsoServer(iedServer); IsoServer_setAuthenticationParameter(isoServer, auth); /* MMS server will be instructed to start listening to client connections. */ IedServer_start(iedServer, 102); if (!IedServer_isRunning(iedServer)) { printf("Staring server failed! Exit.\n"); IedServer_destroy(iedServer); exit(-1); } running = 1; signal(SIGINT, sigint_handler); while (running) { Thread_sleep(1); } /* stop MMS server - close TCP server socket and all client sockets */ IedServer_stop(iedServer); /* Cleanup - free all resources */ IedServer_destroy(iedServer); } /* main() */
void GooseReceiver_stop(GooseReceiver self) { self->running = false; while (self->stopped == false) Thread_sleep(1); }
void MmsServer_lockModel(MmsServer self) { while (MmsServer_isLocked(self)) Thread_sleep(1); self->isLocked = true; }
void Socket_destroy(Socket socket) { closeAndShutdownSocket(socket->fd); /* Wait for other threads to realize that the socket has been closed */ Thread_sleep(100); free(socket); }
int main(int argc, char** argv) { iedServer = IedServer_create(&iedModel); /* MMS server will be instructed to start listening to client connections. */ IedServer_start(iedServer, 102); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO1); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO2); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO3); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO4, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO4); if (!IedServer_isRunning(iedServer)) { printf("Starting server failed! Exit.\n"); IedServer_destroy(iedServer); exit(-1); } /* Start GOOSE publishing */ IedServer_enableGoosePublishing(iedServer); running = 1; signal(SIGINT, sigint_handler); float anIn1 = 0.f; while (running) { IedServer_lockDataModel(iedServer); IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn1_t, Hal_getTimeInMs()); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn1_mag_f, anIn1); IedServer_unlockDataModel(iedServer); anIn1 += 0.1; Thread_sleep(1000); } /* stop MMS server - close TCP server socket and all client sockets */ IedServer_stop(iedServer); /* Cleanup - free all resources */ IedServer_destroy(iedServer); } /* main() */
void Socket_destroy(Socket self) { int fd = self->fd; self->fd = -1; closeAndShutdownSocket(fd); Thread_sleep(10); free(self); }
void Socket_destroy(Socket self) { int fd = self->fd; self->fd = -1; closeAndShutdownSocket(fd); Thread_sleep(10); GLOBAL_FREEMEM(self); }
void IsoServer_startListening(IsoServer self) { self->serverThread = Thread_create((ThreadExecutionFunction) isoServerThread, self, false); Thread_start(self->serverThread); /* wait until server is up */ while (self->state == ISO_SVR_STATE_IDLE) Thread_sleep(1); if (DEBUG_ISO_SERVER) printf("ISO_SERVER: new iso server thread started\n"); }
int main(int argc, char** argv) { IedServer iedServer = IedServer_create(&staticIedModel); /* This will create default values for the complete IEC model and installs them in the * MMS server's value cache. */ IedServer_setAllModelDefaultValues(iedServer); /* Get the MMS domain for an IEC 61850 Logical Device */ MmsDomain* sampleDevice = IedServer_getDomain(iedServer, "SampleIEDDevice1"); /* Get the reference to the structured value object */ MmsValue* totW = IedServer_getValue(iedServer, sampleDevice, "MMXU2$MX$TotW"); /* get references to the relevant elements of the copy */ MmsValue* totW_mag_f = MmsValue_getStructElementByIndex(MmsValue_getStructElementByIndex(totW, 0), 0); MmsValue* totW_t = MmsValue_getStructElementByIndex(totW, 2); /* MMS server will be instructed to start listening to client connections. */ IedServer_start(iedServer); running = 1; signal(SIGINT, sigint_handler); float totW_value = 0.f; while (running) { /* Lock the data model - access from MMS Clients will be blocked */ IedServer_lockDataModel(iedServer); /* Update measurement values */ MmsValue_setFloat(totW_mag_f, totW_value); MmsValue_setUtcTime(totW_t, time(NULL)); /* Unlock the data model - access from MMS clients will be processed */ IedServer_unlockDataModel(iedServer); totW_value += 0.1f; Thread_sleep(1000); } /* stop MMS server - close TCP server socket and all client sockets */ IedServer_stop(iedServer); /* Cleanup - free all resources */ IedServer_destroy(iedServer); } /* main() */
int main(int argc, char** argv) { IedServer iedServer = IedServer_create(&iedModel); // TODO get stored values from persistent storage // TODO set initial measurement and status values from process /* 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 power = 500.f; while (running) { uint64_t timeval = Hal_getTimeInMs(); IedServer_lockDataModel(iedServer); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_Inverter_MMXU1_TotW_mag_f, power); IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_Inverter_MMXU1_TotW_t, timeval); IedServer_unlockDataModel(iedServer); power += 0.1f; Thread_sleep(500); } /* stop MMS server - close TCP server socket and all client sockets */ IedServer_stop(iedServer); /* Cleanup - free all resources */ IedServer_destroy(iedServer); return 0; } /* main() */
int main(int argc, char** argv) { iedServer = IedServer_create(&iedModel); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1, (ControlHandler) controlHandler, IEDMODEL_GenericIO_GGIO1_SPCSO1); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2, (ControlHandler) controlHandler, IEDMODEL_GenericIO_GGIO1_SPCSO2); /* this is optional - performs operative checks */ IedServer_setPerformCheckHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2, checkHandler, IEDMODEL_GenericIO_GGIO1_SPCSO2); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3, (ControlHandler) controlHandler, IEDMODEL_GenericIO_GGIO1_SPCSO3); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO4, (ControlHandler) controlHandler, IEDMODEL_GenericIO_GGIO1_SPCSO4); /* this is optional - performs operative checks */ IedServer_setPerformCheckHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO4, checkHandler, IEDMODEL_GenericIO_GGIO1_SPCSO4); /* 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); while (running) { Thread_sleep(1); } /* stop MMS server - close TCP server socket and all client sockets */ IedServer_stop(iedServer); /* Cleanup - free all resources */ IedServer_destroy(iedServer); } /* main() */
void IsoServer_stopListening(IsoServer self) { stopListening(self); if (self->serverThread != NULL) Thread_destroy(self->serverThread); closeAllOpenClientConnections(self); /* Wait for connection threads to finish */ while (private_IsoServer_getConnectionCounter(self) > 0) Thread_sleep(10); if (DEBUG_ISO_SERVER) printf("ISO_SERVER: IsoServer_stopListening finished!\n"); }
int main(int argc, char** argv) { MmsConnection con = MmsConnection_create(); MmsError mmsError; if (MmsConnection_connect(con, &mmsError, "localhost", 102)) { // add application code here Thread_sleep(1000); printf("Send abort\n"); MmsConnection_abort(con, &mmsError); } else printf("Connect to server failed!\n"); MmsConnection_destroy(con); }
static void gooseReceiverLoop(void* threadParameter) { GooseReceiver self = (GooseReceiver) threadParameter; self->running = true; self->stopped = false; GooseReceiver_startThreadless(self); while (self->running) { if (GooseReceiver_tick(self) == false) Thread_sleep(1); } GooseReceiver_stopThreadless(self); self->stopped = true; }
int main(int argc, char** argv) { int tcpPort = 102; if (argc > 1) { tcpPort = atoi(argv[1]); } iedServer = IedServer_create(&iedModel); /* set control model for WTUR1.SetTurOp.actSt to direct-control-with-normal-security */ IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_WTG_WTUR1_SetTurOp_actSt_ctlModel, 1); IedServer_setControlHandler(iedServer, IEDMODEL_WTG_WTUR1_SetTurOp_actSt, (ControlHandler) controlHandlerForIntegerOutput, IEDMODEL_WTG_WTUR1_SetTurOp_actSt); /* MMS server will be instructed to start listening to client connections. */ IedServer_start(iedServer, tcpPort); if (!IedServer_isRunning(iedServer)) { printf("Starting server failed! Exit.\n"); IedServer_destroy(iedServer); exit(-1); } running = 1; signal(SIGINT, sigint_handler); while (running) { Thread_sleep(1); } /* stop MMS server - close TCP server socket and all client sockets */ IedServer_stop(iedServer); /* Cleanup - free all resources */ IedServer_destroy(iedServer); } /* main() */
// has to be executed as root! int main(int argc, char** argv) { LinkedList dataSetValues = LinkedList_create(); LinkedList_add(dataSetValues, MmsValue_newIntegerFromInt32(1234)); LinkedList_add(dataSetValues, MmsValue_newBinaryTime(false)); LinkedList_add(dataSetValues, MmsValue_newIntegerFromInt32(5678)); CommParameters gooseCommParameters; gooseCommParameters.appId = 1000; gooseCommParameters.dstAddress[0] = 0x01; gooseCommParameters.dstAddress[1] = 0x0c; gooseCommParameters.dstAddress[2] = 0xcd; gooseCommParameters.dstAddress[3] = 0x01; gooseCommParameters.dstAddress[4] = 0x00; gooseCommParameters.dstAddress[5] = 0x01; gooseCommParameters.vlanId = 0; gooseCommParameters.vlanPriority = 4; GoosePublisher publisher = GoosePublisher_create(&gooseCommParameters, "eth0"); GoosePublisher_setGoCbRef(publisher, "simpleIOGenericIO/LLN0$GO$gcbAnalogValues"); GoosePublisher_setConfRev(publisher, 1); GoosePublisher_setDataSetRef(publisher, "simpleIOGenericIO/LLN0$AnalogValues"); int i = 0; for (i = 0; i < 3; i++) { Thread_sleep(1000); if (GoosePublisher_publish(publisher, dataSetValues) == -1) { printf("Error sending message!\n"); } } GoosePublisher_destroy(publisher); }
int main(int argc, char** argv) { iedServer = IedServer_create(&iedModel); /* MMS server will be instructed to start listening to client connections. */ IedServer_start(iedServer, 102); /* Instruct the server that we will be informed if a clients writes to a * certain variables we are interested in. */ IedServer_observeDataAttribute(iedServer, IEDMODEL_GenericIO_GGIO1_NamPlt_vendor, observerCallback); IedServer_observeDataAttribute(iedServer, IEDMODEL_GenericIO_GGIO1_NamPlt_swRev, observerCallback); if (!IedServer_isRunning(iedServer)) { printf("Starting server failed! Exit.\n"); IedServer_destroy(iedServer); exit(-1); } running = 1; signal(SIGINT, sigint_handler); while (running) { Thread_sleep(1); } /* stop MMS server - close TCP server socket and all client sockets */ IedServer_stop(iedServer); /* Cleanup - free all resources */ IedServer_destroy(iedServer); } /* main() */
int main(int argc, char** argv) { char* hostname; int tcpPort = 102; if (argc > 1) hostname = argv[1]; else hostname = "localhost"; if (argc > 2) tcpPort = atoi(argv[2]); IedClientError error; IedConnection con = IedConnection_create(); IedConnection_connect(con, &error, hostname, tcpPort); if (error == IED_ERROR_OK) { /* read an analog measurement value from server */ MmsValue* value = IedConnection_readObject(con, &error, "simpleIOGenericIO/GGIO1.AnIn1.mag.f", MX); if (value != NULL) { float fval = MmsValue_toFloat(value); printf("read float value: %f\n", fval); MmsValue_delete(value); } /* write a variable to the server */ value = MmsValue_newVisibleString("libiec61850.com"); IedConnection_writeObject(con, &error, "simpleIOGenericIO/GGIO1.NamPlt.vendor", DC, value); if (error != IED_ERROR_OK) printf("failed to write simpleIOGenericIO/GGIO1.NamPlt.vendor!\n"); MmsValue_delete(value); /* read data set */ ClientDataSet clientDataSet; clientDataSet = IedConnection_getDataSet(con, &error, "simpleIOGenericIO/LLN0.Events", NULL); if (clientDataSet == NULL) printf("failed to read dataset\n"); printDataSetValues(ClientDataSet_getDataSetValues(clientDataSet)); IedConnection_enableReporting(con, &error, "simpleIOGenericIO/LLN0.RP.EventsRCB", clientDataSet, TRG_OPT_DATA_UPDATE | TRG_OPT_INTEGRITY, reportCallbackFunction, ClientDataSet_getDataSetValues( clientDataSet)); Thread_sleep(5000); IedConnection_disableReporting(con, &error, "simpleIOGenericIO/LLN0.RP.EventsRCB"); IedConnection_close(con); } IedConnection_destroy(con); printf("I've done all work. Press anykey..."); getche(); }
/* * ======== Hello_start ======== * * 1. create semaphore object * 2. register notify callback * 3. wait until remote core has also registered notify callback * 4. create local & shared resources * 5. send resource ready event * 6. wait for remote resource ready event * 7. open remote resources * 8. handshake the ready event */ Int Hello_start(UInt16 remoteProcId) { Int status; UInt32 event; SemThread_Params semParams; HeapBufMP_Params heapParams; Error_Block eb; Error_init(&eb); Module.remoteProcId = remoteProcId; /* * 1. create semaphore object */ SemThread_Params_init(&semParams); semParams.mode = SemThread_Mode_COUNTING; SemThread_construct(&Module.semS, 0, &semParams, &eb); if (Error_check(&eb)) { status = -15; goto leave; } Module.semH = SemThread_handle(&Module.semS); /* * 2. register notify callback */ status = Notify_registerEventSingle(Module.remoteProcId, Module.lineId, Module.eventId, Hello_notifyCB, (UArg)&Module); if (status < 0) { goto leave; } /* * 3. wait until remote core has also registered notify callback */ do { status = Notify_sendEvent(Module.remoteProcId, Module.lineId, Module.eventId, App_CMD_NOP, TRUE); if (status == Notify_E_EVTNOTREGISTERED) { Thread_sleep(1000, &eb); /* microseconds */ } } while (status == Notify_E_EVTNOTREGISTERED); if (status < 0) { goto leave; } /* * 4. create local & shared resources (to be opened by remote processor) */ /* create heap for rcm messages */ HeapBufMP_Params_init(&heapParams); heapParams.name = Global_RcmClientHeapName; heapParams.regionId = 0; heapParams.blockSize = 0x200; /* 512 B */ heapParams.numBlocks = 8; Module.msgHeap = HeapBufMP_create(&heapParams); if (Module.msgHeap == NULL) { Log_error0("Hello_start: HeapBuf_create() failed"); status = -1; goto leave; } /* register heap with MessageQ */ status = MessageQ_registerHeap((Ptr)(Module.msgHeap), Global_RcmClientHeapId); if (status < 0) { goto leave; } /* * 5. send resource ready event */ status = Notify_sendEvent(Module.remoteProcId, Module.lineId, Module.eventId, App_CMD_RESRDY, TRUE); if (status < 0) { goto leave; } /* * 6. wait for remote resource ready event */ do { event = Hello_waitForEvent(); if (event >= App_E_FAILURE) { status = -1; goto leave; } } while (event != App_CMD_RESRDY); /* * 7. open remote resources */ /* * 8. handshake the ready event */ status = Notify_sendEvent(Module.remoteProcId, Module.lineId, Module.eventId, App_CMD_READY, TRUE); if (status < 0) { goto leave; } do { event = Hello_waitForEvent(); if (event >= App_E_FAILURE) { status = -1; goto leave; } } while (event != App_CMD_READY); leave: return(status); }
static void handleTcpConnection(IsoConnection self) { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: connection %p started\n", self); CotpIndication cotpIndication; IsoSessionIndication sIndication; AcseIndication aIndication; AcseConnection acseConnection; ByteBuffer receiveBuffer; self->cotpConnection = (CotpConnection*) calloc(1, sizeof(CotpConnection)); CotpConnection_init(self->cotpConnection, self->socket, &receiveBuffer); self->session = (IsoSession*) calloc(1, sizeof(IsoSession)); IsoSession_init(self->session); self->presentation = (IsoPresentation*) calloc(1, sizeof(IsoPresentation)); IsoPresentation_init(self->presentation); AcseConnection_init(&acseConnection, IsoServer_getAuthenticator(self->isoServer), IsoServer_getAuthenticatorParameter(self->isoServer)); while (self->msgRcvdHandlerParameter == NULL) Thread_sleep(1); if (DEBUG_ISO_SERVER) printf("ISO_SERVER: IsoConnection: Start to handle connection for client %s\n", self->clientAddress); while (self->state == ISO_CON_STATE_RUNNING) { ByteBuffer_wrap(&receiveBuffer, self->receiveBuffer, 0, RECEIVE_BUF_SIZE); cotpIndication = CotpConnection_parseIncomingMessage(self->cotpConnection); switch (cotpIndication) { case CONNECT_INDICATION: if (DEBUG_ISO_SERVER) printf("ISO_SERVER: COTP connection indication\n"); Semaphore_wait(self->conMutex); CotpConnection_sendConnectionResponseMessage(self->cotpConnection); Semaphore_post(self->conMutex); break; case DATA_INDICATION: { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: COTP data indication\n"); ByteBuffer* cotpPayload = CotpConnection_getPayload(self->cotpConnection); sIndication = IsoSession_parseMessage(self->session, cotpPayload); ByteBuffer* sessionUserData = IsoSession_getUserData(self->session); switch (sIndication) { case SESSION_CONNECT: if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: session connect indication\n"); if (IsoPresentation_parseConnect(self->presentation, sessionUserData)) { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: presentation ok\n"); ByteBuffer* acseBuffer = &(self->presentation->nextPayload); aIndication = AcseConnection_parseMessage(&acseConnection, acseBuffer); self->securityToken = acseConnection.securityToken; if (aIndication == ACSE_ASSOCIATE) { Semaphore_wait(self->conMutex); if (DEBUG_ISO_SERVER) printf("ISO_SERVER: cotp_server: acse associate\n"); ByteBuffer mmsRequest; ByteBuffer_wrap(&mmsRequest, acseConnection.userDataBuffer, acseConnection.userDataBufferSize, acseConnection.userDataBufferSize); ByteBuffer mmsResponseBuffer; /* new */ ByteBuffer_wrap(&mmsResponseBuffer, self->sendBuffer, 0, SEND_BUF_SIZE); self->msgRcvdHandler(self->msgRcvdHandlerParameter, &mmsRequest, &mmsResponseBuffer); struct sBufferChain mmsBufferPartStruct; BufferChain mmsBufferPart = &mmsBufferPartStruct; BufferChain_init(mmsBufferPart, mmsResponseBuffer.size, mmsResponseBuffer.size, NULL, self->sendBuffer); if (mmsResponseBuffer.size > 0) { if (DEBUG_ISO_SERVER) printf("iso_connection: application payload size: %i\n", mmsResponseBuffer.size); struct sBufferChain acseBufferPartStruct; BufferChain acseBufferPart = &acseBufferPartStruct; acseBufferPart->buffer = self->sendBuffer + mmsBufferPart->length; acseBufferPart->partMaxLength = SEND_BUF_SIZE - mmsBufferPart->length; AcseConnection_createAssociateResponseMessage(&acseConnection, ACSE_RESULT_ACCEPT, acseBufferPart, mmsBufferPart); struct sBufferChain presentationBufferPartStruct; BufferChain presentationBufferPart = &presentationBufferPartStruct; presentationBufferPart->buffer = self->sendBuffer + acseBufferPart->length; presentationBufferPart->partMaxLength = SEND_BUF_SIZE - acseBufferPart->length; IsoPresentation_createCpaMessage(self->presentation, presentationBufferPart, acseBufferPart); struct sBufferChain sessionBufferPartStruct; BufferChain sessionBufferPart = &sessionBufferPartStruct; sessionBufferPart->buffer = self->sendBuffer + presentationBufferPart->length; sessionBufferPart->partMaxLength = SEND_BUF_SIZE - presentationBufferPart->length; IsoSession_createAcceptSpdu(self->session, sessionBufferPart, presentationBufferPart); CotpConnection_sendDataMessage(self->cotpConnection, sessionBufferPart); } else { if (DEBUG_ISO_SERVER) printf( "ISO_SERVER: iso_connection: association error. No response from application!\n"); } Semaphore_post(self->conMutex); } else { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: acse association failed\n"); self->state = ISO_CON_STATE_STOPPED; } } break; case SESSION_DATA: if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: session data indication\n"); if (!IsoPresentation_parseUserData(self->presentation, sessionUserData)) { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: cotp_server: presentation error\n"); self->state = ISO_CON_STATE_STOPPED; break; } if (self->presentation->nextContextId == self->presentation->mmsContextId) { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: mms message\n"); ByteBuffer* mmsRequest = &(self->presentation->nextPayload); ByteBuffer mmsResponseBuffer; IsoServer_userLock(self->isoServer); Semaphore_wait(self->conMutex); ByteBuffer_wrap(&mmsResponseBuffer, self->sendBuffer, 0, SEND_BUF_SIZE); self->msgRcvdHandler(self->msgRcvdHandlerParameter, mmsRequest, &mmsResponseBuffer); if (mmsResponseBuffer.size > 0) { struct sBufferChain mmsBufferPartStruct; BufferChain mmsBufferPart = &mmsBufferPartStruct; BufferChain_init(mmsBufferPart, mmsResponseBuffer.size, mmsResponseBuffer.size, NULL, self->sendBuffer); struct sBufferChain presentationBufferPartStruct; BufferChain presentationBufferPart = &presentationBufferPartStruct; presentationBufferPart->buffer = self->sendBuffer + mmsBufferPart->length; presentationBufferPart->partMaxLength = SEND_BUF_SIZE - mmsBufferPart->length; IsoPresentation_createUserData(self->presentation, presentationBufferPart, mmsBufferPart); struct sBufferChain sessionBufferPartStruct; BufferChain sessionBufferPart = &sessionBufferPartStruct; sessionBufferPart->buffer = self->sendBuffer + presentationBufferPart->length; sessionBufferPart->partMaxLength = SEND_BUF_SIZE - presentationBufferPart->length; IsoSession_createDataSpdu(self->session, sessionBufferPart, presentationBufferPart); CotpConnection_sendDataMessage(self->cotpConnection, sessionBufferPart); } Semaphore_post(self->conMutex); IsoServer_userUnlock(self->isoServer); } else { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: unknown presentation layer context!"); } break; case SESSION_FINISH: if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: session finish indication\n"); if (IsoPresentation_parseUserData(self->presentation, sessionUserData)) { if (DEBUG_ISO_SERVER) printf("ISO_SERVER: iso_connection: presentation ok\n"); struct sBufferChain acseBufferPartStruct; BufferChain acseBufferPart = &acseBufferPartStruct; acseBufferPart->buffer = self->sendBuffer; acseBufferPart->partMaxLength = SEND_BUF_SIZE; AcseConnection_createReleaseResponseMessage(&acseConnection, acseBufferPart); struct sBufferChain presentationBufferPartStruct; BufferChain presentationBufferPart = &presentationBufferPartStruct; presentationBufferPart->buffer = self->sendBuffer + acseBufferPart->length; presentationBufferPart->partMaxLength = SEND_BUF_SIZE - acseBufferPart->length; IsoPresentation_createUserDataACSE(self->presentation, presentationBufferPart, acseBufferPart); struct sBufferChain sessionBufferPartStruct; BufferChain sessionBufferPart = &sessionBufferPartStruct; sessionBufferPart->buffer = self->sendBuffer + presentationBufferPart->length; sessionBufferPart->partMaxLength = SEND_BUF_SIZE - presentationBufferPart->length; IsoSession_createDisconnectSpdu(self->session, sessionBufferPart, presentationBufferPart); CotpConnection_sendDataMessage(self->cotpConnection, sessionBufferPart); } //TODO else send ABORT message break; case SESSION_ABORT: self->state = ISO_CON_STATE_STOPPED; break; case SESSION_ERROR: self->state = ISO_CON_STATE_STOPPED; break; default: /* illegal state */ self->state = ISO_CON_STATE_STOPPED; break; } } break; case ERROR: if (DEBUG_ISO_SERVER) printf("ISO_SERVER: Connection closed\n"); self->state = ISO_CON_STATE_STOPPED; break; default: if (DEBUG_ISO_SERVER) printf("ISO_SERVER: COTP Unknown Indication: %i\n", cotpIndication); self->state = ISO_CON_STATE_STOPPED; break; } } IsoServer_closeConnection(self->isoServer, self); if (self->socket != NULL) Socket_destroy(self->socket); free(self->session); free(self->presentation); AcseConnection_destroy(&acseConnection); CotpConnection_destroy(self->cotpConnection); free(self->cotpConnection); Semaphore_destroy(self->conMutex); free(self->receiveBuffer); free(self->sendBuffer); free(self->clientAddress); IsoServer isoServer = self->isoServer; free(self); if (DEBUG_ISO_SERVER) printf("ISO_SERVER: connection %p closed\n", self); private_IsoServer_decreaseConnectionCounter(isoServer); }
static void handleTcpConnection(IsoConnection self) { CotpIndication cotpIndication; CotpConnection cotpConnection; IsoSessionIndication sIndication; IsoSession session; IsoPresentation presentation; IsoPresentationIndication pIndication; AcseIndication aIndication; AcseConnection acseConnection; ByteBuffer receiveBuffer; ByteBuffer responseBuffer1; ByteBuffer responseBuffer2; CotpConnection_init(&cotpConnection, self->socket, &receiveBuffer); IsoSession_init(&session); IsoPresentation_init(&presentation); AcseConnection_init(&acseConnection); AcseConnection_setAuthenticationParameter(&acseConnection, IsoServer_getAuthenticationParameter(self->isoServer)); while (self->msgRcvdHandlerParameter == NULL) Thread_sleep(1); printf("IsoConnection: state = RUNNING. Start to handle connection\n"); while (self->state == ISO_CON_STATE_RUNNING) { ByteBuffer_wrap(&receiveBuffer, self->receive_buf, 0, RECEIVE_BUF_SIZE); ByteBuffer_wrap(&responseBuffer1, self->send_buf_1, 0, SEND_BUF_SIZE); ByteBuffer_wrap(&responseBuffer2, self->send_buf_2, 0, SEND_BUF_SIZE); cotpIndication = CotpConnection_parseIncomingMessage(&cotpConnection); switch (cotpIndication) { case CONNECT_INDICATION: if (DEBUG) printf("COTP connection indication\n"); CotpConnection_sendConnectionResponseMessage(&cotpConnection); break; case DATA_INDICATION: if (DEBUG) printf("COTP data indication\n"); ByteBuffer* cotpPayload = CotpConnection_getPayload(&cotpConnection); sIndication = IsoSession_parseMessage(&session, cotpPayload); ByteBuffer* sessionUserData = IsoSession_getUserData(&session); switch (sIndication) { case SESSION_CONNECT: if (DEBUG) printf("cotp_server: session connect indication\n"); pIndication = IsoPresentation_parseConnect(&presentation, sessionUserData); if (pIndication == PRESENTATION_OK) { if (DEBUG) printf("cotp_server: presentation ok\n"); ByteBuffer* acseBuffer = &(presentation.nextPayload); aIndication = AcseConnection_parseMessage(&acseConnection, acseBuffer); if (aIndication == ACSE_ASSOCIATE) { if (DEBUG) printf("cotp_server: acse associate\n"); ByteBuffer mmsRequest; ByteBuffer_wrap(&mmsRequest, acseConnection.userDataBuffer, acseConnection.userDataBufferSize, acseConnection.userDataBufferSize); self->msgRcvdHandler(self->msgRcvdHandlerParameter, &mmsRequest, &responseBuffer1); if (responseBuffer1.size > 0) { if (DEBUG) printf("cotp_server: application payload size: %i\n", responseBuffer1.size); AcseConnection_createAssociateResponseMessage(&acseConnection, &responseBuffer2, &responseBuffer1); responseBuffer1.size = 0; IsoPresentation_createCpaMessage(&presentation, &responseBuffer1, &responseBuffer2); responseBuffer2.size = 0; IsoSession_createAcceptSpdu(&session, &responseBuffer2, responseBuffer1.size); ByteBuffer_append(&responseBuffer2, responseBuffer1.buffer, responseBuffer1.size); CotpConnection_sendDataMessage(&cotpConnection, &responseBuffer2); break; } else { if (DEBUG) printf("cotp_server: association error. No response from application!\n"); } } else { if (DEBUG) printf("cotp_server: acse association failed\n"); self->state = ISO_CON_STATE_STOPPED; } } break; case SESSION_DATA: if (DEBUG) printf("cotp_server: session data indication\n"); pIndication = IsoPresentation_parseUserData(&presentation, sessionUserData); if (pIndication == PRESENTATION_ERROR) { if (DEBUG) printf("cotp_server: presentation error\n"); self->state = ISO_CON_STATE_STOPPED; break; } if (presentation.nextContextId == 3) { if (DEBUG) printf("cotp_server: mms message\n"); ByteBuffer* mmsRequest = &(presentation.nextPayload); self->msgRcvdHandler(self->msgRcvdHandlerParameter, mmsRequest, &responseBuffer1); IsoPresentation_createUserData(&presentation, &responseBuffer2, &responseBuffer1); responseBuffer1.size = 0; IsoSession_createDataSpdu(&session, &responseBuffer1); ByteBuffer_append(&responseBuffer1, responseBuffer2.buffer, responseBuffer2.size); CotpConnection_sendDataMessage(&cotpConnection, &responseBuffer1); } break; case SESSION_ERROR: self->state = ISO_CON_STATE_STOPPED; break; } break; case ERROR: if (DEBUG) printf("COTP protocol error\n"); self->state = ISO_CON_STATE_STOPPED; break; default: if (DEBUG) printf("COTP Unknown Indication: %i\n", cotpIndication); self->state = ISO_CON_STATE_STOPPED; break; } } Socket_destroy(self->socket); //if (DEBUG) printf("IsoConnection: connection closed!\n"); AcseConnection_destroy(&acseConnection); IsoServer_closeConnection(self->isoServer, self); CotpConnection_destroy(&cotpConnection); }
int main(int argc, char** argv) { iedServer = IedServer_create(&iedModel); /* Install handler for operate command */ IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO1); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO2); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO3); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO4, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO4); /* MMS server will be instructed to start listening to client connections. */ IedServer_startThreadless(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; uint64_t lastTimestamp = Hal_getTimeInMs(); while (running) { uint64_t timestamp = Hal_getTimeInMs(); if (timestamp - lastTimestamp >= 100) { t += 0.1f; float an1 = sinf(t); float an2 = sinf(t + 1.f); float an3 = sinf(t + 2.f); float an4 = sinf(t + 3.f); IedServer_lockDataModel(iedServer); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn1_mag_f, an1); IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn1_t, timestamp); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn2_mag_f, an2); IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn2_t, timestamp); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn3_mag_f, an3); IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn3_t, timestamp); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn4_mag_f, an4); IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn4_t, timestamp); IedServer_unlockDataModel(iedServer); lastTimestamp = timestamp; } /* Has to be called whenever the TCP stack receives data */ IedServer_processIncomingData(iedServer); /* Has to be called periodically */ IedServer_performPeriodicTasks(iedServer); Thread_sleep(1); } /* stop MMS server - close TCP server socket and all client sockets */ IedServer_stopThreadless(iedServer); /* Cleanup - free all resources */ IedServer_destroy(iedServer); } /* main() */
Int SystemCfg_createLocalResources(Void) { Error_Block eb; SemThread_Params semThreadP; HeapBufMP_Params heapBufMPP; Int count; Char heapName[32]; Int status = 0; struct SystemCfg *stateObj = &SystemCfg_State; static Int heapId = 1; Log_print1(Diags_ENTRY, "--> %s: ()", (IArg)FXNN); Error_init(&eb); /* create sync object used to wait on remote core startup */ SemThread_Params_init(&semThreadP); semThreadP.mode = SemThread_Mode_COUNTING; SemThread_construct(&stateObj->semObj, 0, &semThreadP, &eb); if (Error_check(&eb)) { /* Log_error() */ Log_print3(Diags_USER8, "Error: %s, line %d: %s: SemThread_construct() failed", (IArg)__FILE__, (IArg)__LINE__, (IArg)FXNN); status = -1; goto leave; } stateObj->semH = SemThread_handle(&stateObj->semObj); /* register notify callback for ready event from remote core */ status = Notify_registerEvent(stateObj->hostProcId, Global_NotifyLineId, Global_HostDspEvtNum, SystemCfg_notifyCB__P, (UArg)stateObj); if (status < 0) { /* Log_error() */ Log_print4(Diags_USER8, "Error: %s, line %d: %s: " "Notify_registerEventSingle() returned error %d", (IArg)__FILE__, (IArg)__LINE__, (IArg)FXNN, (IArg)status); goto leave; } /* create a heap for tiler usage */ Log_print0(Diags_USER2, FXNN": HeapBufMP_create for tiler"); HeapBufMP_Params_init(&heapBufMPP); heapBufMPP.regionId = 0; heapBufMPP.blockSize = 0x200; /* 512 B */ heapBufMPP.numBlocks = 8; /* hack: make a unique heap name */ System_sprintf(heapName, "rcmHeap-%d", heapId); heapBufMPP.name = heapName; stateObj->heapH = HeapBufMP_create(&heapBufMPP); if (stateObj->heapH == NULL) { /* Log_error() */ Log_print3(Diags_USER8, "Error: %s, line %d: %s: HeapBuf_create() failed", (IArg)FXNN, (IArg)__FILE__, (IArg)__LINE__); status = -1; goto leave; } /* register this heap with MessageQ */ Log_print2(Diags_USER2, FXNN": MessageQ_registerHeap: (heapH: 0x%x, heapId: %d)", (IArg)(stateObj->heapH), (IArg)Global_TilerHeapId); MessageQ_registerHeap((Ptr)(stateObj->heapH), Global_TilerHeapId); /* Send create done event to remote core. Need to loop in case * the remote core has not yet registered with notify to receive * this event. */ Log_print0(Diags_USER1, FXNN": send EvtCreateDone to remote core"); count = 0; do { status = Notify_sendEvent(stateObj->hostProcId, Global_NotifyLineId, Global_HostDspEvtNum, Global_EvtCreateDone, TRUE); if (status == Notify_E_EVTNOTREGISTERED) { Thread_sleep(500, &eb); /* 0.5 ms */ } } while ((++count < 10) && (status == Notify_E_EVTNOTREGISTERED)); if (status < 0) { /* Log_error() */ Log_print5(Diags_USER8, "Error: %s, line %d: %s: Notify_sendEvent() returned error %d," "giving up after %d tries", (IArg)__FILE__, (IArg)__LINE__, (IArg)FXNN, (IArg)status, (IArg)count); goto leave; } /* wait for create done event from remote core */ Log_print0(Diags_USER1, FXNN": waiting for EvtCreateDone event..."); SemThread_pend(stateObj->semH, SemThread_FOREVER, &eb); if (Error_check(&eb)) { /* Log_error() */ Log_print3(Diags_USER8, "Error: %s, line %d: %s: SemThread_pend() returned with error", (IArg)__FILE__, (IArg)__LINE__, (IArg)FXNN); status = -1; goto leave; } Log_print0(Diags_USER1, FXNN": ...received EvtCreatDone event"); leave: Log_print2(Diags_EXIT, "<-- %s: %d", (IArg)FXNN, (IArg)status); return(status); }
int main(int argc, char** argv) { printf("Using libIEC61850 version %s\n", LibIEC61850_getVersionString()); iedServer = IedServer_create(&iedModel); /* Install handler for operate command */ IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO1); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO2); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO3); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO4, (ControlHandler) controlHandlerForBinaryOutput, IEDMODEL_GenericIO_GGIO1_SPCSO4); IedServer_setConnectionIndicationHandler(iedServer, (IedConnectionIndicationHandler) connectionHandler, 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; while (running) { uint64_t timestamp = Hal_getTimeInMs(); t += 0.1f; float an1 = sinf(t); float an2 = sinf(t + 1.f); float an3 = sinf(t + 2.f); float an4 = sinf(t + 3.f); IedServer_lockDataModel(iedServer); Timestamp iecTimestamp; Timestamp_clearFlags(&iecTimestamp); Timestamp_setTimeInMilliseconds(&iecTimestamp, timestamp); Timestamp_setLeapSecondKnown(&iecTimestamp, true); /* toggle clock-not-synchronized flag in timestamp */ if (((int) t % 2) == 0) Timestamp_setClockNotSynchronized(&iecTimestamp, true); IedServer_updateTimestampAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn1_t, &iecTimestamp); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn1_mag_f, an1); IedServer_updateTimestampAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn2_t, &iecTimestamp); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn2_mag_f, an2); IedServer_updateTimestampAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn3_t, &iecTimestamp); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn3_mag_f, an3); IedServer_updateTimestampAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn4_t, &iecTimestamp); IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn4_mag_f, an4); 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() */
int main(int argc, char** argv) { char* hostname; int tcpPort = 102; if (argc > 1) hostname = argv[1]; else hostname = "localhost"; if (argc > 2) tcpPort = atoi(argv[2]); IedClientError error; IedConnection con = IedConnection_create(); IedConnection_connect(con, &error, hostname, tcpPort); if (error == IED_ERROR_OK) { /* read an analog measurement value from server */ MmsValue* value = IedConnection_readObject(con, &error, "simpleIOGenericIO/GGIO1.AnIn1.mag.f", IEC61850_FC_MX); if (value != NULL) { float fval = MmsValue_toFloat(value); printf("read float value: %f\n", fval); MmsValue_delete(value); } /* write a variable to the server */ value = MmsValue_newVisibleString("libiec61850.com"); IedConnection_writeObject(con, &error, "simpleIOGenericIO/GGIO1.NamPlt.vendor", IEC61850_FC_DC, value); if (error != IED_ERROR_OK) printf("failed to write simpleIOGenericIO/GGIO1.NamPlt.vendor!\n"); else MmsValue_delete(value); /* read data set */ ClientDataSet clientDataSet = IedConnection_readDataSetValues(con, &error, "simpleIOGenericIO/LLN0.Events", NULL); if (clientDataSet == NULL) printf("failed to read dataset\n"); /* Read RCB values */ ClientReportControlBlock rcb = IedConnection_getRCBValues(con, &error, "simpleIOGenericIO/LLN0.RP.EventsRCB01", NULL); bool rptEna = ClientReportControlBlock_getRptEna(rcb); printf("RptEna = %i\n", rptEna); /* Install handler for reports */ IedConnection_installReportHandler(con, "simpleIOGenericIO/LLN0.RP.EventsRCB01", ClientReportControlBlock_getRptId(rcb), reportCallbackFunction, NULL); /* Set trigger options and enable report */ ClientReportControlBlock_setTrgOps(rcb, TRG_OPT_DATA_UPDATE | TRG_OPT_INTEGRITY | TRG_OPT_GI); ClientReportControlBlock_setRptEna(rcb, true); ClientReportControlBlock_setIntgPd(rcb, 5000); IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA | RCB_ELEMENT_TRG_OPS | RCB_ELEMENT_INTG_PD, true); if (error != IED_ERROR_OK) printf("report activation failed (code: %i)\n", error); Thread_sleep(1000); /* trigger GI report */ ClientReportControlBlock_setGI(rcb, true); IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_GI, true); if (error != IED_ERROR_OK) printf("Error triggering a GI report (code: %i)\n", error); Thread_sleep(60000); /* disable reporting */ ClientReportControlBlock_setRptEna(rcb, false); IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA, true); if (error != IED_ERROR_OK) printf("disable reporting failed (code: %i)\n", error); ClientDataSet_destroy(clientDataSet); close_connection: IedConnection_close(con); } else { printf("Failed to connect to %s:%i\n", hostname, tcpPort); } IedConnection_destroy(con); }