New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

node-red-contrib-denon

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

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

Comparing version 0.1.2 to 0.1.3

example.png

475

denon.js

@@ -5,278 +5,261 @@ /**

var util = require('util');
var DEBUG = false;
var connectionFSM = require('./lib/connectionFSM.js');
const util = require('util'),
debug = require('debug')('node-red-contrib-denon'),
connectionFSM = require('./lib/connectionFSM.js');
module.exports = function(RED) {
module.exports = function (RED) {
/**
* ====== Denon-controller ================
* Holds configuration for denonjs host+port,
* initializes new denonjs connections
* =======================================
*/
function DenonControllerNode(config) {
RED.nodes.createNode(this, config);
this.name = config.name;
this.host = config.host;
this.port = config.port;
this.denon = null;
var node = this;
/**
* ====== Denon-controller ================
* Holds configuration for denonjs host+port,
* initializes new denonjs connections
* =======================================
*/
function DenonControllerNode(config) {
RED.nodes.createNode(this, config);
this.name = config.name;
this.host = config.host;
this.port = config.port;
this.denon = null;
var node = this;
/**
* Initialize an denon_telnet socket, calling the handler function
* when successfully connected, passing it the denon_telnet connection
*/
this.initializeDenonConnection = function (handler) {
if (node.denon) {
debug(`${node.name}: already configured connection to Denon[${config.host}:${config.port}`);
if (handler && (typeof handler === 'function')) {
if (node.denon.connection && node.denon.connected)
handler(node.denon);
else {
if (node.denon.connection && !node.denon.connected)
node.denon.connect();
node.denon.on('connected', function () {
handler(node.denon);
});
}
}
return node.denon;
}
debug(`${node.name}: initializing connection to Denon[${config.host}:${config.port}`);
node.denon = new connectionFSM({
host: config.host,
port: config.port,
debug: false
});
node.denon.connect();
if (handler && (typeof handler === 'function')) {
node.denon.on('connected', function () {
handler(node.denon);
});
}
debug(`${node.name}: successfully connected to to Denon[${config.host}:${config.port}`);
return node.denon;
};
this.on("close", function () {
debug(`${node.name}: disconnecting Denon[${config.host}:${config.port}`);
node.denon && node.denon.disconnect && node.denon.disconnect();
node.denon = null;
});
}
RED.nodes.registerType("denon-controller", DenonControllerNode);
/**
* Initialize an denon_telnet socket, calling the handler function
* when successfully connected, passing it the denon_telnet connection
* ====== Denon-out =======================
* Sends outgoing Denon player from
* messages received via node-red flows
* =======================================
*/
this.initializeDenonConnection = function(handler) {
if (node.denon) {
DEBUG && RED.comms.publish("debug", {
name: node.name,
msg: 'already configured connection to Denon player at ' + config.host + ':' + config.port
});
if (handler && (typeof handler === 'function')) {
if (node.denon.connection && node.denon.connected)
handler(node.denon);
else {
if (node.denon.connection && !node.denon.connected)
node.denon.connect();
node.denon.on('connected', function() {
handler(node.denon);
function DenonOut(config) {
RED.nodes.createNode(this, config);
this.name = config.name;
var controllerNode = RED.nodes.getNode(config.controller);
this.unit_number = config.unit_number;
this.denoncommand = config.denoncommand;
var node = this;
this.on("input", function (msg) {
debug(node.name, `denonout.onInput msg[${util.inspect(msg)}]`);
if (!(msg && msg.hasOwnProperty('payload'))) return;
var payload = msg.payload;
if (typeof(msg.payload) === "object") {
payload = msg.payload;
} else if (typeof(msg.payload) === "string") {
try {
payload = JSON.parse(msg.payload);
if (typeof (payload) === 'number')
payload = {cmd: msg.payload.toString()};
} catch (e) {
payload = {cmd: msg.payload.toString()};
}
}
else
payload = {cmd: msg.payload.toString()};
if (payload == null) {
node.log('denonout.onInput: illegal msg.payload!');
return;
}
//If msg.topic is filled, than set it as cmd
if (msg.topic) {
if (payload.value === null || payload.value === undefined)
payload.value = payload.cmd;
payload = {cmd: msg.topic.toString(), value: payload.value};
}
if (node.denoncommand && node.denoncommand !== 'empty') {
try {
payload = JSON.parse(node.denoncommand);
if (typeof (payload) === 'number')
payload.cmd = node.denoncommand.toString();
} catch (e) {
payload.cmd = node.denoncommand.toString();
}
}
node.send(payload, function (err) {
if (err) {
node.error('send error: ' + err);
}
if (typeof(msg.cb) === 'function')
msg.cb(err);
});
}
}
return node.denon;
}
node.log('configuring connection to Denon player at ' + config.host + ':' + config.port);
node.denon = new connectionFSM({
host: config.host,
port: config.port,
debug: DEBUG
});
node.denon.connect();
if (handler && (typeof handler === 'function')) {
node.denon.on('connected', function() {
handler(node.denon);
});
}
DEBUG && RED.comms.publish("debug", {
name: node.name,
msg: 'Denon: successfully connected to ' + config.host + ':' + config.port
});
this.on("close", function () {
node.log('denonOut.close');
});
return node.denon;
};
this.on("close", function() {
node.log('disconnecting from denon device at ' + config.host + ':' + config.port);
node.denon && node.denon.disconnect && node.denon.disconnect();
node.denon = null;
});
}
node.status({fill: "yellow", shape: "dot", text: "inactive"});
RED.nodes.registerType("denon-controller", DenonControllerNode);
function nodeStatusConnected() {
node.status({fill: "green", shape: "dot", text: "connected"});
}
/**
* ====== Denon-out =======================
* Sends outgoing Denon player from
* messages received via node-red flows
* =======================================
*/
function DenonOut(config) {
RED.nodes.createNode(this, config);
this.name = config.name;
var controllerNode = RED.nodes.getNode(config.controller);
this.unit_number = config.unit_number;
this.denoncommand = config.denoncommand;
var node = this;
this.on("input", function(msg) {
DEBUG && RED.comms.publish("debug", {
name: node.name,
msg: 'denonout.onInput msg[' + util.inspect(msg) + ']'
});
//node.log('denonout.onInput msg[' + util.inspect(msg) + ']');
if (!(msg && msg.hasOwnProperty('payload'))) return;
var payload = msg.payload;
if (typeof(msg.payload) === "object") {
payload = msg.payload;
} else if (typeof(msg.payload) === "string") {
try {
payload = JSON.parse(msg.payload);
if (typeof (payload) === 'number')
payload = {cmd: msg.payload.toString()};
} catch (e) {
payload = {cmd: msg.payload.toString()};
function nodeStatusDisconnected() {
node.status({fill: "red", shape: "dot", text: "disconnected"});
}
}
else
payload = {cmd: msg.payload.toString()};
if (payload == null) {
node.log('denonout.onInput: illegal msg.payload!');
return;
}
//If msg.topic is filled, than set it as cmd
if (msg.topic) {
if (payload.value === null || payload.value === undefined)
payload.value = payload.cmd;
payload = {cmd: msg.topic.toString(), value: payload.value};
}
if (node.denoncommand && node.denoncommand !== 'empty') {
try {
payload = JSON.parse(node.denoncommand);
if (typeof (payload) === 'number')
payload.cmd = node.denoncommand.toString();
} catch (e) {
payload.cmd = node.denoncommand.toString();
function nodeStatusReconnect() {
node.status({fill: "yellow", shape: "ring", text: "reconnecting"});
}
}
node.send(payload, function(err) {
if (err) {
node.error('send error: ' + err);
function nodeStatusConnecting() {
node.status({fill: "green", shape: "ring", text: "connecting"});
}
if (typeof(msg.cb) === 'function')
msg.cb(err);
});
});
this.on("close", function() {
node.log('denonOut.close');
});
controllerNode.initializeDenonConnection(function (fsm) {
if (fsm.connected)
nodeStatusConnected();
else
nodeStatusDisconnected();
fsm.off('connecting', nodeStatusConnecting);
fsm.on('connecting', nodeStatusConnecting);
fsm.off('connected', nodeStatusConnected);
fsm.on('connected', nodeStatusConnected);
fsm.off('disconnected', nodeStatusDisconnected);
fsm.on('disconnected', nodeStatusDisconnected);
fsm.off('reconnect', nodeStatusReconnect);
fsm.on('reconnect', nodeStatusReconnect);
});
node.status({fill: "yellow", shape: "dot", text: "inactive"});
function nodeStatusConnected() {
node.status({fill: "green", shape: "dot", text: "connected"});
this.send = function (data, callback) {
debug(`${node.name}: send data[${JSON.stringify(data)}`);
controllerNode.initializeDenonConnection(function (fsm) {
try {
data.cmd = data.cmd || data.method;
data.value = data.value || data.params;
switch (data.cmd.toLowerCase()) {
case 'setvolumedb':
fsm.connection.setVolumeDb(parseFloat(data.value), function (error, response) {
if (!callback)
return;
if (error)
callback && callback(error, response);
else
callback(response);
});
break;
default:
fsm.connection.send(data.cmd, (data.cmd.substring(0, 2) || 'UNKWN' /*UNKWN means unknown*/), function (error, response) {
if (!callback)
return;
if (error)
callback && callback(error, response);
else
callback(response);
});
}
}
catch (err) {
node.error('error calling send: ' + err);
callback(err);
}
});
}
}
function nodeStatusDisconnected() {
node.status({fill: "red", shape: "dot", text: "disconnected"});
}
//
RED.nodes.registerType("denon-out", DenonOut);
function nodeStatusReconnect() {
node.status({fill: "yellow", shape: "ring", text: "reconnecting"});
}
/**
* ====== Denon-IN ========================
* Handles incoming Global Cache, injecting
* json into node-red flows
* =======================================
*/
function DenonIn(config) {
RED.nodes.createNode(this, config);
this.name = config.name;
this.connection = null;
var node = this;
var controllerNode = RED.nodes.getNode(config.controller);
function nodeStatusConnecting() {
node.status({fill: "green", shape: "ring", text: "connecting"});
}
/* ===== Node-Red events ===== */
function nodeStatusConnecting() {
node.status({fill: "green", shape: "ring", text: "connecting"});
}
controllerNode.initializeDenonConnection(function(fsm) {
if (fsm.connected)
nodeStatusConnected();
else
nodeStatusDisconnected();
fsm.off('connecting', nodeStatusConnecting);
fsm.on('connecting', nodeStatusConnecting);
fsm.off('connected', nodeStatusConnected);
fsm.on('connected', nodeStatusConnected);
fsm.off('disconnected', nodeStatusDisconnected);
fsm.on('disconnected', nodeStatusDisconnected);
fsm.off('reconnect', nodeStatusReconnect);
fsm.on('reconnect', nodeStatusReconnect);
});
function nodeStatusConnected() {
node.status({fill: "green", shape: "dot", text: "connected"});
}
this.send = function(data, callback) {
DEBUG && RED.comms.publish("debug", {name: node.name, msg: 'send data[' + JSON.stringify(data) + ']'});
controllerNode.initializeDenonConnection(function(fsm) {
try {
DEBUG && RED.comms.publish("debug", {name: node.name, msg: "send: " + JSON.stringify(data)});
data.cmd = data.cmd || data.method;
data.value = data.value || data.params;
switch (data.cmd.toLowerCase()) {
case 'setvolumedb':
fsm.connection.setVolumeDb(parseFloat(data.value), function(error, response) {
if (!callback)
return;
if (error)
callback && callback(error, response);
else
callback(response);
});
break;
default:
fsm.connection.send(data.cmd, function(error, response) {
if (!callback)
return;
if (error)
callback && callback(error, response);
else
callback(response);
});
}
function nodeStatusDisconnected() {
node.status({fill: "red", shape: "dot", text: "disconnected"});
}
catch (err) {
node.error('error calling send: ' + err);
callback(err);
function nodeStatusReconnect() {
node.status({fill: "yellow", shape: "ring", text: "reconnecting"});
}
});
}
}
//
RED.nodes.registerType("denon-out", DenonOut);
function receiveNotification(data) {
debug(`${node.name}: receiveNotification data[${JSON.stringify(data)}`);
node.send({
topic: 'denon',
payload: data
});
};
/**
* ====== Denon-IN ========================
* Handles incoming Global Cache, injecting
* json into node-red flows
* =======================================
*/
function DenonIn(config) {
RED.nodes.createNode(this, config);
this.name = config.name;
this.connection = null;
var node = this;
//node.log('new DenonIn, config: %j', config);
var controllerNode = RED.nodes.getNode(config.controller);
/* ===== Node-Red events ===== */
function nodeStatusConnecting() {
node.status({fill: "green", shape: "ring", text: "connecting"});
controllerNode.initializeDenonConnection(function (fsm) {
if (fsm.connected)
nodeStatusConnected();
else
nodeStatusDisconnected();
fsm.off('connecting', nodeStatusConnecting);
fsm.on('connecting', nodeStatusConnecting);
fsm.off('connected', nodeStatusConnected);
fsm.on('connected', nodeStatusConnected);
fsm.off('disconnected', nodeStatusDisconnected);
fsm.on('disconnected', nodeStatusDisconnected);
fsm.off('reconnect', nodeStatusReconnect);
fsm.on('reconnect', nodeStatusReconnect);
fsm.off('data', receiveNotification);
fsm.on('data', receiveNotification);
});
}
function nodeStatusConnected() {
node.status({fill: "green", shape: "dot", text: "connected"});
}
function nodeStatusDisconnected() {
node.status({fill: "red", shape: "dot", text: "disconnected"});
}
function nodeStatusReconnect() {
node.status({fill: "yellow", shape: "ring", text: "reconnecting"});
}
node.receiveNotification = function(notification, data) {
DEBUG && RED.comms.publish("debug", {
name: node.name,
msg: 'denon event data[' + JSON.stringify(data) + ']'
});
node.send({
topic: 'denon',
payload: {
'notification': notification,
'data': data
}
});
};
controllerNode.initializeDenonConnection(function(fsm) {
if (fsm.connected)
nodeStatusConnected();
else
nodeStatusDisconnected();
fsm.off('connecting', nodeStatusConnecting);
fsm.on('connecting', nodeStatusConnecting);
fsm.off('connected', nodeStatusConnected);
fsm.on('connected', nodeStatusConnected);
fsm.off('disconnected', nodeStatusDisconnected);
fsm.on('disconnected', nodeStatusDisconnected);
fsm.off('reconnect', nodeStatusReconnect);
fsm.on('reconnect', nodeStatusReconnect);
});
}
RED.nodes.registerType("denon-in", DenonIn);
RED.nodes.registerType("denon-in", DenonIn);
}

@@ -5,2 +5,7 @@ ~function (undefined) {

var machina = require('machina');
function receiveData(data) {
connectionFSM && connectionFSM.emit('data', data);
}
var connectionFSM = new machina.Fsm({

@@ -112,5 +117,7 @@ debug: options.debug ? true : false,

}.bind(this), this.PING_INTERVAL);
this.connection.getConnection().on('data', receiveData);
},
_onExit: function () {
clearTimeout(this.pingTimer);
this.connection.getConnection().off('data', receiveData);
}

@@ -117,0 +124,0 @@ },

{
"name": "node-red-contrib-denon",
"version": "0.1.2",
"version": "0.1.3",
"description": "Node-RED nodes for communicating with a Denon AVR.",

@@ -35,2 +35,3 @@ "repository": {

"dependencies": {
"debug": "^3.1.0",
"denon-avr": "git+https://github.com/estbeetoo/denon-avr.git",

@@ -37,0 +38,0 @@ "machina": "^1.1.2"

node-red-contrib-denon
========================
A <a href="http://nodered.org" target="_new">Node-RED</a> node to communicate [Denon AVR receivers](http://www.denon.com).
A <a href="http://nodered.org" target="_new">Node-RED</a> node to communicate [Denon AVR receivers](http://www.denon.com) over telnet (port 23) TCP/IP connection.

@@ -13,7 +13,2 @@ # Install

# Pre-reqs
--------
TODO: fill it
# Usage

@@ -24,4 +19,66 @@ -----

If you want to use this node simply inject message's payload as string:
## `Denon-Out` node sends commands to Denon devices
### Commands with no arguments
#### Master Volume
`MV20`
Master Volume set to 20 - command from Denon AVR protocol: [DENON_PROTOCOL_V7.6.0.pdf](doc/AVR3312CI_AVR3312_PROTOCOL_V7.6.0.pdf)
#### Master Volume Up
`MVUP`
Master Volume UP by 0.5 - command from Denon AVR protocol: [DENON_PROTOCOL_V7.6.0.pdf](doc/AVR3312CI_AVR3312_PROTOCOL_V7.6.0.pdf)
#### Master Volume Down
`MVDOWN`
Master Volume DOWN by 0.5 - command from Denon AVR protocol: [DENON_PROTOCOL_V7.6.0.pdf](doc/AVR3312CI_AVR3312_PROTOCOL_V7.6.0.pdf)
### Commands with arguments
Currently, there is only one such command implemented: `SetVolumeDB`.
One may use `setvolumedb` too, cause it's case insensitive.
So, `msg` object shoud looks like:
```javascript
{
topic; "setvolumedb",
payload: -65.5
}
```
It will set the master volume to -65.5dB.
## `Denon-In`
Node sends to single output messages from Denon quipment with structure:
```javascript
{
topic: 'denon',
payload: 'PWON'
}
```
where `notification` could be `PWON` and `data` contain additional info, arguments for current notification.
# Collect debug log for issues
Current package use debug package: https://www.npmjs.com/package/debug.
Run you `node-red` with command to enable debug output:
`set DEBUG=node-red-contrib-denon node-red`
for globally installed Node-RED, or
`set DEBUG=node-red-contrib-denon node node-red/red.js`
for local Node-RED.
# Additinal documentation
Take a look at Denon AVR protocol: [DENON_PROTOCOL_V7.6.0.pdf](doc/AVR3312CI_AVR3312_PROTOCOL_V7.6.0.pdf)

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