History data without data logger

Questions regarding the use of the ANSI C SDK for Server or Client development or integration into customer products ...

Moderator: uasdkc

Post Reply
teal
Jr. Member
Jr. Member
Posts: 3
Joined: 04 Jun 2014, 14:32

History data without data logger

Post by teal »

Hello,

I have some sort of trouble with historizing my data variable.
I do not want to use data logger because I already have complete history data on my server-side and I just want to put it in a_pHistoryReadRawModifiedCtx->pResponse manually.
Unfortunately, this is complete impossible without sources. I want to buy license but first, you know, I want get my solution worked.
So is there any way to put my own history data without having data logger running?

I even try worse trick like this code in my HistoryReadRawModifiedAsync function:

Code: Select all

...
                OpcUa_HistoryReadResult *pHistoryResult =
                     &a_pHistoryReadRawModifiedCtx->pResponse->Results[i];

                // create fictive logger to manually fulfil it.
                OpcUa_Int data_logger = UaServer_DataLogger_Create();
                OpcUa_Int data_logger_value;
                data_logger_value = UaServer_DataLogger_CreateDataLogItem(data_logger,
                        &a_pHistoryReadRawModifiedCtx->pNodesToRead[i].NodeId, 0, NULL, 1);
                UaServer_DataLogger_Start(data_logger);

                // generating some example history data.
                for (j = 0; j < 2; ++j)
                {
                    OpcUa_DataValue* value = (OpcUa_DataValue*)OpcUa_Alloc(sizeof(OpcUa_DataValue));
                    OpcUa_DataValue_Initialize(value);
                    value->Value.Datatype = OpcUaType_Double;
                    value->Value.Value.Double = rand();
                    value->ServerTimestamp = OpcUa_DateTime_UtcNow(); // no matter
                    value->SourceTimestamp = value->ServerTimestamp;

                    // manual put into logger
                    UaServer_DataLogger_LogValue(data_logger, data_logger_value, value);
                }

                // use logger magic to get history data
                a_pHistoryReadRawModifiedCtx->pResponse->Results[i].StatusCode = 
                    UaServer_DataLogger_ReadValues(data_logger, data_logger_value,
                        a_pHistoryReadRawModifiedCtx->pHistoryReadRawModifiedDetails,
                        a_pHistoryReadRawModifiedCtx->TimestampsToReturn,
                        a_pHistoryReadRawModifiedCtx->ReleaseContinuationPoints,
                        &a_pHistoryReadRawModifiedCtx->pNodesToRead[i], pHistoryResult);

                UaServer_DataLogger_Stop(data_logger);
                UaServer_DataLogger_DeleteDataLogItemWithHistory(data_logger, data_logger_value);
                UaServer_DataLogger_Delete(data_logger);
...
but no luck.

Maybe there is some way to access pHistoryResult data structure. I dont know how to manage OpcUa_HistoryReadResult structure (and its secret part OpcUa_ExtensionObject HistoryData).

Thanks.

teal
Jr. Member
Jr. Member
Posts: 3
Joined: 04 Jun 2014, 14:32

Re: History data without data logger

Post by teal »

Ok, I have managed to create a workaround for previous code.
I replaced logger pFctReadValues function to my own:

Code: Select all

OpcUa_StatusCode DataLogger_ReadValues(OpcUa_Int a_hLogger, OpcUa_Int a_hItem, OpcUa_DateTime a_startTime,
    OpcUa_DateTime a_endTime, OpcUa_Boolean a_bInverse, OpcUa_UInt32 *a_puNumValues,
    OpcUa_DataValue *value, OpcUa_ByteString *a_pbsContinuationPoint)
{
    int i = 0;
    if (a_pbsContinuationPoint)
    {
        OpcUa_Int64 time;
        memcpy(&time, &a_startTime, sizeof(OpcUa_Int64));
        *a_puNumValues = 100; // for example
        for (i = 0; i < 100; ++i)
        {
            value[i].Value.Datatype = OpcUaType_Double;
            value[i].Value.Value.Double = rand(); // example values
            time += 1000000;
            memcpy(&a_startTime, &time, sizeof(OpcUa_Int64));
            value[i].ServerTimestamp = a_startTime;
            value[i].SourceTimestamp = a_startTime;
        }
    }
    else
    {
        *a_puNumValues = 0;
    }

    return OpcUa_Good;
}
Now it is works like I want.
Pleace correct me if there are better ways.

samboy
Jr. Member
Jr. Member
Posts: 4
Joined: 11 Jun 2014, 20:31

Re: History data without data logger

Post by samboy »

Hello teal,

thanks for your information.
Could I ask you, in which file have you written the second code?

I would like to use UA server get the data from mysql database and I think your code gives me an Idea. Maybe I can replace the rand() as my real data with sql query language.

Best regards.

samboy

teal
Jr. Member
Jr. Member
Posts: 3
Joined: 04 Jun 2014, 14:32

Re: History data without data logger

Post by teal »

Hello samboy,

In Subscription_Initialize() function I created fictive data logger like this:

Code: Select all

    g_data_logger = UaServer_DataLogger_Create();
    logger = UaServer_DataLogger_Get(g_data_logger);
    logger->pFctReadValues = DataLogger_ReadValues;
DataLogger_ReadValues() - this is my own function, just described above.
If you want to put your own data to logger, in function CustomProvider_HistoryRead() you should prepare the data into mutex-protected dict with unique key which is (as for me) the node id. Then in function CustomProvider_HistoryRead() you have to do this:

Code: Select all

                a_pHistoryReadRawModifiedCtx->pResponse->Results[i].StatusCode = 
                    UaServer_DataLogger_ReadValues(g_data_logger, 
                        node_id->Identifier.Numeric, // your node id
                        a_pHistoryReadRawModifiedCtx->pHistoryReadRawModifiedDetails,
                        a_pHistoryReadRawModifiedCtx->TimestampsToReturn,
                        a_pHistoryReadRawModifiedCtx->ReleaseContinuationPoints,
                        &a_pHistoryReadRawModifiedCtx->pNodesToRead[i], pHistoryResult);
this code calls your DataLogger_ReadValues(), and you will see your unique node identifier (OpcUa_Int a_hItem) as input parameter. Replace rand() with your values from the dict to push them into read stream. That's all.
This is ugly solution and looks like a hack, but I do not figure out a better way till I have no SDK sources.

samboy
Jr. Member
Jr. Member
Posts: 4
Joined: 11 Jun 2014, 20:31

Re: History data without data logger

Post by samboy »

Hello teal,

thanks a lot for your quick reply. I think your method is great and your answer does give me a good idea. I will try it!
thank you again for sharing your experience.

samboy

Post Reply