Comments (1)
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)
- Version 1.4 not linkable with debian linux HOT 2
- Error building nodesetloader in Open62541 library version 1.4.0. HOT 6
- CMake Macros are no longer installed since #6369 HOT 4
- Custom DataType array items changing to ExtensionObject HOT 2
- 'client_encryption.c' returns a 'BadCertificateRevocationUnknown' error
- Guidance for unit testing without UA_ENABLE_ALLOW_REUSEADDR HOT 1
- Help with session disconnect sending and receiving requests from client HOT 1
- At the publisher_rt_level, the UA_String type is not supported HOT 1
- QUESTION - How to add args to callback function HOT 4
- 1.4 Branch: Failure to build on FreeBSD HOT 4
- PubSub UDP interface name HOT 6
- Global Declarations Hides Local Declarations HOT 3
- NOT ISSUE! - Fix Suggestion for MBedTLS 3.6.0 LTS for WIN64
- Problems when enabling encryption as flag in cmake command HOT 4
- Failure to build v1.4 with gcc/mingw HOT 1
- Access OPCUA server Siemens Sinumerik HOT 1
- Possible null pointer access in UA_parseEndpointUrl HOT 2
- No return value from server-method and status code *uncertain* HOT 4
- Increasing delay of UA_DateTime_Now() on embedded device HOT 2
- somewhat inconsistent naming for data type APIs and other APIs HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from open62541.