client_historical.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
  2. * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
  3. /* Enable POSIX features */
  4. #if !defined(_XOPEN_SOURCE) && !defined(_WRS_KERNEL)
  5. # define _XOPEN_SOURCE 600
  6. #endif
  7. #ifndef _DEFAULT_SOURCE
  8. # define _DEFAULT_SOURCE
  9. #endif
  10. /* On older systems we need to define _BSD_SOURCE.
  11. * _DEFAULT_SOURCE is an alias for that. */
  12. #ifndef _BSD_SOURCE
  13. # define _BSD_SOURCE
  14. #endif
  15. #include <stdio.h>
  16. #include "open62541.h"
  17. #ifdef _WIN32
  18. # include <windows.h>
  19. # define UA_sleep_ms(X) Sleep(X)
  20. #else
  21. # include <unistd.h>
  22. # define UA_sleep_ms(X) usleep(X * 1000)
  23. #endif
  24. static UA_Boolean
  25. readHist(const UA_NodeId nodeId, const UA_Boolean isInverse,
  26. const UA_Boolean moreDataAvailable,
  27. const UA_HistoryData *data, void *isDouble) {
  28. printf("\nRead historical callback:\n");
  29. printf("\tValue count:\t%u\n", (UA_UInt32)data->dataValuesSize);
  30. printf("\tIs inverse:\t%d\n", isInverse);
  31. printf("\tHas more data:\t%d\n\n", moreDataAvailable);
  32. /* Iterate over all values */
  33. for (UA_UInt32 i = 0; i < data->dataValuesSize; ++i)
  34. {
  35. UA_DataValue val = data->dataValues[i];
  36. /* If there is no value, we are out of bounds or something bad hapened */
  37. if (!val.hasValue) {
  38. if (val.hasStatus) {
  39. if (val.status == UA_STATUSCODE_BADBOUNDNOTFOUND)
  40. printf("Skipping bounds (i=%u)\n\n", i);
  41. else
  42. printf("Skipping (i=%u) (status=0x%08x -> %s)\n\n", i, val.status, UA_StatusCode_name(val.status));
  43. }
  44. continue;
  45. }
  46. /* The handle is used to determine double and byte request */
  47. if ((UA_Boolean)isDouble) {
  48. UA_Double hrValue = *(UA_Double *)val.value.data;
  49. printf("ByteValue (i=%u) %f\n", i, hrValue);
  50. }
  51. else {
  52. UA_Byte hrValue = *(UA_Byte *)val.value.data;
  53. printf("DoubleValue (i=%u) %d\n", i, hrValue);
  54. }
  55. /* Print status and timestamps */
  56. if (val.hasStatus)
  57. printf("Status 0x%08x\n", val.status);
  58. if (val.hasServerTimestamp) {
  59. UA_DateTimeStruct dts = UA_DateTime_toStruct(val.serverTimestamp);
  60. printf("ServerTime: %02u-%02u-%04u %02u:%02u:%02u.%03u\n",
  61. dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
  62. }
  63. if (val.hasSourceTimestamp) {
  64. UA_DateTimeStruct dts = UA_DateTime_toStruct(val.sourceTimestamp);
  65. printf("ServerTime: %02u-%02u-%04u %02u:%02u:%02u.%03u\n",
  66. dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
  67. }
  68. printf("\n");
  69. }
  70. /* We want more data! */
  71. return true;
  72. }
  73. int main(int argc, char *argv[]) {
  74. UA_Client *client = UA_Client_new(UA_ClientConfig_default);
  75. /* Connect to the Unified Automation demo server */
  76. UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:48020");
  77. if(retval != UA_STATUSCODE_GOOD) {
  78. UA_Client_delete(client);
  79. return (int)retval;
  80. }
  81. /* Read, if data logging is active */
  82. UA_Boolean active = UA_FALSE;
  83. printf("Reading, if data logging is active (4, \"Demo.History.DataLoggerActive\"):\n");
  84. UA_Variant *val = UA_Variant_new();
  85. retval = UA_Client_readValueAttribute(client, UA_NODEID_STRING(4, "Demo.History.DataLoggerActive"), val);
  86. if (retval == UA_STATUSCODE_GOOD && UA_Variant_isScalar(val) &&
  87. val->type == &UA_TYPES[UA_TYPES_BOOLEAN]) {
  88. active = *(UA_Boolean*)val->data;
  89. if (active)
  90. printf("The data logging is active. Continue.\n");
  91. else
  92. printf("The data logging is not active!\n");
  93. }
  94. else {
  95. printf("Failed to read data logging status.\n");
  96. UA_Variant_delete(val);
  97. goto cleanup;
  98. }
  99. UA_Variant_delete(val);
  100. #ifdef UA_ENABLE_METHODCALLS
  101. /* Active server side data logging via remote method call */
  102. if (!active) {
  103. printf("Activate data logging.\n");
  104. retval = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
  105. UA_NODEID_STRING(4, "Demo.History.StartLogging"), 0, NULL, NULL, NULL);
  106. if (retval != UA_STATUSCODE_GOOD) {
  107. printf("Start method call failed.\n");
  108. goto cleanup;
  109. }
  110. /* The server logs a value every 50ms by default */
  111. printf("Successfully started data logging. Let the server collect data for 2000ms..\n");
  112. UA_sleep_ms(2000);
  113. }
  114. #else
  115. if (!active) {
  116. printf("Method calling is not allowed, you have to active the data logging manually.\n");
  117. goto cleanup;
  118. }
  119. #endif
  120. /* Read historical values (Byte) */
  121. printf("\nStart historical read (4, \"Demo.History.ByteWithHistory\"):\n");
  122. retval = UA_Client_readHistorical_raw(client, UA_NODEID_STRING(4, "Demo.History.ByteWithHistory"), readHist,
  123. UA_DateTime_fromUnixTime(0), UA_DateTime_now(), false, 10, UA_TIMESTAMPSTORETURN_BOTH, (void *)UA_FALSE);
  124. if (retval != UA_STATUSCODE_GOOD) {
  125. printf("Failed.\n");
  126. goto cleanup;
  127. }
  128. /* Read historical values (Double) */
  129. printf("\nStart historical read (4, \"Demo.History.DoubleWithHistory\"):\n");
  130. retval = UA_Client_readHistorical_raw(client, UA_NODEID_STRING(4, "Demo.History.DoubleWithHistory"), readHist,
  131. UA_DateTime_fromUnixTime(0), UA_DateTime_now(), false, 10, UA_TIMESTAMPSTORETURN_BOTH, (void *)UA_TRUE);
  132. if (retval != UA_STATUSCODE_GOOD) {
  133. printf("Failed.\n");
  134. }
  135. cleanup:
  136. UA_Client_disconnect(client);
  137. UA_Client_delete(client);
  138. return (int) retval;
  139. }