myq-node
Version:
A module that lets you control your myq chamberlain garage door with node.
199 lines (187 loc) • 5.28 kB
JavaScript
const request = require('request')
const base = 'https://myqexternal.myqdevice.com/api/v4/'
let states = {
2: 'Closed',
8: 'Opening/Closing',
9: 'Open'
}
let config = new Object()
const login = function(user, password, deviceId) {
if (!user) {
throw new Error('Enter an email address')
}
if (!password) {
throw new Error('Enter a password')
}
config.user = user
config.password = password
if (deviceId) {
config.deviceId = deviceId
}
}
function headers(token) {
let base = {
Culture: 'en',
BrandId: 2,
MyQApplicationId: 'OA9I/hgmPHFp9RYKJqCKfwnhh28uqLJzZ9KOJf1DXoo8N2XAaVX6A1wcLYyWsnnv',
ApiVersion: 4.1
}
if (token) {
return Object.assign(base, token)
} else {
return base
}
}
function makeRequest(options, type, url) {
return new Promise((res, rej) => {
request[type](options, (err, req, body) => {
if (!err && req.statusCode === 200) {
res(body)
} else {
if (req.statusCode != 200) {
rej(JSON.stringify({resCode:req.statusCode, body: body}))
}
else {
rej(err)
}
}
})
})
}
function getToken() {
return new Promise((res, rej) => {
makeRequest({
url: `${base}User/Validate`,
headers: headers(),
gzip: true,
body: {
'password': config.password,
'username': config.user
},
json: true
}, 'post').then(code => {
if (code.SecurityToken === undefined) {
rej(code.ErrorMessage)
} else {
res(code.SecurityToken)
}
})
})
}
const getDevices = function() {
return new Promise((res, rej) => {
getToken().then(token => {
makeRequest({
url: `${base}UserDeviceDetails/Get?filterOn=true`,
headers: headers({
SecurityToken: token
}),
gzip: true
}, 'get').then(devices => {
try {
let parsed = JSON.parse(devices)
if (parsed.ErrorMessage) {
rej(parsed.ErrorMessage)
}
else {
res(parsed)
}
}
catch(e) {
rej(e)
}
}).catch(rej)
}).catch(rej)
})
}
const getState = function(deviceId) {
return new Promise((res, rej) => {
deviceId = deviceId || config.deviceId
getToken().then(token => {
makeRequest({
url: `${base}DeviceAttribute/GetDeviceAttribute?myQDeviceId=${deviceId}&attributeName=doorstate`,
headers: headers({
SecurityToken: token
}),
gzip: true
}, 'get').then(state => {
try {
var parsed = JSON.parse(state)
if (parsed.ErrorMessage != 0 || !parsed.ErrorMessage) {
res({code:parsed.AttributeValue, state:states[parsed.AttributeValue], UpdatedTime: parsed.UpdatedTime})
}
else {
rej(parsed.ErrorMessage)
}
}
catch(e) {
rej(e)
}
}).catch(rej)
}).catch(rej)
})
}
function stateChange(change, deviceId) {
return new Promise((res, rej) => {
let types = {
close: 0,
open: 1
}
getToken().then(token => {
makeRequest({
url: `${base}DeviceAttribute/PutDeviceAttribute`,
headers: headers({
SecurityToken: token
}),
body: {
'attributeName':'desireddoorstate',
'AttributeValue':types[change],
'myQDeviceId':deviceId
},
json: true,
gzip: true
}, 'put').then(res).catch(rej)
}).catch(rej)
})
}
const openDoor = function(deviceId) {
return new Promise((res, rej) => {
deviceId = deviceId || config.deviceId
stateChange('open', deviceId).then(state => {
try {
if (state.ErrorMessage) {
rej(state.ErrorMessage)
}
else {
res({doorOpened: true, UpdatedTime: state.UpdatedTime})
}
}
catch(e) {
rej(e)
}
}).catch(rej)
})
}
const closeDoor = function(deviceId) {
return new Promise((res, rej) => {
deviceId = deviceId || config.deviceId
stateChange('close', deviceId).then(state => {
try {
if (state.ErrorMessage) {
rej(parsed.ErrorMessage)
}
else {
res({doorClosed: true, UpdatedTime: state.UpdatedTime})
}
}
catch(e) {
rej(e)
}
}).catch(rej)
})
}
exports.login = login
exports.getDevices = getDevices
exports.getState = getState
exports.openDoor = openDoor
exports.closeDoor = closeDoor