- IEC 61850 client: added missing async functions for files

pull/93/head
Michael Zillgith 7 years ago
parent 0842097b7e
commit 3e30910319

@ -704,7 +704,7 @@ writeMultipleVariablesHandler(uint32_t invokeId, void* parameter, MmsError mmsEr
if (call) {
IedConnection_WriteObjectHandler handler = (IedConnection_WriteObjectHandler) call->callback;
IedConnection_GenericServiceHandler handler = (IedConnection_GenericServiceHandler) call->callback;
if (accessResults != NULL) {
@ -771,7 +771,7 @@ writeVariableHandler(uint32_t invokeId, void* parameter, MmsError mmsError, MmsD
if (call) {
IedConnection_WriteObjectHandler handler = (IedConnection_WriteObjectHandler) call->callback;
IedConnection_GenericServiceHandler handler = (IedConnection_GenericServiceHandler) call->callback;
struct sWriteRcbVariablesParameter* param = (struct sWriteRcbVariablesParameter*) call->specificParameter2.pointer;
@ -822,7 +822,7 @@ writeVariableHandler(uint32_t invokeId, void* parameter, MmsError mmsError, MmsD
uint32_t
IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, ClientReportControlBlock rcb,
uint32_t parametersMask, bool singleRequest, IedConnection_WriteObjectHandler handler, void* parameter)
uint32_t parametersMask, bool singleRequest, IedConnection_GenericServiceHandler handler, void* parameter)
{
uint32_t invokeId = 0;

@ -647,7 +647,7 @@ IedConnection_connect(IedConnection self, IedClientError* error, const char* hos
}
void
IedConnection_installStateChangedHandler(IedConnection self, IedConnectionStateChangedHandler handler, void* parameter)
IedConnection_installStateChangedHandler(IedConnection self, IedConnection_StateChangedHandler handler, void* parameter)
{
self->connectionStateChangedHandler = handler;
self->connectionStateChangedHandlerParameter = parameter;
@ -1444,7 +1444,7 @@ writeVariableHandler(uint32_t invokeId, void* parameter, MmsError err, MmsDataAc
if (call) {
IedConnection_WriteObjectHandler handler = (IedConnection_WriteObjectHandler) call->callback;
IedConnection_GenericServiceHandler handler = (IedConnection_GenericServiceHandler) call->callback;
IedClientError iedError = iedConnection_mapMmsErrorToIedError(err);
@ -1463,7 +1463,7 @@ writeVariableHandler(uint32_t invokeId, void* parameter, MmsError err, MmsDataAc
uint32_t
IedConnection_writeObjectAsync(IedConnection self, IedClientError* error, const char* objectReference,
FunctionalConstraint fc, MmsValue* value, IedConnection_WriteObjectHandler handler, void* parameter)
FunctionalConstraint fc, MmsValue* value, IedConnection_GenericServiceHandler handler, void* parameter)
{
*error = IED_ERROR_OK;
@ -1784,16 +1784,8 @@ IedConnection_getFileDirectoryEx(IedConnection self, IedClientError* error, cons
return fileNames;
}
struct sClientProvidedFileReadHandler {
IedClientGetFileHandler handler;
void* handlerParameter;
bool retVal;
uint32_t byteReceived;
};
static void
fileDirectoryHandler(uint32_t invokeId, void* parameter, MmsError err, char* filename, uint32_t size, uint64_t lastModfified,
fileDirectoryHandlerEx(uint32_t invokeId, void* parameter, MmsError err, char* filename, uint32_t size, uint64_t lastModfified,
bool moreFollows)
{
IedConnection self = (IedConnection) parameter;
@ -1802,9 +1794,12 @@ fileDirectoryHandler(uint32_t invokeId, void* parameter, MmsError err, char* fil
if (call) {
IedConnection_FileDirectoryHandler handler = (IedConnection_FileDirectoryHandler) call->callback;
if (call->specificParameter2.getFileDirectory.cont) {
IedConnection_FileDirectoryEntryHandler handler = (IedConnection_FileDirectoryEntryHandler) call->callback;
handler(invokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(err), filename, size, lastModfified, moreFollows);
call->specificParameter2.getFileDirectory.cont =
handler(invokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(err), filename, size, lastModfified, moreFollows);
}
if (filename == NULL)
iedConnection_releaseOutstandingCall(self, call);
@ -1816,10 +1811,9 @@ fileDirectoryHandler(uint32_t invokeId, void* parameter, MmsError err, char* fil
}
uint32_t
IedConnection_getFileDirectoryAsync(IedConnection self, IedClientError* error, const char* directoryName, const char* continueAfter,
IedConnection_FileDirectoryHandler handler, void* parameter)
IedConnection_getFileDirectoryAsyncEx(IedConnection self, IedClientError* error, const char* directoryName, const char* continueAfter,
IedConnection_FileDirectoryEntryHandler handler, void* parameter)
{
MmsError err = MMS_ERROR_NONE;
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
@ -1831,9 +1825,10 @@ IedConnection_getFileDirectoryAsync(IedConnection self, IedClientError* error, c
call->callback = handler;
call->callbackParameter = parameter;
call->specificParameter2.getFileDirectory.cont = true;
call->invokeId = MmsConnection_getFileDirectoryAsync(self->connection, &err, directoryName, continueAfter,
fileDirectoryHandler, self);
fileDirectoryHandlerEx, self);
*error = iedConnection_mapMmsErrorToIedError(err);
@ -1845,6 +1840,13 @@ IedConnection_getFileDirectoryAsync(IedConnection self, IedClientError* error, c
return call->invokeId;
}
struct sClientProvidedFileReadHandler {
IedClientGetFileHandler handler;
void* handlerParameter;
bool retVal;
uint32_t byteReceived;
};
static void
mmsFileReadHandler(void* parameter, int32_t frsmId, uint8_t* buffer, uint32_t bytesReceived)
{
@ -2086,6 +2088,53 @@ IedConnection_setFile(IedConnection self, IedClientError* error, const char* sou
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
}
static void
deleteFileAndSetFileHandler (uint32_t invokeId, void* parameter, MmsError mmsError, bool success)
{
IedConnection self = (IedConnection) parameter;
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
if (call) {
IedConnection_GenericServiceHandler handler = (IedConnection_GenericServiceHandler) call->callback;
handler(invokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(mmsError));
}
else {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
}
uint32_t
IedConnection_setFileAsync(IedConnection self, IedClientError* error, const char* sourceFilename, const char* destinationFilename,
IedConnection_GenericServiceHandler handler, void* parameter)
{
MmsError err = MMS_ERROR_NONE;
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
if (call == NULL) {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
call->callback = handler;
call->callbackParameter = parameter;
call->invokeId = MmsConnection_obtainFileAsync(self->connection, &err, sourceFilename, destinationFilename, deleteFileAndSetFileHandler, self);
*error = iedConnection_mapMmsErrorToIedError(err);
if (err != MMS_ERROR_NONE) {
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
return call->invokeId;
}
void
IedConnection_deleteFile(IedConnection self, IedClientError* error, const char* fileName)
{
@ -2098,6 +2147,34 @@ IedConnection_deleteFile(IedConnection self, IedClientError* error, const char*
*error = iedConnection_mapMmsErrorToIedError(mmsError);
}
uint32_t
IedConnection_deleteFileAsync(IedConnection self, IedClientError* error, const char* fileName,
IedConnection_GenericServiceHandler handler, void* parameter)
{
MmsError err = MMS_ERROR_NONE;
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
if (call == NULL) {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
call->callback = handler;
call->callbackParameter = parameter;
call->invokeId = MmsConnection_fileDeleteAsync(self->connection, &err, fileName, deleteFileAndSetFileHandler, self);
*error = iedConnection_mapMmsErrorToIedError(err);
if (err != MMS_ERROR_NONE) {
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
return call->invokeId;
}
LinkedList /*<char*>*/
IedConnection_getServerDirectory(IedConnection self, IedClientError* error, bool getFileNames)

@ -221,6 +221,19 @@ IedConnection_destroy(IedConnection self);
LIB61850_API void
IedConnection_setConnectTimeout(IedConnection self, uint32_t timeoutInMs);
/**
* \brief Generic serivce callback handler
*
* NOTE: This callback handler is used by several asynchronous service functions that require
* only a simple feedback in form of a success (IED_ERROR_OK) or failure (other \ref err value).
*
* \param invokeId the invoke ID used by the related service request
* \param parameter user provided parameter
* \param err the result code. IED_ERROR_OK indicates success.
*/
typedef void
(*IedConnection_GenericServiceHandler) (uint32_t invokeId, void* parameter, IedClientError err);
/**************************************************
* Association service
**************************************************/
@ -342,12 +355,21 @@ IedConnection_getState(IedConnection self);
LIB61850_API LastApplError
IedConnection_getLastApplError(IedConnection self);
/**
* \brief Callback handler that is invoked when the connection is closed
*
* \deprecated Use \ref IedConnection_StateChangedHandler instead
*
* \param user provided parameter
* \param connection the connection object of the closed connection
*/
typedef void
(*IedConnectionClosedHandler) (void* parameter, IedConnection connection);
/**
* \brief Install a handler function that will be called when the connection is lost.
* \brief Install a handler function that is called when the connection is lost/closed.
*
* \deprecated Use \ref IedConnection_StateChangedHandler instead
*
* \param self the connection object
* \param handler that callback function
@ -357,11 +379,25 @@ LIB61850_API void
IedConnection_installConnectionClosedHandler(IedConnection self, IedConnectionClosedHandler handler,
void* parameter);
/**
* \brief Callback handler that is invoked whenever the connection state (\ref IedConnectionState) changes
*
* \param user provided parameter
* \param connection the related connection
* \param newState the new state of the connection
*/
typedef void
(*IedConnectionStateChangedHandler) (void* parameter, IedConnection connection, IedConnectionState newState);
(*IedConnection_StateChangedHandler) (void* parameter, IedConnection connection, IedConnectionState newState);
/**
* \brief Install a handler function that is called when the connection state changes
*
* \param self the connection object
* \param handler that callback function
* \param parameter the user provided parameter that is handed over to the callback function
*/
LIB61850_API void
IedConnection_installStateChangedHandler(IedConnection self, IedConnectionStateChangedHandler handler, void* parameter);
IedConnection_installStateChangedHandler(IedConnection self, IedConnection_StateChangedHandler handler, void* parameter);
/**
* \brief get a handle to the underlying MmsConnection
@ -761,9 +797,6 @@ LIB61850_API void
IedConnection_writeObject(IedConnection self, IedClientError* error, const char* dataAttributeReference, FunctionalConstraint fc,
MmsValue* value);
typedef void
(*IedConnection_WriteObjectHandler) (uint32_t invokeId, void* parameter, IedClientError err);
/**
* \brief write a functional constrained data attribute (FCDA) or functional constrained data (FCD) - async version
*
@ -779,7 +812,7 @@ typedef void
*/
LIB61850_API uint32_t
IedConnection_writeObjectAsync(IedConnection self, IedClientError* error, const char* objectReference,
FunctionalConstraint fc, MmsValue* value, IedConnection_WriteObjectHandler handler, void* parameter);
FunctionalConstraint fc, MmsValue* value, IedConnection_GenericServiceHandler handler, void* parameter);
/**
* \brief read a functional constrained data attribute (FCDA) of type boolean
@ -1115,7 +1148,7 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
LIB61850_API uint32_t
IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, ClientReportControlBlock rcb,
uint32_t parametersMask, bool singleRequest, IedConnection_WriteObjectHandler handler, void* parameter);
uint32_t parametersMask, bool singleRequest, IedConnection_GenericServiceHandler handler, void* parameter);
/**
* \brief Callback function for receiving reports
@ -2599,17 +2632,52 @@ IedConnection_getFileDirectoryEx(IedConnection self, IedClientError* error, cons
/**
* \brief Callback handler for the get file directory service
*
* Will be called once for each file directory entry and after the last entry with \ref filename = NULL to indicate
* with \ref moreFollows if more data is available at the server. In case of an error the callback will be called with
* Will be called once for each file directory entry and after the last entry with \ref moreFollows = false to indicate
* to indicate that no more data will follow. In case of an error the callback will be called with
* \ref err != IED_ERROR_OK and moreFollows = false.
*/
typedef void
(*IedConnection_FileDirectoryHandler) (uint32_t invokeId, void* parameter, IedClientError err, char* filename, uint32_t size, uint64_t lastModfified,
/**
* \brief Callback handler for the get file directory service
*
* Will be called once for each file directory entry and after the last entry with \ref filename = NULL to indicate
* with \ref moreFollows set to true if more data is available at the server (can only happen when using the \ref IedConnection_getFileDirectoryAsyncEx
* function). In case of an error the callback will be called with \ref err != IED_ERROR_OK and moreFollows = false.
*
* \param invokeId invoke ID of the request
* \param parameter user provided parameter
* \param err error code in case of a problem, otherwise IED_ERROR_OK
* \param filename the filename of the current file directory entry or NULL if no more entries are available
* \param size the file size in byte of the current file directory entry
* \param lastModified the last modified timestamp of the current file directory entry
*
* \return return false when the request has to be stopped (no further callback invokations), true otherwise
*/
typedef bool
(*IedConnection_FileDirectoryEntryHandler) (uint32_t invokeId, void* parameter, IedClientError err, char* filename, uint32_t size, uint64_t lastModfified,
bool moreFollows);
/**
* \brief Get file directory (single request) - asynchronous version
*
* The provided handler will be called for each received file directory entry.
*
* NOTE: This will only cause a single MMS request. When the resulting file directory doesn't fit into
* a single MMS PDU another request has to be sent indicating a continuation point with the continueAfter
* parameter.
*
* \param self the connection object
* \param error the error code if an error occurs
* \param directoryName the name of the directory or NULL to get the entries of the root directory
* \param continueAfter last received filename to continue after, or NULL for the first request
* \param handler the callback handler
* \param parameter user provided callback parameter
*
* \return the invokeId of the first file directory request
*/
LIB61850_API uint32_t
IedConnection_getFileDirectoryAsync(IedConnection self, IedClientError* error, const char* directoryName, const char* continueAfter,
IedConnection_FileDirectoryHandler handler, void* parameter);
IedConnection_getFileDirectoryAsyncEx(IedConnection self, IedClientError* error, const char* directoryName, const char* continueAfter,
IedConnection_FileDirectoryEntryHandler handler, void* parameter);
/**
* \brief user provided handler to receive the data of the GetFile request
@ -2677,7 +2745,7 @@ typedef bool
* \param error the error code if an error occurs
* \param fileName the name of the file to be read from the server
* \param hander callback handler that is called for each received data or error message
* \param paramter user provided callback parameter
* \param parameter user provided callback parameter
*
* \return invokeId of the first sent request
*/
@ -2711,6 +2779,21 @@ IedConnection_setFilestoreBasepath(IedConnection, const char* basepath);
LIB61850_API void
IedConnection_setFile(IedConnection self, IedClientError* error, const char* sourceFilename, const char* destinationFilename);
/**
* \brief Implementation of the SetFile ACSI service - asynchronous version
*
* Upload a file to the server. The file has to be available in the local VMD filestore.
*
* \param self the connection object
* \param error the error code if an error occurs
* \param sourceFilename the filename of the local (client side) file
* \param destinationFilename the filename of the remote (service side) file
* \param handler callback handler that is called when the obtain file response has been received
* \param parameter user provided callback parameter
*/
LIB61850_API uint32_t
IedConnection_setFileAsync(IedConnection self, IedClientError* error, const char* sourceFilename, const char* destinationFilename,
IedConnection_GenericServiceHandler handler, void* parameter);
/**
* \brief Implementation of the DeleteFile ACSI service
@ -2724,6 +2807,21 @@ IedConnection_setFile(IedConnection self, IedClientError* error, const char* sou
LIB61850_API void
IedConnection_deleteFile(IedConnection self, IedClientError* error, const char* fileName);
/**
* \brief Implementation of the DeleteFile ACSI service - asynchronous version
*
* Delete a file at the server.
*
* \param self the connection object
* \param error the error code if an error occurs
* \param fileName the name of the file to delete
* \param handler callback handler that is called when the obtain file response has been received
* \param parameter user provided callback parameter
*/
LIB61850_API uint32_t
IedConnection_deleteFileAsync(IedConnection self, IedClientError* error, const char* fileName,
IedConnection_GenericServiceHandler handler, void* parameter);
/** @} */

@ -45,6 +45,9 @@ struct sIedConnectionOutstandingCall {
int32_t frsmId;
uint32_t originalInvokeId;
} getFileInfo;
struct {
bool cont;
} getFileDirectory;
} specificParameter2; /* function/service specific parameter */
//void* specificParameter2; /* function/service specific parameter */
@ -68,7 +71,7 @@ struct sIedConnection
IedConnectionClosedHandler connectionCloseHandler;
void* connectionClosedParameter;
IedConnectionStateChangedHandler connectionStateChangedHandler;
IedConnection_StateChangedHandler connectionStateChangedHandler;
void* connectionStateChangedHandlerParameter;
uint32_t connectionTimeout;

@ -1032,7 +1032,7 @@ typedef void
* \brief Callback handler for the get file directory service
*
* Will be called once for each file directory entry and after the last entry with \ref filename = NULL to indicate
* with \ref moreFollows if more data is available at the server. In case of an error the callback will be called with
* with \ref moreFollows set to true when more data is available server side. In case of an error the callback will be called with
* \ref mmsError != MMS_ERROR_NONE and moreFollows = false.
*/
typedef void

@ -184,21 +184,6 @@ public class ModelViewer {
String lNodePrefix = devPrefix + lNode.getName();
printObjectList(lNode.getDataObjects(), output, lNodePrefix);
// for (DataObject dObject : lNode.getDataObjects()) {
//
// String dOPrefix = lNodePrefix + "." + dObject.getName();
//
// for (DataAttribute dAttribute : dObject.getDataAttributes()) {
//
// String daPrefix = dOPrefix + "." + dAttribute.getName();
//
// output.println(daPrefix + " [" + dAttribute.getFc().toString() + "]");
//
// printSubAttributeList(dAttribute, output, daPrefix);
// }
//
// }
}
}

Loading…
Cancel
Save