added method GeoLocation::equals
[public/netxms.git] / src / server / core / mobile.cpp
CommitLineData
4899db4d 1/*
f22c4f7c 2** NetXMS - Network Management System
db091a1f 3** Copyright (C) 2003-2016 Victor Kirhenshtein
f22c4f7c
VK
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** File: mobile.cpp
f22c4f7c
VK
20**/
21
22#include "nxcore.h"
23
24/**
25 * Default constructor
26 */
6fd6de0a 27MobileDevice::MobileDevice() : DataCollectionTarget()
f22c4f7c
VK
28{
29 m_lastReportTime = 0;
30 m_deviceId = NULL;
31 m_vendor = NULL;
32 m_model = NULL;
33 m_serialNumber = NULL;
34 m_osName = NULL;
35 m_osVersion = NULL;
36 m_userId = NULL;
171c2fd6 37 m_batteryLevel = -1;
f22c4f7c
VK
38}
39
40/**
41 * Constructor for creating new mobile device object
42 */
6fd6de0a 43MobileDevice::MobileDevice(const TCHAR *name, const TCHAR *deviceId) : DataCollectionTarget(name)
f22c4f7c
VK
44{
45 m_lastReportTime = 0;
46 m_deviceId = _tcsdup(deviceId);
47 m_vendor = NULL;
48 m_model = NULL;
49 m_serialNumber = NULL;
50 m_osName = NULL;
51 m_osVersion = NULL;
52 m_userId = NULL;
171c2fd6 53 m_batteryLevel = -1;
f22c4f7c
VK
54}
55
56/**
57 * Destructor
58 */
59MobileDevice::~MobileDevice()
60{
61 safe_free(m_deviceId);
62 safe_free(m_vendor);
63 safe_free(m_model);
64 safe_free(m_serialNumber);
65 safe_free(m_osName);
66 safe_free(m_osVersion);
67 safe_free(m_userId);
68}
9aa67910
VK
69
70/**
71 * Create object from database data
72 */
9bd1bace 73bool MobileDevice::loadFromDatabase(DB_HANDLE hdb, UINT32 dwId)
9aa67910 74{
c42b4551 75 m_id = dwId;
9aa67910 76
9bd1bace 77 if (!loadCommonProperties(hdb))
9aa67910 78 {
4dd963e9 79 DbgPrintf(2, _T("Cannot load common properties for mobile device object %d"), dwId);
9bd1bace 80 return false;
9aa67910
VK
81 }
82
83 TCHAR query[256];
c42b4551 84 _sntprintf(query, 256, _T("SELECT device_id,vendor,model,serial_number,os_name,os_version,user_id,battery_level FROM mobile_devices WHERE id=%d"), (int)m_id);
9bd1bace 85 DB_RESULT hResult = DBSelect(hdb, query);
9aa67910 86 if (hResult == NULL)
9bd1bace 87 return false;
9aa67910
VK
88
89 m_deviceId = DBGetField(hResult, 0, 0, NULL, 0);
90 m_vendor = DBGetField(hResult, 0, 1, NULL, 0);
91 m_model = DBGetField(hResult, 0, 2, NULL, 0);
92 m_serialNumber = DBGetField(hResult, 0, 3, NULL, 0);
93 m_osName = DBGetField(hResult, 0, 4, NULL, 0);
94 m_osVersion = DBGetField(hResult, 0, 5, NULL, 0);
95 m_userId = DBGetField(hResult, 0, 6, NULL, 0);
171c2fd6 96 m_batteryLevel = DBGetFieldLong(hResult, 0, 7);
9aa67910
VK
97 DBFreeResult(hResult);
98
99 // Load DCI and access list
9bd1bace
VK
100 loadACLFromDB(hdb);
101 loadItemsFromDB(hdb);
9aa67910 102 for(int i = 0; i < m_dcObjects->size(); i++)
9bd1bace
VK
103 if (!m_dcObjects->get(i)->loadThresholdsFromDB(hdb))
104 return false;
9aa67910 105
9bd1bace 106 return true;
9aa67910
VK
107}
108
109/**
110 * Save object to database
111 */
b4277312 112bool MobileDevice::saveToDatabase(DB_HANDLE hdb)
9aa67910
VK
113{
114 // Lock object's access
c42b4551 115 lockProperties();
9aa67910
VK
116
117 saveCommonProperties(hdb);
118
b4277312 119 bool bResult;
9aa67910 120 DB_STATEMENT hStmt;
c42b4551 121 if (IsDatabaseRecordExist(hdb, _T("mobile_devices"), _T("id"), m_id))
171c2fd6 122 hStmt = DBPrepare(hdb, _T("UPDATE mobile_devices SET device_id=?,vendor=?,model=?,serial_number=?,os_name=?,os_version=?,user_id=?,battery_level=? WHERE id=?"));
9aa67910 123 else
171c2fd6 124 hStmt = DBPrepare(hdb, _T("INSERT INTO mobile_devices (device_id,vendor,model,serial_number,os_name,os_version,user_id,battery_level,id) VALUES (?,?,?,?,?,?,?,?,?)"));
9aa67910
VK
125 if (hStmt != NULL)
126 {
127 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_deviceId), DB_BIND_STATIC);
128 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_vendor), DB_BIND_STATIC);
129 DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_model), DB_BIND_STATIC);
130 DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_serialNumber), DB_BIND_STATIC);
131 DBBind(hStmt, 5, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_osName), DB_BIND_STATIC);
132 DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_osVersion), DB_BIND_STATIC);
133 DBBind(hStmt, 7, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_userId), DB_BIND_STATIC);
171c2fd6 134 DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_batteryLevel);
c42b4551 135 DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, m_id);
9aa67910
VK
136
137 bResult = DBExecute(hStmt);
138
139 DBFreeStatement(hStmt);
140 }
141 else
142 {
b4277312 143 bResult = false;
9aa67910
VK
144 }
145
146 // Save data collection items
147 if (bResult)
148 {
b06436f4 149 lockDciAccess(false);
9aa67910 150 for(int i = 0; i < m_dcObjects->size(); i++)
e7450f3b 151 m_dcObjects->get(i)->saveToDatabase(hdb);
9aa67910
VK
152 unlockDciAccess();
153 }
154
155 // Save access list
156 saveACLToDB(hdb);
157
158 // Clear modifications flag and unlock object
159 if (bResult)
01152a54 160 m_isModified = false;
c42b4551 161 unlockProperties();
9aa67910
VK
162
163 return bResult;
164}
165
166/**
167 * Delete object from database
168 */
c42b4551 169bool MobileDevice::deleteFromDatabase(DB_HANDLE hdb)
9aa67910 170{
c42b4551 171 bool success = DataCollectionTarget::deleteFromDatabase(hdb);
22ee6d97
VK
172 if (success)
173 success = executeQueryOnObject(hdb, _T("DELETE FROM mobile_devices WHERE id=?"));
174 return success;
9aa67910
VK
175}
176
177/**
178 * Create CSCP message with object's data
179 */
8fe90adb 180void MobileDevice::fillMessageInternal(NXCPMessage *msg)
9aa67910 181{
8fe90adb 182 DataCollectionTarget::fillMessageInternal(msg);
e83d726c 183
b368969c
VK
184 msg->setField(VID_DEVICE_ID, CHECK_NULL_EX(m_deviceId));
185 msg->setField(VID_VENDOR, CHECK_NULL_EX(m_vendor));
186 msg->setField(VID_MODEL, CHECK_NULL_EX(m_model));
187 msg->setField(VID_SERIAL_NUMBER, CHECK_NULL_EX(m_serialNumber));
188 msg->setField(VID_OS_NAME, CHECK_NULL_EX(m_osName));
189 msg->setField(VID_OS_VERSION, CHECK_NULL_EX(m_osVersion));
190 msg->setField(VID_USER_ID, CHECK_NULL_EX(m_userId));
191 msg->setField(VID_BATTERY_LEVEL, (UINT32)m_batteryLevel);
192 msg->setField(VID_LAST_CHANGE_TIME, (QWORD)m_lastReportTime);
9aa67910
VK
193}
194
195/**
196 * Modify object from message
197 */
8fe90adb 198UINT32 MobileDevice::modifyFromMessageInternal(NXCPMessage *pRequest)
9aa67910 199{
8fe90adb 200 return DataCollectionTarget::modifyFromMessageInternal(pRequest);
9aa67910 201}
6583a0f8
VK
202
203/**
204 * Update system information from NXCP message
205 */
b368969c 206void MobileDevice::updateSystemInfo(NXCPMessage *msg)
6583a0f8 207{
c42b4551 208 lockProperties();
6583a0f8 209
63862632
VK
210 m_lastReportTime = time(NULL);
211
6583a0f8 212 safe_free(m_vendor);
b368969c 213 m_vendor = msg->getFieldAsString(VID_VENDOR);
6583a0f8
VK
214
215 safe_free(m_model);
b368969c 216 m_model = msg->getFieldAsString(VID_MODEL);
6583a0f8
VK
217
218 safe_free(m_serialNumber);
b368969c 219 m_serialNumber = msg->getFieldAsString(VID_SERIAL_NUMBER);
6583a0f8
VK
220
221 safe_free(m_osName);
b368969c 222 m_osName = msg->getFieldAsString(VID_OS_NAME);
6583a0f8
VK
223
224 safe_free(m_osVersion);
b368969c 225 m_osVersion = msg->getFieldAsString(VID_OS_VERSION);
6583a0f8
VK
226
227 safe_free(m_userId);
b368969c 228 m_userId = msg->getFieldAsString(VID_USER_NAME);
6583a0f8 229
c42b4551
VK
230 setModified();
231 unlockProperties();
6583a0f8
VK
232}
233
234/**
235 * Update status from NXCP message
236 */
b368969c 237void MobileDevice::updateStatus(NXCPMessage *msg)
6583a0f8 238{
c42b4551 239 lockProperties();
6583a0f8 240
63862632
VK
241 m_lastReportTime = time(NULL);
242
4101571e 243 int type = msg->getFieldType(VID_BATTERY_LEVEL);
b368969c
VK
244 if (type == NXCP_DT_INT32)
245 m_batteryLevel = msg->getFieldAsInt32(VID_BATTERY_LEVEL);
246 else if (type == NXCP_DT_INT16)
247 m_batteryLevel = (int)msg->getFieldAsInt16(VID_BATTERY_LEVEL);
6583a0f8
VK
248 else
249 m_batteryLevel = -1;
250
5c44534b 251 if (msg->isFieldExist(VID_GEOLOCATION_TYPE))
4899db4d 252 {
6583a0f8 253 m_geoLocation = GeoLocation(*msg);
4899db4d 254 addLocationToHistory();
255 }
6583a0f8 256
5c44534b 257 if (msg->isFieldExist(VID_IP_ADDRESS))
c75e9ee4 258 m_ipAddress = msg->getFieldAsInetAddress(VID_IP_ADDRESS);
6583a0f8 259
c75e9ee4 260 TCHAR temp[64];
6583a0f8 261 DbgPrintf(5, _T("Mobile device %s [%d] updated from agent (battery=%d addr=%s loc=[%s %s])"),
c75e9ee4 262 m_name, (int)m_id, m_batteryLevel, m_ipAddress.toString(temp),
6583a0f8
VK
263 m_geoLocation.getLatitudeAsString(), m_geoLocation.getLongitudeAsString());
264
c42b4551
VK
265 setModified();
266 unlockProperties();
6583a0f8 267}
eb0c0312
VK
268
269/**
270 * Get value for server's internal parameter
271 */
17b1ab4a 272UINT32 MobileDevice::getInternalItem(const TCHAR *param, size_t bufSize, TCHAR *buffer)
eb0c0312 273{
967893bb 274 UINT32 rc = DataCollectionTarget::getInternalItem(param, bufSize, buffer);
192cb389
VK
275 if (rc != DCE_NOT_SUPPORTED)
276 return rc;
eb0c0312
VK
277 rc = DCE_SUCCESS;
278
279 if (!_tcsicmp(param, _T("MobileDevice.BatteryLevel")))
280 {
281 _sntprintf(buffer, bufSize, _T("%d"), m_batteryLevel);
282 }
283 else if (!_tcsicmp(param, _T("MobileDevice.DeviceId")))
284 {
285 nx_strncpy(buffer, CHECK_NULL_EX(m_deviceId), bufSize);
286 }
287 else if (!_tcsicmp(param, _T("MobileDevice.LastReportTime")))
288 {
289 _sntprintf(buffer, bufSize, INT64_FMT, (INT64)m_lastReportTime);
290 }
291 else if (!_tcsicmp(param, _T("MobileDevice.Model")))
292 {
293 nx_strncpy(buffer, CHECK_NULL_EX(m_model), bufSize);
294 }
295 else if (!_tcsicmp(param, _T("MobileDevice.OS.Name")))
296 {
297 nx_strncpy(buffer, CHECK_NULL_EX(m_osName), bufSize);
298 }
299 else if (!_tcsicmp(param, _T("MobileDevice.OS.Version")))
300 {
301 nx_strncpy(buffer, CHECK_NULL_EX(m_osVersion), bufSize);
302 }
303 else if (!_tcsicmp(param, _T("MobileDevice.SerialNumber")))
304 {
305 nx_strncpy(buffer, CHECK_NULL_EX(m_serialNumber), bufSize);
306 }
307 else if (!_tcsicmp(param, _T("MobileDevice.Vendor")))
308 {
309 nx_strncpy(buffer, CHECK_NULL_EX(m_vendor), bufSize);
310 }
311 else if (!_tcsicmp(param, _T("MobileDevice.UserId")))
312 {
313 nx_strncpy(buffer, CHECK_NULL_EX(m_userId), bufSize);
314 }
315 else
316 {
317 rc = DCE_NOT_SUPPORTED;
318 }
319
320 return rc;
321}
26e2b253
VK
322
323/**
324 * Calculate compound status
325 */
326void MobileDevice::calculateCompoundStatus(BOOL bForcedRecalc)
327{
328 NetObj::calculateCompoundStatus(bForcedRecalc);
329
330 // Assume normal status by default for mobile device
db091a1f 331 if (m_status == STATUS_UNKNOWN)
26e2b253 332 {
c42b4551 333 lockProperties();
db091a1f 334 m_status = STATUS_NORMAL;
c42b4551
VK
335 setModified();
336 unlockProperties();
26e2b253
VK
337 }
338}
297a88eb
VK
339
340/**
341 * Create NXSL object for this object
342 */
343NXSL_Value *MobileDevice::createNXSLObject()
344{
345 return new NXSL_Value(new NXSL_Object(&g_nxslMobileDeviceClass, this));
346}
950b229b
VK
347
348/**
349 * Serialize object to JSON
350 */
351json_t *MobileDevice::toJson()
352{
353 json_t *root = DataCollectionTarget::toJson();
354 json_object_set_new(root, "lastReportTime", json_integer(m_lastReportTime));
355 json_object_set_new(root, "deviceId", json_string_t(m_deviceId));
356 json_object_set_new(root, "vendor", json_string_t(m_vendor));
357 json_object_set_new(root, "model", json_string_t(m_model));
358 json_object_set_new(root, "serialNumber", json_string_t(m_serialNumber));
359 json_object_set_new(root, "osName", json_string_t(m_osName));
360 json_object_set_new(root, "osVersion", json_string_t(m_osVersion));
361 json_object_set_new(root, "userId", json_string_t(m_userId));
362 json_object_set_new(root, "batteryLevel", json_integer(m_batteryLevel));
363 json_object_set_new(root, "ipAddress", m_ipAddress.toJson());
364 return root;
365}