b56476b9299ce94245ecd42a42bb256e277f6a4d
[public/netxms.git] / src / libnxcl / datacoll.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Client Library
4 ** Copyright (C) 2004, 2005, 2006, 2007, 2008 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: datacoll.cpp
21 **
22 **/
23
24 #include "libnxcl.h"
25
26
27 //
28 // Load data collection items list for specified node
29 // This function is NOT REENTRANT
30 //
31
32 DWORD LIBNXCL_EXPORTABLE NXCOpenNodeDCIList(NXC_SESSION hSession, DWORD dwNodeId,
33 NXC_DCI_LIST **ppItemList)
34 {
35 return ((NXCL_Session *)hSession)->OpenNodeDCIList(dwNodeId, ppItemList);
36 }
37
38
39 //
40 // Unlock and destroy previously opened node's DCI list
41 //
42
43 DWORD LIBNXCL_EXPORTABLE NXCCloseNodeDCIList(NXC_SESSION hSession, NXC_DCI_LIST *pItemList)
44 {
45 DWORD i, j, dwRetCode = RCC_INVALID_ARGUMENT, dwRqId;
46 CSCPMessage msg;
47
48 if (pItemList != NULL)
49 {
50 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
51
52 msg.SetCode(CMD_UNLOCK_NODE_DCI_LIST);
53 msg.SetId(dwRqId);
54 msg.SetVariable(VID_OBJECT_ID, pItemList->dwNodeId);
55 ((NXCL_Session *)hSession)->SendMsg(&msg);
56
57 dwRetCode = ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
58
59 for(i = 0; i < pItemList->dwNumItems; i++)
60 {
61 for(j = 0; j < pItemList->pItems[i].dwNumSchedules; j++)
62 free(pItemList->pItems[i].ppScheduleList[j]);
63 safe_free(pItemList->pItems[i].ppScheduleList);
64 safe_free(pItemList->pItems[i].pThresholdList);
65 safe_free(pItemList->pItems[i].pszFormula);
66 safe_free(pItemList->pItems[i].pszCustomUnitName);
67 safe_free(pItemList->pItems[i].pszPerfTabSettings);
68 }
69 safe_free(pItemList->pItems);
70 free(pItemList);
71 }
72 return dwRetCode;
73 }
74
75
76 //
77 // Create new data collection item
78 //
79
80 DWORD LIBNXCL_EXPORTABLE NXCCreateNewDCI(NXC_SESSION hSession, NXC_DCI_LIST *pItemList,
81 DWORD *pdwItemId)
82 {
83 DWORD dwRetCode, dwRqId;
84 CSCPMessage msg, *pResponse;
85
86 CHECK_SESSION_HANDLE();
87
88 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
89
90 msg.SetCode(CMD_CREATE_NEW_DCI);
91 msg.SetId(dwRqId);
92 msg.SetVariable(VID_OBJECT_ID, pItemList->dwNodeId);
93 ((NXCL_Session *)hSession)->SendMsg(&msg);
94
95 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
96 if (pResponse != NULL)
97 {
98 dwRetCode = pResponse->GetVariableLong(VID_RCC);
99 if (dwRetCode == RCC_SUCCESS)
100 {
101 *pdwItemId = pResponse->GetVariableLong(VID_DCI_ID);
102
103 // Create new entry in list
104 pItemList->pItems = (NXC_DCI *)realloc(pItemList->pItems,
105 sizeof(NXC_DCI) * (pItemList->dwNumItems + 1));
106 memset(&pItemList->pItems[pItemList->dwNumItems], 0, sizeof(NXC_DCI));
107 pItemList->pItems[pItemList->dwNumItems].dwId = *pdwItemId;
108 pItemList->pItems[pItemList->dwNumItems].iStatus = ITEM_STATUS_ACTIVE;
109 pItemList->pItems[pItemList->dwNumItems].iPollingInterval = 60;
110 pItemList->pItems[pItemList->dwNumItems].iRetentionTime = 30;
111 pItemList->pItems[pItemList->dwNumItems].iDeltaCalculation = DCM_ORIGINAL_VALUE;
112 pItemList->pItems[pItemList->dwNumItems].iAdvSchedule = 0;
113 pItemList->pItems[pItemList->dwNumItems].dwNumSchedules = 0;
114 pItemList->pItems[pItemList->dwNumItems].ppScheduleList = NULL;
115 pItemList->pItems[pItemList->dwNumItems].iProcessAllThresholds = 0;
116 pItemList->pItems[pItemList->dwNumItems].nBaseUnits = DCI_BASEUNITS_OTHER;
117 pItemList->pItems[pItemList->dwNumItems].nMultiplier = 1;
118 pItemList->dwNumItems++;
119 }
120 delete pResponse;
121 }
122 else
123 {
124 dwRetCode = RCC_TIMEOUT;
125 }
126
127 return dwRetCode;
128 }
129
130
131 //
132 // Update data collection item
133 //
134
135 DWORD LIBNXCL_EXPORTABLE NXCUpdateDCI(NXC_SESSION hSession, DWORD dwNodeId, NXC_DCI *pItem)
136 {
137 DWORD i, dwId, dwRqId, dwRetCode;
138 CSCPMessage msg, *pResponse;
139
140 CHECK_SESSION_HANDLE();
141
142 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
143
144 msg.SetCode(CMD_MODIFY_NODE_DCI);
145 msg.SetId(dwRqId);
146 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
147 msg.SetVariable(VID_DCI_ID, pItem->dwId);
148 msg.SetVariable(VID_DCI_DATA_TYPE, (WORD)pItem->iDataType);
149 msg.SetVariable(VID_POLLING_INTERVAL, (DWORD)pItem->iPollingInterval);
150 msg.SetVariable(VID_RETENTION_TIME, (DWORD)pItem->iRetentionTime);
151 msg.SetVariable(VID_DCI_SOURCE_TYPE, (WORD)pItem->iSource);
152 msg.SetVariable(VID_DCI_DELTA_CALCULATION, (WORD)pItem->iDeltaCalculation);
153 msg.SetVariable(VID_DCI_STATUS, (WORD)pItem->iStatus);
154 msg.SetVariable(VID_NAME, pItem->szName);
155 msg.SetVariable(VID_DESCRIPTION, pItem->szDescription);
156 msg.SetVariable(VID_INSTANCE, pItem->szInstance);
157 msg.SetVariable(VID_SYSTEM_TAG, pItem->szSystemTag);
158 msg.SetVariable(VID_DCI_FORMULA, CHECK_NULL_EX(pItem->pszFormula));
159 msg.SetVariable(VID_ALL_THRESHOLDS, (WORD)pItem->iProcessAllThresholds);
160 msg.SetVariable(VID_ADV_SCHEDULE, (WORD)pItem->iAdvSchedule);
161 msg.SetVariable(VID_RESOURCE_ID, pItem->dwResourceId);
162 msg.SetVariable(VID_PROXY_NODE, pItem->dwProxyNode);
163 msg.SetVariable(VID_BASE_UNITS, (WORD)pItem->nBaseUnits);
164 msg.SetVariable(VID_MULTIPLIER, (DWORD)pItem->nMultiplier);
165 if (pItem->pszCustomUnitName != NULL)
166 msg.SetVariable(VID_CUSTOM_UNITS_NAME, pItem->pszCustomUnitName);
167 if (pItem->pszPerfTabSettings)
168 msg.SetVariable(VID_PERFTAB_SETTINGS, pItem->pszPerfTabSettings);
169 if (pItem->iAdvSchedule)
170 {
171 msg.SetVariable(VID_NUM_SCHEDULES, pItem->dwNumSchedules);
172 for(i = 0, dwId = VID_DCI_SCHEDULE_BASE; i < pItem->dwNumSchedules; i++, dwId++)
173 msg.SetVariable(dwId, pItem->ppScheduleList[i]);
174 }
175 else
176 {
177 msg.SetVariable(VID_NUM_SCHEDULES, (DWORD)0);
178 }
179 msg.SetVariable(VID_NUM_THRESHOLDS, pItem->dwNumThresholds);
180 for(i = 0, dwId = VID_DCI_THRESHOLD_BASE; i < pItem->dwNumThresholds; i++, dwId++)
181 {
182 msg.SetVariable(dwId++, pItem->pThresholdList[i].dwId);
183 msg.SetVariable(dwId++, pItem->pThresholdList[i].dwEvent);
184 msg.SetVariable(dwId++, pItem->pThresholdList[i].dwRearmEvent);
185 msg.SetVariable(dwId++, pItem->pThresholdList[i].wFunction);
186 msg.SetVariable(dwId++, pItem->pThresholdList[i].wOperation);
187 msg.SetVariable(dwId++, pItem->pThresholdList[i].dwArg1);
188 msg.SetVariable(dwId++, pItem->pThresholdList[i].dwArg2);
189 msg.SetVariable(dwId++, (DWORD)pItem->pThresholdList[i].nRepeatInterval);
190 msg.SetVariable(dwId++, pItem->pThresholdList[i].szValue);
191 }
192 ((NXCL_Session *)hSession)->SendMsg(&msg);
193
194 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
195 if (pResponse != NULL)
196 {
197 dwRetCode = pResponse->GetVariableLong(VID_RCC);
198 if (dwRetCode == RCC_SUCCESS)
199 {
200 DWORD dwNumMaps, *pdwMapId, *pdwMapIndex;
201
202 // Get index to id mapping for newly created thresholds
203 dwNumMaps = pResponse->GetVariableLong(VID_DCI_NUM_MAPS);
204 if (dwNumMaps > 0)
205 {
206 pdwMapId = (DWORD *)malloc(sizeof(DWORD) * dwNumMaps);
207 pdwMapIndex = (DWORD *)malloc(sizeof(DWORD) * dwNumMaps);
208 pResponse->GetVariableBinary(VID_DCI_MAP_IDS, (BYTE *)pdwMapId, sizeof(DWORD) * dwNumMaps);
209 pResponse->GetVariableBinary(VID_DCI_MAP_INDEXES, (BYTE *)pdwMapIndex, sizeof(DWORD) * dwNumMaps);
210 for(i = 0; i < dwNumMaps; i++)
211 pItem->pThresholdList[ntohl(pdwMapIndex[i])].dwId = ntohl(pdwMapId[i]);
212 free(pdwMapId);
213 free(pdwMapIndex);
214 }
215 }
216 delete pResponse;
217 }
218 else
219 {
220 dwRetCode = RCC_TIMEOUT;
221 }
222
223 return dwRetCode;
224 }
225
226
227 //
228 // Delete data collection item
229 //
230
231 DWORD LIBNXCL_EXPORTABLE NXCDeleteDCI(NXC_SESSION hSession, NXC_DCI_LIST *pItemList,
232 DWORD dwItemId)
233 {
234 DWORD i, j, dwRqId, dwResult = RCC_INVALID_DCI_ID;
235 CSCPMessage msg;
236
237 CHECK_SESSION_HANDLE();
238
239 // Find item with given ID in list
240 for(i = 0; i < pItemList->dwNumItems; i++)
241 if (pItemList->pItems[i].dwId == dwItemId)
242 {
243 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
244
245 msg.SetCode(CMD_DELETE_NODE_DCI);
246 msg.SetId(dwRqId);
247 msg.SetVariable(VID_OBJECT_ID, pItemList->dwNodeId);
248 msg.SetVariable(VID_DCI_ID, dwItemId);
249 ((NXCL_Session *)hSession)->SendMsg(&msg);
250
251 dwResult = ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
252 if (dwResult == RCC_SUCCESS)
253 {
254 // Item was successfully deleted on server, delete it from our list
255 for(j = 0; j < pItemList->pItems[i].dwNumSchedules; j++)
256 free(pItemList->pItems[i].ppScheduleList[j]);
257 safe_free(pItemList->pItems[i].ppScheduleList);
258 safe_free(pItemList->pItems[i].pThresholdList);
259 safe_free(pItemList->pItems[i].pszFormula);
260 safe_free(pItemList->pItems[i].pszCustomUnitName);
261 safe_free(pItemList->pItems[i].pszPerfTabSettings);
262 pItemList->dwNumItems--;
263 memmove(&pItemList->pItems[i], &pItemList->pItems[i + 1],
264 sizeof(NXC_DCI) * (pItemList->dwNumItems - i));
265 }
266 break;
267 }
268 return dwResult;
269 }
270
271
272 //
273 // Set status for multiple DCIs
274 //
275
276 DWORD LIBNXCL_EXPORTABLE NXCSetDCIStatus(NXC_SESSION hSession, DWORD dwNodeId, DWORD dwNumItems,
277 DWORD *pdwItemList, int iStatus)
278 {
279 CSCPMessage msg;
280 DWORD dwRqId;
281
282 CHECK_SESSION_HANDLE();
283
284 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
285
286 msg.SetCode(CMD_SET_DCI_STATUS);
287 msg.SetId(dwRqId);
288 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
289 msg.SetVariable(VID_DCI_STATUS, (WORD)iStatus);
290 msg.SetVariable(VID_NUM_ITEMS, dwNumItems);
291 msg.SetVariableToInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
292 ((NXCL_Session *)hSession)->SendMsg(&msg);
293 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
294 }
295
296
297 //
298 // Find item in list by id and return it's index
299 //
300
301 DWORD LIBNXCL_EXPORTABLE NXCItemIndex(NXC_DCI_LIST *pItemList, DWORD dwItemId)
302 {
303 DWORD i;
304
305 for(i = 0; i < pItemList->dwNumItems; i++)
306 if (pItemList->pItems[i].dwId == dwItemId)
307 return i;
308 return INVALID_INDEX;
309 }
310
311
312 //
313 // Retrieve collected data from server
314 //
315
316 DWORD LIBNXCL_EXPORTABLE NXCGetDCIData(NXC_SESSION hSession, DWORD dwNodeId, DWORD dwItemId,
317 DWORD dwMaxRows, DWORD dwTimeFrom, DWORD dwTimeTo,
318 NXC_DCI_DATA **ppData)
319 {
320 return NXCGetDCIDataEx(hSession, dwNodeId, dwItemId, dwMaxRows, dwTimeFrom, dwTimeTo, ppData, NULL, NULL);
321 }
322
323 DWORD LIBNXCL_EXPORTABLE NXCGetDCIDataEx(NXC_SESSION hSession, DWORD dwNodeId, DWORD dwItemId,
324 DWORD dwMaxRows, DWORD dwTimeFrom, DWORD dwTimeTo,
325 NXC_DCI_DATA **ppData, NXC_DCI_THRESHOLD **thresholds, DWORD *numThresholds)
326 {
327 CSCPMessage msg, *response;
328 DWORD i, dwRqId, dwId, dwResult;
329 BOOL bRun = TRUE;
330
331 CHECK_SESSION_HANDLE();
332
333 msg.SetCode(CMD_GET_DCI_DATA);
334 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
335 msg.SetVariable(VID_DCI_ID, dwItemId);
336
337 // Allocate memory for results and initialize header
338 *ppData = (NXC_DCI_DATA *)malloc(sizeof(NXC_DCI_DATA));
339 (*ppData)->dwNumRows = 0;
340 (*ppData)->dwNodeId = dwNodeId;
341 (*ppData)->dwItemId = dwItemId;
342 (*ppData)->pRows = NULL;
343 if (thresholds != NULL)
344 {
345 *thresholds = NULL;
346 *numThresholds = 0;
347 }
348
349 do
350 {
351 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
352
353 msg.SetId(dwRqId);
354 msg.SetVariable(VID_MAX_ROWS, dwMaxRows);
355 msg.SetVariable(VID_TIME_FROM, dwTimeFrom);
356 msg.SetVariable(VID_TIME_TO, dwTimeTo);
357 ((NXCL_Session *)hSession)->SendMsg(&msg);
358
359 response = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
360 if (response == NULL)
361 {
362 dwResult = RCC_TIMEOUT;
363 break;
364 }
365 dwResult = response->GetVariableLong(VID_RCC);
366 if (dwResult == RCC_SUCCESS)
367 {
368 CSCP_MESSAGE *pRawMsg;
369
370 if ((thresholds != NULL) && (*thresholds == NULL))
371 {
372 *numThresholds = response->GetVariableLong(VID_NUM_THRESHOLDS);
373 *thresholds = (NXC_DCI_THRESHOLD *)malloc(sizeof(NXC_DCI_THRESHOLD) * (*numThresholds));
374 for(i = 0, dwId = VID_DCI_THRESHOLD_BASE; i < *numThresholds; i++, dwId++)
375 {
376 (*thresholds)[i].dwId = response->GetVariableLong(dwId++);
377 (*thresholds)[i].dwEvent = response->GetVariableLong(dwId++);
378 (*thresholds)[i].dwRearmEvent = response->GetVariableLong(dwId++);
379 (*thresholds)[i].wFunction = response->GetVariableShort(dwId++);
380 (*thresholds)[i].wOperation = response->GetVariableShort(dwId++);
381 (*thresholds)[i].dwArg1 = response->GetVariableLong(dwId++);
382 (*thresholds)[i].dwArg2 = response->GetVariableLong(dwId++);
383 (*thresholds)[i].nRepeatInterval = (LONG)response->GetVariableLong(dwId++);
384 response->GetVariableStr(dwId++, (*thresholds)[i].szValue, MAX_STRING_VALUE);
385 }
386 }
387
388 // We wait a long time because data message can be quite large
389 pRawMsg = ((NXCL_Session *)hSession)->WaitForRawMessage(CMD_DCI_DATA, dwRqId, 60000);
390 if (pRawMsg != NULL)
391 {
392 DCI_DATA_HEADER *pHdr;
393 DCI_DATA_ROW *pSrc;
394 NXC_DCI_ROW *pDst;
395 DWORD dwPrevRowCount, dwRecvRows;
396 static WORD m_wRowSize[] = { 8, 8, 12, 12, 260, 12 };
397
398 pHdr = (DCI_DATA_HEADER *)pRawMsg->df;
399 dwRecvRows = ntohl(pHdr->dwNumRows);
400
401 // Allocate memory for results
402 dwPrevRowCount = (*ppData)->dwNumRows;
403 (*ppData)->dwNumRows += dwRecvRows;
404 (*ppData)->wDataType = (WORD)ntohl(pHdr->dwDataType);
405 if ((*ppData)->wDataType > 5)
406 (*ppData)->wDataType = 0;
407 (*ppData)->wRowSize = m_wRowSize[(*ppData)->wDataType];
408 if (dwRecvRows > 0)
409 (*ppData)->pRows = (NXC_DCI_ROW *)realloc((*ppData)->pRows, (*ppData)->dwNumRows * (*ppData)->wRowSize);
410
411 // Convert and copy values from message to rows in result
412 pSrc = (DCI_DATA_ROW *)(((char *)pHdr) + sizeof(DCI_DATA_HEADER));
413 pDst = (NXC_DCI_ROW *)(((char *)((*ppData)->pRows)) + dwPrevRowCount * (*ppData)->wRowSize);
414 for(i = 0; i < dwRecvRows; i++)
415 {
416 pDst->dwTimeStamp = ntohl(pSrc->dwTimeStamp);
417 switch((*ppData)->wDataType)
418 {
419 case DCI_DT_INT:
420 case DCI_DT_UINT:
421 pDst->value.dwInt32 = ntohl(pSrc->value.dwInteger);
422 break;
423 case DCI_DT_INT64:
424 case DCI_DT_UINT64:
425 pDst->value.qwInt64 = ntohq(pSrc->value.qwInt64);
426 break;
427 case DCI_DT_FLOAT:
428 pDst->value.dFloat = ntohd(pSrc->value.dFloat);
429 break;
430 case DCI_DT_STRING:
431 SwapWideString(pSrc->value.szString);
432 #ifdef UNICODE
433 #ifdef UNICODE_UCS4
434 ucs2_to_ucs4(pSrc->value.szString, -1, pDst->value.szString, MAX_STRING_VALUE);
435 #else
436 wcscpy(pDst->value.szString, pSrc->value.szString);
437 #endif
438 #else
439 ucs2_to_mb(pSrc->value.szString, -1, pDst->value.szString, MAX_STRING_VALUE);
440 #endif
441 break;
442 }
443
444 pSrc = (DCI_DATA_ROW *)(((char *)pSrc) + (*ppData)->wRowSize);
445 pDst = (NXC_DCI_ROW *)(((char *)pDst) + (*ppData)->wRowSize);
446 }
447
448 // Shift boundaries
449 if (((dwMaxRows == 0) || (dwMaxRows > MAX_DCI_DATA_RECORDS)) &&
450 (dwRecvRows == MAX_DCI_DATA_RECORDS))
451 {
452 // Shift to last record
453 pDst = (NXC_DCI_ROW *)(((char *)pDst) - (*ppData)->wRowSize);
454 dwTimeTo = pDst->dwTimeStamp - 1; // Assume that we have no more than one value per second
455 if (dwMaxRows > 0)
456 dwMaxRows -= MAX_DCI_DATA_RECORDS;
457 }
458 else
459 {
460 bRun = FALSE;
461 }
462
463 // Destroy message
464 free(pRawMsg);
465 }
466 else
467 {
468 dwResult = RCC_TIMEOUT;
469 }
470 }
471 } while((dwResult == RCC_SUCCESS) && bRun);
472
473 // Destroy already allocated buffer if request was unsuccessful
474 if (dwResult != RCC_SUCCESS)
475 {
476 safe_free((*ppData)->pRows);
477 free(*ppData);
478 if (thresholds != NULL)
479 safe_free(*thresholds);
480 }
481
482 return dwResult;
483 }
484
485
486 //
487 // Destroy DCI result set
488 //
489
490 void LIBNXCL_EXPORTABLE NXCDestroyDCIData(NXC_DCI_DATA *pData)
491 {
492 if (pData != NULL)
493 {
494 safe_free(pData->pRows);
495 free(pData);
496 }
497 }
498
499
500 //
501 // Get pointer to specific row in result set
502 //
503
504 NXC_DCI_ROW LIBNXCL_EXPORTABLE *NXCGetRowPtr(NXC_DCI_DATA *pData, DWORD dwRow)
505 {
506 if (dwRow >= pData->dwNumRows)
507 return NULL;
508
509 return (NXC_DCI_ROW *)(((char *)(pData->pRows)) + dwRow * pData->wRowSize);
510 }
511
512
513 //
514 // Add threshold to item
515 //
516
517 DWORD LIBNXCL_EXPORTABLE NXCAddThresholdToItem(NXC_DCI *pItem, NXC_DCI_THRESHOLD *pThreshold)
518 {
519 DWORD dwIndex;
520
521 dwIndex = pItem->dwNumThresholds++;
522 pItem->pThresholdList = (NXC_DCI_THRESHOLD *)realloc(pItem->pThresholdList,
523 sizeof(NXC_DCI_THRESHOLD) * pItem->dwNumThresholds);
524 memcpy(&pItem->pThresholdList[dwIndex], pThreshold, sizeof(NXC_DCI_THRESHOLD));
525 return dwIndex;
526 }
527
528
529 //
530 // Delete threshold from item
531 //
532
533 BOOL LIBNXCL_EXPORTABLE NXCDeleteThresholdFromItem(NXC_DCI *pItem, DWORD dwIndex)
534 {
535 BOOL bResult = FALSE;
536
537 if (pItem->dwNumThresholds > dwIndex)
538 {
539 pItem->dwNumThresholds--;
540 if (pItem->dwNumThresholds > 0)
541 memmove(&pItem->pThresholdList[dwIndex], &pItem->pThresholdList[dwIndex + 1],
542 sizeof(NXC_DCI_THRESHOLD) * (pItem->dwNumThresholds - dwIndex));
543 bResult = TRUE;
544 }
545 return bResult;
546 }
547
548
549 //
550 // Swap two threshold items
551 //
552
553 BOOL LIBNXCL_EXPORTABLE NXCSwapThresholds(NXC_DCI *pItem, DWORD dwIndex1, DWORD dwIndex2)
554 {
555 BOOL bResult = FALSE;
556 NXC_DCI_THRESHOLD dct;
557
558 if ((pItem->dwNumThresholds > dwIndex1) &&
559 (pItem->dwNumThresholds > dwIndex2) &&
560 (dwIndex1 != dwIndex2))
561 {
562 memcpy(&dct, &pItem->pThresholdList[dwIndex1], sizeof(NXC_DCI_THRESHOLD));
563 memcpy(&pItem->pThresholdList[dwIndex1], &pItem->pThresholdList[dwIndex2], sizeof(NXC_DCI_THRESHOLD));
564 memcpy(&pItem->pThresholdList[dwIndex2], &dct, sizeof(NXC_DCI_THRESHOLD));
565 bResult = TRUE;
566 }
567 return bResult;
568 }
569
570
571 //
572 // Copy data collection items from one node to another
573 //
574
575 DWORD LIBNXCL_EXPORTABLE NXCCopyDCI(NXC_SESSION hSession, DWORD dwSrcNodeId, DWORD dwDstNodeId,
576 DWORD dwNumItems, DWORD *pdwItemList, BOOL bMove)
577 {
578 CSCPMessage msg;
579 DWORD dwRqId;
580
581 CHECK_SESSION_HANDLE();
582
583 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
584
585 msg.SetCode(CMD_COPY_DCI);
586 msg.SetId(dwRqId);
587 msg.SetVariable(VID_SOURCE_OBJECT_ID, dwSrcNodeId);
588 msg.SetVariable(VID_DESTINATION_OBJECT_ID, dwDstNodeId);
589 msg.SetVariable(VID_NUM_ITEMS, dwNumItems);
590 msg.SetVariableToInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
591 msg.SetVariable(VID_MOVE_FLAG, (WORD)bMove);
592 ((NXCL_Session *)hSession)->SendMsg(&msg);
593
594 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
595 }
596
597
598 //
599 // Query value of specific parameter from node
600 //
601
602 DWORD LIBNXCL_EXPORTABLE NXCQueryParameter(NXC_SESSION hSession, DWORD dwNodeId, int iOrigin,
603 TCHAR *pszParameter, TCHAR *pszBuffer,
604 DWORD dwBufferSize)
605 {
606 CSCPMessage msg, *pResponse;
607 DWORD dwRqId, dwResult;
608
609 CHECK_SESSION_HANDLE();
610
611 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
612
613 msg.SetCode(CMD_QUERY_PARAMETER);
614 msg.SetId(dwRqId);
615 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
616 msg.SetVariable(VID_DCI_SOURCE_TYPE, (WORD)iOrigin);
617 msg.SetVariable(VID_NAME, pszParameter);
618 ((NXCL_Session *)hSession)->SendMsg(&msg);
619
620 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 120000);
621 if (pResponse != NULL)
622 {
623 dwResult = pResponse->GetVariableLong(VID_RCC);
624 if (dwResult == RCC_SUCCESS)
625 pResponse->GetVariableStr(VID_VALUE, pszBuffer, dwBufferSize);
626 delete pResponse;
627 }
628 else
629 {
630 dwResult = RCC_TIMEOUT;
631 }
632 return dwResult;
633 }
634
635
636 //
637 // Get threshold list for given DCI
638 //
639
640 DWORD LIBNXCL_EXPORTABLE NXCGetDCIThresholds(NXC_SESSION hSession, DWORD dwNodeId, DWORD dwItemId,
641 NXC_DCI_THRESHOLD **ppList, DWORD *pdwSize)
642 {
643 CSCPMessage msg, *pResponse;
644 DWORD i, dwId, dwRqId, dwResult;
645
646 CHECK_SESSION_HANDLE();
647
648 *ppList = NULL;
649 *pdwSize = 0;
650
651 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
652
653 msg.SetCode(CMD_GET_DCI_THRESHOLDS);
654 msg.SetId(dwRqId);
655 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
656 msg.SetVariable(VID_DCI_ID, dwItemId);
657 ((NXCL_Session *)hSession)->SendMsg(&msg);
658
659 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
660 if (pResponse != NULL)
661 {
662 dwResult = pResponse->GetVariableLong(VID_RCC);
663 if (dwResult == RCC_SUCCESS)
664 {
665 *pdwSize = pResponse->GetVariableLong(VID_NUM_THRESHOLDS);
666 *ppList = (NXC_DCI_THRESHOLD *)malloc(sizeof(NXC_DCI_THRESHOLD) * (*pdwSize));
667 for(i = 0, dwId = VID_DCI_THRESHOLD_BASE; i < *pdwSize; i++, dwId++)
668 {
669 (*ppList)[i].dwId = pResponse->GetVariableLong(dwId++);
670 (*ppList)[i].dwEvent = pResponse->GetVariableLong(dwId++);
671 (*ppList)[i].dwRearmEvent = pResponse->GetVariableLong(dwId++);
672 (*ppList)[i].wFunction = pResponse->GetVariableShort(dwId++);
673 (*ppList)[i].wOperation = pResponse->GetVariableShort(dwId++);
674 (*ppList)[i].dwArg1 = pResponse->GetVariableLong(dwId++);
675 (*ppList)[i].dwArg2 = pResponse->GetVariableLong(dwId++);
676 (*ppList)[i].nRepeatInterval = (LONG)pResponse->GetVariableLong(dwId++);
677 pResponse->GetVariableStr(dwId++, (*ppList)[i].szValue, MAX_STRING_VALUE);
678 }
679 }
680 delete pResponse;
681 }
682 else
683 {
684 dwResult = RCC_TIMEOUT;
685 }
686 return dwResult;
687 }
688
689
690 //
691 // Get last values for all DCIs of selected node
692 //
693
694 DWORD LIBNXCL_EXPORTABLE NXCGetLastValues(NXC_SESSION hSession, DWORD dwNodeId,
695 DWORD *pdwNumItems, NXC_DCI_VALUE **ppValueList)
696 {
697 CSCPMessage msg, *pResponse;
698 DWORD i, dwId, dwRqId, dwResult;
699
700 *pdwNumItems = 0;
701 *ppValueList = NULL;
702
703 CHECK_SESSION_HANDLE();
704
705 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
706
707 msg.SetCode(CMD_GET_LAST_VALUES);
708 msg.SetId(dwRqId);
709 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
710 ((NXCL_Session *)hSession)->SendMsg(&msg);
711
712 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
713 if (pResponse != NULL)
714 {
715 dwResult = pResponse->GetVariableLong(VID_RCC);
716 if (dwResult == RCC_SUCCESS)
717 {
718 *pdwNumItems = pResponse->GetVariableLong(VID_NUM_ITEMS);
719 *ppValueList = (NXC_DCI_VALUE *)malloc(sizeof(NXC_DCI_VALUE) * (*pdwNumItems));
720 memset(*ppValueList, 0, sizeof(NXC_DCI_VALUE) * (*pdwNumItems));
721 for(i = 0, dwId = VID_DCI_VALUES_BASE; i < *pdwNumItems; i++, dwId +=2)
722 {
723 (*ppValueList)[i].dwId = pResponse->GetVariableLong(dwId++);
724 pResponse->GetVariableStr(dwId++, (*ppValueList)[i].szName, MAX_ITEM_NAME);
725 pResponse->GetVariableStr(dwId++, (*ppValueList)[i].szDescription, MAX_DB_STRING);
726 (*ppValueList)[i].nSource = (BYTE)pResponse->GetVariableShort(dwId++);
727 (*ppValueList)[i].nDataType = (BYTE)pResponse->GetVariableShort(dwId++);
728 pResponse->GetVariableStr(dwId++, (*ppValueList)[i].szValue, MAX_DB_STRING);
729 (*ppValueList)[i].dwTimestamp = pResponse->GetVariableLong(dwId++);
730 (*ppValueList)[i].nStatus = (BYTE)pResponse->GetVariableShort(dwId++);
731 }
732 }
733 delete pResponse;
734 }
735 else
736 {
737 dwResult = RCC_TIMEOUT;
738 }
739 return dwResult;
740 }
741
742
743 //
744 // Apply template to node
745 //
746
747 DWORD LIBNXCL_EXPORTABLE NXCApplyTemplate(NXC_SESSION hSession, DWORD dwTemplateId, DWORD dwNodeId)
748 {
749 DWORD dwRqId;
750 CSCPMessage msg;
751
752 CHECK_SESSION_HANDLE();
753
754 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
755
756 msg.SetCode(CMD_APPLY_TEMPLATE);
757 msg.SetId(dwRqId);
758 msg.SetVariable(VID_SOURCE_OBJECT_ID, dwTemplateId);
759 msg.SetVariable(VID_DESTINATION_OBJECT_ID, dwNodeId);
760 ((NXCL_Session *)hSession)->SendMsg(&msg);
761
762 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
763 }
764
765
766 //
767 // Resolve DCI names
768 //
769
770 DWORD LIBNXCL_EXPORTABLE NXCResolveDCINames(NXC_SESSION hSession, DWORD dwNumDCI,
771 INPUT_DCI *pDCIList, TCHAR ***pppszNames)
772 {
773 CSCPMessage msg, *pResponse;
774 DWORD i, j, dwId, dwRqId, dwResult, *pdwList;
775
776 CHECK_SESSION_HANDLE();
777
778 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
779
780 msg.SetCode(CMD_RESOLVE_DCI_NAMES);
781 msg.SetId(dwRqId);
782 msg.SetVariable(VID_NUM_ITEMS, dwNumDCI);
783
784 pdwList = (DWORD *)malloc(sizeof(DWORD) * dwNumDCI * 2);
785 for(i = 0, j = dwNumDCI; i < dwNumDCI; i++, j++)
786 {
787 pdwList[i] = pDCIList[i].dwNodeId;
788 pdwList[j] = pDCIList[i].dwId;
789 }
790 msg.SetVariableToInt32Array(VID_NODE_LIST, dwNumDCI, pdwList);
791 msg.SetVariableToInt32Array(VID_DCI_LIST, dwNumDCI, &pdwList[dwNumDCI]);
792 free(pdwList);
793
794 ((NXCL_Session *)hSession)->SendMsg(&msg);
795
796 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
797 if (pResponse != NULL)
798 {
799 dwResult = pResponse->GetVariableLong(VID_RCC);
800 if (dwResult == RCC_SUCCESS)
801 {
802 *pppszNames = (TCHAR **)malloc(sizeof(TCHAR *) * dwNumDCI);
803 for(i = 0, dwId = VID_DCI_LIST_BASE; i < dwNumDCI; i++)
804 (*pppszNames)[i] = pResponse->GetVariableStr(dwId++);
805 }
806 delete pResponse;
807 }
808 else
809 {
810 dwResult = RCC_TIMEOUT;
811 }
812 return dwResult;
813 }
814
815
816 //
817 // Push DCI data
818 //
819
820 DWORD LIBNXCL_EXPORTABLE NXCPushDCIData(NXC_SESSION hSession, DWORD dwNumItems,
821 NXC_DCI_PUSH_DATA *pItems, DWORD *pdwIndex)
822 {
823 CSCPMessage msg, *pResponse;
824 DWORD i, dwRqId, dwId, dwResult;
825
826 CHECK_SESSION_HANDLE();
827
828 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
829
830 msg.SetCode(CMD_PUSH_DCI_DATA);
831 msg.SetId(dwRqId);
832 msg.SetVariable(VID_NUM_ITEMS, dwNumItems);
833
834 for(i = 0, dwId = VID_PUSH_DCI_DATA_BASE; i < dwNumItems; i++)
835 {
836 msg.SetVariable(dwId++, pItems[i].dwNodeId);
837 if (pItems[i].dwNodeId == 0)
838 {
839 msg.SetVariable(dwId++, pItems[i].pszNodeName);
840 }
841
842 msg.SetVariable(dwId++, pItems[i].dwId);
843 if (pItems[i].dwId == 0)
844 {
845 msg.SetVariable(dwId++, pItems[i].pszName);
846 }
847
848 msg.SetVariable(dwId++, pItems[i].pszValue);
849 }
850
851 ((NXCL_Session *)hSession)->SendMsg(&msg);
852
853 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
854 if (pResponse != NULL)
855 {
856 dwResult = pResponse->GetVariableLong(VID_RCC);
857 if (dwResult != RCC_SUCCESS)
858 {
859 *pdwIndex = pResponse->GetVariableLong(VID_FAILED_DCI_INDEX);
860 }
861 delete pResponse;
862 }
863 else
864 {
865 dwResult = RCC_TIMEOUT;
866 *pdwIndex = 0;
867 }
868 return dwResult;
869 }
870
871
872 //
873 // Get DCI info
874 //
875
876 DWORD LIBNXCL_EXPORTABLE NXCGetDCIInfo(NXC_SESSION hSession, DWORD dwNodeId,
877 DWORD dwItemId, NXC_DCI *pInfo)
878 {
879 CSCPMessage msg, *pResponse;
880 DWORD dwRqId, dwResult;
881
882 CHECK_SESSION_HANDLE();
883
884 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
885
886 msg.SetCode(CMD_GET_DCI_INFO);
887 msg.SetId(dwRqId);
888 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
889 msg.SetVariable(VID_DCI_ID, dwItemId);
890
891 ((NXCL_Session *)hSession)->SendMsg(&msg);
892
893 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
894 if (pResponse != NULL)
895 {
896 dwResult = pResponse->GetVariableLong(VID_RCC);
897 if (dwResult == RCC_SUCCESS)
898 {
899 memset(pInfo, 0, sizeof(NXC_DCI));
900 pInfo->dwId= dwItemId;
901 pInfo->dwResourceId = pResponse->GetVariableLong(VID_RESOURCE_ID);
902 pInfo->dwTemplateId = pResponse->GetVariableLong(VID_TEMPLATE_ID);
903 pInfo->iDataType = (BYTE)pResponse->GetVariableShort(VID_DCI_DATA_TYPE);
904 pInfo->iSource = (BYTE)pResponse->GetVariableShort(VID_DCI_SOURCE_TYPE);
905 pResponse->GetVariableStr(VID_NAME, pInfo->szName, MAX_ITEM_NAME);
906 pResponse->GetVariableStr(VID_DESCRIPTION, pInfo->szDescription, MAX_DB_STRING);
907 }
908 delete pResponse;
909 }
910 else
911 {
912 dwResult = RCC_TIMEOUT;
913 }
914 return dwResult;
915 }
916
917
918 //
919 // Get list of system DCIs
920 //
921
922 DWORD LIBNXCL_EXPORTABLE NXCGetPerfTabDCIList(NXC_SESSION hSession, DWORD dwNodeId,
923 DWORD *pdwNumItems, NXC_PERFTAB_DCI **ppList)
924 {
925 CSCPMessage msg, *pResponse;
926 DWORD i, dwId, dwRqId, dwResult;
927
928 CHECK_SESSION_HANDLE();
929
930 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
931 *ppList = NULL;
932 *pdwNumItems = 0;
933
934 msg.SetCode(CMD_GET_PERFTAB_DCI_LIST);
935 msg.SetId(dwRqId);
936 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
937
938 ((NXCL_Session *)hSession)->SendMsg(&msg);
939
940 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
941 if (pResponse != NULL)
942 {
943 dwResult = pResponse->GetVariableLong(VID_RCC);
944 if (dwResult == RCC_SUCCESS)
945 {
946 *pdwNumItems = pResponse->GetVariableLong(VID_NUM_ITEMS);
947 *ppList = (NXC_PERFTAB_DCI *)malloc(sizeof(NXC_PERFTAB_DCI) * (*pdwNumItems));
948 for(i = 0, dwId = VID_SYSDCI_LIST_BASE; i < *pdwNumItems; i++, dwId += 6)
949 {
950 (*ppList)[i].dwId = pResponse->GetVariableLong(dwId++);
951 pResponse->GetVariableStr(dwId++, (*ppList)[i].szName, MAX_DB_STRING);
952 (*ppList)[i].nStatus = pResponse->GetVariableShort(dwId++);
953 (*ppList)[i].pszSettings = pResponse->GetVariableStr(dwId++);
954 }
955 }
956 delete pResponse;
957 }
958 else
959 {
960 dwResult = RCC_TIMEOUT;
961 }
962 return dwResult;
963 }
964
965
966 //
967 // Clear collected data for DCI
968 //
969
970 DWORD LIBNXCL_EXPORTABLE NXCClearDCIData(NXC_SESSION hSession, DWORD dwNodeId, DWORD dwItemId)
971 {
972 DWORD dwRqId;
973 CSCPMessage msg;
974
975 CHECK_SESSION_HANDLE();
976
977 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
978
979 msg.SetCode(CMD_CLEAR_DCI_DATA);
980 msg.SetId(dwRqId);
981 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
982 msg.SetVariable(VID_DCI_ID, dwItemId);
983 ((NXCL_Session *)hSession)->SendMsg(&msg);
984
985 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
986 }
987
988
989 //
990 // Test DCI's transformation script
991 //
992
993 DWORD LIBNXCL_EXPORTABLE NXCTestDCITransformation(NXC_SESSION hSession, DWORD dwNodeId, DWORD dwItemId,
994 const TCHAR *script, const TCHAR *value, BOOL *execStatus,
995 TCHAR *execResult, size_t resultBufSize)
996 {
997 DWORD dwRqId, dwResult;
998 CSCPMessage msg, *pResponse;
999
1000 CHECK_SESSION_HANDLE();
1001
1002 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1003
1004 msg.SetCode(CMD_TEST_DCI_TRANSFORMATION);
1005 msg.SetId(dwRqId);
1006 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
1007 msg.SetVariable(VID_DCI_ID, dwItemId);
1008 msg.SetVariable(VID_SCRIPT, script);
1009 msg.SetVariable(VID_VALUE, value);
1010 ((NXCL_Session *)hSession)->SendMsg(&msg);
1011
1012 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
1013 if (pResponse != NULL)
1014 {
1015 dwResult = pResponse->GetVariableLong(VID_RCC);
1016 if (dwResult == RCC_SUCCESS)
1017 {
1018 *execStatus = pResponse->GetVariableShort(VID_EXECUTION_STATUS);
1019 pResponse->GetVariableStr(VID_EXECUTION_RESULT, execResult, (DWORD)resultBufSize);
1020 }
1021 delete pResponse;
1022 }
1023 else
1024 {
1025 dwResult = RCC_TIMEOUT;
1026 }
1027 return dwResult;
1028 }