- IEC 61850 client: add function IedConnection_getFileAsync

pull/93/head
Michael Zillgith 7 years ago
parent aca462c761
commit 89d623866e

@ -522,7 +522,7 @@ readObjectHandlerInternal(uint32_t invokeId, void* parameter, MmsError err, MmsV
IedConnection_GetRCBValuesHandler handler = (IedConnection_GetRCBValuesHandler) call->callback; IedConnection_GetRCBValuesHandler handler = (IedConnection_GetRCBValuesHandler) call->callback;
ClientReportControlBlock updateRcb = (ClientReportControlBlock) call->specificParameter; ClientReportControlBlock updateRcb = (ClientReportControlBlock) call->specificParameter;
char* rcbReference = (char*) call->specificParameter2; char* rcbReference = (char*) call->specificParameter2.pointer;
if (err != MMS_ERROR_NONE) { if (err != MMS_ERROR_NONE) {
@ -607,7 +607,7 @@ IedConnection_getRCBValuesAsync(IedConnection self, IedClientError* error, const
call->callback = handler; call->callback = handler;
call->callbackParameter = parameter; call->callbackParameter = parameter;
call->specificParameter = updateRcb; call->specificParameter = updateRcb;
call->specificParameter2 = StringUtils_copyString(rcbReference); call->specificParameter2.pointer = StringUtils_copyString(rcbReference);
if (DEBUG_IED_CLIENT) if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: readRCBValues for %s\n", rcbReference); printf("DEBUG_IED_CLIENT: readRCBValues for %s\n", rcbReference);
@ -619,7 +619,7 @@ IedConnection_getRCBValuesAsync(IedConnection self, IedClientError* error, const
*error = iedConnection_mapMmsErrorToIedError(err); *error = iedConnection_mapMmsErrorToIedError(err);
if (err != MMS_ERROR_NONE) { if (err != MMS_ERROR_NONE) {
GLOBAL_FREEMEM(call->specificParameter2); GLOBAL_FREEMEM(call->specificParameter2.pointer);
iedConnection_releaseOutstandingCall(self, call); iedConnection_releaseOutstandingCall(self, call);
return 0; return 0;
} }
@ -773,7 +773,7 @@ writeVariableHandler(uint32_t invokeId, void* parameter, MmsError mmsError, MmsD
IedConnection_WriteObjectHandler handler = (IedConnection_WriteObjectHandler) call->callback; IedConnection_WriteObjectHandler handler = (IedConnection_WriteObjectHandler) call->callback;
struct sWriteRcbVariablesParameter* param = (struct sWriteRcbVariablesParameter*) call->specificParameter2; struct sWriteRcbVariablesParameter* param = (struct sWriteRcbVariablesParameter*) call->specificParameter2.pointer;
if ((mmsError != MMS_ERROR_NONE) || (accessError != DATA_ACCESS_ERROR_SUCCESS)) { if ((mmsError != MMS_ERROR_NONE) || (accessError != DATA_ACCESS_ERROR_SUCCESS)) {
@ -997,7 +997,7 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
struct sWriteRcbVariablesParameter* param = (struct sWriteRcbVariablesParameter*) GLOBAL_MALLOC(sizeof(struct sWriteRcbVariablesParameter)); struct sWriteRcbVariablesParameter* param = (struct sWriteRcbVariablesParameter*) GLOBAL_MALLOC(sizeof(struct sWriteRcbVariablesParameter));
call->specificParameter2 = param; call->specificParameter2.pointer = param;
param->itemIds = itemIds; param->itemIds = itemIds;
param->values = values; param->values = values;

@ -1908,6 +1908,162 @@ IedConnection_getFile(IedConnection self, IedClientError* error, const char* fil
return clientFileReadHandler.byteReceived; return clientFileReadHandler.byteReceived;
} }
static void
mmsConnectionFileCloseHandler (uint32_t invokeId, void* parameter, MmsError mmsError, bool success)
{
IedConnection self = (IedConnection) parameter;
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
if (call) {
IedConnection_GetFileAsyncHandler handler = (IedConnection_GetFileAsyncHandler) call->callback;
iedConnection_releaseOutstandingCall(self, call);
}
else {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
}
static void
mmsConnectionFileReadHandler (uint32_t invokeId, void* parameter, MmsError mmsError, uint8_t* buffer, uint32_t byteReceived,
bool moreFollows)
{
IedConnection self = (IedConnection) parameter;
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
if (call) {
IedConnection_GetFileAsyncHandler handler = (IedConnection_GetFileAsyncHandler) call->callback;
if (mmsError != MMS_ERROR_NONE) {
IedClientError err = iedConnection_mapMmsErrorToIedError(mmsError);
handler(call->specificParameter2.getFileInfo.originalInvokeId, call->callbackParameter, err, invokeId, NULL, 0, false);
/* close file */
MmsConnection_fileCloseAsync(self->connection, &mmsError, call->specificParameter2.getFileInfo.frsmId, mmsConnectionFileCloseHandler, self);
if (mmsError != MMS_ERROR_NONE)
iedConnection_releaseOutstandingCall(self, call);
}
else {
bool cont = handler(call->specificParameter2.getFileInfo.originalInvokeId, call->callbackParameter, IED_ERROR_OK, invokeId, buffer, byteReceived, moreFollows);
if ((moreFollows == false) || (cont == false)) {
/* close file */
MmsConnection_fileCloseAsync(self->connection, &mmsError, call->specificParameter2.getFileInfo.frsmId, mmsConnectionFileCloseHandler, self);
if (mmsError != MMS_ERROR_NONE)
iedConnection_releaseOutstandingCall(self, call);
}
else {
/* send next read request */
call->invokeId = MmsConnection_fileReadAsync(self->connection, &mmsError, call->specificParameter2.getFileInfo.frsmId,
mmsConnectionFileReadHandler, self);
if (mmsError != MMS_ERROR_NONE) {
IedClientError err = iedConnection_mapMmsErrorToIedError(mmsError);
handler(invokeId, call->callbackParameter, err, invokeId, NULL, 0, false);
/* close file */
MmsConnection_fileCloseAsync(self->connection, &mmsError, call->specificParameter2.getFileInfo.frsmId, mmsConnectionFileCloseHandler, self);
if (mmsError != MMS_ERROR_NONE) {
iedConnection_releaseOutstandingCall(self, call);
}
}
}
}
}
else {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
}
static void
mmsConnectionFileOpenHandler (uint32_t invokeId, void* parameter, MmsError mmsError, int32_t frsmId, uint32_t fileSize, uint64_t lastModified)
{
IedConnection self = (IedConnection) parameter;
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
if (call) {
IedConnection_GetFileAsyncHandler handler = (IedConnection_GetFileAsyncHandler) call->callback;
call->specificParameter2.getFileInfo.originalInvokeId = invokeId;
if (mmsError != MMS_ERROR_NONE) {
IedClientError err = iedConnection_mapMmsErrorToIedError(mmsError);
handler(invokeId, call->callbackParameter, err, invokeId, NULL, 0, false);
iedConnection_releaseOutstandingCall(self, call);
}
else {
call->specificParameter2.getFileInfo.frsmId = frsmId;
call->specificParameter2.getFileInfo.originalInvokeId = invokeId;
call->invokeId = MmsConnection_fileReadAsync(self->connection, &mmsError, frsmId, mmsConnectionFileReadHandler, self);
if (mmsError != MMS_ERROR_NONE) {
IedClientError err = iedConnection_mapMmsErrorToIedError(mmsError);
handler(invokeId, call->callbackParameter, err, invokeId, NULL, 0, false);
/* close file */
MmsConnection_fileCloseAsync(self->connection, &mmsError, frsmId, mmsConnectionFileCloseHandler, self);
if (mmsError != MMS_ERROR_NONE)
iedConnection_releaseOutstandingCall(self, call);
}
}
}
else {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
}
uint32_t
IedConnection_getFileAsync(IedConnection self, IedClientError* error, const char* fileName, IedConnection_GetFileAsyncHandler 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_fileOpenAsync(self->connection, &err, fileName, 0, mmsConnectionFileOpenHandler, self);
*error = iedConnection_mapMmsErrorToIedError(err);
if (err != MMS_ERROR_NONE) {
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
return call->invokeId;
}
void void
IedConnection_setFilestoreBasepath(IedConnection self, const char* basepath) IedConnection_setFilestoreBasepath(IedConnection self, const char* basepath)
{ {
@ -3019,7 +3175,7 @@ getDataSetHandlerInternal(uint32_t invokeId, void* parameter, MmsError err, MmsV
IedConnection_ReadDataSetHandler handler = (IedConnection_ReadDataSetHandler) call->callback; IedConnection_ReadDataSetHandler handler = (IedConnection_ReadDataSetHandler) call->callback;
ClientDataSet dataSet = (ClientDataSet) call->specificParameter; ClientDataSet dataSet = (ClientDataSet) call->specificParameter;
char* dataSetReference = (char*) call->specificParameter2; char* dataSetReference = (char*) call->specificParameter2.pointer;
if (value != NULL) { if (value != NULL) {
@ -3108,9 +3264,9 @@ IedConnection_readDataSetValuesAsync(IedConnection self, IedClientError* error,
call->specificParameter = dataSet; call->specificParameter = dataSet;
if (dataSet == NULL) if (dataSet == NULL)
call->specificParameter2 = StringUtils_copyString(dataSetReference); call->specificParameter2.pointer = StringUtils_copyString(dataSetReference);
else else
call->specificParameter2 = NULL; call->specificParameter2.pointer = NULL;
MmsError err = MMS_ERROR_NONE; MmsError err = MMS_ERROR_NONE;
@ -3126,7 +3282,7 @@ IedConnection_readDataSetValuesAsync(IedConnection self, IedClientError* error,
if (err != MMS_ERROR_NONE) if (err != MMS_ERROR_NONE)
*error = iedConnection_mapMmsErrorToIedError(err); *error = iedConnection_mapMmsErrorToIedError(err);
GLOBAL_FREEMEM(call->specificParameter2); GLOBAL_FREEMEM(call->specificParameter2.pointer);
iedConnection_releaseOutstandingCall(self, call); iedConnection_releaseOutstandingCall(self, call);

@ -2658,6 +2658,48 @@ LIB61850_API uint32_t
IedConnection_getFile(IedConnection self, IedClientError* error, const char* fileName, IedClientGetFileHandler handler, IedConnection_getFile(IedConnection self, IedClientError* error, const char* fileName, IedClientGetFileHandler handler,
void* handlerParameter); void* handlerParameter);
/**
* \brief User provided handler to receive the data of the asynchronous GetFile request
*
* This handler will be invoked whenever the clients receives a data block from
* the server. The API user has to copy the data to another location before returning.
* The other location could for example be a file in the clients file system. When the
* last data block is received the moreFollows parameter will be set to false.
*
* \param invokeId invoke ID of the message containing the received data
* \param parameter user provided parameter passed to the callback
* \param err error code in case of an error or IED_ERROR_OK
* \param originalInvokeId the invoke ID of the original (first) request. This is usually the request to open the file.
* \param buffer the buffer that contains the received file data
* \param bytesRead the number of bytes read into the buffer
* \param moreFollows indicates that more file data is following
*/
typedef bool
(*IedConnection_GetFileAsyncHandler) (uint32_t invokeId, void* parameter, IedClientError err, uint32_t originalInvokeId,
uint8_t* buffer, uint32_t bytesRead, bool moreFollows);
/**
* \brief Implementation of the GetFile ACSI service - asynchronous version
*
* Download a file from the server.
*
* NOTE: This function can cause several request messages to be sent until the complete file is received
* or the file transfer is canceled. It allocates a background task and an outstanding call slot.
*
* \param self the connection object
* \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
*
* \return invokeId of the first sent request
*/
LIB61850_API uint32_t
IedConnection_getFileAsync(IedConnection self, IedClientError* error, const char* fileName, IedConnection_GetFileAsyncHandler handler,
void* parameter);
/** /**
* \brief Set the virtual filestore basepath for the setFile service * \brief Set the virtual filestore basepath for the setFile service
* *

@ -38,7 +38,16 @@ struct sIedConnectionOutstandingCall {
void* callback; void* callback;
void* callbackParameter; void* callbackParameter;
void* specificParameter; /* function/service specific parameter */ void* specificParameter; /* function/service specific parameter */
void* specificParameter2; /* function/service specific parameter */
union {
void* pointer;
struct {
int32_t frsmId;
uint32_t originalInvokeId;
} getFileInfo;
} specificParameter2; /* function/service specific parameter */
//void* specificParameter2; /* function/service specific parameter */
}; };
struct sIedConnection struct sIedConnection

Loading…
Cancel
Save