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