Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

node-red-contrib-deconz

Package Overview
Dependencies
Maintainers
2
Versions
146
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-red-contrib-deconz - npm Package Compare versions

Comparing version 2.0.0-rc.2 to 2.0.0-rc.3

10

deconz.js

@@ -164,5 +164,9 @@ const NODE_PATH = '/node-red-contrib-deconz/';

let server = RED.nodes.getNode(config.server);
let configMigration = new ConfigMigration(data.type, config, server);
let result = configMigration.migrate(config);
res.json(result);
if (server.state.ready === true) {
let configMigration = new ConfigMigration(data.type, config, server);
let result = configMigration.migrate(config);
res.json(result);
} else {
res.json({errors: [`The server node is not ready. Please check the server configuration.`]});
}
} catch (e) {

@@ -169,0 +173,0 @@ console.warn(e.toString());

@@ -101,4 +101,9 @@ const OutputMsgFormatter = require("../src/runtime/OutputMsgFormatter");

if (options.errorEvent === true) {
node.status(options.errorCode || "Unknown Error");
node.error(options.errorMsg || "Unknown Error");
node.status({
fill: "red",
shape: "dot",
text: options.errorCode || "Unknown Error"
});
if (options.isGlobalError === false)
node.error(options.errorMsg || "Unknown Error");
return;

@@ -156,3 +161,3 @@ }

shape: "ring",
text: "node-red-contrib-deconz/battery:status.not_reachable"
text: "node-red-contrib-deconz/battery:status.device_not_reachable"
});

@@ -163,3 +168,3 @@ } else if ("config" in device && "reachable" in device.config && device.config.reachable === false) {

shape: "ring",
text: "node-red-contrib-deconz/battery:status.not_reachable"
text: "node-red-contrib-deconz/battery:status.device_not_reachable"
});

@@ -166,0 +171,0 @@ } else {

@@ -9,3 +9,7 @@ module.exports = function (RED) {

node.status({});
node.status({
fill: "blue",
shape: "dot",
text: "node-red-contrib-deconz/server:status.starting"
});

@@ -28,4 +32,9 @@ //get server node

if (options.errorEvent === true) {
node.status(options.errorCode || "Unknown Error");
node.error(options.errorMsg || "Unknown Error");
node.status({
fill: "red",
shape: "dot",
text: options.errorCode || "Unknown Error"
});
if (options.isGlobalError === false)
node.error(options.errorMsg || "Unknown Error");
return;

@@ -32,0 +41,0 @@ }

@@ -103,4 +103,9 @@ const dotProp = require('dot-prop');

if (options.errorEvent === true) {
node.status(options.errorCode || "Unknown Error");
node.error(options.errorMsg || "Unknown Error");
node.status({
fill: "red",
shape: "dot",
text: options.errorCode || "Unknown Error"
});
if (options.isGlobalError === false)
node.error(options.errorMsg || "Unknown Error");
return;

@@ -107,0 +112,0 @@ }

@@ -28,3 +28,5 @@ {

"server_node_error": "server node error",
"not_reachable": "not reachable",
"deconz_not_reachable": "deconz not reachable",
"device_not_reachable": "device not reachable",
"invalid_api_key": "invalid api key",
"device_not_set": "device not set",

@@ -31,0 +33,0 @@ "reconnecting": "reconnecting...",

@@ -17,5 +17,22 @@ const got = require('got');

node.config = config;
node.discoverProcessRunning = false;
node.ready = false;
node.event_count = 0;
node.state = {
ready: false,
startFailed: false,
pooling: {
isValid: false,
reachable: false,
discoverProcessRunning: false,
lastPooling: undefined,
failCount: 0,
errorTriggered: false
},
websocket: {
isValid: false,
reachable: false,
lastConnected: undefined,
lastEvent: undefined,
lastDisconnected: undefined,
eventCount: 0
}
};

@@ -27,3 +44,3 @@ // Config migration

migrationResult.errors.forEach(
error => console.error(`Error with migration of node ${node.type} with id ${node.id}`, error)
error => node.error(`Error with migration of node ${node.type} with id ${node.id}`, error)
);

@@ -56,9 +73,42 @@ }

let pooling = async () => {
let result = await node.discoverDevices({
forceRefresh: true
});
// Wait for a valid device discovery before connecting to the websocket
let result = await node.discoverDevices({forceRefresh: true});
if (result === true) {
if (node.socket === undefined) this.setupDeconzSocket(node);
node.ready = true;
if (node.state.pooling.isValid === false) {
node.state.pooling.isValid = true;
node.state.ready = true;
this.setupDeconzSocket(node);
node.emit('onStart');
}
node.state.pooling.reachable = true;
node.state.pooling.lastPooling = Date.now();
node.state.pooling.failCount = 0;
if (node.state.pooling.errorTriggered === true) {
node.log(`discoverDevices: Connected to deconz API.`);
}
node.state.pooling.errorTriggered = false;
} else if (node.state.pooling.isValid === false) {
if (node.state.startFailed) return;
node.state.pooling.failCount++;
let code = RED._('node-red-contrib-deconz/server:status.deconz_not_reachable');
let reason = "discoverDevices: Can't connect to deconz API since starting. " +
"Please check server configuration.";
if (node.state.pooling.errorTriggered === false) {
node.state.pooling.errorTriggered = true;
node.propagateErrorNews(code, reason, true);
}
if (node.state.pooling.failCount % 4 === 2) {
node.error(reason);
}
} else {
node.state.pooling.failCount++;
let code = RED._('node-red-contrib-deconz/server:status.deconz_not_reachable');
let reason = "discoverDevices: Can't connect to deconz API.";
if (node.state.pooling.errorTriggered === false) {
node.state.pooling.errorTriggered = true;
node.propagateErrorNews(code, reason, true);
}
if (node.state.pooling.failCount % 4 === 2) {
node.error(reason);
}
}

@@ -68,9 +118,9 @@ };

await pooling();
this.refreshDiscoverTimer = setInterval(pooling, node.refreshDiscoverInterval);
if (node.state.startFailed !== true)
this.refreshDiscoverTimer = setInterval(pooling, node.refreshDiscoverInterval);
} catch (e) {
node.ready = false;
node.state.ready = false;
node.error("Deconz Server node error " + e.toString());
}
node.emit('onStart');
})();

