28031afce76057d5a576dd45e895276d51a327a7
[public/netxms.git] / src / server / core / mobile.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2016 Victor Kirhenshtein
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
20 **/
21
22 #include "nxcore.h"
23
24 /**
25 * Default constructor
26 */
27 MobileDevice::MobileDevice() : DataCollectionTarget()
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;
37 m_batteryLevel = -1;
38 }
39
40 /**
41 * Constructor for creating new mobile device object
42 */
43 MobileDevice::MobileDevice(const TCHAR *name, const TCHAR *deviceId) : DataCollectionTarget(name)
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;
53 m_batteryLevel = -1;
54 }
55
56 /**
57 * Destructor
58 */
59 MobileDevice::~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 }
69
70 /**
71 * Create object from database data
72 */
73 bool MobileDevice::loadFromDatabase(DB_HANDLE hdb, UINT32 dwId)
74 {
75 m_id = dwId;
76
77 if (!loadCommonProperties(hdb))
78 {
79 DbgPrintf(2, _T("Cannot load common properties for mobile device object %d"), dwId);
80 return false;
81 }
82
83 TCHAR query[256];
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);
85 DB_RESULT hResult = DBSelect(hdb, query);
86 if (hResult == NULL)
87 return false;
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);
96 m_batteryLevel = DBGetFieldLong(hResult, 0, 7);
97 DBFreeResult(hResult);
98
99 // Load DCI and access list
100 loadACLFromDB(hdb);
101 loadItemsFromDB(hdb);
102 for(int i = 0; i < m_dcObjects->size(); i++)
103 if (!m_dcObjects->get(i)->loadThresholdsFromDB(hdb))
104 return false;
105
106 return true;
107 }
108
109 /**
110 * Save object to database
111 */
112 bool MobileDevice::saveToDatabase(DB_HANDLE hdb)
113 {
114 // Lock object's access
115 lockProperties();
116
117 saveCommonProperties(hdb);
118
119 bool bResult;
120 DB_STATEMENT hStmt;
121 if (IsDatabaseRecordExist(hdb, _T("mobile_devices"), _T("id"), m_id))
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=?"));
123 else
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 (?,?,?,?,?,?,?,?,?)"));
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);
134 DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_batteryLevel);
135 DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, m_id);
136
137 bResult = DBExecute(hStmt);
138
139 DBFreeStatement(hStmt);
140 }
141 else
142 {
143 bResult = false;
144 }
145
146 // Save data collection items
147 if (bResult)
148 {
149 lockDciAccess(false);
150 for(int i = 0; i < m_dcObjects->size(); i++)
151 m_dcObjects->get(i)->saveToDatabase(hdb);
152 unlockDciAccess();
153 }
154
155 // Save access list
156 saveACLToDB(hdb);
157
158 // Clear modifications flag and unlock object
159 if (bResult)
160 m_isModified = false;
161 unlockProperties();
162
163 return bResult;
164 }
165
166 /**
167 * Delete object from database
168 */
169 bool MobileDevice::deleteFromDatabase(DB_HANDLE hdb)
170 {
171 bool success = DataCollectionTarget::deleteFromDatabase(hdb);
172 if (success)
173 success = executeQueryOnObject(hdb, _T("DELETE FROM mobile_devices WHERE id=?"));
174 return success;
175 }
176
177 /**
178 * Create CSCP message with object's data
179 */
180 void MobileDevice::fillMessageInternal(NXCPMessage *msg)
181 {
182 DataCollectionTarget::fillMessageInternal(msg);
183
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);
193 }
194
195 /**
196 * Modify object from message
197 */
198 UINT32 MobileDevice::modifyFromMessageInternal(NXCPMessage *pRequest)
199 {
200 return DataCollectionTarget::modifyFromMessageInternal(pRequest);
201 }
202
203 /**
204 * Update system information from NXCP message
205 */
206 void MobileDevice::updateSystemInfo(NXCPMessage *msg)
207 {
208 lockProperties();
209
210 m_lastReportTime = time(NULL);
211
212 safe_free(m_vendor);
213 m_vendor = msg->getFieldAsString(VID_VENDOR);
214
215 safe_free(m_model);
216 m_model = msg->getFieldAsString(VID_MODEL);
217
218 safe_free(m_serialNumber);
219 m_serialNumber = msg->getFieldAsString(VID_SERIAL_NUMBER);
220
221 safe_free(m_osName);
222 m_osName = msg->getFieldAsString(VID_OS_NAME);
223
224 safe_free(m_osVersion);
225 m_osVersion = msg->getFieldAsString(VID_OS_VERSION);
226
227 safe_free(m_userId);
228 m_userId = msg->getFieldAsString(VID_USER_NAME);
229
230 setModified();
231 unlockProperties();
232 }
233
234 /**
235 * Update status from NXCP message
236 */
237 void MobileDevice::updateStatus(NXCPMessage *msg)
238 {
239 lockProperties();
240
241 m_lastReportTime = time(NULL);
242
243 int type = msg->getFieldType(VID_BATTERY_LEVEL);
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);
248 else
249 m_batteryLevel = -1;
250
251 if (msg->isFieldExist(VID_GEOLOCATION_TYPE))
252 {
253 m_geoLocation = GeoLocation(*msg);
254 addLocationToHistory();
255 }
256
257 if (msg->isFieldExist(VID_IP_ADDRESS))
258 m_ipAddress = msg->getFieldAsInetAddress(VID_IP_ADDRESS);
259
260 TCHAR temp[64];
261 DbgPrintf(5, _T("Mobile device %s [%d] updated from agent (battery=%d addr=%s loc=[%s %s])"),
262 m_name, (int)m_id, m_batteryLevel, m_ipAddress.toString(temp),
263 m_geoLocation.getLatitudeAsString(), m_geoLocation.getLongitudeAsString());
264
265 setModified();
266 unlockProperties();
267 }
268
269 /**
270 * Get value for server's internal parameter
271 */
272 UINT32 MobileDevice::getInternalItem(const TCHAR *param, size_t bufSize, TCHAR *buffer)
273 {
274 UINT32 rc = DataCollectionTarget::getInternalItem(param, bufSize, buffer);
275 if (rc != DCE_NOT_SUPPORTED)
276 return rc;
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 }
322
323 /**
324 * Calculate compound status
325 */
326 void MobileDevice::calculateCompoundStatus(BOOL bForcedRecalc)
327 {
328 NetObj::calculateCompoundStatus(bForcedRecalc);
329
330 // Assume normal status by default for mobile device
331 if (m_status == STATUS_UNKNOWN)
332 {
333 lockProperties();
334 m_status = STATUS_NORMAL;
335 setModified();
336 unlockProperties();
337 }
338 }
339
340 /**
341 * Create NXSL object for this object
342 */
343 NXSL_Value *MobileDevice::createNXSLObject()
344 {
345 return new NXSL_Value(new NXSL_Object(&g_nxslMobileDeviceClass, this));
346 }
347
348 /**
349 * Serialize object to JSON
350 */
351 json_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 }