ua_historydatagathering_default.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  4. *
  5. * Copyright 2018 (c) basysKom GmbH <opensource@basyskom.com> (Author: Peter Rustler)
  6. */
  7. #include <string.h>
  8. #include <open62541/client_subscriptions.h>
  9. #include "ua_historydatagathering_default.h"
  10. typedef struct {
  11. UA_NodeId nodeId;
  12. UA_HistorizingNodeIdSettings setting;
  13. UA_MonitoredItemCreateResult monitoredResult;
  14. } UA_NodeIdStoreContextItem_gathering_default;
  15. typedef struct {
  16. UA_NodeIdStoreContextItem_gathering_default *dataStore;
  17. size_t storeEnd;
  18. size_t storeSize;
  19. } UA_NodeIdStoreContext;
  20. static void
  21. dataChangeCallback_gathering_default(UA_Server *server,
  22. UA_UInt32 monitoredItemId,
  23. void *monitoredItemContext,
  24. const UA_NodeId *nodeId,
  25. void *nodeContext,
  26. UA_UInt32 attributeId,
  27. const UA_DataValue *value)
  28. {
  29. UA_NodeIdStoreContextItem_gathering_default *context = (UA_NodeIdStoreContextItem_gathering_default*)monitoredItemContext;
  30. context->setting.historizingBackend.serverSetHistoryData(server,
  31. context->setting.historizingBackend.context,
  32. NULL,
  33. NULL,
  34. nodeId,
  35. UA_TRUE,
  36. value);
  37. }
  38. static UA_NodeIdStoreContextItem_gathering_default*
  39. getNodeIdStoreContextItem_gathering_default(UA_NodeIdStoreContext *context,
  40. const UA_NodeId *nodeId)
  41. {
  42. for (size_t i = 0; i < context->storeEnd; ++i) {
  43. if (UA_NodeId_equal(&context->dataStore[i].nodeId, nodeId)) {
  44. return &context->dataStore[i];
  45. }
  46. }
  47. return NULL;
  48. }
  49. static UA_StatusCode
  50. startPoll(UA_Server *server, UA_NodeIdStoreContextItem_gathering_default *item)
  51. {
  52. UA_MonitoredItemCreateRequest monitorRequest =
  53. UA_MonitoredItemCreateRequest_default(item->nodeId);
  54. monitorRequest.requestedParameters.samplingInterval = (double)item->setting.pollingInterval;
  55. monitorRequest.monitoringMode = UA_MONITORINGMODE_REPORTING;
  56. item->monitoredResult =
  57. UA_Server_createDataChangeMonitoredItem(server,
  58. UA_TIMESTAMPSTORETURN_BOTH,
  59. monitorRequest,
  60. item,
  61. &dataChangeCallback_gathering_default);
  62. return item->monitoredResult.statusCode;
  63. }
  64. static UA_StatusCode
  65. stopPoll(UA_Server *server, UA_NodeIdStoreContextItem_gathering_default *item)
  66. {
  67. UA_StatusCode retval = UA_Server_deleteMonitoredItem(server, item->monitoredResult.monitoredItemId);
  68. UA_MonitoredItemCreateResult_init(&item->monitoredResult);
  69. return retval;
  70. }
  71. static UA_StatusCode
  72. stopPoll_gathering_default(UA_Server *server,
  73. void *context,
  74. const UA_NodeId *nodeId)
  75. {
  76. UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext *)context;
  77. UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(ctx, nodeId);
  78. if (!item) {
  79. return UA_STATUSCODE_BADNODEIDUNKNOWN;
  80. }
  81. if (item->setting.historizingUpdateStrategy != UA_HISTORIZINGUPDATESTRATEGY_POLL)
  82. return UA_STATUSCODE_BADNODEIDINVALID;
  83. if (item->monitoredResult.monitoredItemId == 0)
  84. return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
  85. return stopPoll(server, item);
  86. }
  87. static UA_StatusCode
  88. startPoll_gathering_default(UA_Server *server,
  89. void *context,
  90. const UA_NodeId *nodeId)
  91. {
  92. UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext *)context;
  93. UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(ctx, nodeId);
  94. if (!item) {
  95. return UA_STATUSCODE_BADNODEIDUNKNOWN;
  96. }
  97. if (item->setting.historizingUpdateStrategy != UA_HISTORIZINGUPDATESTRATEGY_POLL)
  98. return UA_STATUSCODE_BADNODEIDINVALID;
  99. if (item->monitoredResult.monitoredItemId > 0)
  100. return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
  101. return startPoll(server, item);
  102. }
  103. static UA_StatusCode
  104. registerNodeId_gathering_default(UA_Server *server,
  105. void *context,
  106. const UA_NodeId *nodeId,
  107. const UA_HistorizingNodeIdSettings setting)
  108. {
  109. UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context;
  110. if (getNodeIdStoreContextItem_gathering_default(ctx, nodeId)) {
  111. return UA_STATUSCODE_BADNODEIDEXISTS;
  112. }
  113. if (ctx->storeEnd >= ctx->storeSize) {
  114. size_t newStoreSize = ctx->storeSize * 2;
  115. ctx->dataStore = (UA_NodeIdStoreContextItem_gathering_default*)UA_realloc(ctx->dataStore, (newStoreSize * sizeof(UA_NodeIdStoreContextItem_gathering_default)));
  116. if (!ctx->dataStore) {
  117. ctx->storeSize = 0;
  118. return UA_STATUSCODE_BADOUTOFMEMORY;
  119. }
  120. ctx->storeSize = newStoreSize;
  121. }
  122. UA_NodeId_copy(nodeId, &ctx->dataStore[ctx->storeEnd].nodeId);
  123. size_t current = ctx->storeEnd;
  124. ctx->dataStore[current].setting = setting;
  125. ++ctx->storeEnd;
  126. return UA_STATUSCODE_GOOD;
  127. }
  128. static const UA_HistorizingNodeIdSettings*
  129. getHistorizingSetting_gathering_default(UA_Server *server,
  130. void *context,
  131. const UA_NodeId *nodeId)
  132. {
  133. UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context;
  134. UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(ctx, nodeId);
  135. if (item) {
  136. return &item->setting;
  137. }
  138. return NULL;
  139. }
  140. static void
  141. deleteMembers_gathering_default(UA_HistoryDataGathering *gathering)
  142. {
  143. if (gathering == NULL || gathering->context == NULL)
  144. return;
  145. UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)gathering->context;
  146. for (size_t i = 0; i < ctx->storeEnd; ++i) {
  147. UA_NodeId_deleteMembers(&ctx->dataStore[i].nodeId);
  148. // There is still a monitored item present for this gathering
  149. // You need to remove it with UA_Server_deleteMonitoredItem
  150. UA_assert(ctx->dataStore[i].monitoredResult.monitoredItemId == 0);
  151. }
  152. UA_free(ctx->dataStore);
  153. UA_free(gathering->context);
  154. }
  155. static UA_Boolean
  156. updateNodeIdSetting_gathering_default(UA_Server *server,
  157. void *context,
  158. const UA_NodeId *nodeId,
  159. const UA_HistorizingNodeIdSettings setting)
  160. {
  161. UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context;
  162. UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(ctx, nodeId);
  163. if (!item) {
  164. return false;
  165. }
  166. stopPoll_gathering_default(server, context, nodeId);
  167. item->setting = setting;
  168. return true;
  169. }
  170. static void
  171. setValue_gathering_default(UA_Server *server,
  172. void *context,
  173. const UA_NodeId *sessionId,
  174. void *sessionContext,
  175. const UA_NodeId *nodeId,
  176. UA_Boolean historizing,
  177. const UA_DataValue *value)
  178. {
  179. UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context;
  180. UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(ctx, nodeId);
  181. if (!item) {
  182. return;
  183. }
  184. if (item->setting.historizingUpdateStrategy == UA_HISTORIZINGUPDATESTRATEGY_VALUESET) {
  185. item->setting.historizingBackend.serverSetHistoryData(server,
  186. item->setting.historizingBackend.context,
  187. sessionId,
  188. sessionContext,
  189. nodeId,
  190. historizing,
  191. value);
  192. }
  193. }
  194. UA_HistoryDataGathering
  195. UA_HistoryDataGathering_Default(size_t initialNodeIdStoreSize)
  196. {
  197. UA_HistoryDataGathering gathering;
  198. memset(&gathering, 0, sizeof(UA_HistoryDataGathering));
  199. gathering.setValue = &setValue_gathering_default;
  200. gathering.getHistorizingSetting = &getHistorizingSetting_gathering_default;
  201. gathering.registerNodeId = &registerNodeId_gathering_default;
  202. gathering.startPoll = &startPoll_gathering_default;
  203. gathering.stopPoll = &stopPoll_gathering_default;
  204. gathering.deleteMembers = &deleteMembers_gathering_default;
  205. gathering.updateNodeIdSetting = &updateNodeIdSetting_gathering_default;
  206. UA_NodeIdStoreContext *context = (UA_NodeIdStoreContext*)UA_calloc(1, sizeof(UA_NodeIdStoreContext));
  207. context->storeEnd = 0;
  208. context->storeSize = initialNodeIdStoreSize;
  209. context->dataStore = (UA_NodeIdStoreContextItem_gathering_default*)UA_calloc(initialNodeIdStoreSize, sizeof(UA_NodeIdStoreContextItem_gathering_default));
  210. gathering.context = context;
  211. return gathering;
  212. }