- IEC 61850 client: added async discovery functions

pull/93/head
Michael Zillgith 7 years ago
parent 1d120f87de
commit e90d5d44fa

@ -67,6 +67,61 @@ getVarSpecHandler (uint32_t invokeId, void* parameter, IedClientError err, MmsVa
} }
} }
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);
}
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
char* hostname; char* hostname;
@ -102,6 +157,15 @@ int main(int argc, char** argv) {
if (success) { 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"); IedConnection_readObjectAsync(con, &error, "simpleIOGenericIO/GGIO1.AnIn1.mag.f", IEC61850_FC_MX, readObjectHandler, "simpleIOGenericIO/GGIO1.AnIn1.mag.f");
if (error != IED_ERROR_OK) { if (error != IED_ERROR_OK) {

@ -875,18 +875,92 @@ cleanup_and_exit:
return invokeId; return invokeId;
} }
static void
getNameListHandler(uint32_t invokeId, void* parameter, MmsError mmsError, LinkedList nameList, bool moreFollows)
{
IedConnection self = (IedConnection) parameter;
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
if (call) {
IedConnection_GetNameListHandler handler = (IedConnection_GetNameListHandler) call->callback;
handler(invokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(mmsError), nameList, moreFollows);
iedConnection_releaseOutstandingCall(self, call);
}
else {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
}
uint32_t uint32_t
IedConnection_getServerDirectoryAsync(IedConnection self, IedClientError* error, const char* continueAfter, bool getFileNames, IedConnection_getServerDirectoryAsync(IedConnection self, IedClientError* error, const char* continueAfter, LinkedList result,
IedConnection_GetNameListHandler handler, void* parameter) IedConnection_GetNameListHandler handler, void* parameter)
{ {
//TODO implement me IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
if (call == NULL) {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
} }
call->callback = handler;
call->callbackParameter = parameter;
MmsError err = MMS_ERROR_NONE;
call->invokeId = MmsConnection_getDomainNamesAsync(self->connection, &err, continueAfter, result, getNameListHandler, self);
if (err != MMS_ERROR_NONE) {
*error = iedConnection_mapMmsErrorToIedError(err);
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
else {
*error = IED_ERROR_OK;
}
return call->invokeId;
}
uint32_t uint32_t
IedConnection_getLogicalDeviceVariables(IedConnection self, IedClientError* error, const char* continueAfter, IedConnection_getLogicalDeviceVariablesAsync(IedConnection self, IedClientError* error, const char* ldName, const char* continueAfter, LinkedList result,
IedConnection_GetNameListHandler handler, void* parameter) IedConnection_GetNameListHandler handler, void* parameter)
{ {
//TODO implement me IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
if (call == NULL) {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
call->callback = handler;
call->callbackParameter = parameter;
MmsError err = MMS_ERROR_NONE;
call->invokeId = MmsConnection_getDomainVariableNamesAsync(self->connection, &err, ldName, continueAfter, result, getNameListHandler, self);
if (err != MMS_ERROR_NONE) {
*error = iedConnection_mapMmsErrorToIedError(err);
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
else {
*error = IED_ERROR_OK;
}
return call->invokeId;
} }
static void static void

@ -2018,18 +2018,54 @@ IedConnection_getVariableSpecification(IedConnection self, IedClientError* error
typedef void typedef void
(*IedConnection_GetNameListHandler) (uint32_t invokeId, void* parameter, IedClientError err, LinkedList nameList, bool moreFollows); (*IedConnection_GetNameListHandler) (uint32_t invokeId, void* parameter, IedClientError err, LinkedList nameList, bool moreFollows);
/**
* \brief Get the server directory (logical devices name) - asynchronous version
*
* \param[in] self the connection object
* \param[out] error the error code if an error occurs
* \param[in] continueAfter the name of the last received element when the call is a continuation, or NULL for the first call
* \param[in] result list to store (append) the response names, or NULL to create a new list for the response names
* \param[in] handler will be called when response is received or timed out.
* \param[in] parameter
*
* \return the invoke ID of the request
*/
LIB61850_API uint32_t LIB61850_API uint32_t
IedConnection_getServerDirectoryAsync(IedConnection self, IedClientError* error, const char* continueAfter, bool getFileNames, IedConnection_getServerDirectoryAsync(IedConnection self, IedClientError* error, const char* continueAfter, LinkedList result,
IedConnection_GetNameListHandler handler, void* parameter); IedConnection_GetNameListHandler handler, void* parameter);
/**
* \brief Get the variables in the logical device - asynchronous version
*
* \param[in] self the connection object
* \param[out] error the error code if an error occurs
* \param[in] ldName the logical device name
* \param[in] continueAfter the name of the last received element when the call is a continuation, or NULL for the first call
* \param[in] result list to store (append) the response names, or NULL to create a new list for the response names
* \param[in] handler will be called when response is received or timed out.
* \param[in] parameter
*
* \return the invoke ID of the request
*/
LIB61850_API uint32_t LIB61850_API uint32_t
IedConnection_getLogicalDeviceVariables(IedConnection self, IedClientError* error, const char* continueAfter, IedConnection_getLogicalDeviceVariablesAsync(IedConnection self, IedClientError* error, const char* ldName, const char* continueAfter, LinkedList result,
IedConnection_GetNameListHandler handler, void* parameter); IedConnection_GetNameListHandler handler, void* parameter);
typedef void typedef void
(*IedConnection_GetVariableSpecificationHandler) (uint32_t invokeId, void* parameter, IedClientError err, MmsVariableSpecification* spec); (*IedConnection_GetVariableSpecificationHandler) (uint32_t invokeId, void* parameter, IedClientError err, MmsVariableSpecification* spec);
/**
* \brief Get the specification of a variable (data attribute or functional constraint data object) - asynchronous version
*
* \param[in] self the connection object
* \param[out] error the error code if an error occurs
* \param[in] dataAttributeReference the data attribute reference (FCDA or FCDO)
* \param[in] handler will be called when response is received or timed out.
* \param[in] parameter
*
* \return the invoke ID of the request
*/
LIB61850_API uint32_t LIB61850_API uint32_t
IedConnection_getVariableSpecificationAsync(IedConnection self, IedClientError* error, const char* dataAttributeReference, IedConnection_getVariableSpecificationAsync(IedConnection self, IedClientError* error, const char* dataAttributeReference,
FunctionalConstraint fc, IedConnection_GetVariableSpecificationHandler handler, void* parameter); FunctionalConstraint fc, IedConnection_GetVariableSpecificationHandler handler, void* parameter);

@ -363,8 +363,20 @@ MmsConnection_getVMDVariableNamesAsync(MmsConnection self, MmsError* mmsError, c
LIB61850_API LinkedList /* <char*> */ LIB61850_API LinkedList /* <char*> */
MmsConnection_getDomainNames(MmsConnection self, MmsError* mmsError); MmsConnection_getDomainNames(MmsConnection self, MmsError* mmsError);
/**
* \brief Get the domain names of the server (asynchronous version).
*
* \param[in] self MmsConnection instance to operate on
* \param[out] mmsError user provided variable to store error code
* \param[in] continueAfter the name of the last received element when the call is a continuation, or NULL for the first call
* \param[in] result list to store (append) the response names, or NULL to create a new list for the response names
* \param[in] handler will be called when response is received or timed out.
* \param[in] parameter
*
* \return the invoke ID of the request
*/
LIB61850_API uint32_t LIB61850_API uint32_t
MmsConnection_getDomainNamesAsync(MmsConnection self, MmsError* mmsError, const char* continueAfter, MmsConnection_getDomainNamesAsync(MmsConnection self, MmsError* mmsError, const char* continueAfter, LinkedList result,
MmsConnection_GetNameListHandler handler, void* parameter); MmsConnection_GetNameListHandler handler, void* parameter);
/** /**
@ -372,18 +384,33 @@ MmsConnection_getDomainNamesAsync(MmsConnection self, MmsError* mmsError, const
* *
* This will result in a domain specific GetNameList request. * This will result in a domain specific GetNameList request.
* *
* \param self MmsConnection instance to operate on * \param[in] self MmsConnection instance to operate on
* \param mmsError user provided variable to store error code * \param[out] mmsError user provided variable to store error code
* \param domainId the domain name for the domain specific request * \param[in] domainId the domain name for the domain specific request
* *
* \return the of domain specific variable names or NULL if the request failed. * \return the of domain specific variable names or NULL if the request failed.
*/ */
LIB61850_API LinkedList /* <char*> */ LIB61850_API LinkedList /* <char*> */
MmsConnection_getDomainVariableNames(MmsConnection self, MmsError* mmsError, const char* domainId); MmsConnection_getDomainVariableNames(MmsConnection self, MmsError* mmsError, const char* domainId);
/**
* \brief Get the names of all variables present in a MMS domain of the server (asynchronous version).
*
* This will result in a domain specific GetNameList request.
*
* \param[in] self MmsConnection instance to operate on
* \param[out] mmsError user provided variable to store error code
* \param[in] domainId the domain name for the domain specific request
* \param[in] continueAfter the name of the last received element when the call is a continuation, or NULL for the first call
* \param[in] result list to store (append) the response names, or NULL to create a new list for the response names
* \param[in] handler will be called when response is received or timed out.
* \param[in] parameter
*
* \return the invoke ID of the request
*/
LIB61850_API uint32_t LIB61850_API uint32_t
MmsConnection_getDomainVariableNamesAsync(MmsConnection self, MmsError* mmsError, const char* domainId, MmsConnection_getDomainVariableNamesAsync(MmsConnection self, MmsError* mmsError, const char* domainId,
const char* continueAfter, MmsConnection_GetNameListHandler handler, void* parameter); const char* continueAfter, LinkedList result, MmsConnection_GetNameListHandler handler, void* parameter);
/** /**
* \brief Get the names of all named variable lists present in a MMS domain or VMD scope of the server. * \brief Get the names of all named variable lists present in a MMS domain or VMD scope of the server.

@ -1964,11 +1964,11 @@ MmsConnection_getDomainNames(MmsConnection self, MmsError* mmsError)
} }
uint32_t uint32_t
MmsConnection_getDomainNamesAsync(MmsConnection self, MmsError* mmsError, const char* continueAfter, MmsConnection_getDomainNamesAsync(MmsConnection self, MmsError* mmsError, const char* continueAfter, LinkedList result,
MmsConnection_GetNameListHandler handler, void* parameter) MmsConnection_GetNameListHandler handler, void* parameter)
{ {
return mmsClient_getNameListSingleRequestAsync(self, mmsError, NULL, MMS_OBJECT_CLASS_DOMAIN, false, return mmsClient_getNameListSingleRequestAsync(self, mmsError, NULL, MMS_OBJECT_CLASS_DOMAIN, false,
continueAfter, handler, parameter, NULL); continueAfter, handler, parameter, result);
} }
LinkedList /* <char*> */ LinkedList /* <char*> */
@ -1979,10 +1979,10 @@ MmsConnection_getDomainVariableNames(MmsConnection self, MmsError* mmsError, con
uint32_t uint32_t
MmsConnection_getDomainVariableNamesAsync(MmsConnection self, MmsError* mmsError, const char* domainId, MmsConnection_getDomainVariableNamesAsync(MmsConnection self, MmsError* mmsError, const char* domainId,
const char* continueAfter, MmsConnection_GetNameListHandler handler, void* parameter) const char* continueAfter, LinkedList result, MmsConnection_GetNameListHandler handler, void* parameter)
{ {
return mmsClient_getNameListSingleRequestAsync(self, mmsError, domainId, MMS_OBJECT_CLASS_NAMED_VARIABLE, false, return mmsClient_getNameListSingleRequestAsync(self, mmsError, domainId, MMS_OBJECT_CLASS_NAMED_VARIABLE, false,
continueAfter, handler, parameter, NULL); continueAfter, handler, parameter, result);
} }
LinkedList /* <char*> */ LinkedList /* <char*> */

Loading…
Cancel
Save