forked from savsw/node-ubnt-mfi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
186 lines (173 loc) · 6.42 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//Copyright 2015 Savannah Scriptworks
/*******************************************************************************
This file is part of node-ubnt-mfi.
node-ubnt-mfi is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
node-ubnt-mfi is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with node-ubnt-mfi. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
const extend = require('extend')
const request = require('request')
function mFi(args){
this._J = request.jar()
this._options = {
protocol: 'https',
port : 6443,
host : 'localhost',
username: '',
password: ''
}
if(args instanceof Object) extend(this._options, args)
}
mFi.prototype._url = function(path){
//This function takes a path and turns it into a full URL.
var url = this._options.protocol + '://' + this._options.host
var port = ':' + this._options.port
if(this._options.protocol == 'http' && this._options.port == 80 ) port = ''
if(this._options.protocol == 'https' && this._options.port == 443) port = ''
return url + port + path
}
mFi.prototype._login = function(){
var that = this
return new Promise(function(resolve, reject){
request.post({
timeout: 1500,
strictSSL: false,
url: that._url('/login'),
jar: that._J,
form: {username: that._options.username, password: that._options.password, login: 'Login'}
}, function(e,r,b){
if(e) return reject(e)
if(r.statusCode == 302 && r.headers.location == that._url('/manage')) return resolve()
reject(r.statusCode)
})
})
}
mFi.prototype._getUrl = function(url){
/**********************************************************
* This is an abstraction of a process for getting a URL asychronously. If
* the server replies `unauthorized` one attempt will be made to login
* followed by a reattempt to get the URL.
********************************/
var that = this //context shift imminent.
function getURL(){
/************************************
* This local function gets the desired URL
**************************************************/
return new Promise(function(resolve, reject){
request.get({
timeout: 1500, strictSSL: false, url: that._url(url), jar: that._J
}, function(e,r,b){
if(e) return reject(e)
if(r.statusCode == 200) return resolve(reformat(b))
reject(r.statusCode)
})
})
}
return new Promise(function(resolve, reject){
/**************************
* This promise function wraps up the local getURL function
* with one reattempt if the server replies with a 403 reject.
*************************************************************/
getURL().then(resolve, function(code){
if(code == 403){
that._login().then(function(){
getURL().then(resolve, function(){ reject('unrecoverable error') })
},function(){ reject('not authorized') })
}else reject('unrecoverable error')
})
})
}
mFi.prototype._setUrl = function(url, status){
/**********************************************************
* This is an abstraction of a process for getting a URL asychronously. If
* the server replies `unauthorized` one attempt will be made to login
* followed by a reattempt to get the URL.
********************************/
var that = this //context shift imminent.
function setURL(){
/************************************
* This local function gets the desired URL
**************************************************/
return new Promise(function(resolve, reject){
request.post({
headers: {'content-type' : 'application/x-www-form-urlencoded'},
url: that._url(url),
body: "output=".status,
jar: that._J
}, function(e,r,b){
if(e) return reject(e)
if(r.statusCode == 200) return resolve(reformat(b))
reject(r.statusCode)
})
})
}
return new Promise(function(resolve, reject){
/**************************
* This promise function wraps up the local getURL function
* with one reattempt if the server replies with a 403 reject.
*************************************************************/
setURL().then(resolve, function(code){
if(code == 403){
that._login().then(function(){
setURL().then(resolve, function(){ reject('unrecoverable error') })
},function(){ reject('not authorized') })
}else reject('unrecoverable error')
})
})
}
mFi.prototype.listAdmin = function(){
return this._getUrl('/api/v1.0/list/admin')
}
mFi.prototype.listAlarm = function(){
return this._getUrl('/api/v1.0/list/alarm')
}
mFi.prototype.listSensors = function(){
return this._getUrl('/api/v1.0/list/sensors')
}
mFi.prototype.listScript = function(){
return this._getUrl('/api/v1.0/list/script')
}
mFi.prototype.statDevice = function(){
return this._getUrl('/api/v1.0/stat/device')
}
mFi.prototype.statSysinfo = function(){
return this._getUrl('/api/v1.0/stat/sysinfo')
}
mFi.prototype.setSensor = function(id, params){
return this._setUrl('/api/v1.0/sensors/'+id, params)
}
/*
TODO: arguments
TODO: Other API calls we've seen:
/api/v1.0/list/defined_sensors
/api/v2.0/schedule
/api/v1.0/list/liveview
/api/v1.0/list/event?limit=500&purpose=recentEvent&sort=desc&startTime=-604800000
/api/v1.0/list/setting?fmt=json
/api/v2.0/conditionset
/api/v2.0/scene
/api/v1.0/list/nearest?fmt=json×=1438401600000,1441080000000&tag=energy_sum
/api/v1.0/list/rulesets?fmt=json
/api/v1.0/list/map
/api/v1.0/data/m2mgeneric_by_id?fmt=json&ids=[space (%20) delimited list of ids]&tags=temperature&indices=1,2,3,4&collection=null&func=trend&startTime=1441512000000&endTime=1441568809880
*/
module.exports = mFi
function reformat(data){
try{
data = JSON.parse(data).data
for(var i=0; i<data.length; i++){
if(data[i].val_time) data[i].val_time = new Date(data[i].val_time)
if(data[i].rpt_time) data[i].rpt_time = new Date(data[i].rpt_time)
}
return data
}catch(e){
return null
}
}