UNPKG

node-red-contrib-domotz

Version:

A collection of Node-Red nodes to access the Domotz public API

199 lines (174 loc) 7.47 kB
/** This file is part of node-red-domotz-contrib. * Copyright (C) 2018 Domotz Ltd * * node-red-domotz-contrib is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * node-red-domotz-contrib 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with node-red-domotz-contrib. If not, see <http://www.gnu.org/licenses/>. * * Created by Andrea Azzara <a.azzara@domotz.com> on 01/11/2018. */ const rq = require('request'); const url = require('url'); const querystring = require('querystring'); module.exports = function (RED) { function DomotzApi (config) { RED.nodes.createNode(this, config); let node = this; let setStatusDisconnected = function () { node.status({fill: 'red', shape: 'ring', text: 'disconnected'}); }; let setStatusConnected = function () { node.status({fill: 'green', shape: 'dot', text: 'connected'}); }; node.api = RED.nodes.getNode(config.api); if (!node.api) { setStatusDisconnected(); return; } let apiKey = node.api.credentials.key; let getRequestOptions = function (uri, apiKey, method, body) { let options = { headers: { 'X-API-KEY': apiKey, }, uri: uri, encoding: null, }; if (method) { options.method = method; } if (body) { options.body = body; options.json = true; } return options; }; let isQueryParam = function (paramName, operationDetails) { for (let i = 0; i < operationDetails.parameters.length; i++) { if (operationDetails.parameters[i].name === paramName) { return (operationDetails.parameters[i].in === 'query'); } } }; node.on('input', function (msg) { let operationDetails = config.endpointsMap[config.operation]; if (!node.api || !apiKey || !node.api.endpoint || !config.operation || !operationDetails) { setStatusDisconnected(); return; } let method = operationDetails['method']; let hasBody = operationDetails['requestBody']; let publicApiEndpoint = url.resolve(node.api.endpoint, '/public-api/v1'); let domotzUrl = publicApiEndpoint + operationDetails['path']; let queryParams = {}; let inputBody = null; let addParameters = function (name, value) { if (isQueryParam(name, operationDetails) && value) { queryParams[name] = value; } else { domotzUrl = domotzUrl.replace('{' + name + '}', value); } }; if (operationDetails.hasParams) { if ((config.useinputparams || config.parameterOptions === 'INPUT_PARAMS')) { if (msg.payload.params) { for (let param in msg.payload.params) { if (msg.payload.params.hasOwnProperty(param)) { addParameters(param, msg.payload.params[param]); } } } if (hasBody && msg.payload.body) { inputBody = msg.payload.body; } } else { for (let param in config.parameters) { if (config.parameters.hasOwnProperty(param)) { addParameters(param, config.parameters[param]); } } inputBody = hasBody && config.body ? JSON.parse(config.body) : null; } } if (Object.keys(queryParams).length > 0) { let queryString = querystring.stringify(queryParams); domotzUrl = domotzUrl + '?' + queryString; } if (domotzUrl.indexOf('{') !== -1) { node.send([ null, { payload: 'Not all URL params converted: ' + domotzUrl, }, ]); return; } let options = getRequestOptions(domotzUrl, apiKey, method, inputBody); node.debug('performing request to ' + domotzUrl); rq(options, (error, response, result) => { if (error) { node.debug('Unable to get resource: ' + JSON.stringify(error)); node.send([ null, { payload: { code: error.response.statusCode, message: error.error, }, }, ]); return; } try { result = JSON.parse(result); } catch (e) { node.log('result is not JSON'); } let output = { payload: { message: result, code: response.statusCode, headers: response.headers, configParams: config.parameters, inputParams: msg.payload && msg.payload.params, }, }; if (method.toLowerCase() === 'head') { output.payload.headers = {}; let expectedResponseHeaders = operationDetails['responses'][response.statusCode.toString()]['headers']; for (let h in expectedResponseHeaders) { let responseHeaders = response['headers']; for (let actualHeader in responseHeaders) { if (responseHeaders.hasOwnProperty(actualHeader) && actualHeader.toLowerCase() === h.toLowerCase()) { output.payload.headers[h] = responseHeaders[actualHeader]; } } } } node.send([output, null]); node.status({fill: 'green', shape: 'dot', text: 'connected'}); }); }); if (!node.api || !apiKey || !node.api.endpoint) { setStatusDisconnected(); } else { let options = getRequestOptions(url.resolve(node.api.endpoint, 'public-api/v1/user'), apiKey); rq(options, (error) => { if (error) { node.warn('Unable to authenticate'); setStatusDisconnected(); return; } setStatusConnected(); }); } } RED.nodes.registerType('domotz-api', DomotzApi); };