· 6 years ago · Oct 12, 2019, 01:34 PM
1let debug = require('debug')('UnifiAPI');
2let merge = require('merge');
3let UnifiRequest = require('./lib/unifi-request');
4let SSHSession = require('./lib/ssh-session');
5
6let defaultOptions = {
7 'username': 'unifi',
8 'password': 'unifi',
9 'baseUrl': 'https://127.0.0.1:8443',
10 'debug': false,
11 'debugNet': false,
12 'gzip': true,
13 'site': 'default'
14};
15
16/**
17 * The main class and the initialization of the Unifi Access
18 * @param {object} options the options during initialization
19 * @param {string} options.baseUrl the URL where the Unifi controller is. Default https://127.0.0.1:8443
20 * @param {string} options.username default username
21 * @param {string} options.password default password
22 * @param {string} options.site default site. Default is "default"
23 * @param {boolean} options.debug if the debug log is enabled
24 * @param {boolean} options.debugNet if the debug of the request module is enabled
25 * @returns this
26 * @example let UnifiAPI = require('node-unifiapi');
27 * let unifi = UnifiAPI({
28 * baseUrl: 'https://127.0.0.1:8443', // The URL of the Unifi Controller
29 * username: 'ubnt',
30 * password: 'ubnt',
31 * // debug: true, // More debug of the API (uses the debug module)
32 * // debugNet: true // Debug of the network requests (uses request module)
33 * });
34 */
35function UnifiAPI(options) {
36 if (!(this instanceof UnifiAPI)) return new UnifiAPI(options);
37 merge(this, defaultOptions, options);
38 this.debugging(this.debug);
39 if (typeof this.net === 'undefined') {
40 this.net = new UnifiRequest(merge(true, defaultOptions, options));
41 }
42 debug('UnifiAPI Initialized with options %o', options);
43}
44
45/**
46 * Enable or disable the debug of the module
47 * @param {boolean} enable Enable or disable the debugging
48 * @returns {undefined}
49 */
50UnifiAPI.prototype.debugging = function(enabled) {
51 this.debug = enabled;
52 debug.enabled = this.debug ? true : false;
53 debug('Debug is', this.debug ? 'enabled' : 'disabled');
54};
55
56/**
57 * Generic network operation, executing Ubiquiti command under /api/s/{site}/... rest api
58 * @param {string} url The right part of the URL (/api/s/{site}/ is automatically added)
59 * @param {object} jsonParams optional. Default undefined. If it is defined and it is object, those will be the JSON POST attributes sent to the URL and the the default method is changed from GET to POST
60 * @param {object} headers optional. Default {}. HTTP headers that we require to be sent in the request
61 * @param {object} method optional. Default undefined. The HTTP request method. If undefined, then it is automatic. If no jsonParams specified, it will be GET. If jsonParams are specified it will be POST
62 * @param {string} site optional. The {site} atribute of the request. If not specified, it is taken from the UnifiAPI init options, where if it is not specified, it is "default"
63 * @return {Promise}
64 * @example unifi.netsite('/cmd/stamgr', { cmd: 'authorize-guest', mac: '00:01:02:03:04:05', minutes: 60 }, {}, 'POST', 'default')
65 * .then(data => console.log('Success', data))
66 * .catch(error => console.log('Error', error));
67 */
68UnifiAPI.prototype.netsite = function(url = '', jsonParams = undefined, headers = {}, method = undefined, site = undefined) {
69 site = site || this.site;
70 if (typeof method === 'undefined') {
71 if (typeof jsonParams === 'undefined') method = 'GET';
72 else method = 'POST';
73 }
74 return this.net.req('/api/s/' + site + url, jsonParams, headers, method)
75};
76
77/**
78 * @description Explicit login to the controller. It is not necessary, as every other method calls implicid login (with the default username and password) before execution
79 * @param {string} username The username
80 * @param {string} password The password
81 * @return {Promise} success or failure
82 * @example unifi.login(username, password)
83 * .then(data => console.log('success', data))
84 * .catch(err => console.log('Error', err))
85 */
86UnifiAPI.prototype.login = function(username, password) {
87 return this.net.login(username, password);
88};
89
90/**
91 * Logout of the controller
92 * @example unifi.logout()
93 * .then(() => console.log('Success'))
94 * .catch(err => console.log('Error', err))
95 */
96UnifiAPI.prototype.logout = function() {
97 return this.net.logout();
98};
99
100/**
101 * Authorize guest by a MAC address
102 * @param {string} mac mac address of the guest - mandatory
103 * @param {string} minutes minutes for the authorization - optional, default 60 min
104 * @param {string} up upstream bandwidth in Kbps. Default no limit
105 * @param {string} down downstream bandwidth in Kbps. Default no _limit
106 * @param {string} mbytes download limit in Mbytes. Default no limit
107 * @param {string} apmac to which mac address the authorization belongs. Default any
108 * @param {string} site to which site (Ubiquiti) the command will be applied if it is different than the default
109 * @return {Promise} Promise
110 * @example unifi.authorize_guest('01:02:aa:bb:cc')
111 * .then(data => console.log('Successful authorization'))
112 * .catch(err => console.log('Error', err))
113 */
114UnifiAPI.prototype.authorize_guest = function(mac = '', minutes = 60, up = undefined, down = undefined, mbytes = undefined, apmac = undefined, site = undefined) {
115 return this.netsite('/cmd/stamgr', {
116 cmd: 'authorize-guest',
117 mac: mac.toLowerCase(),
118 minutes: minutes,
119 up: up,
120 down: down,
121 bytes: mbytes,
122 ap_mac: apmac && apmac.toLowerCase()
123 }, {}, undefined, site);
124};
125
126/**
127 * De-authorize guest by a MAC address
128 * @param {string} mac the mac address
129 * @param {site} site Ubiquiti site, if different from default - optional
130 * @return {Promise} Promise
131 * @example unifi.unauthorize_guest('00:01:02:03:aa:bb')
132 * .then(done => console.log('Success', done))
133 * .catch(err => console.log('Error', err))
134 */
135UnifiAPI.prototype.unauthorize_guest = function(mac = '', site = undefined) {
136 return this.netsite('/cmd/stamgr', {
137 cmd: 'uauthorize-guest',
138 mac: mac.toLowerCase()
139 }, {}, undefined, site);
140};
141
142/**
143 * Kick a client (station) of the network. This will disconnect a wireless user if it is connected
144 * @param {string} mac Mac address
145 * @param {string} site Ubiquiti site, if different from default - optional
146 * @return {Promise} Promise
147 * @example unifi.kick_sta('00:00:11:22:33:44')
148 * .then(done => console.log('Success', done))
149 * .catch(err => console.log('Error', err))
150 */
151UnifiAPI.prototype.kick_sta = function(mac = '', site = undefined) {
152 return this.netsite('/cmd/stamgr', {
153 cmd: 'kick_sta',
154 mac: mac.toLowerCase()
155 }, {}, undefined, site);
156};
157
158/**
159 * Terminate access of a Guest (logged in via Guest Authorization). It kicks it out of the wireless and authroization
160 * @param {string} id the ID of the guest that have to be kicked out
161 * @param {string} site Ubiquiti site, if different from default - optional
162 * @return {Promise} Promise
163 * @example unifi.terminate_guest('aa01af0133d334d77d')
164 * .this(done => console.log('Success', done))
165 * .catch(err => console.log('Error', err))
166 */
167UnifiAPI.prototype.terminate_guest = function(id = '', site = undefined) {
168 return this.netsite('/cmd/hotspot', {
169 _id: id,
170 cmd: 'terminate'
171 }, {}, undefined, site);
172};
173
174/**
175 * Block station of the network
176 * @param {string} mac Mac address
177 * @param {string} site Ubiquiti site, if different from default - optional
178 * @return {Promise} Promise
179 * @example unifi.block_sta('00:01:02:03:04:05')
180 * .then(done => console.log('Success',done))
181 * .catch(err => console.log('Error', err))
182 */
183UnifiAPI.prototype.block_sta = function(mac = '', site = undefined) {
184 return this.netsite('/cmd/stamgr', {
185 cmd: 'block-sta',
186 mac: mac.toLowerCase()
187 }, {}, undefined, site);
188};
189
190/**
191 * Unblock station of the network
192 * @param {string} mac Mac address
193 * @param {string} site Ubiquiti site, if different from default - optional
194 * @return {Promise} Promise
195 * @example unifi.block_sta('00:01:02:03:04:05')
196 * .then(done => console.log('Success',done))
197 * .catch(err => console.log('Error', err))
198 */
199UnifiAPI.prototype.unblock_sta = function(mac = '', site = undefined) {
200 return this.netsite('/cmd/stamgr', {
201 cmd: 'unblock-sta',
202 mac: mac.toLowerCase()
203 }, {}, undefined, site);
204};
205
206/**
207 * Set or remove Note to a station
208 * @param {string} user User ID
209 * @param {string} note Note
210 * @param {string} site Ubiquiti site, if different from default - optional
211 * @return {Promise} Promise
212 * @example unifi.set_sta_note('aabbaa0102aa03aa3322','Test note')
213 * .then(done => console.log('Success',done))
214 * .catch(err => console.log('Error',err))
215 * @example unifi.set_sta_note('aabbaa0102aa03aa3322','') // remove note
216 * .then(done => console.log('Success',done))
217 * .catch(err => console.log('Error',err))
218 */
219UnifiAPI.prototype.set_sta_note = function(user = '', note = '', site = undefined) {
220 return this.netsite('/upd/user/' + user, {
221 note: note,
222 noted: note ? true : false
223 }, {}, undefined, site);
224};
225
226/**
227 * Set or remove Name to a station
228 * @param {string} user User ID
229 * @param {string} name Name
230 * @param {string} site Ubiquiti site, if different from default - optional
231 * @return {Promise} Promise
232 * @example unifi.set_sta_name('aabbaa0102aa03aa3322','Central Access Point')
233 * .then(done => console.log('Success',done))
234 * .catch(err => console.log('Error',err))
235 * @example unifi.set_sta_name('aabbaa0102aa03aa3322','') // remove name
236 * .then(done => console.log('Success',done))
237 * .catch(err => console.log('Error',err))
238 */
239UnifiAPI.prototype.set_sta_name = function(user = '', name = '', site = undefined) {
240 return this.netsite('/upd/user/' + user, {
241 name: name
242 }, {}, undefined, site);
243};
244
245/**
246 * List client sessions
247 * @param {number} start Start time in Unix Timestamp - Optional. Default 7 days ago
248 * @param {number} end End time in Unix timestamp - Optional. Default - now
249 * @param {string} type Sessions type. Optional. Default all
250 * @param {string} site Ubiquiti site, if different from default - optional
251 * @return {Promise} Promise
252 * @example unifi.stat_sessions()
253 * .then(done => console.log('Success',done))
254 * .catch(err => console.log('Error',err))
255 */
256UnifiAPI.prototype.stat_sessions = function(start = undefined, end = undefined, type = 'all', site = undefined) {
257 return this.netsite('/stat/sessions', {
258 type: type,
259 start: start || (new Date()).getTime() / 1000 - 7 * 24 * 3600 * 1000,
260 end: end || (new Date()).getTime()
261 }, {}, undefined, site);
262};
263
264/**
265 * List daily site statistics
266 * @param {number} start Start time in Unix Timestamp - Optional. Default 7 days ago
267 * @param {number} end End time in Unix timestamp - Optional. Default - now
268 * @param {array} attrs What attributes we are quering for. Optional. Default [ 'bytes', 'wan-tx_bytes', 'wan-rx_bytes', 'wlan_bytes', 'num_sta', 'lan-num_sta', 'wlan-num_sta', 'time' ]
269 * @param {string} site Ubiquiti site, if different from default - optional
270 * @return {Promise} Promise
271 * @example unifi.stat_daily_site()
272 * .then(done => console.log('Success',done))
273 * .catch(err => console.log('Error',err))
274 */
275UnifiAPI.prototype.stat_daily_site = function(start = undefined, end = undefined, attrs = ['bytes', 'wan-tx_bytes', 'wan-rx_bytes', 'wlan_bytes', 'num_sta', 'lan-num_sta', 'wlan-num_sta', 'time'], site = undefined) {
276 return this.netsite('/stat/report/daily.site', {
277 start: start ? start : (new Date()).getTime() - 52 * 7 * 24 * 3600 * 1000,
278 end: end ? end : (new Date()).getTime(),
279 attrs: attrs
280 }, {}, undefined, site);
281};
282
283/**
284 * List hourly site statistics
285 * @param {number} start Start time in Unix Timestamp - Optional. Default 7 days ago
286 * @param {number} end End time in Unix timestamp - Optional. Default - now
287 * @param {array} attrs What attributes we are quering for. Optional. Default [ 'bytes', 'wan-tx_bytes', 'wan-rx_bytes', 'wlan_bytes', 'num_sta', 'lan-num_sta', 'wlan-num_sta', 'time' ]
288 * @param {string} site Ubiquiti site, if different from default - optional
289 * @return {Promise} Promise
290 * @example unifi.stat_hourly_site()
291 * .then(done => console.log('Success',done))
292 * .catch(err => console.log('Error',err))
293 */
294UnifiAPI.prototype.stat_hourly_site = function(start = undefined, end = undefined, attrs = ['bytes', 'wan-tx_bytes', 'wan-rx_bytes', 'wlan_bytes', 'num_sta', 'lan-num_sta', 'wlan-num_sta', 'time'], site = undefined) {
295 return this.netsite('/stat/report/hourly.site', {
296 start: start ? start : (new Date()).getTime() - 7 * 24 * 3600 * 1000,
297 end: end ? end : (new Date()).getTime(),
298 attrs: attrs
299 }, {}, undefined, site);
300};
301
302/**
303 * List hourly site statistics for ap
304 * @param {number} start Start time in Unix Timestamp - Optional. Default 7 days ago
305 * @param {number} end End time in Unix timestamp - Optional. Default - now
306 * @param {array} attrs What attributes we are quering for. Optional. Default [ 'bytes', 'num_sta', 'time' ]
307 * @param {string} site Ubiquiti site, if different from default - optional
308 * @return {Promise} Promise
309 * @example unifi.stat_hourly_ap()
310 * .then(done => console.log('Success',done))
311 * .catch(err => console.log('Error',err))
312 */
313UnifiAPI.prototype.stat_hourly_ap = function(start = undefined, end = undefined, attrs = ['bytes', 'num_sta', 'time'], site = undefined) {
314 return this.netsite('/stat/report/hourly.ap', {
315 start: start ? start : (new Date()).getTime() - 7 * 24 * 3600 * 1000,
316 end: end ? end : (new Date()).getTime(),
317 attrs: attrs
318 }, {}, undefined, site);
319};
320
321/**
322 * Last station sessions
323 * @param {string} mac Mac address
324 * @param {number} limit How many sessions. Optional. Default 5
325 * @param {string} sort Sorting. Optional. Default Ascending (asc)
326 * @param {string} site Ubiquiti site, if different from default - optional
327 * @return {Promise} Promise
328 * @example unifi.stat_sta_sessions_latest('00:01:02:03:04:05', 10)
329 * .then(done => console.log('Success', done))
330 * .catch(err => console.log('Error',err))
331 */
332UnifiAPI.prototype.stat_sta_sessions_latest = function(mac = '', limit = 5, sort = '-asoc-time', site = undefined) {
333 return this.netsite('/stat/sessions', {
334 mac: mac.toLowerCase(),
335 '_limit': limit,
336 '_sort': sort
337 }, {}, undefined, site);
338};
339
340/**
341 * List authorizations
342 * @param {number} start Start time in Unix Timestamp - Optional. Default 7 days ago
343 * @param {number} end End time in Unix timestamp - Optional. Default - now
344 * @param {string} site Ubiquiti site, if different from default - optional
345 * @return {Promise} Promise
346 * @example unifi.stat_auths()
347 * .then(done => console.log('Success',done))
348 * .catch(err => console.log('Error',err))
349 */
350UnifiAPI.prototype.stat_auths = function(start = undefined, end = undefined, site = undefined) {
351 return this.netsite('/stat/authorization', {
352 end: end || (new Date()).getTime(),
353 start: start || (new Date()).getTime() - 7 * 24 * 3600000
354 }, {}, undefined, site);
355};
356
357/**
358 * List all users
359 * @param {number} historyhours How many hours back to query. Optional. Default 8670
360 * @param {string} site Ubiquiti site, if different from default - optional
361 * @return {Promise} Promise
362 * @example unifi.stat_allusers()
363 * .then(done => console.log('Success',done))
364 * .catch(err => console.log('Error',err))
365 */
366UnifiAPI.prototype.stat_allusers = function(historyhours = 8670, type = 'all', conn = 'all', site = undefined) {
367 return this.netsite('/stat/alluser', {
368 type: type,
369 conn: conn,
370 within: historyhours
371 }, {}, undefined, site);
372};
373
374/**
375 * List of guests (authorized via the guest portal)
376 * @param {number} historyhours How many hours back to query. Optional. Default 8670
377 * @param {string} site Ubiquiti site, if different from default - optional
378 * @return {Promise} Promise
379 * @example unifi.list_guests()
380 * .then(done => console.log('Success',done))
381 * .catch(err => console.log('Error',err))
382 */
383UnifiAPI.prototype.list_guests = function(historyhours = 8670, site = undefined) {
384 return this.netsite('/stat/guest', {
385 within: historyhours
386 }, {}, undefined, site);
387};
388
389/**
390 * List of guests (authorized via the guest portal) but with modern internal api
391 * @param {number} historyhours How many hours back to query. Optional. Default 8670
392 * @param {string} site Ubiquiti site, if different from default - optional
393 * @return {Promise} Promise
394 * @example unifi.list_guests2()
395 * .then(done => console.log('Success',done))
396 * .catch(err => console.log('Error',err))
397 */
398UnifiAPI.prototype.list_guests2 = function(historyhours = 8670, site = undefined) {
399 return this.netsite('/stat/guest?within=' + historyhours, undefined, {}, undefined, site);
400};
401
402/**
403 * List of (all) clients per station
404 * @param {string} mac Mac address
405 * @param {string} site Ubiquiti site, if different from default - optional
406 * @return {Promise} Promise
407 * @example unifi.list_clients()
408 * .then(done => console.log('Success',done))
409 * .catch(err => console.log('Error',err))
410 */
411UnifiAPI.prototype.list_clients = function(mac = '', site = undefined) {
412 return this.netsite('/stat/sta/' + mac, undefined, {}, undefined, site);
413};
414
415/**
416 * List of group of clients per station
417 * @param {string} macs String mac or array of mac addresses as strings, to get information about them
418 * @param {string} ap Station man address
419 * @param {string} site Ubiquiti site, if different from default - optional
420 * @return {Promise} Promise
421 * @example unifi.list_some_clients()
422 * .then(done => console.log('Success',done))
423 * .catch(err => console.log('Error',err))
424 */
425UnifiAPI.prototype.list_some_clients = function(macs = undefined, ap = '', site = undefined) {
426 var clients = undefined;
427 if (macs) {
428 if (typeof macs == 'string') clients = { macs: [ macs ] }
429 else if (macs instanceof Array) clients = { macs: macs };
430 }
431 return this.netsite('/stat/sta/' + ap, clients, {}, undefined, site);
432};
433
434/**
435 * Statistics of (all) clients per station
436 * @param {string} mac Mac address
437 * @param {string} site Ubiquiti site, if different from default - optional
438 * @return {Promise} Promise
439 * @example unifi.stat_client()
440 * .then(done => console.log('Success',done))
441 * .catch(err => console.log('Error',err))
442 */
443UnifiAPI.prototype.stat_client = function(mac = '', site = undefined) {
444 return this.netsite('/stat/user/' + mac, undefined, {}, undefined, site);
445};
446
447/**
448 * List of the usergroups
449 * @param {string} site Ubiquiti site, if different from default - optional
450 * @return {Promise} Promise
451 * @example unifi.list_usergroup()
452 * .then(done => console.log('Success',done))
453 * .catch(err => console.log('Error',err))
454 */
455UnifiAPI.prototype.list_usergroup = function(site = undefined) {
456 return this.netsite('/list/usergroup', undefined, {}, undefined, site);
457};
458
459/**
460 * Add user to a group
461 * @param {string} userid ID of the user
462 * @param {string} groupid ID of the group
463 * @param {string} site Ubiquiti site, if different from default - optional
464 * @return {Promise} Promise
465 * @example unifi.set_usergroup('11aa22bb33cc44dd55ee66ff', '112233445566778899aabb')
466 * .then(done => console.log('Success',done))
467 * .catch(err => console.log('Error',err))
468 */
469UnifiAPI.prototype.set_usergroup = function(userid = '', groupid = '', site = undefined) {
470 return this.netsite('/upd/user/' + userid, {
471 usergroup_id: groupid
472 }, {}, undefined, site);
473};
474
475/**
476 * List health
477 * @param {string} site Ubiquiti site, if different from default - optional
478 * @return {Promise} Promise
479 * @example unifi.list_health()
480 * .then(done => console.log('Success',done))
481 * .catch(err => console.log('Error',err))
482 */
483UnifiAPI.prototype.list_health = function(site = undefined) {
484 return this.netsite('/stat/health', undefined, {}, undefined, site);
485};
486
487/**
488 * List dashboard
489 * @param {string} site Ubiquiti site, if different from default - optional
490 * @return {Promise} Promise
491 * @example unifi.list_dashboard()
492 * .then(done => console.log('Success',done))
493 * .catch(err => console.log('Error',err))
494 */
495UnifiAPI.prototype.list_dashboard = function(site = undefined) {
496 return this.netsite('/stat/dashboard', undefined, {}, undefined, site)
497};
498
499/**
500 * List users
501 * @param {string} site Ubiquiti site, if different from default - optional
502 * @return {Promise} Promise
503 * @example unifi.list_users()
504 * .then(done => console.log('Success',done))
505 * .catch(err => console.log('Error',err))
506 */
507UnifiAPI.prototype.list_users = function(site = undefined) {
508 return this.netsite('/list/user', undefined, {}, undefined, site);
509};
510
511/**
512 * List APs
513 * @param {string} mac AP mac/id, Optional
514 * @param {string} site Ubiquiti site, if different from default - optional
515 * @return {Promise} Promise
516 * @example unifi.list_aps()
517 * .then(done => console.log('Success',done))
518 * .catch(err => console.log('Error',err))
519 */
520UnifiAPI.prototype.list_aps = function(mac = '', site = undefined) { // TODO: not working with mac different than none
521 return this.netsite('/stat/device/' + mac, undefined, {}, undefined, site)
522};
523
524/**
525 * List Rogue APs
526 * @param {number} within For how many hours back. Optional. Default 24h
527 * @param {string} site Ubiquiti site, if different from default - optional
528 * @return {Promise} Promise
529 * @example unifi.list_rogueaps()
530 * .then(done => console.log('Success',done))
531 * .catch(err => console.log('Error',err))
532 */
533UnifiAPI.prototype.list_rogueaps = function(within = 24, site = undefined) {
534 return this.netsite('/stat/rogueap', {
535 within: within
536 }, {}, undefined, site);
537};
538
539/**
540 * List sites
541 * @return {Promise} Promise
542 * @example unifi.list_sites()
543 * .then(done => console.log('Success',done))
544 * .catch(err => console.log('Error',err))
545 */
546UnifiAPI.prototype.list_sites = function() {
547 return this.net.req('/api/self/sites');
548};
549
550/**
551 * Sites stats
552 * @return {Promise} Promise
553 * @example unifi.stat_sites()
554 * .then(done => console.log('Success',done))
555 * .catch(err => console.log('Error',err))
556 */
557UnifiAPI.prototype.stat_sites = function() {
558 return this.net.req('/api/stat/sites');
559};
560
561/**
562 * Add new site
563 * @param {string} name name
564 * @param {string} description description - optional
565 * @param {string} site Ubiquiti site to query, if different from default - optional
566 * @return {Promise} Promise
567 * @example unifi.add_site('mysite','Experimental site')
568 * .then(done => console.log('Success',done))
569 * .catch(err => console.log('Error',err))
570 */
571UnifiAPI.prototype.add_site = function(name = 'default', description = '', site = undefined) {
572 return this.netsite('/cmd/sitemgr', site = site, {
573 cmd: 'add-site',
574 name: name,
575 desc: description
576 }, {}, undefined, site);
577};
578
579/**
580 * Remove site
581 * @param {string} name name
582 * @param {string} site Ubiquiti site to query, if different from default - optional
583 * @return {Promise} Promise
584 * @example unifi.remove_site('mysite')
585 * .then(done => console.log('Success',done))
586 * .catch(err => console.log('Error',err))
587 */
588UnifiAPI.prototype.remove_site = function(name = 'none', site = undefined) { // TODO: test it
589 return this.netsite('/cmd/sitemgr', site = site, {
590 cmd: 'remove-site',
591 name: name
592 }, {}, undefined, site);
593};
594
595/**
596 * List WLANGroups
597 * @param {string} site Ubiquiti site to query, if different from default - optional
598 * @return {Promise} Promise
599 * @example unifi.list_wlan_groups()
600 * .then(done => console.log('Success',done))
601 * .catch(err => console.log('Error',err))
602 */
603UnifiAPI.prototype.list_wlan_groups = function(site = undefined) {
604 return this.netsite('/list/wlangroup', undefined, {}, undefined, site);
605};
606
607/**
608 * Stat Sysinfo
609 * @param {string} site Ubiquiti site to query, if different from default - optional
610 * @return {Promise} Promise
611 * @example unifi.stat_sysinfo()
612 * .then(done => console.log('Success',done))
613 * .catch(err => console.log('Error',err))
614 */
615UnifiAPI.prototype.stat_sysinfo = function(site = undefined) {
616 return this.netsite('/stat/sysinfo', undefined, {}, undefined, site);
617};
618
619/**
620 * Get information aboult self (username, etc)
621 * @param {string} site Ubiquiti site to query, if different from default - optional
622 * @return {Promise} Promise
623 * @example unifi.list_self()
624 * .then(done => console.log('Success',done))
625 * .catch(err => console.log('Error',err))
626 */
627UnifiAPI.prototype.list_self = function(site = undefined) { // TODO: test
628 return this.netsite('/self', undefined, {}, undefined, site);
629};
630
631/**
632 * Get information aboult the network configuration
633 * @param {string} site Ubiquiti site to query, if different from default - optional
634 * @return {Promise} Promise
635 * @example unifi.list_networkconf()
636 * .then(done => console.log('Success',done))
637 * .catch(err => console.log('Error',err))
638 */
639UnifiAPI.prototype.list_networkconf = function(site = undefined) {
640 return this.netsite('/list/networkconf', undefined, {}, undefined, site);
641};
642
643/**
644 * Get accounting / status of the vouchers
645 * @param {number} createtime Unixtimestamp since when we return information about the vouchers. Optional. Default any
646 * @param {string} site Ubiquiti site to query, if different from default - optional
647 * @return {Promise} Promise
648 * @example unifi.stat_voucher()
649 * .then(done => console.log('Success',done))
650 * .catch(err => console.log('Error',err))
651 */
652UnifiAPI.prototype.stat_voucher = function(createtime = undefined, site = undefined) {
653 return this.netsite('/stat/voucher', {
654 create_time: createtime
655 }, {}, undefined, site);
656};
657
658/**
659 * Get accounting / status of the payments
660 * @param {number} within how many hours back we query. Optional. Default any
661 * @param {string} site Ubiquiti site to query, if different from default - optional
662 * @return {Promise} Promise
663 * @example unifi.stat_payment()
664 * .then(done => console.log('Success',done))
665 * .catch(err => console.log('Error',err))
666 */
667UnifiAPI.prototype.stat_payment = function(within = undefined, site = undefined) {
668 return this.netsite('/stat/payment', { // TODO: test it, is it payment or voucher
669 within: within
670 }, {}, undefined, site);
671};
672
673/**
674 * Create HotSpot (version 1)
675 * @todo Check if the URL of the rest service is correct
676 * @todo Test that it is working
677 * @param {string} name name
678 * @param {string} password password
679 * @param {string} note Note (optional)
680 * @param {string} site Ubiquiti site to query, if different from default - optional
681 * @return {Promise} Promise
682 * @example unifi.create_hotspot('myhotspot', 'password', 'note')
683 * .then(done => console.log('Success',done))
684 * .catch(err => console.log('Error',err))
685 */
686UnifiAPI.prototype.create_hotspot = function(name = '', password = '', note = '', site = undefined) {
687 return this.netsite('/stat/voucher', {
688 name: name,
689 note: note,
690 x_password: password
691 }, {}, undefined, site);
692};
693
694/**
695 * List all of the hotspots (v1)
696 * @param {string} site Ubiquiti site to query, if different from default - optional
697 * @return {Promise} Promise
698 * @example unifi.list_hotspot()
699 * .then(done => console.log('Success',done))
700 * .catch(err => console.log('Error',err))
701 */
702UnifiAPI.prototype.list_hotspot = function(site = undefined) {
703 return this.netsite('/list/hotspotop', undefined, {}, undefined, site);
704};
705
706/**
707 * Create vouchers. Generate a set of vouchers
708 * @param {number} count how many vouchers to generate. Optional. default is 1
709 * @param {number} minutes how long the voucher may be active after activation in minutes. Optional. default is 60 minutes
710 * @param {number} quota how many times a user may reuse (login with) this voucher. Default 0 = unlimited. 1 means only once. 2 means two times and so on
711 * @param {string} note the note of the voucher. Optional
712 * @param {number} up Upstream bandwidth rate limit in Kbits. Optional. Default - no limit
713 * @param {number} down Downstream bandwidth rate limit in Kbits. Optional. Default - no limit
714 * @param {number} mbytes Limit of the maximum download traffic in Mbytes. Optional. Default - no limit
715 * @param {string} site Ubiquiti site to query, if different from default - optional
716 * @return {Promise} Promise
717 * @example unifi.create_voucher(10, 2880, 1, 'Test vouchers', 1000, 2000, 250)
718 * .then(done => console.log('Success',done))
719 * .catch(err => console.log('Error',err))
720 */
721UnifiAPI.prototype.create_voucher = function(count = 1, minutes = 60, quota = 0, note = undefined, up = undefined, down = undefined, mbytes = undefined, site = undefined) {
722 return this.netsite('/cmd/hotspot', {
723 note: note,
724 up: up,
725 down: down,
726 bytes: mbytes,
727 cmd: 'create-voucher',
728 expire: minutes,
729 n: count,
730 quota: quota
731 }, {}, undefined, site);
732};
733
734/**
735 * Revoke Voucher. Voucher revoking is the same as deleting the voucher. In most of the cases the authorized user is kicked out of the network too
736 * @param {string} voucher_id description
737 * @param {string} site Ubiquiti site to query, if different from default - optional
738 * @return {Promise} Promise
739 * @example unifi.revoke_voucher('9912982aaff182728a0f03')
740 * .then(done => console.log('Success',done))
741 * .catch(err => console.log('Error',err))
742 */
743UnifiAPI.prototype.revoke_voucher = function(voucher_id, site = undefined) {
744 return this.netsite('/cmd/hotspot', {
745 cmd: 'delete-voucher',
746 _id: voucher_id
747 }, {}, undefined, site);
748};
749
750/**
751 * List port forwarding configuration
752 * @param {string} site Ubiquiti site to query, if different from default - optional
753 * @return {Promise} Promise
754 * @example unifi.list_portforwarding()
755 * .then(done => console.log('Success',done))
756 * .catch(err => console.log('Error',err))
757 */
758UnifiAPI.prototype.list_portforwarding = function(site = undefined) {
759 return this.netsite('/list/portforward', undefined, {}, undefined, site);
760};
761
762/**
763 * List dynamic dns configuration
764 * @param {string} site Ubiquiti site to query, if different from default - optional
765 * @return {Promise} Promise
766 * @example unifi.list_dynamicdns()
767 * .then(done => console.log('Success',done))
768 * .catch(err => console.log('Error',err))
769 */
770UnifiAPI.prototype.list_dynamicdns = function(site = undefined) {
771 return this.netsite('/list/dynamicdns', undefined, {}, undefined, site);
772};
773
774/**
775 * List network port configuration
776 * @todo Test it
777 * @param {string} site Ubiquiti site to query, if different from default - optional
778 * @return {Promise} Promise
779 * @example unifi.list_portconf()
780 * .then(done => console.log('Success',done))
781 * .catch(err => console.log('Error',err))
782 */
783UnifiAPI.prototype.list_portconf = function(site = undefined) {
784 return this.netsite('/list/portconf', undefined, {}, undefined, site);
785};
786
787/**
788 * List extensions
789 * @todo Learn more what exactly is this
790 * @param {string} site Ubiquiti site to query, if different from default - optional
791 * @return {Promise} Promise
792 * @example unifi.list_extension()
793 * .then(done => console.log('Success',done))
794 * .catch(err => console.log('Error',err))
795 */
796UnifiAPI.prototype.list_extension = function(site = undefined) {
797 return this.netsite('/list/extension', undefined, {}, undefined, site);
798};
799
800/**
801 * Get array with all the settings refered by settings key
802 * @param {string} site Ubiquiti site to query, if different from default - optional
803 * @return {Promise} Promise
804 * @example unifi.list_settings()
805 * .then(done => console.log('Success',done))
806 * .catch(err => console.log('Error',err))
807 */
808UnifiAPI.prototype.list_settings = function(site = undefined) {
809 return this.netsite('/get/setting', undefined, {}, undefined, site)
810};
811
812/**
813 * Restart Wireless Access Point
814 * @param {string} mac mac address of the AP
815 * @param {string} site Ubiquiti site to query, if different from default - optional
816 * @return {Promise} Promise
817 * @example unifi.restart_ap('00:01:02:03:aa:04')
818 * .then(done => console.log('Success',done))
819 * .catch(err => console.log('Error',err))
820 */
821UnifiAPI.prototype.restart_ap = function(mac = '', site = undefined) {
822 return this.netsite('/cmd/devmgr', {
823 cmd: 'restart',
824 mac: mac.toLowerCase()
825 }, {}, undefined, site);
826};
827
828/**
829 * Disable Wireless Access Point
830 * @param {string} ap_id The internal ID of the AP
831 * @param {boolean} disable Shall we disable it. Optional. Default true. If false, the AP is enabled
832 * @param {string} site Ubiquiti site to query, if different from default - optional
833 * @return {Promise} Promise
834 * @example unifi.disable_ap('001fa98a00a22328123')
835 * .then(done => console.log('Success',done))
836 * .catch(err => console.log('Error',err))
837 */
838UnifiAPI.prototype.disable_ap = function(ap_id = '', disable = true, site = undefined) {
839 return this.netsite('/rest/device/' + ap_id, {
840 disabled: disable
841 }, {}, undefined, site);
842};
843
844/**
845 * Enable Wireless Access Point
846 * @param {string} ap_id The internal ID of the AP
847 * @param {boolean} disable Shall we disable it. Optional. Default true. If false, the AP is enabled
848 * @param {string} site Ubiquiti site to query, if different from default - optional
849 * @return {Promise} Promise
850 * @example unifi.enable_ap('001fa98a00a22328123')
851 * .then(done => console.log('Success',done))
852 * .catch(err => console.log('Error',err))
853 */
854UnifiAPI.prototype.enable_ap = function(ap_id = '', disable = false, site = undefined) {
855 return this.disable_ap(ap_id, disable, site);
856};
857
858/**
859 * Locate Wireless Access Point. The Access Point will start blinking
860 * @param {string} mac mac of the AP
861 * @param {string} site Ubiquiti site to query, if different from default - optional
862 * @return {Promise} Promise
863 * @example unifi.set_locate_ap('00:01:aa:03:04:05')
864 * .then(done => console.log('Success',done))
865 * .catch(err => console.log('Error',err))
866 */
867UnifiAPI.prototype.set_locate_ap = function(mac = '', site = undefined) {
868 return this.netsite('/cmd/devmgr', {
869 mac: mac.toLowerCase(),
870 cmd: 'set-locate'
871 }, {}, undefined, site);
872};
873
874/**
875 * Turn off Locate Wireless Access Point. The Access Point will stop blinking
876 * @param {string} mac mac of the AP
877 * @param {string} site Ubiquiti site to query, if different from default - optional
878 * @return {Promise} Promise
879 * @example unifi.unset_locate_ap('00:01:aa:03:04:05')
880 * .then(done => console.log('Success',done))
881 * .catch(err => console.log('Error',err))
882 */
883UnifiAPI.prototype.unset_locate_ap = function(mac = '', site = undefined) {
884 return this.netsite('/cmd/devmgr', {
885 mac: mac.toLowerCase(),
886 cmd: 'unset-locate'
887 }, {}, undefined, site);
888};
889
890/**
891 * All devices in the site group will start blinking
892 * @param {string} site Ubiquiti site to query, if different from default - optional
893 * @return {Promise} Promise
894 * @example unifi.site_ledson()
895 * .then(done => console.log('Success',done))
896 * .catch(err => console.log('Error',err))
897 */
898UnifiAPI.prototype.site_ledson = function(site = undefined) {
899 return this.netsite('/set/setting/mgmt', {
900 led_enabled: true
901 }, {}, undefined, site);
902};
903
904/**
905 * All devices in the site group will stop blinking
906 * @param {string} site Ubiquiti site to query, if different from default - optional
907 * @return {Promise} Promise
908 * @example unifi.site_ledsoff()
909 * .then(done => console.log('Success',done))
910 * .catch(err => console.log('Error',err))
911 */
912UnifiAPI.prototype.site_ledsoff = function(site = undefined) {
913 return this.netsite('/set/setting/mgmt', {
914 led_enabled: false
915 }, {}, undefined, site);
916};
917
918/**
919 * Change AP wireless settings
920 * @param {string} ap_id internal id of the AP
921 * @param {string} radio The radio type. Supports ng or ac. Default ng. Optional
922 * @param {number} channel Wireless channel. Optional. Default 1. Could be string 'auto'
923 * @param {number} ht HT width in MHz. 20, 40, 80, 160. Optional. Default 20
924 * @param {number} tx_power_mode TX Power Mode. Optional. Default 0
925 * @param {number} tx_power TX Power. Optional. Default 0
926 * @param {string} site Ubiquiti site to query, if different from default - optional
927 * @return {Promise} Promise
928 * @example unifi.set_ap_radiosettings('aa0101023faabbaacc0c0', 'ng', 3, 20)
929 * .then(done => console.log('Success',done))
930 * .catch(err => console.log('Error',err))
931 */
932UnifiAPI.prototype.set_ap_radiosettings = function(ap_id = '', radio = 'ng', channel = 1, ht = '20', tx_power_mode = 0, tx_power = 0) {
933 return this.netsite('/upd/device/' + ap_id, {
934 radio: radio,
935 channel: channel,
936 ht: ht,
937 tx_power_mode: tx_power_mode,
938 tx_power: tx_power
939 }, {}, undefined, site);
940};
941
942/**
943 * Alias to list_settings. Retrieve array with settings defined by setting key.
944 * @alias list_settings
945 * @param {string} site Ubiquiti site to query, if different from default - optional
946 * @return {Promise} Promise
947 * @example unifi.get_settings()
948 * .then(done => console.log('Success',done))
949 * .catch(err => console.log('Error',err))
950 */
951UnifiAPI.prototype.get_settings = function(site = undefined) {
952 return this.netsite('/get/setting', undefined, {}, undefined, site);
953};
954
955/**
956 * Retrieve settings by a specific settings key. Only elements with this settings key will be returned in the array. Usually 1 or 0
957 * Typical keys are mgmt, snmp, porta, locale, rsyslogd, auto_speedtest, country, connectivity
958 * @param {string} key key
959 * @param {string} site Ubiquiti site to query, if different from default - optional
960 * @return {Promise} Promise
961 * @example unifi.get_settings_by_key('mgmt')
962 * .then(done => console.log('Success',done))
963 * .catch(err => console.log('Error',err))
964 */
965UnifiAPI.prototype.get_settings_by_key = function(key, site = undefined) {
966 return new Promise((resolve, reject) => {
967 this.get_settings(site)
968 .then((data) => {
969 data.data = data.data.filter(n => n.key == key);
970 resolve(data);
971 })
972 .catch(reject);
973 });
974};
975
976/**
977 * Set settings by key modifies properties of the settings, defined by key
978 * @param {string} key key
979 * @param {object} obj object of properties that overwrite the original values
980 * @param {string} site Ubiquiti site to query, if different from default - optional
981 * @return {Promise} Promise
982 * @example unifi.set_settings_by_key('mgmt', { auto_upgrade: true })
983 * .then(done => console.log('Success',done))
984 * .catch(err => console.log('Error',err))
985 */
986UnifiAPI.prototype.set_settings = function(key, obj, site = undefined) {
987 return new Promise((resolve, reject) => {
988 this.get_settings_by_key(key, site)
989 .then((data) => {
990 if (data.data.length < 1) return reject({ msg: 'No such key', meta: { rc: 'error' } });
991 let o = merge(true, data.data[0], obj);
992 return this.netsite('/set/setting/' + o.key + '/' + o._id, o, {}, undefined, site);
993 })
994 .then(resolve)
995 .catch(reject);
996 });
997};
998
999/**
1000 * Set Guest Settings and Guest Access Portal are created with this method
1001 * @param {object} obj Object of properties that modify the original values
1002 * @param {string} obj.auth Optional. Type of authentication. hotspot, radius, none, .... Default hotspot
1003 * @param {string} obj.expire Optional. How long the authentication is valid in minutes. Default 480 (8h)
1004 * @param {boolean} obj.facebook_enabled Optional. Allow authentication with facebook. Default false
1005 * @param {boolean} obj.google_enabled Optional. Allow authentication with google+. Default false
1006 * @param {boolean} obj.payment Optional. Allow payments for authentication. Default false
1007 * @param {boolean} obj.portal_customized Optional. Customize the auth portal. Default false
1008 * @param {boolean} obj.portal_enabled Optional. Enable the portal. Default true
1009 * @param {boolean} obj.redirect_enabled Optional. Redirect after authentication. Default false
1010 * @param {string} obj.redirect_url Optional. Redirect URL after successful authentication. Default empty
1011 * @param {boolean} obj.voucher_enabled Optional. If voucher authentication is enabled. Default false
1012 * @param {string} guest_id From the get_settings, the ID of the guest settings
1013 * @param {string} site_id The ID of the current site
1014 * @param {string} site Ubiquiti site to query, if different from default - optonal
1015 * @return {Promise} Promise
1016 * @example unifi.set_guest_access({ auth: 'hotspot', payment_enabled: true }, 'aabbaa01010203','ccffee0102030303')
1017 * .then(done => console.log('Success',done))
1018 * .catch(err => console.log('Error',err))
1019 */
1020UnifiAPI.prototype.set_guest_access = function(obj, guest_id, site_id, site = undefined) {
1021 let o = merge({}, {
1022 _id: guest_id || obj._id,
1023 site_id: site_id || obj.site_id,
1024 'auth': 'hotspot',
1025 'expire': '480',
1026 'facebook_enabled': false,
1027 'google_enabled': false,
1028 'key': 'guest_access',
1029 'payment_enabled': false,
1030 'payment_fields_address_enabled': true,
1031 'payment_fields_address_required': true,
1032 'payment_fields_city_enabled': true,
1033 'payment_fields_city_required': true,
1034 'payment_fields_country_default': '',
1035 'payment_fields_country_enabled': true,
1036 'payment_fields_country_required': true,
1037 'payment_fields_first_name_enabled': true,
1038 'payment_fields_first_name_required': true,
1039 'payment_fields_last_name_enabled': true,
1040 'payment_fields_last_name_required': true,
1041 'payment_fields_state_enabled': true,
1042 'payment_fields_state_required': true,
1043 'payment_fields_zip_enabled': true,
1044 'payment_fields_zip_required': true,
1045 'portal_customized': false,
1046 'portal_customized_bg_color': '#cccccc',
1047 'portal_customized_bg_image_enabled': false,
1048 'portal_customized_bg_image_tile': true,
1049 'portal_customized_box_color': '#ffffff',
1050 'portal_customized_box_link_color': '#1379b7',
1051 'portal_customized_box_opacity': 90,
1052 'portal_customized_box_text_color': '#000000',
1053 'portal_customized_button_color': '#1379b7',
1054 'portal_customized_button_text_color': '#ffffff',
1055 'portal_customized_languages': ['en'],
1056 'portal_customized_link_color': '#1379b7',
1057 'portal_customized_logo_enabled': false,
1058 'portal_customized_text_color': '#000000',
1059 'portal_customized_title': 'Hotspot portal',
1060 'portal_customized_tos': 'Terms of Use\n\nBy accessing the wireless network, you acknowledge that you\'re of legal age, you have read and understood and agree to be bound by this agreement.\n\nThe wireless network service is provided by the property owners and is completely at their discretion. Your access to the network may be blocked, suspended, or terminated at any time for any reason.\n\nYou agree not to use the wireless network for any purpose that is unlawful and take full responsibility of your acts.\n\nThe wireless network is provided "as is" without warranties of any kind, either expressed or implied.',
1061 'portal_customized_tos_enabled': true,
1062 'portal_customized_welcome_text_enabled': true,
1063 'portal_customized_welcome_text_position': 'under_logo',
1064 'portal_enabled': true,
1065 'redirect_enabled': false,
1066 'redirect_https': false,
1067 'redirect_to_https': false,
1068 'redirect_url': '',
1069 'restricted_subnet_1': '192.168.0.0/16',
1070 'restricted_subnet_2': '172.16.0.0/12',
1071 'restricted_subnet_3': '10.0.0.0/8',
1072 'template_engine': 'angular',
1073 'voucher_customized': false,
1074 'voucher_enabled': true,
1075 'x_facebook_app_secret': 'UBNT',
1076 'x_google_client_secret': 'UBNT',
1077 'x_password': 'UBNT'
1078 }, obj);
1079 return this.netsite('/set/setting/guest_access/' + o._id, o, {}, undefined, site);
1080};
1081
1082/**
1083 * Set Guest Login Settings (simplified version)
1084 * @param {boolean} portal_enabled If the portal is enabled. Optional. Default true
1085 * @param {boolean} portal_customized If the portal is customized. Optional. Default true
1086 * @param {boolean} redirect_enabled If the redirection is enabled. Optional. Default false
1087 * @param {string} redirect_url The url for redirection. Optional. Default ''
1088 * @param {string} x_password Password for the portal. Optional. Default ''
1089 * @param {string} site Ubiquiti site to query, if different from default - optonal
1090 * @return {Promise} Promise
1091 * @example unifi.set_guestlogin_settings(true, true, true, 'http://news.com')
1092 * .then(done => console.log('Success',done))
1093 * .catch(err => console.log('Error',err))
1094 */
1095UnifiAPI.prototype.set_guestlogin_settings = function(portal_enabled = true, portal_customized = true, redirect_enabled = false, redirect_url = '', x_password = '', expire_number = undefined, expire_unit = undefined, site_id = undefined, site = undefined) {
1096 return this.netsite('/set/setting/guest_access', {
1097 portal_enabled: portal_enabled,
1098 portal_customized: portal_customized,
1099 redirect_enabled: redirect_enabled,
1100 redirect_url: redirect_url,
1101 x_password: x_password,
1102 expire_number: expire_number,
1103 expire_unit: expire_unit,
1104 site_id: site_id
1105 }, {}, undefined, site);
1106};
1107
1108/**
1109 * Rename Access Point
1110 * @param {string} ap_id Id of the AP
1111 * @param {string} ap_name New name of the AP
1112 * @param {string} site Ubiquiti site to query, if different from default - optonal
1113 * @return {Promise} Promise
1114 * @example unifi.rename_ap('ccffee0102030303','My Access Point')
1115 * .then(done => console.log('Success',done))
1116 * .catch(err => console.log('Error',err))
1117 */
1118UnifiAPI.prototype.rename_ap = function(ap_id = '', ap_name = '', site = undefined) {
1119 return this.netsite('/upd/device/' + ap_id, {
1120 name: ap_name
1121 }, {}, undefined, site);
1122};
1123
1124/**
1125 * Set WLAN Settings
1126 * @param {strings} wlan_id ID of the Wlan
1127 * @param {string} x_password Password of the WLAN
1128 * @param {string} name Name of the WLAN
1129 * @param {string} site Ubiquiti site to query, if different from default - optonal
1130 * @return {Promise} Promise
1131 * @example unifi.set_wlansettings('ccffee0102030303', 'guest', 'GuestWLAN')
1132 * .then(done => console.log('Success',done))
1133 * .catch(err => console.log('Error',err))
1134 */
1135UnifiAPI.prototype.set_wlansettings = function(wlan_id = '', x_password = undefined, name = undefined, site = undefined) { // TODO: test it
1136 return this.netsite('/upd/wlanconf/' + wlan_id, {
1137 x_passphrase: x_password,
1138 name: name
1139 }, {}, undefined, site);
1140};
1141
1142/**
1143 * List the Events
1144 * @param {string} site Ubiquiti site to query, if different from default - optonal
1145 * @return {Promise} Promise
1146 * @example unifi.list_events()
1147 * .then(done => console.log('Success',done))
1148 * .catch(err => console.log('Error',err))
1149 */
1150UnifiAPI.prototype.list_events = function(site = undefined) {
1151 return this.netsite('/stat/event', undefined, {}, undefined, site);
1152};
1153
1154/**
1155 * Get WLAN Config. Respond with Array of Wlan configurations
1156 * @param {string} site Ubiquiti site to query, if different from default - optonal
1157 * @return {Promise} Promise
1158 * @example unifi.list_wlanconf()
1159 * .then(done => console.log('Success',done))
1160 * .catch(err => console.log('Error',err))
1161 */
1162UnifiAPI.prototype.list_wlanconf = function(site = undefined) {
1163 return this.netsite('/list/wlanconf', undefined, {}, undefined, site);
1164};
1165
1166/**
1167 * Get WLAN Config. Second REST option. Respond with Array of Wlan configurations
1168 * @param {string} site Ubiquiti site to query, if different from default - optonal
1169 * @return {Promise} Promise
1170 * @example unifi.get_wlanconf()
1171 * .then(done => console.log('Success',done))
1172 * .catch(err => console.log('Error',err))
1173 */
1174UnifiAPI.prototype.get_wlanconf = function(site = undefined) {
1175 return this.netsite('/rest/wlanconf', undefined, {}, undefined, site);
1176};
1177
1178/**
1179 * List the Alarms
1180 * @param {string} site Ubiquiti site to query, if different from default - optonal
1181 * @return {Promise} Promise
1182 * @example unifi.list_alarms()
1183 * .then(done => console.log('Success',done))
1184 * .catch(err => console.log('Error',err))
1185 */
1186UnifiAPI.prototype.list_alarms = function(site = undefined) {
1187 return this.netsite('/list/alarm', undefined, {}, undefined, site);
1188};
1189
1190/**
1191 * Set the access point LED
1192 * @param {string} ap_id AP ID
1193 * @param {string} led_override Do we follow the standard LED config. Options default and overwrite
1194 * @param {string} site Ubiquiti site to query, if different from default - optonal
1195 * @return {Promise} Promise
1196 * @example unifi.set_ap_led('12312312312','default')
1197 * .then(done => console.log('Success',done))
1198 * .catch(err => console.log('Error',err))
1199 */
1200UnifiAPI.prototype.set_ap_led = function(ap_id = '', led_override = 'default', site = undefined) {
1201 return this.netsite('/rest/device/' + ap_id, {
1202 led_override: led_override
1203 }, {}, undefined, site);
1204};
1205
1206/**
1207 * Change the name of an Access Point
1208 * @param {string} ap_id the ID of the AP
1209 * @param {string} name the new name
1210 * @param {string} site Ubiquiti site to query, if different from default - optonal
1211 * @return {Promise} Promise
1212 * @example unifi.set_ap_name('12312312312','new ap')
1213 * .then(done => console.log('Success',done))
1214 * .catch(err => console.log('Error',err))
1215 */
1216UnifiAPI.prototype.set_ap_name = function(ap_id, name = '', site = undefined) {
1217 return this.netsite('/rest/device/' + ap_id, {
1218 name: name
1219 }, {}, 'PUT', site);
1220};
1221
1222/**
1223 * Set wireless properties per AP
1224 * @param {string} ap_id the ID of the AP
1225 * @param {string} radio radio type. ng/ac/bg. Optional. Default ng
1226 * @param {number} channel The channel number or auto. Optional. Default auto.
1227 * @param {number} ht channel width. 20/40/80/160. Optional. Default 20.
1228 * @param {number} min_rssi Minimal RSSI accepted in dbi. Optional. Default -94
1229 * @param {boolean} min_rssi_enabled If enabled, drops users bellow that rssi valur. Optional. Default false
1230 * @param {number} antenna_gain The antenna gain. Optional. Default 6 dbi
1231 * @param {string} tx_power_mode TX Power Mode. Optional. Default auto
1232 * @param {string} site Ubiquiti site to query, if different from default - optonal
1233 * @return {Promise} Promise
1234 * @example unifi.set_ap_wireless('12312312312','ng', 3)
1235 * .then(done => console.log('Success',done))
1236 * .catch(err => console.log('Error',err))
1237 */
1238UnifiAPI.prototype.set_ap_wireless = function(ap_id, radio = 'ng', channel = 'auto', ht = 20, min_rssi = -94, min_rssi_enabled = false, antenna_gain = 6, tx_power_mode = 'auto') {
1239 return this.netsite('/rest/device/' + ap_id, {
1240 'radio_table': [{
1241 'antenna_gain': antenna_gain,
1242 'channel': channel,
1243 'radio': radio,
1244 'ht': ht,
1245 'min_rssi': min_rssi,
1246 'min_rssi_enabled': min_rssi_enabled,
1247 'tx_power_mode': tx_power_mode
1248 }]
1249 }, {}, 'PUT', site);
1250};
1251
1252/**
1253 * Check status
1254 * @param {string} site Ubiquiti site to query, if different from default - optonal
1255 * @return {Promise} Promise
1256 * @example unifi.status()
1257 * .then(done => console.log('Success',done))
1258 * .catch(err => console.log('Error',err))
1259 */
1260UnifiAPI.prototype.status = function(site = undefined) {
1261 return this.net.req('/status', undefined, {}, undefined, site);
1262};
1263
1264/**
1265 * Configure the network settings of AP/device
1266 * @param {string} ap_id ID of the AP
1267 * @param {string} type static or dhcp. Optional. Default dhcp
1268 * @param {string} ip IP address. Optional
1269 * @param {string} netmask netmask. Optional
1270 * @param {string} gateway gateway. Optional
1271 * @param {string} dns1 dns. Optional
1272 * @param {string} dns2 dns. Optional
1273 * @param {string} site Ubiquiti site to query, if different from default - optonal
1274 * @return {Promise} Promise
1275 * @example unifi.set_ap_network('00:01:02:03:04:05', 'dhcp')
1276 * .then(done => console.log('Success',done))
1277 * .catch(err => console.log('Error',err))
1278 */
1279UnifiAPI.prototype.set_ap_network = function(ap_id = '', type = 'dhcp', ip = '192.168.1.6', netmask = '255.255.255.0', gateway = '192.168.1.1', dns1 = '8.8.8.8', dns2 = '8.8.4.4', site = undefined) {
1280 return this.netsite('/rest/device/' + ap_id, {
1281 'config_network': [{
1282 'type': type,
1283 'ip': ip,
1284 'netmask': netmask,
1285 'gateway': gateway,
1286 'dns1': dns1,
1287 'dns2': dns2
1288 }]
1289 }, {}, 'PUT', site);
1290};
1291
1292/**
1293 * Request a spectrum scan
1294 * @param {string} mac Mac of the AP
1295 * @param {string} site Ubiquiti site to query, if different from default - optonal
1296 * @return {Promise} Promise
1297 * @example unifi.request_spectrumscan('00:01:02:03:04:05')
1298 * .then(done => console.log('Success',done))
1299 * .catch(err => console.log('Error',err))
1300 */
1301UnifiAPI.prototype.request_spectrumscan = function(mac = '', site = undefined) {
1302 return this.netsite('/cmd/devmgr', {
1303 cmd: 'spectrum-scan',
1304 mac: mac.toLowerCase()
1305 }, {}, undefined, site);
1306};
1307
1308/**
1309 * Set description to the site
1310 * @param {string} description description
1311 * @param {string} site Ubiquiti site to query, if different from default - optonal
1312 * @return {Promise} Promise
1313 * @example unifi.set_site_descr('My site')
1314 * .then(done => console.log('Success',done))
1315 * .catch(err => console.log('Error',err))
1316 */
1317UnifiAPI.prototype.set_site_descr = function(description = '', site = undefined) {
1318 return this.netsite('/cmd/sitemgr', {
1319 cmd: 'update-site',
1320 desc: description
1321 }, {}, undefined, site);
1322};
1323
1324/**
1325 * Set settings of the site (optional)
1326 * @todo To be tested and completed
1327 * @param {string} gen_id The id of the settings
1328 * @param {string} site_id The id of the site
1329 * @param {boolean} advanced advanced options enabled. Optional. default true
1330 * @param {boolean} alerts alerts enabled. Optional. default true
1331 * @param {boolean} auto_upgrade auto upgrade of the AP enabled. Optional. default true
1332 * @param {string} key always mgmt. Optional. default mgmt
1333 * @param {boolean} led_enabled Led enabled. Optional. default true
1334 * @param {string} x_ssh_username SSH username. Optional. Default ubnt
1335 * @param {string} x_ssh_password SSH password. Optional. Default ubnt
1336 * @param {string} site Ubiquiti site to query, if different from default - optonal
1337 * @return {Promise} Promise
1338 * @example unifi.set_site_settings('0101923920a3a4fbff', '3333923920a3a4fbff', false)
1339 * .then(done => console.log('Success',done))
1340 * .catch(err => console.log('Error',err))
1341 */
1342UnifiAPI.prototype.set_site_settings = function(gen_id = '', site_id = '', advanced = true, alerts = true, auto_upgrade = true, key = 'mgmt', led_enabled = true, x_ssh_username = 'ubnt', x_ssh_password = 'ubnt', x_ssh_md5passwd = '$1$PiGDOzRF$GX49UVoQSqwaLgXu/Cuvb/', site = undefined) {
1343 return this.netsite('/set/setting/mgmt/' + gen_id, {
1344 '_id': gen_id,
1345 'advanced_feature_enabled': advanced,
1346 'alert_enabled': alerts,
1347 'auto_upgrade': auto_upgrade,
1348 'key': key,
1349 'led_enabled': led_enabled,
1350 'site_id': site_id,
1351 'x_ssh_username': x_ssh_username,
1352 'x_ssh_password': x_ssh_password,
1353 'x_ssh_md5passwd': x_ssh_md5passwd
1354 }, {}, undefined, site);
1355};
1356
1357/**
1358 * Add HotSpot 2.0 configuration
1359 * @param {string} name hotspot name. Default hotspot
1360 * @param {string} network_access_internet Network access
1361 * @param {number} network_type Network type. Optional. Default 2
1362 * @param {number} venue_group Venue group. Optional. Default 2
1363 * @param {number} venue_type Venue type. Optional. Default 0
1364 * @param {string} site Ubiquiti site to query, if different from default - optonal
1365 * @return {Promise} Promise
1366 * @example unifi.add_hotspot2('hotspot2.0 config')
1367 * .then(done => console.log('Success',done))
1368 * .catch(err => console.log('Error',err))
1369 */
1370UnifiAPI.prototype.add_hotspot2 = function(name = 'hotspot', network_access_internet = undefined, network_type = 2, venue_group = 2, venue_type = 0, site = undefined) {
1371 return this.netsite('/rest/hotspot2conf', {
1372 name: name,
1373 network_access_internet: network_access_internet,
1374 network_type: network_type,
1375 venue_group: venue_group,
1376 venue_type: venue_type
1377 }, {}, undefined, site);
1378};
1379
1380/**
1381 * List hotspot 2.0 configurations
1382 * @param {string} site Ubiquiti site to query, if different from default - optonal
1383 * @return {Promise} Promise
1384 * @example unifi.list_hotspot2()
1385 * .then(done => console.log('Success',done))
1386 * .catch(err => console.log('Error',err))
1387 */
1388UnifiAPI.prototype.list_hotspot2 = function(site = undefined) {
1389 return this.netsite('/rest/hotspot2conf', undefined, {}, undefined, site);
1390};
1391
1392/**
1393 * Delete hotspot 2.0 configuration
1394 * @param {string} site Ubiquiti site to query, if different from default - optonal
1395 * @return {Promise} Promise
1396 * @example unifi.delete_hotspot2('112233445566778899aabb')
1397 * .then(done => console.log('Success',done))
1398 * .catch(err => console.log('Error',err))
1399 * @example unifi.list_hotspot2()
1400 * .then(data => unifi.delete_hotspot2(data.data.shift()._id))
1401 * .then(done => console.log('Success',done))
1402 * .catch(err => console.log('Error',err))
1403 */
1404UnifiAPI.prototype.delete_hotspot2 = function(hs_id, site = undefined) {
1405 return this.netsite('/rest/hotspot2conf/' + hs_id, undefined, {}, 'DELETE', site);
1406};
1407
1408/**
1409 * Modify Hotspot 2.0 configuration
1410 * @param {string} hs_id Hotspot2.0 config id
1411 * @param {string} name name. Optional
1412 * @param {string} network_access_internet Network access. Optional
1413 * @param {number} network_type Network type. Optional
1414 * @param {number} venue_group Venue group. Optional
1415 * @param {number} venue_type Venue type. Optional
1416 * @param {string} site Ubiquiti site to query, if different from default - optonal
1417 * @return {Promise} Promise
1418 * @example unifi.set_hotspot2('112323322aaaffa191', 'new name')
1419 * .then(done => console.log('Success',done))
1420 * .catch(err => console.log('Error',err))
1421 */
1422UnifiAPI.prototype.set_hotspot2 = function(hs_id = '', name = undefined, network_access_internet = undefined, network_type = undefined, venue_type = undefined, venue_group = undefined, site = undefined) {
1423 return this.netsite('/rest/hotspot2conf/' + hs_id, {
1424 name: name,
1425 network_access_internet: network_access_internet,
1426 _id: hs_id,
1427 network_type: network_type,
1428 venue_type: venue_type,
1429 venue_group: venue_group
1430 }, {}, 'PUT', site);
1431};
1432
1433/**
1434 * Remove WLAN configuration
1435 * @param {string} id wlan config id
1436 * @param {string} site Ubiquiti site to query, if different from default - optonal
1437 * @return {Promise} Promise
1438 * @example unifi.remove_wlanconf('112323322aaaffa191')
1439 * .then(done => console.log('Success',done))
1440 * .catch(err => console.log('Error',err))
1441 */
1442UnifiAPI.prototype.remove_wlanconf = function(id, site = undefined) {
1443 return this.netsite('/rest/wlanconf/' + id, undefined, {}, 'DELETE', site);
1444};
1445
1446UnifiAPI.prototype.add_wlanconf = function(name, is_guest = true, usergroup_id = undefined, wlangroup_id = undefined, security = 'open', enabled = true, dtim_mode = 'default', dtim_na = 1, dtim_ng = 1, mac_filter_enabled = false, mac_filter_list = [], mac_filter_policy = 'deny', radius_port_1 = 1812, schedule = [], schedule_enabled = false, usergroup = 'Default', wlangroup = 'Default', wep_idx = 1, wpa_enc = 'ccmp', wpa_mode = 'wpa2', ratectrl_na_6 = 'basic', ratectrl_na_9 = 'supported', ratectrl_na_12 = 'basic', ratectrl_na_18 = 'supported', ratectrl_na_24 = 'basic', ratectrl_na_36 = 'supported', ratectrl_na_48 = 'supported', ratectrl_na_54 = 'supported', ratectrl_na_mode = 'default', ratectrl_ng_6 = 'basic', ratectrl_ng_9 = 'supported', ratectrl_ng_12 = 'basic', ratectrl_ng_18 = 'supported', ratectrl_ng_24 = 'basic', ratectrl_ng_36 = 'supported', ratectrl_ng_48 = 'supported', ratectrl_ng_54 = 'supported', ratectrl_ng_cck_1 = 'disabled', ratectrl_ng_cck_2 = 'disabled', ratectrl_ng_cck_5_5 = 'disabled', ratectrl_ng_cck_11 = 'disabled', ratectrl_ng_mode = 'default', site = undefined) {
1447 return this.netsite('/rest/wlanconf', {
1448 'name': name,
1449 'is_guest': is_guest,
1450 'security': security,
1451 'dtim_mode': dtim_mode,
1452 'dtim_na': dtim_na,
1453 'dtim_ng': dtim_ng,
1454 'enabled': enabled,
1455 'mac_filter_enabled': mac_filter_enabled,
1456 'mac_filter_list': mac_filter_list,
1457 'mac_filter_policy': mac_filter_policy,
1458 'radius_port_1': radius_port_1,
1459 'schedule': schedule,
1460 'schedule_enabled': schedule_enabled,
1461 'usergroup_id': usergroup_id,
1462 'wlangroup_id': wlangroup_id,
1463 'wep_idx': wep_idx,
1464 'wpa_enc': wpa_enc,
1465 'wpa_mode': wpa_mode,
1466 'ratectrl_na_6': ratectrl_na_6,
1467 'ratectrl_na_9': ratectrl_na_9,
1468 'ratectrl_na_12': ratectrl_na_12,
1469 'ratectrl_na_18': ratectrl_na_18,
1470 'ratectrl_na_24': ratectrl_na_24,
1471 'ratectrl_na_36': ratectrl_na_36,
1472 'ratectrl_na_48': ratectrl_na_48,
1473 'ratectrl_na_54': ratectrl_na_54,
1474 'ratectrl_na_mode': ratectrl_na_mode,
1475 'ratectrl_ng_6': ratectrl_ng_6,
1476 'ratectrl_ng_9': ratectrl_ng_9,
1477 'ratectrl_ng_12': ratectrl_ng_12,
1478 'ratectrl_ng_18': ratectrl_ng_18,
1479 'ratectrl_ng_24': ratectrl_ng_24,
1480 'ratectrl_ng_36': ratectrl_ng_36,
1481 'ratectrl_ng_48': ratectrl_ng_48,
1482 'ratectrl_ng_54': ratectrl_ng_54,
1483 'ratectrl_ng_cck_1': ratectrl_ng_cck_1,
1484 'ratectrl_ng_cck_2': ratectrl_ng_cck_2,
1485 'ratectrl_ng_cck_5_5': ratectrl_ng_cck_5_5,
1486 'ratectrl_ng_cck_11': ratectrl_ng_cck_11,
1487 'ratectrl_ng_mode': ratectrl_ng_mode
1488 }, {}, undefined, site);
1489};
1490
1491/**
1492 * Register to the SDN (Ubiquiti cloud)
1493 * @param {string} username Cloud username
1494 * @param {string} password Cloud password
1495 * @param {string} site Ubiquiti site to query, if different from default - optonal
1496 * @return {Promise} Promise
1497 * @example unifi.sdn_register('unifi_user', 'unifi_pass')
1498 * .then(done => console.log('Success',done))
1499 * .catch(err => console.log('Error',err))
1500 */
1501UnifiAPI.prototype.sdn_register = function(username, password, site = undefined) {
1502 return this.netsite('/cmd/sdn', {
1503 cmd: 'register',
1504 ubic_username: username,
1505 ubic_password: password
1506 }, {}, undefined, site);
1507};
1508
1509/**
1510 * Deregister of the SDN (Ubiquiti cloud)
1511 * @param {string} site Ubiquiti site to query, if different from default - optonal
1512 * @return {Promise} Promise
1513 * @example unifi.sdn_unregister()
1514 * .then(done => console.log('Success',done))
1515 * .catch(err => console.log('Error',err))
1516 */
1517UnifiAPI.prototype.sdn_unregister = function(site = undefined) {
1518 return this.netsite('/cmd/sdn', {
1519 cmd: 'unregister'
1520 }, {}, undefined, site);
1521};
1522
1523/**
1524 * Get information about the Ubiquiti cloud registration
1525 * @param {string} site Ubiquiti site to query, if different from default - optonal
1526 * @return {Promise} Promise
1527 * @example unifi.sdn_stat()
1528 * .then(done => console.log('Success',done))
1529 * .catch(err => console.log('Error',err))
1530 */
1531UnifiAPI.prototype.sdn_stat = function(site = undefined) {
1532 return this.netsite('/stat/sdn', undefined, {}, undefined, site);
1533};
1534
1535/**
1536 * SDN on, off, deregistration
1537 * @param {boolean} enabled Enable SDN or disable it. Default true
1538 * @param {string} site_id Site id
1539 * @param {string} site Ubiquiti site to query, if different from default - optonal
1540 * @return {Promise} Promise
1541 * @example unifi.sdn_onoff(true, '00010102221adffaa03')
1542 * .then(done => console.log('Success',done))
1543 * .catch(err => console.log('Error',err))
1544 */
1545UnifiAPI.prototype.sdn_onoff = function(enabled = true, site_id = '', site = undefined) {
1546 return this.netsite('/set/setting/super_sdn', {
1547 key: 'super_sdn',
1548 enabled: enabled,
1549 site_id: site_id
1550 }, {}, undefined, site);
1551};
1552
1553/**
1554 * Extend voucher
1555 * @todo Test it and verify that the REST url is correct
1556 * @param {string} voucher_id voucher id
1557 * @param {string} site Ubiquiti site to query, if different from default - optonal
1558 * @return {Promise} Promise
1559 * @example unifi.extend_voucher('00010102221adffaa03')
1560 * .then(done => console.log('Success',done))
1561 * .catch(err => console.log('Error',err))
1562 */
1563UnifiAPI.prototype.extend_voucher = function(voucher_id = '', site = undefined) {
1564 return this.netsite('/set/setting/super_sdn', {
1565 cmd: 'extend',
1566 _id: voucher_id
1567 }, {}, undefined, site);
1568};
1569
1570UnifiAPI.prototype.buildSSHSession = function(mac, uuid, ttl = '-1', stun = undefined, turn = undefined, username = undefined, password = undefined, site = undefined) {
1571 return this.netsite('/cmd/devmgr', {
1572 cmd: 'build-ssh-session',
1573 mac: mac,
1574 uuid: uuid,
1575 ttl: ttl,
1576 stun: stun,
1577 turn: turn,
1578 username: username,
1579 password: password
1580 }, {}, undefined, site);
1581};
1582
1583UnifiAPI.prototype.getSDPOffer = function(mac, uuid, site = undefined) {
1584 return new Promise((resolve, reject) => {
1585 let count = 10;
1586 let retry = () => {
1587 this.netsite('/cmd/devmgr', {
1588 cmd: 'get-sdp-offer',
1589 mac: mac,
1590 uuid: uuid
1591 }, {}, undefined, site)
1592 .then((data) => {
1593 if (data && data.data && data.data instanceof Array && data.data.length === 0) {
1594 // Empty response
1595 if (--count >= 0) {
1596 debug('Empty offer, wait and retry');
1597 return setTimeout(retry, 2000);
1598 } else reject('SDP Offer timeout');
1599 }
1600 resolve(data);
1601 })
1602 .catch(reject);
1603 };
1604 retry();
1605 });
1606};
1607
1608UnifiAPI.prototype.sshSDPAnswer = function(mac, uuid, sdpanswer, site = undefined) {
1609 return this.netsite('/cmd/devmgr', {
1610 cmd: 'ssh-sdp-answer',
1611 mac: mac,
1612 uuid: uuid,
1613 sdpanswer: sdpanswer
1614 }, {}, undefined, site);
1615};
1616
1617UnifiAPI.prototype.closeSSHSession = function(mac, uuid, site = undefined) {
1618 if (this.wrtc) this.wrtc.close();
1619 return this.netsite('/cmd/devmgr', {
1620 cmd: 'close-ssh-session',
1621 mac: mac,
1622 uuid: uuid
1623 }, {}, undefined, site);
1624};
1625
1626/**
1627 * Open SSH tunnel to a device managed by the controller (currently only Unifi AP) using WebRTC
1628 * @alias SSH
1629 * @param {string} mac The mac address of the AP
1630 * @param {string} uuid Unique UUID of the session. Optional. Auto generated if undefined
1631 * @param {string} stun Stun server url. Optional. If undefined, automatically populated
1632 * @param {string} turn Turn server url. Optional. If undefined, automatically populated
1633 * @param {string} username Turn username. Optional
1634 * @param {string} password Turn password. Optional
1635 * @param {string} site Ubiquiti site to query, if different from default - optonal
1636 * @param {number} autoclose Timeout (milisec) of inactivity before the session is automatically closed. Optional. Default 30000
1637 * @param {object} webrtc Object containing initialized WebRTC module. Optional. If not specified wrtc module is used or the one set in the UnifiAPI initialization. Tested with electron-webrtc
1638 * @param {number} waiter How many ms to wait before the next webrtc API call. Optionl. With wrtc is 100ms. However with electron-webrtc must be more than 1500 to avoid crashing on MAC and sometimes on Linux
1639 * @return {SSHSession} Return SSHSession object with connect, send, recv, expect, close methods
1640 * @example let ssh = unifi.connectSSH('00:01:02:03:04:05');
1641 * ssh.connect()
1642 * .then((data) => {
1643 * ssh.send('\nls -al\n');
1644 * return ssh.expect('#')
1645 * })
1646 * .then(data => console.log(data))
1647 * .catch(err => console.log('Error', err))
1648 */
1649UnifiAPI.prototype.connectSSH = function(mac, uuid, stun, turn, username, password, site, autoclose, webrtc, waiter) {
1650 return new SSHSession(this, mac, uuid, stun, turn, username, password, site, autoclose, webrtc || this.webrtc, waiter || this.waiter);
1651};
1652
1653UnifiAPI.prototype.getSshTurnServers = function() {
1654 return new Promise((resolve, reject) => {
1655 debug('Respond with stun/turn servers');
1656 resolve({
1657 stun: 'stun:stun.l.google.com:19302',
1658 turn: 'turn:numb.viagenie.ca',
1659 username: 'webrtc@live.com',
1660 password: 'muazkh'
1661 });
1662 });
1663};
1664
1665UnifiAPI.prototype.getTurnCredentials = function(site = undefined) {
1666 return this.netsite('/cmd/sdn', {
1667 cmd: 'get-turn-credentials'
1668 }, {}, undefined, site);
1669};
1670
1671module.exports = UnifiAPI;