node-red-contrib-gardena-smart-system
Version:
A node to connect to Gardena Smart System
212 lines (197 loc) • 8.22 kB
JavaScript
module.exports = function(RED) {
const axios = require('axios');
const deserialize = require('json-api-deserialize');
const { URLSearchParams } = require('url');
const gardena = require('./client/GardenaApiClient.js')(axios, URLSearchParams, deserialize);
function ApiCredentialsNode(n) {
RED.nodes.createNode(this, n);
}
RED.nodes.registerType('api-credentials', ApiCredentialsNode, {
credentials: {
application: { type: 'text' },
password: { type: 'password' }
}
});
function GardenaDevicesStatusNode(config) {
RED.nodes.createNode(this, config);
const node = this;
const credentials = RED.nodes.getCredentials(config.api);
setNodeStatusBasedOnGardenaApiConnection(node, credentials);
node.on('input', function(msg) {
if (!credentials) {
node.error('Credentials are not properly setup. Cannot contact Gardena Api.');
return;
}
setNodeStatusBasedOnGardenaApiConnection(node, credentials);
gardena
.getAllDevicesStatusAsync()
.then(function(response) {
msg.payload = response;
node.send(msg);
})
.catch(function(response) {
node.error(response);
});
});
}
RED.nodes.registerType("devices_status", GardenaDevicesStatusNode);
function GardenaServiceStatusNode(config) {
RED.nodes.createNode(this, config);
const node = this;
const serviceId = config.service;
const serviceType = config.servicetype;
node.on('input', function(msg) {
let serviceFound = false;
const inputData = msg.payload;
if (!Array.isArray(inputData)) {
node.warn('Obtained data seems not to be coming from the Gardena Devices Status node. Cannot find service data.');
return;
}
inputData.forEach(function(location) {
if (!location.devices || !Array.isArray(location.devices)) {
node.warn('Obtained data seems not to be coming from the Gardena Devices Status node. Cannot find service data.');
return;
}
location.devices.forEach(function(device) {
if (serviceFound || !device.services) {
return;
}
device.services.forEach(function(deviceService) {
if (deviceService.id === serviceId && deviceService.type === serviceType) {
serviceFound = true;
msg.payload = deviceService;
}
});
});
});
if (!serviceFound) {
node.error('Could not find service in node input data.');
return;
}
node.send(msg);
});
}
RED.nodes.registerType("service_status", GardenaServiceStatusNode);
function GardenaValveControlNode(config) {
RED.nodes.createNode(this, config);
const node = this;
const credentials = RED.nodes.getCredentials(config.api);
setNodeStatusBasedOnGardenaApiConnection(node, credentials);
node.on('input', function(msg) {
if (!credentials) {
node.error('Credentials are not properly setup. Cannot contact Gardena Api.');
return;
}
setNodeStatusBasedOnGardenaApiConnection(node, credentials);
const duration = config.durationtype === 'msg' ? (resolveNestedProperty(msg, config.duration) || 1) : config.duration;
gardena
.sendValveControlAsync(config.service, config.operation, duration)
.then(function(response) {
msg.payload = response;
node.send(msg);
})
.catch(function(response) {
node.error(response);
node.status({
fill: 'orange',
shape: 'ring',
text: 'Request error'
})
});
});
}
RED.nodes.registerType("valve_control", GardenaValveControlNode);
function GardenaMowerControlNode(config) {
RED.nodes.createNode(this, config);
const node = this;
const credentials = RED.nodes.getCredentials(config.api);
setNodeStatusBasedOnGardenaApiConnection(node, credentials);
node.on('input', function(msg) {
if (!credentials) {
node.error('Credentials are not properly setup. Cannot contact Gardena Api.');
return;
}
setNodeStatusBasedOnGardenaApiConnection(node, credentials);
const duration = config.durationtype === 'msg' ? (resolveNestedProperty(msg, config.duration) || 1) : config.duration;
gardena
.sendMowerControlAsync(config.service, config.operation, duration)
.then(function(response) {
msg.payload = response;
node.send(msg);
})
.catch(function(response) {
node.error(response);
node.status({
fill: 'orange',
shape: 'ring',
text: 'Request error'
})
});
});
}
RED.nodes.registerType("mower_control", GardenaMowerControlNode);
function GardenaPowerSocketControlNode(config) {
RED.nodes.createNode(this, config);
const node = this;
const credentials = RED.nodes.getCredentials(config.api);
setNodeStatusBasedOnGardenaApiConnection(node, credentials);
node.on('input', function(msg) {
if (!credentials) {
node.error('Credentials are not properly setup. Cannot contact Gardena Api.');
return;
}
setNodeStatusBasedOnGardenaApiConnection(node, credentials);
const duration = config.durationtype === 'msg' ? (resolveNestedProperty(msg, config.duration) || 1) : config.duration;
gardena
.sendPowerSocketControlAsync(config.service, config.operation, duration)
.then(function(response) {
msg.payload = response;
node.send(msg);
})
.catch(function(response) {
node.error(response);
node.status({
fill: 'orange',
shape: 'ring',
text: 'Request error'
})
});
});
}
RED.nodes.registerType("powersocket_control", GardenaPowerSocketControlNode);
function setNodeStatusBasedOnGardenaApiConnection(node, credentials) {
if (credentials) {
gardena
.setCredentials(credentials)
.setFlowContext(node.context().flow)
.getLoginStatusAsync()
.then(function(connected) {
if (connected) {
node.status({
fill: 'green',
shape: 'dot',
text: 'Connected'
})
} else {
node.status({
fill: 'red',
shape: 'ring',
text: 'Could not connect'
})
}
});
} else {
node.status({
fill: 'red',
shape: 'ring',
text: 'Credentials missing'
})
}
}
}
function resolveNestedProperty(object, path) {
const properties = Array.isArray(path) ? path : path.split('.')
return properties.reduce(function(prev, curr) {
return prev && prev[curr]
}, object);
}