@@ -97,18 +147,37 @@ }

});
node.socket.on('open', () => {
node.log(`WebSocket opened`);
node.state.websocket.isValid = true;
node.state.websocket.reachable = true;
node.state.websocket.lastConnected = Date.now();
// This is used only on websocket reconnect, not the initial connection.
if (node.state.ready) node.propagateStartNews();
});
node.socket.on('message', (payload) => this.onSocketMessage(payload));
node.socket.on('error', (err) => {
let node = this;
node.state.websocket.reachable = false;
node.state.websocket.lastDisconnected = Date.now();
node.error(`WebSocket error: ${err}`);
});
node.socket.on('close', (code, reason) => {
node.state.websocket.reachable = false;
node.state.websocket.lastDisconnected = Date.now();
if (reason) { // don't bother the user unless there's a reason
node.warn(`WebSocket disconnected: ${code} - ${reason}`);
}
if (node.ready) node.propagateErrorNews(code, reason);
if (node.state.ready) node.propagateErrorNews(code, reason);
});
node.socket.on('unauthorized', () => this.onSocketUnauthorized());
node.socket.on('open', () => {
node.log(`WebSocket opened`);
// This is used only on websocket reconnect, not the initial connection.
if (node.ready) node.propagateStartNews();
node.socket.on('pong-timeout', () => {
let node = this;
node.state.websocket.reachable = false;
node.state.websocket.lastDisconnected = Date.now();
node.warn('WebSocket connection timeout, reconnecting');
});
node.socket.on('message', (payload) => this.onSocketMessage(payload));
node.socket.on('error', (err) => this.onSocketError(err));
node.socket.on('pong-timeout', () => this.onSocketPongTimeout());
node.socket.on('unauthorized', () => () => {
let node = this;
node.state.websocket.isValid = false;
node.state.websocket.lastDisconnected = Date.now();
node.warn('WebSocket authentication failed');
});
}

@@ -124,17 +193,27 @@

if (node.ready && (options.forceRefresh === false || node.discoverProcessRunning === true)) {
node.log('discoverDevices: Using cached devices');
if (options.forceRefresh === false || node.state.pooling.discoverProcessRunning === true) {
//node.log('discoverDevices: Using cached devices');
return;
}
node.discoverProcessRunning = true;
node.state.pooling.discoverProcessRunning = true;
try {
const response = await got(node.api.url.main()).json();
const response = await got(node.api.url.main(), {retry: 1, timeout: 2000}).json();
node.device_list.parse(response);
node.log(`discoverDevices: Updated ${node.device_list.count}`);
node.discoverProcessRunning = false;
//node.log(`discoverDevices: Updated ${node.device_list.count}`);
node.state.pooling.discoverProcessRunning = false;
return true;
} catch (e) {
node.error(`discoverDevices: Can't connect to deconz API.`);
node.discoverProcessRunning = false;
if (e.response !== undefined && e.response.statusCode === 403) {
node.state.startFailed = true;
console.log("invalid_api_key");
let code = RED._('node-red-contrib-deconz/server:status.invalid_api_key');
let reason = "discoverDevices: Can't use to deconz API, invalid api key. " +
"Please check server configuration.";
node.error(reason);
node.propagateErrorNews(code, reason, true);
node.onClose();
}
//node.error(`discoverDevices: Can't connect to deconz API.`);
node.state.pooling.discoverProcessRunning = false;
return false;

@@ -192,6 +271,20 @@ }

propagateErrorNews(code, reason) {
propagateErrorNews(code, reason, isGlobalError = false) {
let node = this;
if (!reason) return;
if (node.state.ready === false) {
RED.nodes.eachNode((target) => {
if (['deconz-input', 'deconz-battery', 'deconz-get', 'deconz-out', 'deconz-event'].includes(target.type)) {
let targetNode = RED.nodes.getNode(target.id);
if (targetNode) targetNode.status({
fill: "red",
shape: "dot",
text: code
});
}
});
return;
}
// Node with device selected

@@ -204,3 +297,4 @@ for (let [device_path, nodeIDs] of Object.entries(node.nodesByDevicePath)) {

errorCode: code,
errorMsg: `WebSocket disconnected: ${reason || 'no reason provided'}`
errorMsg: reason || "Unknown error",
isGlobalError
});

@@ -234,3 +328,4 @@ }

errorCode: code,
errorMsg: `WebSocket disconnected: ${reason || 'no reason provided'}`
errorMsg: reason || "Unknown error",
isGlobalError
});

