a5ce85424b1ae1f962ea0c435475cc8f462a6df1
[public/netxms.git] / src / libnxcl / datacoll.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Client Library
4 ** Copyright (C) 2004, 2005, 2006, 2007 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 }
67 safe_free(pItemList->pItems);
68 free(pItemList);
69 }
70 return dwRetCode;
71 }
72
73
74 //
75 // Create new data collection item
76 //
77
78 DWORD LIBNXCL_EXPORTABLE NXCCreateNewDCI(NXC_SESSION hSession, NXC_DCI_LIST *pItemList,
79 DWORD *pdwItemId)
80 {
81 DWORD dwRetCode, dwRqId;
82 CSCPMessage msg, *pResponse;
83
84 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
85
86 msg.SetCode(CMD_CREATE_NEW_DCI);
87 msg.SetId(dwRqId);
88 msg.SetVariable(VID_OBJECT_ID, pItemList->dwNodeId);
89 ((NXCL_Session *)hSession)->SendMsg(&msg);
90
91 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
92 if (pResponse != NULL)
93 {
94 dwRetCode = pResponse->GetVariableLong(VID_RCC);
95 if (dwRetCode == RCC_SUCCESS)
96 {
97 *pdwItemId = pResponse->GetVariableLong(VID_DCI_ID);
98
99 // Create new entry in list
100 pItemList->pItems = (NXC_DCI *)realloc(pItemList->pItems,
101 sizeof(NXC_DCI) * (pItemList->dwNumItems + 1));
102 memset(&pItemList->pItems[pItemList->dwNumItems], 0, sizeof(NXC_DCI));
103 pItemList->pItems[pItemList->dwNumItems].dwId = *pdwItemId;
104 pItemList->pItems[pItemList->dwNumItems].iStatus = ITEM_STATUS_ACTIVE;
105 pItemList->pItems[pItemList->dwNumItems].iPollingInterval = 60;
106 pItemList->pItems[pItemList->dwNumItems].iRetentionTime = 30;
107 pItemList->pItems[pItemList->dwNumItems].iDeltaCalculation = DCM_ORIGINAL_VALUE;
108 pItemList->pItems[pItemList->dwNumItems].iAdvSchedule = 0;
109 pItemList->pItems[pItemList->dwNumItems].dwNumSchedules = 0;
110 pItemList->pItems[pItemList->dwNumItems].ppScheduleList = NULL;
111 pItemList->pItems[pItemList->dwNumItems].iProcessAllThresholds = 0;
112 pItemList->dwNumItems++;
113 }
114 delete pResponse;
115 }
116 else
117 {
118 dwRetCode = RCC_TIMEOUT;
119 }
120
121 return dwRetCode;
122 }
123
124
125 //
126 // Update data collection item
127 //
128
129 DWORD LIBNXCL_EXPORTABLE NXCUpdateDCI(NXC_SESSION hSession, DWORD dwNodeId, NXC_DCI *pItem)
130 {
131 DWORD i, dwId, dwRqId, dwRetCode;
132 CSCPMessage msg, *pResponse;
133 DCI_THRESHOLD dct;
134
135 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
136
137 msg.SetCode(CMD_MODIFY_NODE_DCI);
138 msg.SetId(dwRqId);
139 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
140 msg.SetVariable(VID_DCI_ID, pItem->dwId);
141 msg.SetVariable(VID_DCI_DATA_TYPE, (WORD)pItem->iDataType);
142 msg.SetVariable(VID_POLLING_INTERVAL, (DWORD)pItem->iPollingInterval);
143 msg.SetVariable(VID_RETENTION_TIME, (DWORD)pItem->iRetentionTime);
144 msg.SetVariable(VID_DCI_SOURCE_TYPE, (WORD)pItem->iSource);
145 msg.SetVariable(VID_DCI_DELTA_CALCULATION, (WORD)pItem->iDeltaCalculation);
146 msg.SetVariable(VID_DCI_STATUS, (WORD)pItem->iStatus);
147 msg.SetVariable(VID_NAME, pItem->szName);
148 msg.SetVariable(VID_DESCRIPTION, pItem->szDescription);
149 msg.SetVariable(VID_INSTANCE, pItem->szInstance);
150 msg.SetVariable(VID_DCI_FORMULA, CHECK_NULL_EX(pItem->pszFormula));
151 msg.SetVariable(VID_ALL_THRESHOLDS, (WORD)pItem->iProcessAllThresholds);
152 msg.SetVariable(VID_ADV_SCHEDULE, (WORD)pItem->iAdvSchedule);
153 msg.SetVariable(VID_RESOURCE_ID, pItem->dwResourceId);
154 msg.SetVariable(VID_PROXY_NODE, pItem->dwProxyNode);
155 if (pItem->iAdvSchedule)
156 {
157 msg.SetVariable(VID_NUM_SCHEDULES, pItem->dwNumSchedules);
158 for(i = 0, dwId = VID_DCI_SCHEDULE_BASE; i < pItem->dwNumSchedules; i++, dwId++)
159 msg.SetVariable(dwId, pItem->ppScheduleList[i]);
160 }
161 else
162 {
163 msg.SetVariable(VID_NUM_SCHEDULES, (DWORD)0);
164 }
165 msg.SetVariable(VID_NUM_THRESHOLDS, pItem->dwNumThresholds);
166 for(i = 0, dwId = VID_DCI_THRESHOLD_BASE; i < pItem->dwNumThresholds; i++, dwId++)
167 {
168 dct.dwId = htonl(pItem->pThresholdList[i].dwId);
169 dct.dwEvent = htonl(pItem->pThresholdList[i].dwEvent);
170 dct.dwRearmEvent = htonl(pItem->pThresholdList[i].dwRearmEvent);
171 dct.dwArg1 = htonl(pItem->pThresholdList[i].dwArg1);
172 dct.dwArg2 = htonl(pItem->pThresholdList[i].dwArg2);
173 dct.wFunction = htons(pItem->pThresholdList[i].wFunction);
174 dct.wOperation = htons(pItem->pThresholdList[i].wOperation);
175 dct.nRepeatInterval = htonl(pItem->pThresholdList[i].nRepeatInterval);
176 switch(pItem->iDataType)
177 {
178 case DCI_DT_INT:
179 case DCI_DT_UINT:
180 dct.value.dwInt32 = htonl(pItem->pThresholdList[i].value.dwInt32);
181 break;
182 case DCI_DT_INT64:
183 case DCI_DT_UINT64:
184 dct.value.qwInt64 = htonq(pItem->pThresholdList[i].value.qwInt64);
185 break;
186 case DCI_DT_FLOAT:
187 dct.value.dFloat = htond(pItem->pThresholdList[i].value.dFloat);
188 break;
189 case DCI_DT_STRING:
190 #ifdef UNICODE
191 wcscpy(dct.value.szString, pItem->pThresholdList[i].value.szString);
192 #else
193 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
194 pItem->pThresholdList[i].value.szString, -1,
195 dct.value.szString, MAX_DCI_STRING_VALUE);
196 #endif
197 SwapWideString(dct.value.szString);
198 break;
199 default:
200 break;
201 }
202 msg.SetVariable(dwId, (BYTE *)&dct, sizeof(DCI_THRESHOLD));
203 }
204 ((NXCL_Session *)hSession)->SendMsg(&msg);
205
206 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
207 if (pResponse != NULL)
208 {
209 dwRetCode = pResponse->GetVariableLong(VID_RCC);
210 if (dwRetCode == RCC_SUCCESS)
211 {
212 DWORD dwNumMaps, *pdwMapId, *pdwMapIndex;
213
214 // Get index to id mapping for newly created thresholds
215 dwNumMaps = pResponse->GetVariableLong(VID_DCI_NUM_MAPS);
216 if (dwNumMaps > 0)
217 {
218 pdwMapId = (DWORD *)malloc(sizeof(DWORD) * dwNumMaps);
219 pdwMapIndex = (DWORD *)malloc(sizeof(DWORD) * dwNumMaps);
220 pResponse->GetVariableBinary(VID_DCI_MAP_IDS, (BYTE *)pdwMapId, sizeof(DWORD) * dwNumMaps);
221 pResponse->GetVariableBinary(VID_DCI_MAP_INDEXES, (BYTE *)pdwMapIndex, sizeof(DWORD) * dwNumMaps);
222 for(i = 0; i < dwNumMaps; i++)
223 pItem->pThresholdList[ntohl(pdwMapIndex[i])].dwId = ntohl(pdwMapId[i]);
224 free(pdwMapId);
225 free(pdwMapIndex);
226 }
227 }
228 delete pResponse;
229 }
230 else
231 {
232 dwRetCode = RCC_TIMEOUT;
233 }
234
235 return dwRetCode;
236 }
237
238
239 //
240 // Delete data collection item
241 //
242
243 DWORD LIBNXCL_EXPORTABLE NXCDeleteDCI(NXC_SESSION hSession, NXC_DCI_LIST *pItemList,
244 DWORD dwItemId)
245 {
246 DWORD i, j, dwRqId, dwResult = RCC_INVALID_DCI_ID;
247 CSCPMessage msg;
248
249 // Find item with given ID in list
250 for(i = 0; i < pItemList->dwNumItems; i++)
251 if (pItemList->pItems[i].dwId == dwItemId)
252 {
253 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
254
255 msg.SetCode(CMD_DELETE_NODE_DCI);
256 msg.SetId(dwRqId);
257 msg.SetVariable(VID_OBJECT_ID, pItemList->dwNodeId);
258 msg.SetVariable(VID_DCI_ID, dwItemId);
259 ((NXCL_Session *)hSession)->SendMsg(&msg);
260
261 dwResult = ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
262 if (dwResult == RCC_SUCCESS)
263 {
264 // Item was successfully deleted on server, delete it from our list
265 for(j = 0; j < pItemList->pItems[i].dwNumSchedules; j++)
266 free(pItemList->pItems[i].ppScheduleList[j]);
267 safe_free(pItemList->pItems[i].ppScheduleList);
268 safe_free(pItemList->pItems[i].pThresholdList);
269 safe_free(pItemList->pItems[i].pszFormula);
270 pItemList->dwNumItems--;
271 memmove(&pItemList->pItems[i], &pItemList->pItems[i + 1],
272 sizeof(NXC_DCI) * (pItemList->dwNumItems - i));
273 }
274 break;
275 }
276 return dwResult;
277 }
278
279
280 //
281 // Set status for multiple DCIs
282 //
283
284 DWORD LIBNXCL_EXPORTABLE NXCSetDCIStatus(NXC_SESSION hSession, DWORD dwNodeId, DWORD dwNumItems,
285 DWORD *pdwItemList, int iStatus)
286 {
287 CSCPMessage msg;
288 DWORD dwRqId;
289
290 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
291
292 msg.SetCode(CMD_SET_DCI_STATUS);
293 msg.SetId(dwRqId);
294 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
295 msg.SetVariable(VID_DCI_STATUS, (WORD)iStatus);
296 msg.SetVariable(VID_NUM_ITEMS, dwNumItems);
297 msg.SetVariableToInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
298 ((NXCL_Session *)hSession)->SendMsg(&msg);
299 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
300 }
301
302
303 //
304 // Find item in list by id and return it's index
305 //
306
307 DWORD LIBNXCL_EXPORTABLE NXCItemIndex(NXC_DCI_LIST *pItemList, DWORD dwItemId)
308 {
309 DWORD i;
310
311 for(i = 0; i < pItemList->dwNumItems; i++)
312 if (pItemList->pItems[i].dwId == dwItemId)
313 return i;
314 return INVALID_INDEX;
315 }
316
317
318 //
319 // Retrieve collected data from server
320 //
321
322 DWORD LIBNXCL_EXPORTABLE NXCGetDCIData(NXC_SESSION hSession, DWORD dwNodeId, DWORD dwItemId,
323 DWORD dwMaxRows, DWORD dwTimeFrom, DWORD dwTimeTo,
324 NXC_DCI_DATA **ppData)
325 {
326 CSCPMessage msg;
327 DWORD i, dwRqId, dwResult;
328 BOOL bRun = TRUE;
329
330 msg.SetCode(CMD_GET_DCI_DATA);
331 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
332 msg.SetVariable(VID_DCI_ID, dwItemId);
333
334 // Allocate memory for results and initialize header
335 *ppData = (NXC_DCI_DATA *)malloc(sizeof(NXC_DCI_DATA));
336 (*ppData)->dwNumRows = 0;
337 (*ppData)->dwNodeId = dwNodeId;
338 (*ppData)->dwItemId = dwItemId;
339 (*ppData)->pRows = NULL;
340
341 do
342 {
343 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
344
345 msg.SetId(dwRqId);
346 msg.SetVariable(VID_MAX_ROWS, dwMaxRows);
347 msg.SetVariable(VID_TIME_FROM, dwTimeFrom);
348 msg.SetVariable(VID_TIME_TO, dwTimeTo);
349 ((NXCL_Session *)hSession)->SendMsg(&msg);
350
351 dwResult = ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
352 if (dwResult == RCC_SUCCESS)
353 {
354 CSCP_MESSAGE *pRawMsg;
355
356 // We wait a long time because data message can be quite large
357 pRawMsg = ((NXCL_Session *)hSession)->WaitForRawMessage(CMD_DCI_DATA, dwRqId, 60000);
358 if (pRawMsg != NULL)
359 {
360 DCI_DATA_HEADER *pHdr;
361 DCI_DATA_ROW *pSrc;
362 NXC_DCI_ROW *pDst;
363 DWORD dwPrevRowCount, dwRecvRows;
364 static WORD m_wRowSize[] = { 8, 8, 12, 12, 260, 12 };
365
366 pHdr = (DCI_DATA_HEADER *)pRawMsg->df;
367 dwRecvRows = ntohl(pHdr->dwNumRows);
368
369 // Allocate memory for results
370 dwPrevRowCount = (*ppData)->dwNumRows;
371 (*ppData)->dwNumRows += dwRecvRows;
372 (*ppData)->wDataType = (WORD)ntohl(pHdr->dwDataType);
373 if ((*ppData)->wDataType > 5)
374 (*ppData)->wDataType = 0;
375 (*ppData)->wRowSize = m_wRowSize[(*ppData)->wDataType];
376 if (dwRecvRows > 0)
377 (*ppData)->pRows = (NXC_DCI_ROW *)realloc((*ppData)->pRows, (*ppData)->dwNumRows * (*ppData)->wRowSize);
378
379 // Convert and copy values from message to rows in result
380 pSrc = (DCI_DATA_ROW *)(((char *)pHdr) + sizeof(DCI_DATA_HEADER));
381 pDst = (NXC_DCI_ROW *)(((char *)((*ppData)->pRows)) + dwPrevRowCount * (*ppData)->wRowSize);
382 for(i = 0; i < dwRecvRows; i++)
383 {
384 pDst->dwTimeStamp = ntohl(pSrc->dwTimeStamp);
385 switch((*ppData)->wDataType)
386 {
387 case DCI_DT_INT:
388 case DCI_DT_UINT:
389 pDst->value.dwInt32 = ntohl(pSrc->value.dwInteger);
390 break;
391 case DCI_DT_INT64:
392 case DCI_DT_UINT64:
393 pDst->value.qwInt64 = ntohq(pSrc->value.qwInt64);
394 break;
395 case DCI_DT_FLOAT:
396 pDst->value.dFloat = ntohd(pSrc->value.dFloat);
397 break;
398 case DCI_DT_STRING:
399 SwapWideString(pSrc->value.szString);
400 #ifdef UNICODE
401 wcscpy(pDst->value.szString, pSrc->value.szString);
402 #else
403 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
404 pSrc->value.szString, -1,
405 pDst->value.szString, MAX_STRING_VALUE,
406 NULL, NULL);
407 #endif
408 break;
409 }
410
411 pSrc = (DCI_DATA_ROW *)(((char *)pSrc) + (*ppData)->wRowSize);
412 pDst = (NXC_DCI_ROW *)(((char *)pDst) + (*ppData)->wRowSize);
413 }
414
415 // Shift boundaries
416 if (((dwMaxRows == 0) || (dwMaxRows > MAX_DCI_DATA_RECORDS)) &&
417 (dwRecvRows == MAX_DCI_DATA_RECORDS))
418 {
419 // Shift to last record
420 pDst = (NXC_DCI_ROW *)(((char *)pDst) - (*ppData)->wRowSize);
421 dwTimeTo = pDst->dwTimeStamp - 1; // Assume that we have no more than one value per second
422 if (dwMaxRows > 0)
423 dwMaxRows -= MAX_DCI_DATA_RECORDS;
424 }
425 else
426 {
427 bRun = FALSE;
428 }
429
430 // Destroy message
431 free(pRawMsg);
432 }
433 else
434 {
435 dwResult = RCC_TIMEOUT;
436 }
437 }
438 } while((dwResult == RCC_SUCCESS) && bRun);
439
440 // Destroy already allocated buffer if request was unsuccessful
441 if (dwResult != RCC_SUCCESS)
442 {
443 safe_free((*ppData)->pRows);
444 free(*ppData);
445 }
446
447 return dwResult;
448 }
449
450
451 //
452 // Destroy DCI result set
453 //
454
455 void LIBNXCL_EXPORTABLE NXCDestroyDCIData(NXC_DCI_DATA *pData)
456 {
457 if (pData != NULL)
458 {
459 safe_free(pData->pRows);
460 free(pData);
461 }
462 }
463
464
465 //
466 // Get pointer to specific row in result set
467 //
468
469 NXC_DCI_ROW LIBNXCL_EXPORTABLE *NXCGetRowPtr(NXC_DCI_DATA *pData, DWORD dwRow)
470 {
471 if (dwRow >= pData->dwNumRows)
472 return NULL;
473
474 return (NXC_DCI_ROW *)(((char *)(pData->pRows)) + dwRow * pData->wRowSize);
475 }
476
477
478 //
479 // Add threshold to item
480 //
481
482 DWORD LIBNXCL_EXPORTABLE NXCAddThresholdToItem(NXC_DCI *pItem, NXC_DCI_THRESHOLD *pThreshold)
483 {
484 DWORD dwIndex;
485
486 dwIndex = pItem->dwNumThresholds++;
487 pItem->pThresholdList = (NXC_DCI_THRESHOLD *)realloc(pItem->pThresholdList,
488 sizeof(NXC_DCI_THRESHOLD) * pItem->dwNumThresholds);
489 memcpy(&pItem->pThresholdList[dwIndex], pThreshold, sizeof(NXC_DCI_THRESHOLD));
490 return dwIndex;
491 }
492
493
494 //
495 // Delete threshold from item
496 //
497
498 BOOL LIBNXCL_EXPORTABLE NXCDeleteThresholdFromItem(NXC_DCI *pItem, DWORD dwIndex)
499 {
500 BOOL bResult = FALSE;
501
502 if (pItem->dwNumThresholds > dwIndex)
503 {
504 pItem->dwNumThresholds--;
505 if (pItem->dwNumThresholds > 0)
506 memmove(&pItem->pThresholdList[dwIndex], &pItem->pThresholdList[dwIndex + 1],
507 sizeof(NXC_DCI_THRESHOLD) * (pItem->dwNumThresholds - dwIndex));
508 bResult = TRUE;
509 }
510 return bResult;
511 }
512
513
514 //
515 // Swap two threshold items
516 //
517
518 BOOL LIBNXCL_EXPORTABLE NXCSwapThresholds(NXC_DCI *pItem, DWORD dwIndex1, DWORD dwIndex2)
519 {
520 BOOL bResult = FALSE;
521 NXC_DCI_THRESHOLD dct;
522
523 if ((pItem->dwNumThresholds > dwIndex1) &&
524 (pItem->dwNumThresholds > dwIndex2) &&
525 (dwIndex1 != dwIndex2))
526 {
527 memcpy(&dct, &pItem->pThresholdList[dwIndex1], sizeof(NXC_DCI_THRESHOLD));
528 memcpy(&pItem->pThresholdList[dwIndex1], &pItem->pThresholdList[dwIndex2], sizeof(NXC_DCI_THRESHOLD));
529 memcpy(&pItem->pThresholdList[dwIndex2], &dct, sizeof(NXC_DCI_THRESHOLD));
530 bResult = TRUE;
531 }
532 return bResult;
533 }
534
535
536 //
537 // Copy data collection items from one node to another
538 //
539
540 DWORD LIBNXCL_EXPORTABLE NXCCopyDCI(NXC_SESSION hSession, DWORD dwSrcNodeId, DWORD dwDstNodeId,
541 DWORD dwNumItems, DWORD *pdwItemList, BOOL bMove)
542 {
543 CSCPMessage msg;
544 DWORD dwRqId;
545
546 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
547
548 msg.SetCode(CMD_COPY_DCI);
549 msg.SetId(dwRqId);
550 msg.SetVariable(VID_SOURCE_OBJECT_ID, dwSrcNodeId);
551 msg.SetVariable(VID_DESTINATION_OBJECT_ID, dwDstNodeId);
552 msg.SetVariable(VID_NUM_ITEMS, dwNumItems);
553 msg.SetVariableToInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
554 msg.SetVariable(VID_MOVE_FLAG, (WORD)bMove);
555 ((NXCL_Session *)hSession)->SendMsg(&msg);
556
557 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
558 }
559
560
561 //
562 // Query value of specific parameter from node
563 //
564
565 DWORD LIBNXCL_EXPORTABLE NXCQueryParameter(NXC_SESSION hSession, DWORD dwNodeId, int iOrigin,
566 TCHAR *pszParameter, TCHAR *pszBuffer,
567 DWORD dwBufferSize)
568 {
569 CSCPMessage msg, *pResponse;
570 DWORD dwRqId, dwResult;
571
572 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
573
574 msg.SetCode(CMD_QUERY_PARAMETER);
575 msg.SetId(dwRqId);
576 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
577 msg.SetVariable(VID_DCI_SOURCE_TYPE, (WORD)iOrigin);
578 msg.SetVariable(VID_NAME, pszParameter);
579 ((NXCL_Session *)hSession)->SendMsg(&msg);
580
581 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 120000);
582 if (pResponse != NULL)
583 {
584 dwResult = pResponse->GetVariableLong(VID_RCC);
585 if (dwResult == RCC_SUCCESS)
586 pResponse->GetVariableStr(VID_VALUE, pszBuffer, dwBufferSize);
587 delete pResponse;
588 }
589 else
590 {
591 dwResult = RCC_TIMEOUT;
592 }
593 return dwResult;
594 }
595
596
597 //
598 // Get last values for all DCIs of selected node
599 //
600
601 DWORD LIBNXCL_EXPORTABLE NXCGetLastValues(NXC_SESSION hSession, DWORD dwNodeId,
602 DWORD *pdwNumItems, NXC_DCI_VALUE **ppValueList)
603 {
604 CSCPMessage msg, *pResponse;
605 DWORD i, dwId, dwRqId, dwResult;
606
607 *pdwNumItems = 0;
608 *ppValueList = NULL;
609
610 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
611
612 msg.SetCode(CMD_GET_LAST_VALUES);
613 msg.SetId(dwRqId);
614 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
615 ((NXCL_Session *)hSession)->SendMsg(&msg);
616
617 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
618 if (pResponse != NULL)
619 {
620 dwResult = pResponse->GetVariableLong(VID_RCC);
621 if (dwResult == RCC_SUCCESS)
622 {
623 *pdwNumItems = pResponse->GetVariableLong(VID_NUM_ITEMS);
624 *ppValueList = (NXC_DCI_VALUE *)malloc(sizeof(NXC_DCI_VALUE) * (*pdwNumItems));
625 memset(*ppValueList, 0, sizeof(NXC_DCI_VALUE) * (*pdwNumItems));
626 for(i = 0, dwId = VID_DCI_VALUES_BASE; i < *pdwNumItems; i++, dwId +=2)
627 {
628 (*ppValueList)[i].dwId = pResponse->GetVariableLong(dwId++);
629 pResponse->GetVariableStr(dwId++, (*ppValueList)[i].szName, MAX_ITEM_NAME);
630 pResponse->GetVariableStr(dwId++, (*ppValueList)[i].szDescription, MAX_DB_STRING);
631 (*ppValueList)[i].nSource = (BYTE)pResponse->GetVariableShort(dwId++);
632 (*ppValueList)[i].nDataType = (BYTE)pResponse->GetVariableShort(dwId++);
633 pResponse->GetVariableStr(dwId++, (*ppValueList)[i].szValue, MAX_DB_STRING);
634 (*ppValueList)[i].dwTimestamp = pResponse->GetVariableLong(dwId++);
635 (*ppValueList)[i].nStatus = (BYTE)pResponse->GetVariableShort(dwId++);
636 }
637 }
638 delete pResponse;
639 }
640 else
641 {
642 dwResult = RCC_TIMEOUT;
643 }
644 return dwResult;
645 }
646
647
648 //
649 // Apply template to node
650 //
651
652 DWORD LIBNXCL_EXPORTABLE NXCApplyTemplate(NXC_SESSION hSession, DWORD dwTemplateId, DWORD dwNodeId)
653 {
654 DWORD dwRqId;
655 CSCPMessage msg;
656
657 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
658
659 msg.SetCode(CMD_APPLY_TEMPLATE);
660 msg.SetId(dwRqId);
661 msg.SetVariable(VID_SOURCE_OBJECT_ID, dwTemplateId);
662 msg.SetVariable(VID_DESTINATION_OBJECT_ID, dwNodeId);
663 ((NXCL_Session *)hSession)->SendMsg(&msg);
664
665 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
666 }
667
668
669 //
670 // Resolve DCI names
671 //
672
673 DWORD LIBNXCL_EXPORTABLE NXCResolveDCINames(NXC_SESSION hSession, DWORD dwNumDCI,
674 INPUT_DCI *pDCIList, TCHAR ***pppszNames)
675 {
676 CSCPMessage msg, *pResponse;
677 DWORD i, j, dwId, dwRqId, dwResult, *pdwList;
678
679 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
680
681 msg.SetCode(CMD_RESOLVE_DCI_NAMES);
682 msg.SetId(dwRqId);
683 msg.SetVariable(VID_NUM_ITEMS, dwNumDCI);
684
685 pdwList = (DWORD *)malloc(sizeof(DWORD) * dwNumDCI * 2);
686 for(i = 0, j = dwNumDCI; i < dwNumDCI; i++, j++)
687 {
688 pdwList[i] = pDCIList[i].dwNodeId;
689 pdwList[j] = pDCIList[i].dwId;
690 }
691 msg.SetVariableToInt32Array(VID_NODE_LIST, dwNumDCI, pdwList);
692 msg.SetVariableToInt32Array(VID_DCI_LIST, dwNumDCI, &pdwList[dwNumDCI]);
693 free(pdwList);
694
695 ((NXCL_Session *)hSession)->SendMsg(&msg);
696
697 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
698 if (pResponse != NULL)
699 {
700 dwResult = pResponse->GetVariableLong(VID_RCC);
701 if (dwResult == RCC_SUCCESS)
702 {
703 *pppszNames = (TCHAR **)malloc(sizeof(TCHAR *) * dwNumDCI);
704 for(i = 0, dwId = VID_DCI_LIST_BASE; i < dwNumDCI; i++)
705 (*pppszNames)[i] = pResponse->GetVariableStr(dwId++);
706 }
707 delete pResponse;
708 }
709 else
710 {
711 dwResult = RCC_TIMEOUT;
712 }
713 return dwResult;
714 }
715
716
717 //
718 // Push DCI data
719 //
720
721 DWORD LIBNXCL_EXPORTABLE NXCPushDCIData(NXC_SESSION hSession, DWORD dwNumItems,
722 NXC_DCI_PUSH_DATA *pItems, DWORD *pdwIndex)
723 {
724 CSCPMessage msg, *pResponse;
725 DWORD i, dwRqId, dwId, dwResult;
726
727 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
728
729 msg.SetCode(CMD_PUSH_DCI_DATA);
730 msg.SetId(dwRqId);
731 msg.SetVariable(VID_NUM_ITEMS, dwNumItems);
732
733 for(i = 0, dwId = VID_PUSH_DCI_DATA_BASE; i < dwNumItems; i++)
734 {
735 msg.SetVariable(dwId++, pItems[i].dwNodeId);
736 if (pItems[i].dwNodeId == 0)
737 {
738 msg.SetVariable(dwId++, pItems[i].pszNodeName);
739 }
740
741 msg.SetVariable(dwId++, pItems[i].dwId);
742 if (pItems[i].dwId == 0)
743 {
744 msg.SetVariable(dwId++, pItems[i].pszName);
745 }
746
747 msg.SetVariable(dwId++, pItems[i].pszValue);
748 }
749
750 ((NXCL_Session *)hSession)->SendMsg(&msg);
751
752 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
753 if (pResponse != NULL)
754 {
755 dwResult = pResponse->GetVariableLong(VID_RCC);
756 if (dwResult != RCC_SUCCESS)
757 {
758 *pdwIndex = pResponse->GetVariableLong(VID_FAILED_DCI_INDEX);
759 }
760 delete pResponse;
761 }
762 else
763 {
764 dwResult = RCC_TIMEOUT;
765 *pdwIndex = 0;
766 }
767 return dwResult;
768 }
769
770
771 //
772 // Get DCI info
773 //
774
775 DWORD LIBNXCL_EXPORTABLE NXCGetDCIInfo(NXC_SESSION hSession, DWORD dwNodeId,
776 DWORD dwItemId, NXC_DCI *pInfo)
777 {
778 CSCPMessage msg, *pResponse;
779 DWORD dwRqId, dwResult;
780
781 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
782
783 msg.SetCode(CMD_GET_DCI_INFO);
784 msg.SetId(dwRqId);
785 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
786 msg.SetVariable(VID_DCI_ID, dwItemId);
787
788 ((NXCL_Session *)hSession)->SendMsg(&msg);
789
790 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
791 if (pResponse != NULL)
792 {
793 dwResult = pResponse->GetVariableLong(VID_RCC);
794 if (dwResult == RCC_SUCCESS)
795 {
796 memset(pInfo, 0, sizeof(NXC_DCI));
797 pInfo->dwId= dwItemId;
798 pInfo->dwResourceId = pResponse->GetVariableLong(VID_RESOURCE_ID);
799 pInfo->dwTemplateId = pResponse->GetVariableLong(VID_TEMPLATE_ID);
800 pInfo->iDataType = (BYTE)pResponse->GetVariableShort(VID_DCI_DATA_TYPE);
801 pInfo->iSource = (BYTE)pResponse->GetVariableShort(VID_DCI_SOURCE_TYPE);
802 pResponse->GetVariableStr(VID_NAME, pInfo->szName, MAX_ITEM_NAME);
803 pResponse->GetVariableStr(VID_DESCRIPTION, pInfo->szDescription, MAX_DB_STRING);
804 }
805 delete pResponse;
806 }
807 else
808 {
809 dwResult = RCC_TIMEOUT;
810 }
811 return dwResult;
812 }
813
814
815 //
816 // Get list of system DCIs
817 //
818
819 DWORD LIBNXCL_EXPORTABLE NXCGetSystemDCIList(NXC_SESSION hSession, DWORD dwNodeId,
820 DWORD *pdwNumItems, NXC_SYSTEM_DCI **ppList)
821 {
822 CSCPMessage msg, *pResponse;
823 DWORD i, dwId, dwRqId, dwResult;
824
825 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
826 *ppList = NULL;
827 *pdwNumItems = 0;
828
829 msg.SetCode(CMD_GET_SYSTEM_DCI_LIST);
830 msg.SetId(dwRqId);
831 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
832
833 ((NXCL_Session *)hSession)->SendMsg(&msg);
834
835 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
836 if (pResponse != NULL)
837 {
838 dwResult = pResponse->GetVariableLong(VID_RCC);
839 if (dwResult == RCC_SUCCESS)
840 {
841 *pdwNumItems = pResponse->GetVariableLong(VID_NUM_ITEMS);
842 *ppList = (NXC_SYSTEM_DCI *)malloc(sizeof(NXC_SYSTEM_DCI) * (*pdwNumItems));
843 for(i = 0, dwId = VID_SYSDCI_LIST_BASE; i < *pdwNumItems; i++, dwId += 7)
844 {
845 (*ppList)[i].dwId = pResponse->GetVariableLong(dwId++);
846 pResponse->GetVariableStr(dwId++, (*ppList)[i].szName, MAX_DB_STRING);
847 (*ppList)[i].nStatus = pResponse->GetVariableShort(dwId++);
848 }
849 }
850 delete pResponse;
851 }
852 else
853 {
854 dwResult = RCC_TIMEOUT;
855 }
856 return dwResult;
857 }