Giter Site home page Giter Site logo

"BadDataEncodingInvalid" when trying to view historical event using UA_Client_HistoryRead_events with ABB server about open62541 HOT 1 CLOSED

AdrianMadajewski avatar AdrianMadajewski commented on June 8, 2024
"BadDataEncodingInvalid" when trying to view historical event using UA_Client_HistoryRead_events with ABB server

from open62541.

Comments (1)

AdrianMadajewski avatar AdrianMadajewski commented on June 8, 2024

I've managed to fix the code - but I had to overwrite the wrapper for the UA_Client_HistoryRead_events(). The main issue was that according to the OPC Foundation documentation docs the UA_QualifiedName field for the UA_HistoryReadValueId.encoding in my case should not be set up (in the sample implementation of the read service it is set as "") because for that the server shall decide what type of encoding to use. It worked. I can read historical events.

Here is a code that was changed.

static UA_HistoryReadResponse
my__UA_Client_HistoryRead(UA_Client *client, const UA_NodeId *nodeId,
    UA_ExtensionObject* details, UA_String indexRange,
    UA_TimestampsToReturn timestampsToReturn,
    UA_ByteString continuationPoint, UA_Boolean releaseConti) {

    UA_HistoryReadValueId item;
    UA_HistoryReadValueId_init(&item);

    item.nodeId = *nodeId;
    item.indexRange = indexRange;
    item.continuationPoint = continuationPoint;
    // item.dataEncoding = UA_QUALIFIEDNAME(0, "");
    // This line upon removal fix my issues - shouldn't it be default behaviour for the server 
    // to automatically choose the encoding as stated in the docs? 

    UA_HistoryReadRequest request;
    UA_HistoryReadRequest_init(&request);

    request.nodesToRead = &item;
    request.nodesToReadSize = 1;
    request.timestampsToReturn = timestampsToReturn; // Defaults to Source
    request.releaseContinuationPoints = releaseConti; // No values are returned, if true

    /* Build ReadDetails */
    request.historyReadDetails = *details;

    return UA_Client_Service_historyRead(client, request);
}

UA_StatusCode my__UA_Client_HistoryRead_service(UA_Client *client, const UA_NodeId *nodeId,
    const UA_HistoricalIteratorCallback callback,
    UA_ExtensionObject *details, UA_String indexRange,
    UA_TimestampsToReturn timestampsToReturn,
    void *callbackContext) {

    UA_ByteString continuationPoint = UA_BYTESTRING_NULL;
    UA_Boolean continuationAvail = false;
    UA_Boolean fetchMore = false;
    UA_StatusCode retval = UA_STATUSCODE_GOOD;

    do {
        /* We release the continuation point, if no more data is requested by the user */
        UA_Boolean cleanup = !fetchMore && continuationAvail;
        UA_HistoryReadResponse response =
            my__UA_Client_HistoryRead(client, nodeId, details, indexRange, timestampsToReturn, continuationPoint, cleanup);

        if (cleanup) {
            retval = response.responseHeader.serviceResult;
        cleanup:    UA_HistoryReadResponse_clear(&response);
            UA_ByteString_clear(&continuationPoint);
            return retval;
        }

        retval = response.responseHeader.serviceResult;
        if (retval == UA_STATUSCODE_GOOD) {
            if (response.resultsSize == 1)
                retval = response.results[0].statusCode;
            else
                retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
        }
        if (!UA_StatusCode_isEqualTop(retval, UA_STATUSCODE_GOOD))
            goto cleanup;

        UA_HistoryReadResult *res = response.results;

        /* Clear old and check / store new continuation point */
        UA_ByteString_clear(&continuationPoint);
        UA_ByteString_copy(&res->continuationPoint, &continuationPoint);
        continuationAvail = !UA_ByteString_equal(&continuationPoint, &UA_BYTESTRING_NULL);

        /* Client callback with possibility to request further values */
        fetchMore = callback(client, nodeId, continuationAvail, &res->historyData, callbackContext);

        /* Regular cleanup */
        UA_HistoryReadResponse_clear(&response);
    } while (continuationAvail);

    return retval;
}