@@ -329,3 +424,3 @@ }

text: RED._('node-red-contrib-deconz/server:status.event_count')
.replace('{{event_count}}', node.event_count)
.replace('{{event_count}}', node.state.websocket.eventCount)
});

@@ -434,28 +529,12 @@ } else {

let node = this;
node.log('Shutting down deconz server node.');
clearInterval(node.refreshDiscoverTimer);
node.ready = false;
node.log('WebSocket connection closed');
node.state.ready = false;
if (node.socket !== undefined) {
node.socket.close();
node.socket = undefined;
}
node.emit('onClose');
node.socket.close();
node.socket = undefined;
}
onSocketPongTimeout() {
let node = this;
node.warn('WebSocket connection timeout, reconnecting');
node.emit('onSocketPongTimeout');
}
onSocketUnauthorized() {
let node = this;
node.warn('WebSocket authentication failed');
node.emit('onSocketUnauthorized');
}
onSocketError(err) {
let node = this;
node.error(`WebSocket error: ${err}`);
node.emit('onSocketError');
}
updateDevice(device, dataParsed) {

@@ -488,4 +567,11 @@ let node = this;

let node = this;
if (node.event_count >= Number.MAX_SAFE_INTEGER) node.event_count = 0;
node.event_count++;
node.state.websocket.lastEvent = Date.now();
node.state.websocket.isValid = true;
node.state.websocket.reachable = true;
if (node.state.websocket.eventCount >= Number.MAX_SAFE_INTEGER) node.state.websocket.eventCount = 0;
node.state.websocket.eventCount++;
// Drop websocket msgs if the pooling don't work
if (node.state.pooling.isValid === false) return console.error('Got websocket msg but the pooling is invalid. This should not happen.');
node.emit('onSocketMessage', dataParsed); //Used by event node, TODO Really used ?

@@ -501,3 +587,3 @@

// TODO handle case if device is not found
if (device === undefined) return;
if (device === undefined) return console.error('Got websocket msg but the device does not exist. ' + JSON.stringify(dataParsed));
let changed = node.updateDevice(device, dataParsed);

@@ -613,3 +699,3 @@

shape: "ring",
text: "node-red-contrib-deconz/server:status.not_reachable"
text: "node-red-contrib-deconz/server:status.device_not_reachable"
});

@@ -616,0 +702,0 @@ return;

@@ -51,3 +51,3 @@ {

},
"version": "2.0.0-rc.2",
"version": "2.0.0-rc.3",
"devDependencies": {

@@ -54,0 +54,0 @@ "grunt": "^1.3.0",

@@ -178,4 +178,5 @@ const Utils = require("./Utils");

}
if (HK.TargetHorizontalTiltAngle !== undefined) {
this.result.state.tilt = Utils.convertRange(HK.TargetHorizontalTiltAngle, [-90, 90], [0, 100]);
for (const side of ['Horizontal', 'Vertical']) {
if (HK[`Target${side}TiltAngle`] !== undefined)
this.result.state.tilt = Utils.convertRange(HK[`Target${side}TiltAngle`], [-90, 90], [0, 100]);
}

@@ -182,0 +183,0 @@ this.result.state.transitiontime = this.getNodeProperty(this.arg.transitiontime);

@@ -45,2 +45,3 @@ const Query = require('./Query');

let domain = parts.shift();
if (resourceName === 'uniqueid') return this.getDeviceByUniqueID(domain);
let sub_path = parts.join("/");

@@ -47,0 +48,0 @@ switch (domain) {

@@ -248,5 +248,8 @@ const dotProp = require('dot-prop');

case 'onchange':
let payloadPath = payloadFormat;
if (this.rule.type === 'state' || this.rule.type === 'config')
payloadPath = `${this.rule.type}.${payloadPath}`;
return device && Array.isArray(device.changed) && (
(payloadFormat === '__complete__' && device.changed.length > 0) ||
(payloadFormat !== '__complete__' && device.changed.includes(payloadFormat))
(payloadFormat !== '__complete__' && device.changed.includes(payloadPath))
);

@@ -253,0 +256,0 @@ case 'onupdate':

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc