/* * client_example_async.c * * Shows how to use the asynchronous client API * * This example is intended to be used with server_example_basic_io. */ #include "iec61850_client.h" #include #include #include "hal_thread.h" static ClientDataSet clientDataSet = NULL; static void printValue(char* name, MmsValue* value) { char buf[1000]; MmsValue_printToBuffer(value, buf, 1000); printf("%s: %s\n", name, buf); } static void readObjectHandler (uint32_t invokeId, void* parameter, IedClientError err, MmsValue* value) { if (err == IED_ERROR_OK) { printValue((char*) parameter, value); MmsValue_delete(value); } else { printf("Failed to read object %s (err=%i)\n", (char*) parameter, err); } } static void readDataSetHandler(uint32_t invokeId, void* parameter, IedClientError err, ClientDataSet dataSet) { if (err == IED_ERROR_OK) { clientDataSet = dataSet; printf("Data set has %d entries\n", ClientDataSet_getDataSetSize(dataSet)); MmsValue* values = ClientDataSet_getValues(dataSet); if (MmsValue_getType(values) == MMS_ARRAY) { int i; for (i = 0; i < MmsValue_getArraySize(values); i++) { printf(" [%i]", i); printValue("", MmsValue_getElement(values, i)); } } } else { printf("Failed to read data set (err=%i)\n", err); } } static void writeDataSetHandler(uint32_t invokeId, void* parameter, IedClientError err, LinkedList /* */accessResults) { if (err == IED_ERROR_OK) { if (accessResults) { int i = 0; LinkedList element = LinkedList_getNext(accessResults); while (element) { MmsValue* accessResultValue = LinkedList_getData(element); printf(" access-result[%i]", i); printValue("", accessResultValue); element = LinkedList_getNext(element); i++; } LinkedList_destroyDeep(accessResults, (LinkedListValueDeleteFunction) MmsValue_delete); } } else { printf("Failed to write data set (err=%i)\n", err); } } static void reportCallbackFunction(void* parameter, ClientReport report) { MmsValue* dataSetValues = ClientReport_getDataSetValues(report); printf("received report for %s\n", ClientReport_getRcbReference(report)); int i; for (i = 0; i < 4; i++) { ReasonForInclusion reason = ClientReport_getReasonForInclusion(report, i); if (reason != IEC61850_REASON_NOT_INCLUDED) { printf(" GGIO1.SPCSO%i.stVal: %i (included for reason %i)\n", i, MmsValue_getBoolean(MmsValue_getElement(dataSetValues, i)), reason); } } } static void getVarSpecHandler (uint32_t invokeId, void* parameter, IedClientError err, MmsVariableSpecification* spec) { if (err == IED_ERROR_OK) { printf("variable: %s has type %d\n", (char*) parameter, MmsVariableSpecification_getType(spec)); MmsVariableSpecification_destroy(spec); } else { printf("Failed to get variable specification for object %s (err=%i)\n", (char*) parameter, err); } } static void getNameListHandler(uint32_t invokeId, void* parameter, IedClientError err, LinkedList nameList, bool moreFollows) { if (err != IED_ERROR_OK) { printf("Get name list error: %d\n", err); } else { char* ldName = (char*) parameter; LinkedList element = LinkedList_getNext(nameList); while (element) { char* variableName = (char*) LinkedList_getData(element); printf(" %s/%s\n", ldName, variableName); element = LinkedList_getNext(element); } LinkedList_destroy(nameList); free(ldName); } } static void getServerDirectoryHandler(uint32_t invokeId, void* parameter, IedClientError err, LinkedList nameList, bool moreFollows) { IedConnection con = (IedConnection) parameter; if (err != IED_ERROR_OK) { printf("Get server directory error: %d\n", err); } else { LinkedList element = LinkedList_getNext(nameList); while (element) { char* ldName = (char*) LinkedList_getData(element); printf("LD: %s\n", ldName); IedClientError cerr; IedConnection_getLogicalDeviceVariablesAsync(con, &cerr, ldName, NULL, NULL, getNameListHandler, strdup(ldName)); element = LinkedList_getNext(element); } LinkedList_destroy(nameList); } } static void controlActionHandler(uint32_t invokeId, void* parameter, IedClientError err, ControlActionType type, bool success) { printf("control: ID: %d type: %i err: %d success: %i\n", invokeId, type, err, success); } 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_connectAsync(con, &error, hostname, tcpPort); if (error == IED_ERROR_OK) { bool success = true; while (IedConnection_getState(con) != IED_STATE_CONNECTED) { if (IedConnection_getState(con) == IED_STATE_CLOSED) { success = false; break; } Thread_sleep(10); } if (success) { IedConnection_getServerDirectoryAsync(con, &error, NULL, NULL, getServerDirectoryHandler, con); if (error != IED_ERROR_OK) { printf("read server directory error %i\n", error); } Thread_sleep(1000); IedConnection_readObjectAsync(con, &error, "simpleIOGenericIO/GGIO1.AnIn1.mag.f", IEC61850_FC_MX, readObjectHandler, "simpleIOGenericIO/GGIO1.AnIn1.mag.f"); if (error != IED_ERROR_OK) { printf("read object error %i\n", error); } IedConnection_readObjectAsync(con, &error, "simpleIOGenericIO/GGIO1.AnIn2.mag.f", IEC61850_FC_MX, readObjectHandler, "simpleIOGenericIO/GGIO1.AnIn2.mag.f"); if (error != IED_ERROR_OK) { printf("read object error %i\n", error); } IedConnection_getVariableSpecificationAsync(con, &error, "simpleIOGenericIO/GGIO1.AnIn1", IEC61850_FC_MX, getVarSpecHandler, "simpleIOGenericIO/GGIO1.AnIn1"); if (error != IED_ERROR_OK) { printf("get variable specification error %i\n", error); } IedConnection_readDataSetValuesAsync(con, &error, "simpleIOGenericIO/LLN0.Events", NULL, readDataSetHandler, NULL); if (error != IED_ERROR_OK) { printf("read data set error %i\n", error); } LinkedList values = LinkedList_create(); LinkedList_add(values, MmsValue_newBoolean(true)); LinkedList_add(values, MmsValue_newBoolean(false)); LinkedList_add(values, MmsValue_newBoolean(true)); LinkedList_add(values, MmsValue_newBoolean(false)); IedConnection_writeDataSetValuesAsync(con, &error, "simpleIOGenericIO/LLN0.Events", values, writeDataSetHandler, NULL); if (error != IED_ERROR_OK) { printf("write data set error %i\n", error); } LinkedList_destroyDeep(values, (LinkedListValueDeleteFunction) MmsValue_delete); Thread_sleep(1000); ControlObjectClient controlClient = ControlObjectClient_create("simpleIOGenericIO/GGIO1.SPCSO1", con); if (controlClient != NULL) { ControlObjectClient_setOrigin(controlClient, "test1", CONTROL_ORCAT_AUTOMATIC_REMOTE); MmsValue* ctlVal = MmsValue_newBoolean(true); ControlObjectClient_operateAsync(controlClient, &error, ctlVal, 0, controlActionHandler, NULL); if (error != IED_ERROR_OK) { printf("Failed to send operate %i\n", error); } } else { printf("Failed to connect to control object\n"); } } Thread_sleep(1000); IedConnection_releaseAsync(con, &error); if (error != IED_ERROR_OK) { printf("Release returned error: %d\n", error); } else { while (IedConnection_getState(con) != IED_STATE_CLOSED) { Thread_sleep(10); } } } else { printf("Failed to connect to %s:%i\n", hostname, tcpPort); } if (clientDataSet) ClientDataSet_destroy(clientDataSet); IedConnection_destroy(con); }