- IEC 61850 client: implemented IedConnection_writeDataSetValuesAsync

pull/93/head
Michael Zillgith 7 years ago
parent c04b4e928d
commit 1cc350ed4a

@ -3,7 +3,7 @@
*
* Shows how to use the asynchronous client API
*
* This example is intended to be used with server_example_basic_io or server_example_goose.
* This example is intended to be used with server_example_basic_io.
*/
#include "iec61850_client.h"
@ -15,6 +15,29 @@
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)
{
@ -22,13 +45,54 @@ readDataSetHandler(uint32_t invokeId, void* parameter, IedClientError err, Clien
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);
}
}
void
static void
writeDataSetHandler(uint32_t invokeId, void* parameter, IedClientError err, LinkedList /* <MmsValue*> */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);
@ -46,29 +110,6 @@ reportCallbackFunction(void* parameter, ClientReport report)
}
}
static void
printValue(char* name, MmsValue* value)
{
char buf[1000];
MmsValue_printToBuffer(value, buf, 1000);
printf("Received value for %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
getVarSpecHandler (uint32_t invokeId, void* parameter, IedClientError err, MmsVariableSpecification* spec)
{
@ -204,6 +245,20 @@ int main(int argc, char** argv) {
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);

@ -3121,6 +3121,102 @@ exit_function:
return;
}
static void
writeDataSetHandlerInternal(uint32_t invokeId, void* parameter, MmsError err, LinkedList /* <MmsValue*> */ accessResults)
{
IedConnection self = (IedConnection) parameter;
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
if (call) {
IedConnection_WriteDataSetHandler handler = (IedConnection_WriteDataSetHandler) call->callback;
handler(invokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(err), accessResults);
iedConnection_releaseOutstandingCall(self, call);
}
else {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
}
LIB61850_API uint32_t
IedConnection_writeDataSetValuesAsync(IedConnection self, IedClientError* error, const char* dataSetReference,
LinkedList/*<MmsValue*>*/ values, IedConnection_WriteDataSetHandler handler, void* parameter)
{
char domainIdBuffer[65];
char itemIdBuffer[DATA_SET_MAX_NAME_LENGTH + 1];
const char* domainId = NULL;
const char* itemId = NULL;
bool isAssociationSpecific = false;
if (dataSetReference[0] != '@') {
if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
domainId = NULL;
if (dataSetReference[0] == '/')
itemId = dataSetReference + 1;
else
itemId = dataSetReference;
}
else {
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
if (domainId == NULL) {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
const char* itemIdRefOrig = dataSetReference + strlen(domainId) + 1;
if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH) {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
char* itemIdRef = StringUtils_copyStringToBuffer(itemIdRefOrig, itemIdBuffer);
StringUtils_replace(itemIdRef, '.', '$');
itemId = itemIdRef;
}
}
else {
itemId = dataSetReference + 1;
isAssociationSpecific = true;
}
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_writeNamedVariableListAsync(self->connection, &err, isAssociationSpecific, domainId, itemId, values, writeDataSetHandlerInternal, self);
if ((err != MMS_ERROR_NONE) || (*error != IED_ERROR_OK)) {
if (err != MMS_ERROR_NONE)
*error = iedConnection_mapMmsErrorToIedError(err);
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
return call->invokeId;
}
LinkedList /* <MmsJournalEntry> */
IedConnection_queryLogByTime(IedConnection self, IedClientError* error, const char* logReference,
uint64_t startTime, uint64_t endTime, bool* moreFollows)

@ -1585,11 +1585,11 @@ typedef void
* \param dataSetReference object reference of the data set
* \param dataSet a data set instance where to store the retrieved values or NULL if a new instance
* shall be created.
* \param handler the user provided callback handler
* \param parameter user provided parameter that is passed to the callback handler
*
* \return the invoke ID of the request
*/
* \param handler the user provided callback handler
* \param parameter user provided parameter that is passed to the callback handler
*
* \return the invoke ID of the request
*/
LIB61850_API uint32_t
IedConnection_readDataSetValuesAsync(IedConnection self, IedClientError* error, const char* dataSetReference, ClientDataSet dataSet,
IedConnection_ReadDataSetHandler handler, void* parameter);
@ -1638,9 +1638,9 @@ IedConnection_deleteDataSet(IedConnection self, IedClientError* error, const cha
* this object references is LDName/LNodeName.item(arrayIndex)component[FC].
*
* \param connection the connection object
* \param error the error code if an error occurs
* \param[out] error the error code if an error occurs
* \param dataSetReference object reference of the data set
* \param isDeletable this is an output parameter indicating that the requested data set is deletable by clients.
* \param[out] isDeletable this is an output parameter indicating that the requested data set is deletable by clients.
* If this information is not required a NULL pointer can be used.
*
* \return LinkedList containing the data set elements as char* strings.
@ -1658,15 +1658,51 @@ IedConnection_getDataSetDirectory(IedConnection self, IedClientError* error, con
* contains a value for each data set member.
*
* \param connection the connection object
* \param error the error code if an error occurs
* \param[out] error the error code if an error occurs
* \param dataSetReference object reference of the data set
* \param values the new data set values
* \param accessResults the access results for each data set member
* \param[out] accessResults the access results for each data set member
*/
LIB61850_API void
IedConnection_writeDataSetValues(IedConnection self, IedClientError* error, const char* dataSetReference,
LinkedList/*<MmsValue*>*/ values, /* OUTPUT */LinkedList* /* <MmsValue*> */accessResults);
/**
* \brief Callback handler for asynchronous write data set values services (set data set)
*
* \param invokeId the invoke ID of the service request
* \param parameter used provided parameter
* \param err the error code if an error occurs
* \param accessResults the list of access results for the data set entries.
*/
typedef void
(*IedConnection_WriteDataSetHandler) (uint32_t invokeId, void* parameter, IedClientError err, LinkedList /* <MmsValue*> */accessResults);
/**
* \brief Write the data set values to the server - async version
*
* The parameter dataSetReference is the name of the data set to write. It is either in the form LDName/LNodeName.dataSetName
* for permanent domain or VMD scope data sets or @dataSetName for an association specific data set.
* If the LDName part of the reference is missing the resulting data set will be of VMD scope.
* The values parameter has to be the same number of elements as are members in the data set.
*
* When the service call had been successful the \ref IedConnection_WriteDataSetHandler is called with an error value of
* IED_ERROR_OK and a list of MmsValue instances of type data access error. These describe the access results of the individual
* data set entries.
*
* \param connection the connection object
* \param[out] error the error code if an error occurs
* \param dataSetReference object reference of the data set
* \param values the new data set values
* \param handler the user provided callback handler
* \param parameter user provided parameter that is passed to the callback handler
*
* \return the invoke ID of the request
*/
LIB61850_API uint32_t
IedConnection_writeDataSetValuesAsync(IedConnection self, IedClientError* error, const char* dataSetReference,
LinkedList/*<MmsValue*>*/ values, IedConnection_WriteDataSetHandler handler, void* parameter);
/********************************************************
* Data set object (local representation of a data set)

Loading…
Cancel
Save