UA_StatusCode
my_UA_Client_HistoryRead_events(UA_Client *client, const UA_NodeId *nodeId,
    const UA_HistoricalIteratorCallback callback,
    UA_DateTime startTime, UA_DateTime endTime,
    UA_String indexRange, const UA_EventFilter filter, UA_UInt32 numValuesPerNode,
    UA_TimestampsToReturn timestampsToReturn, void *callbackContext) {

    UA_ReadEventDetails details;
    UA_ReadEventDetails_init(&details);
    details.filter = filter;

    // At least two of the following parameters must be set
    details.numValuesPerNode = numValuesPerNode; // 0 = return all / max server is capable of
    details.startTime = startTime;
    details.endTime = endTime;

    UA_ExtensionObject detailsExtensionObject;
    UA_ExtensionObject_init(&detailsExtensionObject);
    detailsExtensionObject.content.decoded.type = &UA_TYPES[UA_TYPES_READEVENTDETAILS];
    detailsExtensionObject.content.decoded.data = &details;
    detailsExtensionObject.encoding = UA_EXTENSIONOBJECT_DECODED;

    return my__UA_Client_HistoryRead_service(client, nodeId, callback, &detailsExtensionObject,
        indexRange, timestampsToReturn, callbackContext);
}

UA_StatusCode my_UA_Client_HistoryRead_service_rawMod(UA_Client *client, const UA_NodeId *nodeId,
    const UA_HistoricalIteratorCallback callback,
    UA_DateTime startTime, UA_DateTime endTime,
    UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 numValuesPerNode,
    UA_Boolean readModified, UA_TimestampsToReturn timestampsToReturn,
    void *callbackContext) {

    UA_ReadRawModifiedDetails details;
    UA_ReadRawModifiedDetails_init(&details);
    details.isReadModified = readModified; // Return only modified values
    details.returnBounds = returnBounds;   // Return values pre / post given range

    // At least two of the following parameters must be set
    details.numValuesPerNode = numValuesPerNode;   // 0 = return all / max server is capable of
    details.startTime = startTime;
    details.endTime = endTime;

    UA_ExtensionObject detailsExtensionObject;
    UA_ExtensionObject_init(&detailsExtensionObject);
    detailsExtensionObject.content.decoded.type = &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS];
    detailsExtensionObject.content.decoded.data = &details;
    detailsExtensionObject.encoding = UA_EXTENSIONOBJECT_DECODED;

    return my__UA_Client_HistoryRead_service(client, nodeId, callback,
        &detailsExtensionObject, indexRange,
        timestampsToReturn, callbackContext);
}

static UA_Boolean
readEvents(const UA_HistoryEvent *data) {
	printf("readEvent Value count: %lu\n", (long unsigned)data->eventsSize);
	for (size_t i = 0; i < data->eventsSize; ++i) {
		printf("Processing event: %lu\n", (long unsigned)i);
}

static UA_Boolean
readHist(UA_Client *client, const UA_NodeId *nodeId,
	UA_Boolean moreDataAvailable,
	const UA_ExtensionObject *data, void *unused) {
	printf("\nRead historical callback:\n");
	printf("\tHas more data:\t%d\n\n", moreDataAvailable);
	if (data->content.decoded.type == &UA_TYPES[UA_TYPES_HISTORYEVENT]) {
		return readEvents((UA_HistoryEvent*)data->content.decoded.data);
	}
	return true;
}

int main(int argc, char *argv[]) 
{
    ...
    retval = my_UA_Client_HistoryRead_events(client, &node, readHist,
        UA_DateTime_fromStruct(start), UA_DateTime_fromStruct(end), UA_STRING_NULL, filter,
        10, UA_TIMESTAMPSTORETURN_BOTH, (void*)UA_FALSE);
}

Shouldn't it be set as default? (see code comment) I think that there may be issue with comparing and empty QualifiedName with the UA_QUALIFIEDNAME(0, "") and that's why the server respond with BadDataEncodingInvalid

from open62541.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.