@caitken-com/node-red-contrib-daikin-api
Version:
Daikin Control API
278 lines (225 loc) • 5.84 kB
JavaScript
const http = require('http');
/**
* @description Connects to Daikin Wifi adaptor
* @package daikin-api
* @param {Object} RED
* @author Christopher Aitken
* @version 1.0
*/
module.exports = function(RED)
{
function DaikinServerNode(config)
{
RED.nodes.createNode(this, config);
const node = this;
node.dt = Date.now();
node.ip = config.ip;
node.auto_id = config.auto_id;
node.dehumidifier_id = config.dehumidifier_id;
node.fan_id = config.fan_id;
node.heat_id = config.heat_id;
node.cool_id = config.cool_id;
node.dry_id = config.dry_id;
/**
* @description Create request options
* @memberof DaikinServerNode
* @param {string} endpoint Endpoint
* @param {Object} payload Data
* @returns {Object}
*/
node.setRequestOpts = function(endpoint, payload)
{
let opts = {};
opts.hostname = node.ip;
opts.headers = {'Host': node.ip};
switch (endpoint)
{
case 'basic_info':
opts.path = '/skyfi/common/basic_info';
opts.method = 'GET';
break;
case 'get_remote_method':
opts.path = '/skyfi/common/get_remote_method';
opts.method = 'GET';
break;
case 'set_remote_method':
opts.path = '/skyfi/common/set_remote_method';
opts.method = 'POST';
break;
case 'get_model_info':
opts.path = '/skyfi/aircon/get_model_info';
opts.method = 'GET';
break;
case 'get_timer':
opts.path = '/skyfi/aircon/get_timer';
opts.method = 'GET';
break;
case 'set_timer':
opts.path = '/skyfi/aircon/set_timer';
opts.method = 'POST';
break;
case 'get_price':
opts.path = '/skyfi/aircon/get_price';
opts.method = 'GET';
break;
case 'set_price':
opts.path = '/skyfi/aircon/set_price';
opts.method = 'POST';
break;
case 'get_notify':
opts.path = '/skyfi/common/get_notify';
opts.method = 'GET';
break;
case 'set_notify':
opts.path = '/skyfi/common/set_notify';
opts.method = 'POST';
break;
case 'set_regioncode':
opts.path = '/skyfi/common/set_regioncode';
opts.method = 'POST';
break;
case 'set_led':
opts.path = '/skyfi/common/set_led';
opts.method = 'POST';
break;
case 'reboot':
opts.path = '/skyfi/common/reboot';
opts.method = 'POST';
break;
case 'get_target':
opts.path = '/skyfi/aircon/get_target';
opts.method = 'GET';
break;
case 'set_target':
opts.path = '/skyfi/aircon/set_target';
opts.method = 'POST';
break;
case 'get_week_power':
opts.path = '/skyfi/aircon/get_week_power';
opts.method = 'GET';
break;
case 'get_year_power':
opts.path = '/skyfi/aircon/get_year_power';
opts.method = 'GET';
break;
case 'get_program':
opts.path = '/skyfi/aircon/get_program';
opts.method = 'GET';
break;
case 'set_program':
opts.path = '/skyfi/aircon/set_program';
opts.method = 'POST';
break;
case 'get_scdltimer':
opts.path = '/skyfi/aircon/get_scdltimer';
opts.method = 'GET';
break;
case 'set_scdltimer':
opts.path = '/skyfi/aircon/set_scdltimer';
opts.method = 'POST';
break;
case 'get_sensor_info':
opts.path = '/skyfi/aircon/get_sensor_info';
opts.method = 'GET';
break;
case 'get_zone_setting':
opts.path = '/skyfi/aircon/get_zone_setting';
opts.method = 'GET';
break;
case 'set_zone_setting':
opts.path = '/skyfi/aircon/set_zone_setting';
opts.method = 'GET';
break;
case 'set_control_info':
opts.path = '/skyfi/aircon/set_control_info';
opts.method = 'GET';
break;
case 'get_control_info':
default:
opts.path = '/skyfi/aircon/get_control_info';
opts.method = 'GET';
break;
}
if (opts.method == 'GET' && payload)
{
let params = new URLSearchParams(payload).toString();
opts.path += `?${params.toString()}`;
}
return opts;
}
/**
* @description Send request to wifi adaptor
* @memberof DaikinServerNode
* @param {string} endpoint Daikin API endpoint
* @param {Object} payload Data
* @returns {Promise}
*/
node.request = function(endpoint, payload)
{
return new Promise((resolve, reject) =>
{
let data = '';
let opts = node.setRequestOpts(endpoint, payload);
// Rate limit requests
let delay = new Promise(res =>
{
setTimeout(res, Date.now() - node.dt < 2000 ? 2000 : 0);
});
delay.then((payload) =>
{
node.dt = Date.now();
let request = http.request(opts, (result) =>
{
result.setEncoding('utf8');
result.on("data", (chunk) =>
{
data += chunk;
});
result.on("end", () =>
{
resolve(node.formatResponse(data));
});
});
request.on("error", (err) =>
{
reject(err);
});
if (payload && opts.method == 'POST') request.write(payload);
request.end();
})
.catch(err =>
{
reject(err);
});
});
}
/**
* @description Formats response string into json data
* @memberof DaikinServerNode
* @param {string} payload
* @returns {Object}
*/
node.formatResponse = function(payload)
{
// Results are comma separated
let data = decodeURIComponent(payload).split(',').reduce((acc, pair) =>
{
// Each result is `key=value` pair
let [key, value] = pair.split('=');
// Determine if value should be an array
let vals = value.split(';');
// Not array, return as single value
if (vals.length == 1)
{
acc[key] = vals[0];
return acc;
}
// Return value as array
acc[key] = [...vals];
return acc;
}, {});
return data;
}
}
RED.nodes.registerType('daikin-server', DaikinServerNode);
}