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

node-comfoairq

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-comfoairq - npm Package Compare versions

Comparing version 0.5.4 to 0.5.5

.vscode/settings.json

36

.eslintrc.json
{
"env": {
"browser": true,
"commonjs": true,
"es6": true
"es6": true,
"node": true,
"mocha": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
"rules": {
"indent": [
"error",
2,
{
"SwitchCase": 1
}
],
"no-console": "off",
"no-var": "error",
"prefer-const": "error",
"quotes": [
"error",
"single",
{
"avoidEscape": true,
"allowTemplateLiterals": true
}
],
"semi": [
"error",
"always"
]
},
"parserOptions": {
"ecmaVersion": 11
},
"rules": {
"ecmaVersion": 2018
}
}

@@ -1,4 +0,4 @@

'use strict'
'use strict';
const debug = require('debug')('node-zehnder')
//const debug = require('debug')('node-zehnder');
const Buffer = require('safe-buffer').Buffer;

@@ -8,12 +8,12 @@

const messages = protoBuf.loadSync(__dirname + '/protocol/zehnder.proto');
const statics = require('./const');
const config = require('./const');
function cmd_GatewayOperation(data) {
let message = {}
const message = {};
try {
let cmd_len = data.readInt16BE(36);
const cmd_len = data.readInt16BE(36);
message.operation = data.slice(38, 38 + cmd_len);
message.command = data.slice(38 + cmd_len);
let operation = messages.lookupType('GatewayOperation').decode(message.operation);
const operation = messages.lookupType('GatewayOperation').decode(message.operation);
message.reference = operation.reference;

@@ -24,3 +24,3 @@ message.type = operation.type;

case messages.GatewayOperation.GatewayResult.OK:
message.result = 'OK'
message.result = 'OK';
break;

@@ -65,3 +65,3 @@

} catch (error) {
console.log(error + ' --> data = ' + data.toString("hex"));
//
}

@@ -73,3 +73,3 @@

function cmd_DecodeMessage(message) {
let result = {
const result = {
error: '',

@@ -82,6 +82,6 @@ kind: '',

let msgType = statics.msgCodes.find( ({ code }) => code === message.type);
const msgType = config.msgCodes.find( ({ code }) => code === message.type);
if (message.result == 'OK') {
let command = messages.lookupType(msgType.name);
const command = messages.lookupType(msgType.name);
result.kind = msgType.name;

@@ -100,3 +100,2 @@ result.data = command.decode(message.command);

} catch (error) {
console.log(error + " - " + JSON.stringify(message));
result.error = error;

@@ -108,5 +107,21 @@ }

function analyze_ListRegisteredApps(data) {
let result = [];
for (let idx = 0; idx < data.apps.length; idx++) {
const uuid = Buffer.from(data.apps[idx].uuid, 'base64');
result += JSON.stringify({
'uuid' : uuid.toString('hex'),
'uuid64' : uuid.toString('base64'),
'devicename' : data.apps[idx].devicename
});
}
return result;
}
function analyze_CnRpdoNotification(data) {
let sensorData = statics.sensorCodes.find( ({ code }) => code === data.pdid);
let binVal = Buffer.from(data.data, 'base64');
const sensorData = config.sensorCodes.find( ({ code }) => code === data.pdid);
const binVal = Buffer.from(data.data, 'base64');
let value = null;

@@ -129,3 +144,2 @@

return {

@@ -135,9 +149,21 @@ 'pdid': data.pdid,

'data': value
}
};
}
function analyze_CnTimeConfirm(data) {
const baseTime = new Date(2000,1,1,0,0,0);
const result = new Date(baseTime.setSeconds(baseTime.getSeconds() + data.currentTime));
return {
'CnTimeRequest': data.currentTime,
'timestamp': result
};
}
module.exports = {
cmd_GatewayOperation,
cmd_DecodeMessage,
analyze_CnRpdoNotification
}
analyze_ListRegisteredApps,
analyze_CnRpdoNotification,
analyze_CnTimeConfirm
};

@@ -1,43 +0,41 @@

'use strict'
'use strict';
const debug = require('debug')('node-zehnder')
const debug = require('debug');
const Buffer = require('safe-buffer').Buffer;
const udp = require('dgram');
var tcp = require('net');
const tcp = require('net');
const events = require('events');
//const emitter = new events.EventEmitter;
const protoBuf = require('protobufjs');
const messages = protoBuf.loadSync(__dirname + '/protocol/zehnder.proto');
//const after = require('./analysis')
const config = require('./const');
/*
const bridgeStatus = {
NOT_CONFIGURED = 0,
DISCOVERED = 1,
NOT_CONNECTED = 2,
CONNECTED = 3,
OTHER_SESSION = 4
}
*/
class ComfoAirQBridge extends events {
constructor (options) {
constructor(options) {
super();
this._settings = {};
if (typeof options.port === 'undefined') {
options.port = 56747;
}
//this._settings = {};
//if (typeof options.port === 'undefined') {
// options.port = 56747;
//}
this._settings = options;
this.txheader = Buffer.alloc(38).fill(0);
this.isdiscovered = false;
this.isconnected = false;
this.wasconnected = false;
this.iswriting = false;
this.isreading = false;
this.txheader = Buffer.alloc(38).fill(0);
// if comfouuid is already known, the TX header can be prepared
if (this._settings.comfouuid) {
if (this._settings.debug) {
debug('bridge constructor: comfouuid already known');
}
this._settings.uuid.copy(this.txheader, 4);
this._settings.comfouuid.copy(this.txheader, 20);
this.isdiscovered = true;
} else if (this._settings.debug) {
debug('bridge constructor: comfouuid not known -> discovery needed');
}
this.initSocket();

@@ -55,12 +53,12 @@

this.sock.on('connect', () => {
console.log('bridge : connected to comfoAir unit -> ' + (new Date(Date.now())).toLocaleString());
debug('bridge : connected to comfoAir unit -> ' + config.getTimestamp());
this.isconnected = true;
})
});
this.sock.on('timeout', () => {
console.log('bridge : TCP socket timeout -> ' + (new Date(Date.now())).toLocaleString());
let reason = {
console.log('bridge : TCP socket timeout -> ' + config.getTimestamp());
const reason = {
error: 'timeout'
}
};
if (this.isconnected) {

@@ -72,3 +70,3 @@ this.emit('error', reason);

this.isconnected = false;
})
});

@@ -78,3 +76,3 @@ this.sock.on('data', (data) => {

let offset = 0;
let datalen = data.length;
const datalen = data.length;

@@ -84,4 +82,4 @@ // search the receive buffer for multiple messages received at the same time

msglen = data.readInt32BE(offset);
let buffer = data.slice(offset, offset + msglen + 4)
let rxdata = {
const buffer = data.slice(offset, offset + msglen + 4);
const rxdata = {
'time': new Date(),

@@ -91,28 +89,29 @@ 'data': buffer,

'msg': null
}
};
if (this._settings.debug) {
console.log(" <- RX : " + buffer.toString("hex"));
debug(' <- RX : ' + buffer.toString('hex'));
}
this.emit('received', rxdata);
offset += msglen + 4
offset += msglen + 4;
}
})
});
this.sock.on('error', (err) => {
console.error('bridge : sock error: ' + err + ' -> ' + (new Date(Date.now())).toLocaleString());
let reason = {
console.error('bridge : sock error: ' + err + ' -> ' + config.getTimestamp());
const reason = {
error: err
}
};
this.sock.end('socket error');
this.emit('error', reason);
})
});
this.sock.on('close', (had_error) => {
if (had_error) {
console.log("bridge : TCP socket closed with error -> " + (new Date(Date.now())).toLocaleString());
debug('bridge : TCP socket closed with error -> ' + config.getTimestamp());
} else {
console.log("bridge : TCP socket closed -> " + (new Date(Date.now())).toLocaleString());
debug('bridge : TCP socket closed -> ' + config.getTimestamp());
}

@@ -125,10 +124,10 @@

})
});
this.sock.on('end', () => {
console.log("bridge : TCP socket ended -> " + (new Date(Date.now())).toLocaleString());
debug('bridge : TCP socket ended -> ' + config.getTimestamp());
// the socket will close
//this.isconnected = false;
})
});

@@ -139,16 +138,15 @@ }

async discovery() {
let listener = udp.createSocket('udp4');
const listener = udp.createSocket('udp4');
return new Promise((resolve, reject) => {
listener.bind(this._settings.port, () => {
let txdata = Buffer.from('0a00', 'hex');
const txdata = Buffer.from('0a00', 'hex');
if (typeof this.settings.port === 'undefined') {
this.settings.port = 56747;
}
if (this.settings.port == 0) {
this.settings.port = 56747;
}
//if ((typeof this.settings.port === 'undefined') ||
// (this.settings.port == 0)) {
// this.settings.port = 56747;
//}
if (this._settings.debug) {
console.log(" -> TX (UDP) : " + txdata.toString("hex"));
console.log(' -> TX (UDP) : ' + txdata.toString('hex'));
}

@@ -173,21 +171,27 @@

this._settings.uuid.copy(this.txheader, 4);
this._settings.comfoUuid.copy(this.txheader, 20);
this._settings.comfouuid.copy(this.txheader, 20);
resolve(this._settings);
})
const result = {
'localuuid' : this._settings.uuid,
'comfouuid' : this._settings.comfouuid,
'device' : this._settings.comfoair,
'port' : this._settings.port
};
resolve(result);
});
listener.on('message', (message, remote) => {
if (this._settings.debug) {
console.log(" <- RX (UDP) : " + message.toString("hex"));
console.log(" (" + remote.address + ':' + remote.port + ")")
console.log(' <- RX (UDP) : ' + message.toString('hex'));
console.log(' (' + remote.address + ':' + remote.port + ')');
}
let protoData = messages.DiscoveryOperation.decode(message);
const protoData = messages.DiscoveryOperation.decode(message);
this._settings.comfoair = protoData.searchGatewayResponse.ipaddress;
this._settings.comfoUuid = protoData.searchGatewayResponse.uuid;
this._settings.comfouuid = protoData.searchGatewayResponse.uuid;
listener.close();
})
});
})
});
}

@@ -203,11 +207,4 @@

const sleep = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds));
}
ComfoAirQBridge.prototype.discover = async function () {
ComfoAirQBridge.prototype.discover = async function (options) {
this._settings.multicast = options.multicast;
this._settings.comfoair = options.comfoair;
return new Promise((resolve,reject) => {

@@ -219,4 +216,4 @@ //let result = null;

.then((result) => {
if (this.debug) {
console.log(' discovery complete -> ' + (new Date(Date.now())).toLocaleString())
if (this._settings.debug) {
console.log(' discovery complete -> ' + config.getTimestamp());
}

@@ -227,8 +224,9 @@ this.isdiscovered = true;

} catch (exc) {
}
catch (exc) {
reject(exc);
}
})
});
}
};

@@ -239,3 +237,3 @@ ComfoAirQBridge.prototype.transmit = async function (data) {

while (!this.isdiscovered) {
await sleep(25);
await config.sleep(25);
}

@@ -250,3 +248,3 @@

while (!this.isconnected) {
await sleep(25);
await config.sleep(25);
}

@@ -256,5 +254,5 @@ }

return new Promise((resolve, reject) => {
let op_len = data.operation.length;
let msg_len = 16 + 16 + 2 + data.command.length + data.operation.length;
let txdata = Buffer.concat([this.txheader, data.operation, data.command]);
const op_len = data.operation.length;
const msg_len = 16 + 16 + 2 + data.command.length + data.operation.length;
const txdata = Buffer.concat([this.txheader, data.operation, data.command]);

@@ -265,3 +263,3 @@ txdata.writeInt16BE(op_len, 36);

if (this._settings.debug) {
console.log(" -> TX : " + txdata.toString("hex"));
console.log(' -> TX : ' + txdata.toString('hex'));
}

@@ -271,3 +269,3 @@

if (err) {
console.log("bridge : error sending data -> " + err + " -> " + (new Date(Date.now())).toLocaleString());
console.log('bridge : error sending data -> ' + err + ' -> ' + config.getTimestamp());
reject(err);

@@ -279,5 +277,4 @@ }

});
}
};
module.exports = ComfoAirQBridge;

@@ -1,2 +0,2 @@

'use strict'
'use strict';

@@ -6,27 +6,22 @@ const debug = require('debug')('comfoconnect');

const events = require('events');
//const emitter = new events.EventEmitter;
var comfoIP = '10.0.0.14'
var comfoPin = 4321
var localUUID = Buffer.from('20200428000000000000000009080407', 'hex')
var comfoDevice = 'node-comfoairq'
const comfoBridge = require('./bridge');
const before = require('./preparation')
const after = require('./analysis')
const before = require('./preparation');
const after = require('./analysis');
const config = require('./const');
class ComfoAirQ extends events {
constructor () {
constructor(options) {
super();
this._settings = {
'pin' : comfoPin,
'uuid' : localUUID,
'device' : comfoDevice,
'multicast': '10.0.0.255',
'pin' : options.pin,
'uuid' : Buffer.from(options.uuid, 'hex'),
'device' : options.device,
'comfoair' : options.comfoair,
'multicast': options.multicast,
'port' : 56747,
'comfoair' : comfoIP,
'debug' : false,
'verbose' : false,
'debug' : options.debug,
'verbose' : options.verbose,
'keepalive': 15000

@@ -37,13 +32,10 @@ };

'reconnect' : false,
'resume' : false //,
// 'emitevents': false
}
'resume' : false
};
this._exec = {
'keepalive': null,
'reconnect': null
}
};
this.rxlist = []; // array of messages to receive
//this.rxdata = []; // array of received messages for 'manual' receive operations
//this.txdata = []; // array of messages to transmit

@@ -57,3 +49,3 @@ this.nodes = [];

data.msg = after.cmd_GatewayOperation(data.data);
data.result = after.cmd_DecodeMessage(data.msg)
data.result = after.cmd_DecodeMessage(data.msg);
data.error = data.msg.result;

@@ -63,5 +55,5 @@ data.kind = data.msg.type;

if (this.rxlist.length > 0) {
let idx = this.rxlist.findIndex( ({ kind }) => kind === data.kind);
const idx = this.rxlist.findIndex( ({ kind }) => kind === data.kind);
if (idx >= 0) {
this.rxlist.splice(idx)
this.rxlist.splice(idx);
}

@@ -83,3 +75,3 @@ }

if (data.result.data.resumed){
console.log(" StartSessionConfirm --> OK - resuming session")
debug(' StartSessionConfirm --> OK - resuming session');
this._status.resume = true;

@@ -90,17 +82,26 @@ } else {

} else {
console.log(" StartSessionConfirm --> " + data.error);
debug(' StartSessionConfirm --> ' + data.error);
this._status.connected = false;
}
this._status.reconnect = true;
} else if (data.kind == 32) { // CnNodeNotification
} else if (data.kind == 31) { // CnTimeConfirmType
debug(' CnTimeConfirm --> ' + data.error);
data.result.data = after.analyze_CnTimeConfirm(data.result.data);
} else if (data.kind == 32) { // CnNodeNotificationType
// TODO
debug(' CnNodeNotification --> ' + data.error);
} else if (data.kind == 52) { // RegisterAppConfirmType
debug(' RegisterAppConfirm --> ' + data.error);
} else if (data.kind == 55) { // ListRegisteredAppsConfirmType
debug(' ListAppConfirm --> ' + data.error);
data.result.data = after.analyze_ListRegisteredApps(data.result.data);
} else if (data.kind == 4) { // CloseSessionRequest
let reason = {
const reason = {
state: 'OTHER_SESSION'
}
};
this.emit('disconnect', reason);
} else if (data.kind == 52) {
console.log(" RegisterAppConfirm --> " + data.error)
}
}
// push the received data to the calling program
this.emit('receive', data);

@@ -115,4 +116,3 @@

catch (exc) {
console.log('comfo: ' + JSON.stringify(reason));
console.log(' **: ' + exc);
console.log('comfo: ' + JSON.stringify(reason) + ' - ' + exc);
}

@@ -122,14 +122,11 @@

this._bridge.on('disconnect', () => {
let reason = {
const reason = {
state: 'DISC'
}
};
console.log('comfo: DISCONNECTED -> ' + (new Date(Date.now())).toLocaleString());
debug('comfo: DISCONNECTED -> ' + config.getTimestamp());
this._status.connected = false;
//if (this._exec.reconnect == null) {
// this._exec.reconnect = setTimeout(this._reconnect.bind(this), this._settings.keepalive)
//}
this.emit('disconnect', reason);
})
});

@@ -149,3 +146,3 @@ }

// copy some values through to the bridge settings
let settings = this._bridge.settings;
const settings = this._bridge.settings;
settings.debug = value.debug;

@@ -165,6 +162,2 @@ this._bridge.settings = settings;

const sleep = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds));
}
ComfoAirQ.prototype._keepalive = async function () {

@@ -174,3 +167,3 @@

if ((this._status.reconnect) && (this._exec.reconnect == null)) {
this._exec.reconnect = setTimeout(this._reconnect.bind(this), this._settings.keepalive)
this._exec.reconnect = setTimeout(this._reconnect.bind(this), this._settings.keepalive);
}

@@ -183,7 +176,7 @@ this._exec.keepalive = null;

this.rxlist.forEach((element) => {
let diff = Date.now() - element.timestamp;
const diff = Date.now() - element.timestamp;
if (diff.valueOf() > this._settings.keepalive) {
console.log('timout receiving: ' + JSON.stringify(element) + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('timout receiving: ' + JSON.stringify(element) + ' -> ' + config.getTimestamp());
}
})
});
}

@@ -201,6 +194,6 @@

console.log('error sending KeepAlive: ' + reason + ' -> ' + (new Date(Date.now())).toLocaleString());
})
console.log('error sending KeepAlive: ' + reason + ' -> ' + config.getTimestamp());
});
}
};

@@ -210,18 +203,17 @@ ComfoAirQ.prototype._reconnect = function () {

if (this._status.connected) {
return
return;
}
console.log("** starting reconnection -> " + (new Date(Date.now())).toLocaleString())
console.log('** starting reconnection -> ' + config.getTimestamp()());
this.StartSession(false)
.then(() => {
//if (!this._status.resume) {
// re-register to all previously registered sensors
this.sensors.forEach(async sensor => {
// re-register to all previously registered sensors
this.sensors.forEach(async sensor => {
let result = await this.RegisterSensor(sensor);
if (this._settings.verbose) {
console.log("SENSID: " + sensor.toString() + " - " +JSON.stringify(result));
}
await sleep(100);
});
//}
const result = await this.RegisterSensor(sensor);
if (this._settings.verbose) {
console.log('SENSID: ' + sensor.toString() + ' - ' + JSON.stringify(result));
}
await config.sleep(100);
});

@@ -244,22 +236,36 @@ if (this._status.connected) {

this._exec.reconnect = setTimeout(this._reconnect.bind(this), this._settings.keepalive);
})
});
}
};
// run a specific discovery of the comfoair device
ComfoAirQ.prototype.discover = function () {
ComfoAirQ.prototype.discover = async function () {
return new Promise((resolve, reject) => {
try {
this._bridge.discover(this._settings, (options) => {
console.log('comfoIP : ' + options.comfoair + ':' + options.port);
console.log('comfoUUID : ' + options.comfoUuid.toString('hex'));
console.log('localUUID : ' + options.uuid.toString('hex'));
this._bridge.discover(this._settings)
.then(async (options) => {
console.log('comfoIP : ' + options.device + ':' + options.port);
console.log('comfoUUID : ' + options.comfouuid.toString('hex'));
console.log('localUUID : ' + options.localuuid.toString('hex'));
// copy back in case of a broadcast
this._settings.comfoair = options.device;
this._settings.comfouuid = options.comfouuid;
resolve(this._settings);
});
/*
await this._bridge.discover(this._settings, (options) => {
console.log('comfoIP : ' + options.device + ':' + options.port);
console.log('comfoUUID : ' + options.comfouuid.toString('hex'));
console.log('localUUID : ' + options.localuuid.toString('hex'));
// copy back in case of a broadcast
this._settings.comfoair = options.comfoair;
this._settings.comfoUuid = options.comfoUuid;
this._settings.comfoair = options.device;
this._settings.comfouuid = options.comfouuid;
resolve(this._settings);
});
*/
}

@@ -270,3 +276,3 @@ catch (exc) {

});
}
};

@@ -278,7 +284,7 @@ ComfoAirQ.prototype.StartSession = function (force) {

try {
let txData = before.cmd_StartSession(force);
let rxkind = {
"timestamp" : new Date(),
"kind" : 53
}
const txData = before.cmd_StartSession(force);
const rxkind = {
'timestamp' : new Date(),
'kind' : 53
};
this.rxlist.push(rxkind);

@@ -290,7 +296,7 @@

while (!this._bridge.isconnected) {
await sleep(100);
await config.sleep(100);
}
while ((cnt-- > 0) && (!this._status.connected)) {
await sleep(100);
await config.sleep(100);
}

@@ -304,3 +310,3 @@

reject('timeout connecting (1)')
reject('timeout connecting (1)');
}

@@ -319,13 +325,13 @@

}
reject('timeout connecting (2)')
reject('timeout connecting (2)');
}
},(reason) => {
console.log('comfo : TX reject -> ' + reason + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX reject -> ' + reason + ' -> ' + config.getTimestamp());
reject(reason);
})
});
}
catch (exc) {
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + config.getTimestamp());
this.opensession = false;

@@ -336,3 +342,3 @@ reject(exc);

});
}
};

@@ -344,3 +350,3 @@ ComfoAirQ.prototype.KeepAlive = function () {

try {
let txData = before.cmd_KeepAlive();
const txData = before.cmd_KeepAlive();

@@ -351,9 +357,9 @@ this._bridge.transmit(txData)

},(reason) => {
console.log('comfo : TX reject -> ' + reason + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX reject -> ' + reason + ' -> ' + config.getTimestamp());
reject(reason);
})
});
}
catch (exc) {
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + config.getTimestamp());
reject(exc);

@@ -363,3 +369,3 @@ }

}
};

@@ -375,3 +381,3 @@ ComfoAirQ.prototype.CloseSession = function () {

try {
let txData = before.cmd_CloseSession();
const txData = before.cmd_CloseSession();

@@ -386,15 +392,15 @@ this._bridge.transmit(txData)

this.sensors = [];
console.log('comfo : session closed -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : session closed -> ' + config.getTimestamp());
resolve({});
},(reason) => {
console.log('comfo : TX reject -> ' + reason + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX reject -> ' + reason + ' -> ' + config.getTimestamp());
reject(reason);
})
});
}
catch (exc) {
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + config.getTimestamp());
reject(exc);
}
});
}
};

@@ -406,7 +412,7 @@ ComfoAirQ.prototype.ListRegisteredApps = function() {

try {
let txData = before.cmd_ListRegisteredApps();
let rxkind = {
"timestamp" : new Date(),
"kind" : 55
}
const txData = before.cmd_ListRegisteredApps();
const rxkind = {
'timestamp' : new Date(),
'kind' : 55
};
this.rxlist.push(rxkind);

@@ -419,9 +425,9 @@

},(reason) => {
console.log('comfo : TX reject -> ' + reason + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX reject -> ' + reason + ' -> ' + config.getTimestamp());
reject(reason);
})
});
}
catch (exc) {
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + config.getTimestamp());
reject(exc);

@@ -432,3 +438,3 @@

}
};

@@ -440,7 +446,7 @@ ComfoAirQ.prototype.RegisterApp = function () {

try {
let txData = before.cmd_RegisterApp(this._settings, true);
let rxkind = {
"timestamp" : new Date(),
"kind" : 52
}
const txData = before.cmd_RegisterApp(this._settings, true);
const rxkind = {
'timestamp' : new Date(),
'kind' : 52
};
this.rxlist.push(rxkind);

@@ -453,9 +459,9 @@

},(reason) => {
console.log('comfo : TX reject -> ' + reason + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX reject -> ' + reason + ' -> ' + config.getTimestamp());
reject(reason);
})
});
}
catch (exc) {
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + config.getTimestamp());
reject(exc);

@@ -466,3 +472,3 @@

}
};

@@ -474,7 +480,7 @@ ComfoAirQ.prototype.DeRegisterApp = function (uuid) {

try {
let txData = before.cmd_DeRegisterApp(uuid);
let rxkind = {
"timestamp" : new Date(),
"kind" : 56
}
const txData = before.cmd_DeRegisterApp(uuid);
const rxkind = {
'timestamp' : new Date(),
'kind' : 56
};
this.rxlist.push(rxkind);

@@ -487,9 +493,9 @@

},(reason) => {
console.log('comfo : TX reject -> ' + reason + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX reject -> ' + reason + ' -> ' + config.getTimestamp());
reject(reason);
})
});
}
catch (exc) {
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + config.getTimestamp());
reject(exc);

@@ -499,3 +505,3 @@

});
}
};

@@ -506,3 +512,3 @@ ComfoAirQ.prototype.RegisterSensor = function (sensor) {

// this will automate things in case of reconnection
let idx = this.sensors.indexOf(sensor);
const idx = this.sensors.indexOf(sensor);
if (idx == -1) {

@@ -515,7 +521,7 @@ this.sensors.push(sensor);

try {
let txData = before.cmd_RegisterSensor(sensor);
let rxkind = {
"timestamp" : new Date(),
"kind" : 39
}
const txData = before.cmd_RegisterSensor(sensor);
const rxkind = {
'timestamp' : new Date(),
'kind' : 39
};
this.rxlist.push(rxkind);

@@ -528,9 +534,9 @@

},(reason) => {
console.log('comfo : TX reject -> ' + reason + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX reject -> ' + reason + ' -> ' + config.getTimestamp());
reject(reason);
})
});
}
catch (exc) {
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + config.getTimestamp());
reject(exc);

@@ -541,3 +547,3 @@

}
};

@@ -549,7 +555,7 @@ ComfoAirQ.prototype.SendCommand = function (node, message) {

try {
let txData = before.cmd_SendCommand(node, message);
let rxkind = {
"timestamp" : new Date(),
"kind" : 34
}
const txData = before.cmd_SendCommand(node, message);
const rxkind = {
'timestamp': new Date(),
'kind' : 34
};
this.rxlist.push(rxkind);

@@ -562,9 +568,9 @@

},(reason) => {
console.log('comfo : TX reject -> ' + reason + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX reject -> ' + reason + ' -> ' + config.config.getTimestamp());
reject(reason);
})
});
}
catch (exc) {
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + config.getTimestamp());
reject(exc);

@@ -574,3 +580,3 @@

});
}
};

@@ -582,7 +588,7 @@ ComfoAirQ.prototype.VersionRequest = async function () {

try {
let txData = before.cmd_VersionRequest();
let rxkind = {
"timestamp" : new Date(),
"kind" : 68
}
const txData = before.cmd_VersionRequest();
const rxkind = {
'timestamp' : new Date(),
'kind' : 68
};
this.rxlist.push(rxkind);

@@ -595,9 +601,9 @@

},(reason) => {
console.log('comfo : TX reject -> ' + reason + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX reject -> ' + reason + ' -> ' + config.getTimestamp());
reject(reason);
})
});
}
catch (exc) {
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + (new Date(Date.now())).toLocaleString());
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + config.getTimestamp());
reject(exc);

@@ -608,5 +614,31 @@

}
};
ComfoAirQ.prototype.TimeRequest = function() {
return new Promise((resolve, reject) => {
try {
const txData = before.cmd_TimeRequest(this._settings);
const rxkind = {
'timestamp': new Date(),
'kind': 31 // TimeConfirmType
};
this.rxlist.push(rxkind);
this._bridge.transmit(txData)
.then(async () => {
resolve({});
}, (reason) => {
console.log('comfo : TX reject -> ' + reason + ' -> ' + config.getTimestamp());
reject(reason);
});
} catch (exc) {
console.log('comfo : TX error -> ' + JSON.stringify(exc) + ' -> ' + config.getTimestamp());
reject(exc);
}
});
};
module.exports = ComfoAirQ;

@@ -1,2 +0,2 @@

'use strict'
'use strict';

@@ -22,3 +22,3 @@ const msgCodes = [

{code: 100, name: 'GatewayNotification'}
]
];

@@ -30,12 +30,22 @@ const comfoCommands = [

{name: 'FAN_MODE_HIGH', code: '84150101000000000100000003'},
{name: 'FAN_BOOST_10M', code: '84150106000000005802000003'},
{name: 'FAN_BOOST_20M', code: '8415010600000000B004000003'},
{name: 'FAN_BOOST_30M', code: '84150106000000000807000003'},
{name: 'FAN_BOOST_END', code: '85150106'},
{name: 'MODE_AUTO', code: '85150801'},
{name: 'MODE_MANUAL', code: '84150801000000000100000001'},
{name: 'VENTMODE_SUPPLY', code: '8415060100000000100e000001'},
{name: 'VENTMODE_BALANCE', code: '85150601'},
{name: 'TEMPPROF_NORMAL', code: '8415030100000000ffffffff00'},
{name: 'TEMPPROF_COOL', code: '8415030100000000ffffffff01'},
{name: 'TEMPPROF_WARM', code: '8415030100000000ffffffff02'},
{name: 'BYPASS_ON', code: '8415020100000000100e000001'},
{name: 'BYPASS_OFF', code: '8415020100000000100e000002'},
{name: 'BYPASS_AUTO', code: '85150201'},
{name: 'SENSOR_TEMP_OFF', code: '031d010400'},

@@ -50,17 +60,24 @@ {name: 'SENSOR_TEMP_AUTO', code: '031d010401'},

{name: 'SENSOR_HUMP_ON', code: '031d010702'}
]
];
// sensorcode.kind:
// * 0 : unknown
// * 1 : 8-bit integer value
// * 2 : 16-bit integer value
// * 3 : 32-bit integer value
// * 6 : 16-bit decimal value
const sensorCodes = [
{code: 16, kind: 1, name: ''},
{code: 16, kind: 1, name: 'SENSOR_AWAY_INDICATOR'}, // (0x01 = low, medium, high fan speed, 07 = away)
{code: 33, kind: 1, name: ''},
{code: 37, kind: 1, name: ''},
{code: 49, kind: 1, name: 'SENSOR_OPERATING_MODE_BIS'},
{code: 49, kind: 1, name: 'SENSOR_OPERATING_MODE_BIS'}, // (0x01 = limited manual, 0x05 = unlimited manual, 0xff = auto)
{code: 53, kind: 1, name: ''},
{code: 56, kind: 1, name: 'SENSOR_OPERATING_MODE'},
{code: 65, kind: 1, name: 'SENSOR_FAN_SPEED_MODE'},
{code: 66, kind: 1, name: ''},
{code: 67, kind: 1, name: ''},
{code: 56, kind: 1, name: 'SENSOR_OPERATING_MODE'}, // (0x01 = unlimited manual, 0xff = auto)
{code: 65, kind: 1, name: 'SENSOR_FAN_SPEED_MODE'}, // (0x00 (away), 0x01 (low), 0x02 (medium) or 0x03 (high))
{code: 66, kind: 1, name: 'SENSOR_BYPASS_ACTIVATION_MODE'}, // (0x00 = auto, 0x01 = activated, 0x02 = deactivated)
{code: 67, kind: 1, name: 'SENSOR_TEMPERATURE_PROFILE'}, // (0x00 = normal, 0x01 = cold, 0x02 = warm)
{code: 70, kind: 1, name: ''},
{code: 71, kind: 1, name: ''},
{code: 81, kind: 3, name: 'SENSOR_FAN_NEXT_CHANGE'},
{code: 81, kind: 3, name: 'SENSOR_FAN_NEXT_CHANGE'}, // (0x52020000 = 0x00000252 -> 594 seconds)
{code: 82, kind: 3, name: ''},

@@ -70,27 +87,27 @@ {code: 85, kind: 3, name: ''},

{code: 87, kind: 3, name: ''},
{code: 117, kind: 1, name: 'SENSOR_FAN_EXHAUST_DUTY'},
{code: 118, kind: 1, name: 'SENSOR_FAN_SUPPLY_DUTY'},
{code: 119, kind: 2, name: 'SENSOR_FAN_EXHAUST_FLOW'},
{code: 120, kind: 2, name: 'SENSOR_FAN_SUPPLY_FLOW'},
{code: 121, kind: 2, name: 'SENSOR_FAN_EXHAUST_SPEED'},
{code: 122, kind: 2, name: 'SENSOR_FAN_SUPPLY_SPEED'},
{code: 128, kind: 2, name: 'SENSOR_POWER_CURRENT'},
{code: 129, kind: 2, name: 'SENSOR_POWER_TOTAL_YEAR'},
{code: 130, kind: 2, name: 'SENSOR_POWER_TOTAL'},
{code: 144, kind: 2, name: 'SENSOR_PREHEATER_POWER_TOTAL_YEAR'},
{code: 145, kind: 2, name: 'SENSOR_PREHEATER_POWER_TOTAL'},
{code: 146, kind: 2, name: 'SENSOR_PREHEATER_POWER_CURRENT'},
{code: 117, kind: 1, name: 'SENSOR_FAN_EXHAUST_DUTY'}, // (0x1c = 28%)
{code: 118, kind: 1, name: 'SENSOR_FAN_SUPPLY_DUTY'}, // (0x1d = 29%)
{code: 119, kind: 2, name: 'SENSOR_FAN_EXHAUST_FLOW'}, // (0x6e00 = 110 m³/h)
{code: 120, kind: 2, name: 'SENSOR_FAN_SUPPLY_FLOW'}, // (0x6900 = 105 m³/h)
{code: 121, kind: 2, name: 'SENSOR_FAN_EXHAUST_SPEED'}, // (0x2d04 = 1069 rpm)
{code: 122, kind: 2, name: 'SENSOR_FAN_SUPPLY_SPEED'}, // (0x5904 = 1113 rpm)
{code: 128, kind: 2, name: 'SENSOR_POWER_CURRENT'}, // (0x0f00 = 15 W)
{code: 129, kind: 2, name: 'SENSOR_POWER_TOTAL_YEAR'}, // (0x1700 = 23 kWh)
{code: 130, kind: 2, name: 'SENSOR_POWER_TOTAL'}, // (0x1700 = 23 kWh)
{code: 144, kind: 2, name: 'SENSOR_PREHEATER_POWER_TOTAL_YEAR'}, // (0x1700 = 23 kWh)
{code: 145, kind: 2, name: 'SENSOR_PREHEATER_POWER_TOTAL'}, // (0x1700 = 23 kWh)
{code: 146, kind: 2, name: 'SENSOR_PREHEATER_POWER_CURRENT'}, // (0x0f00 = 15 W)
{code: 176, kind: 1, name: ''},
{code: 192, kind: 2, name: 'SENSOR_DAYS_TO_REPLACE_FILTER'},
{code: 192, kind: 2, name: 'SENSOR_DAYS_TO_REPLACE_FILTER'}, // (0x8200 = 130 days)
{code: 208, kind: 1, name: ''},
{code: 209, kind: 6, name: 'SENSOR_CURRENT_RMOT'},
{code: 209, kind: 6, name: 'SENSOR_CURRENT_RMOT'}, // (0x7500 = 117 -> 11.7 °C)
{code: 210, kind: 0, name: ''},
{code: 211, kind: 0, name: ''},
{code: 212, kind: 6, name: ''},
{code: 213, kind: 2, name: 'SENSOR_AVOIDED_HEATING_CURRENT'},
{code: 214, kind: 2, name: 'SENSOR_AVOIDED_HEATING_TOTAL_YEAR'},
{code: 215, kind: 2, name: 'SENSOR_AVOIDED_HEATING_TOTAL'},
{code: 216, kind: 2, name: ''},
{code: 217, kind: 2, name: ''},
{code: 218, kind: 2, name: ''},
{code: 213, kind: 2, name: 'SENSOR_AVOIDED_HEATING_CURRENT'}, // (0xb901 = 441 -> 4.41 W)
{code: 214, kind: 2, name: 'SENSOR_AVOIDED_HEATING_TOTAL_YEAR'}, // (0xdd01 = 477 kWh)
{code: 215, kind: 2, name: 'SENSOR_AVOIDED_HEATING_TOTAL'}, // (0xdd01 = 477 kWh)
{code: 216, kind: 2, name: 'SENSOR_AVOIDED_COOLING_CURRENT'}, // (0xb901 = 441 -> 4.41 W)
{code: 217, kind: 2, name: 'SENSOR_AVOIDED_COOLING_TOTAL_YEAR'}, // (0xdd01 = 477 kWh)
{code: 218, kind: 2, name: 'SENSOR_AVOIDED_COOLING_TOTAL'}, // (0xdd01 = 477 kWh)
{code: 219, kind: 2, name: ''},

@@ -101,11 +118,11 @@ {code: 221, kind: 6, name: 'SENSOR_TEMPERATURE_SUPPLY'},

{code: 226, kind: 2, name: ''},
{code: 227, kind: 1, name: 'SENSOR_BYPASS_STATE'},
{code: 228, kind: 1, name: ''},
{code: 274, kind: 6, name: 'SENSOR_TEMPERATURE_EXTRACT'},
{code: 275, kind: 6, name: 'SENSOR_TEMPERATURE_EXHAUST'},
{code: 276, kind: 6, name: 'SENSOR_TEMPERATURE_OUTDOOR'},
{code: 290, kind: 1, name: 'SENSOR_HUMIDITY_EXTRACT'},
{code: 291, kind: 1, name: 'SENSOR_HUMIDITY_EXHAUST'},
{code: 292, kind: 1, name: 'SENSOR_HUMIDITY_OUTDOOR'},
{code: 294, kind: 1, name: 'SENSOR_HUMIDITY_SUPPLY'},
{code: 227, kind: 1, name: 'SENSOR_BYPASS_STATE'}, // (0x64 = 100%)
{code: 228, kind: 1, name: ''},
{code: 274, kind: 6, name: 'SENSOR_TEMPERATURE_EXTRACT'}, // (0xab00 = 171 -> 17.1 °C)
{code: 275, kind: 6, name: 'SENSOR_TEMPERATURE_EXHAUST'}, // (0x5600 = 86 -> 8.6 °C)
{code: 276, kind: 6, name: 'SENSOR_TEMPERATURE_OUTDOOR'}, // (0x3c00 = 60 -> 6.0 °C)
{code: 290, kind: 1, name: 'SENSOR_HUMIDITY_EXTRACT'}, // (0x31 = 49%)
{code: 291, kind: 1, name: 'SENSOR_HUMIDITY_EXHAUST'}, // (0x57 = 87%)
{code: 292, kind: 1, name: 'SENSOR_HUMIDITY_OUTDOOR'}, // (0x43 = 67%)
{code: 294, kind: 1, name: 'SENSOR_HUMIDITY_SUPPLY'}, // (0x23 = 35%)
{code: 321, kind: 2, name: ''},

@@ -129,8 +146,29 @@ {code: 325, kind: 2, name: ''},

{code: 419, kind: 0, name: ''},
]
];
/*
* create timestamp for logging on screen
*/
const getTimestamp = () => {
const current_datetime = new Date();
return current_datetime.getFullYear() + '-'
+ (current_datetime.getMonth() + 1).toString().padStart(2, '0') + '-'
+ current_datetime.getDate().toString().padStart(2, '0') + ' '
+ current_datetime.getHours().toString().padStart(2, '0') + ':'
+ current_datetime.getMinutes().toString().padStart(2, '0') + ':'
+ current_datetime.getSeconds().toString().padStart(2, '0');
};
const sleep = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds));
};
module.exports = {
msgCodes,
sensorCodes,
comfoCommands
}
comfoCommands,
getTimestamp,
sleep
};

@@ -1,8 +0,5 @@

'use strict'
'use strict';
const debug = require('debug')('node-zehnder')
//const debug = require('debug')('node-zehnder');
const Buffer = require('safe-buffer').Buffer;
//const fs = require('fs');
//const protoBuf = require('protocol-buffers');
//const messages = protoBuf(fs.readFileSync(__dirname + '/protocol/zehnder.proto'));
const protoBuf = require('protobufjs');

@@ -12,7 +9,7 @@ const messages = protoBuf.loadSync(__dirname + '/protocol/zehnder.proto');

var reference = 1;
let reference = 1;
function cmd_ListRegisteredApps(debug = false) {
let operation = messages.lookupType('GatewayOperation');
const operation = messages.lookupType('GatewayOperation');
let data = operation.create({

@@ -22,10 +19,10 @@ type: messages.GatewayOperation.OperationType.ListRegisteredAppsRequestType,

});
let opBuffer = operation.encode(data).finish();
const opBuffer = operation.encode(data).finish();
let command = messages.lookupType('ListRegisteredAppsRequest')
const command = messages.lookupType('ListRegisteredAppsRequest');
data = command.create({});
let cmdBuffer = command.encode(data).finish();
const cmdBuffer = command.encode(data).finish();
if (debug) {
console.log(" ** " + opBuffer.toString("hex") + " - " + cmdBuffer.toString("hex"));
console.log(' ** ' + opBuffer.toString('hex') + ' - ' + cmdBuffer.toString('hex'));
}

@@ -36,9 +33,9 @@

'command' : cmdBuffer
}
};
}
function cmd_KeepAlive() {
function cmd_KeepAlive(debug = false) {
let operation = messages.lookupType('GatewayOperation');
const operation = messages.lookupType('GatewayOperation');
let data = operation.create({

@@ -48,11 +45,11 @@ type: messages.GatewayOperation.OperationType.KeepAliveType,

});
let opBuffer = operation.encode(data).finish();
const opBuffer = operation.encode(data).finish();
let command = messages.lookupType('KeepAlive');
const command = messages.lookupType('KeepAlive');
data = command.create({});
let cmdBuffer = command.encode(data).finish();
const cmdBuffer = command.encode(data).finish();
//if (debug) {
// console.log(" ** " + opBuffer.toString("hex") + " - " + cmdBuffer.toString("hex"));
//}
if (debug) {
console.log(' ** ' + opBuffer.toString('hex') + ' - ' + cmdBuffer.toString('hex'));
}

@@ -62,11 +59,9 @@ return {

'command' : cmdBuffer
}
};
}
// PY : 0000004a2020042800000000000000000102030400000000000910138001144fd71e13cb0004080220020a102020042800000000000000000102030410a6371a0d6465762d636f6d666f61697271
// JS : 0000004a2020042800000000000000000908040700000000000910138001144fd71e13cb0004080220010a102020042800000000000000000102030410a6371a0d6465762d636f6d666f61697271
function cmd_RegisterApp(options, debug = false) {
let operation = messages.lookupType('GatewayOperation');
const operation = messages.lookupType('GatewayOperation');
let data = operation.create({

@@ -76,8 +71,7 @@ type: messages.GatewayOperation.OperationType.RegisterAppRequestType,

});
let opBuffer = operation.encode(data).finish();
const opBuffer = operation.encode(data).finish();
const command = messages.lookupType('RegisterAppRequest');
const uuidBuffer = Buffer.from(options.uuid, 'hex');
let command = messages.lookupType('RegisterAppRequest');
let uuidBuffer = Buffer.from(options.uuid, 'hex');
data = command.create({

@@ -88,8 +82,7 @@ uuid: uuidBuffer.toString('base64'),

});
let cmdBuffer = command.encode(data).finish();
const cmdBuffer = command.encode(data).finish();
if (debug) {
console.log(' register app : ' + JSON.stringify(data));
console.log(" ** " + opBuffer.toString("hex") + " - " + cmdBuffer.toString("hex"));
console.log(' ** ' + opBuffer.toString('hex') + ' - ' + cmdBuffer.toString('hex'));
}

@@ -100,10 +93,8 @@

'command' : cmdBuffer
}
};
}
// PY : 000000383020042800000000000000000102030400000000000910138001144fd71e13cb0004080620060a1020200428000000000000000001020304
// JS : 000000282020042800000000000000000908040700000000000910138001144fd71e13cb0004080620020a00
function cmd_DeRegisterApp(uuid, debug = false) {
let operation = messages.lookupType('GatewayOperation');
const operation = messages.lookupType('GatewayOperation');
let data = operation.create({

@@ -113,12 +104,12 @@ type : messages.GatewayOperation.OperationType.DeregisterAppRequestType,

});
let opBuffer = operation.encode(data).finish();
const opBuffer = operation.encode(data).finish();
let command = messages.lookupType('DeregisterAppRequest');
const command = messages.lookupType('DeregisterAppRequest');
data = command.create({
uuid: uuid
});
let cmdBuffer = command.encode(data).finish();
const cmdBuffer = command.encode(data).finish();
if (debug) {
console.log(" ** " + opBuffer.toString("hex") + " - " + cmdBuffer.toString("hex"));
console.log(' ** ' + opBuffer.toString('hex') + ' - ' + cmdBuffer.toString('hex'));
}

@@ -129,7 +120,7 @@

'command' : cmdBuffer
}
};
}
function cmd_StartSession(takeover, debug = false) {
let operation = messages.lookupType('GatewayOperation');
const operation = messages.lookupType('GatewayOperation');
let data = operation.create({

@@ -139,12 +130,12 @@ type : messages.GatewayOperation.OperationType.StartSessionRequestType,

});
let opBuffer = operation.encode(data).finish();
const opBuffer = operation.encode(data).finish();
let command = messages.lookupType('StartSessionRequest');
const command = messages.lookupType('StartSessionRequest');
data = command.create({
takeover: takeover
});
let cmdBuffer = command.encode(data).finish();
const cmdBuffer = command.encode(data).finish();
if (debug) {
console.log(" ** " + opBuffer.toString("hex") + " - " + cmdBuffer.toString("hex"));
console.log(' ** ' + opBuffer.toString('hex') + ' - ' + cmdBuffer.toString('hex'));
}

@@ -155,3 +146,3 @@

'command' : cmdBuffer
}
};

@@ -161,3 +152,3 @@ }

function cmd_RegisterSensor(sensor, debug = false) {
let operation = messages.lookupType('GatewayOperation');
const operation = messages.lookupType('GatewayOperation');
let data = operation.create({

@@ -167,6 +158,6 @@ type : messages.GatewayOperation.OperationType.CnRpdoRequestType,

});
let opBuffer = operation.encode(data).finish();
const opBuffer = operation.encode(data).finish();
let command = messages.lookupType('CnRpdoRequest');
let sensorData = statics.sensorCodes.find( ({ code }) => code === sensor);
const command = messages.lookupType('CnRpdoRequest');
const sensorData = statics.sensorCodes.find( ({ code }) => code === sensor);
data = command.create({

@@ -176,6 +167,6 @@ pdid: sensor,

});
let cmdBuffer = command.encode(data).finish();
const cmdBuffer = command.encode(data).finish();
if (debug) {
console.log(" ** " + opBuffer.toString("hex") + " - " + cmdBuffer.toString("hex"));
console.log(' ** ' + opBuffer.toString('hex') + ' - ' + cmdBuffer.toString('hex'));
}

@@ -186,7 +177,7 @@

'command' : cmdBuffer
}
};
}
function cmd_SendCommand(node, message) {
let operation = messages.lookupType('GatewayOperation');
function cmd_SendCommand(node, message, debug = false) {
const operation = messages.lookupType('GatewayOperation');
let data = operation.create({

@@ -196,13 +187,13 @@ type : messages.GatewayOperation.OperationType.CnRmiRequestType,

});
let opBuffer = operation.encode(data).finish();
const opBuffer = operation.encode(data).finish();
let command = messages.lookupType('CnRmiRequest');
let msgData = statics.comfoCommands.find( ({ name }) => name === message);
let cmdData = {
const command = messages.lookupType('CnRmiRequest');
const msgData = statics.comfoCommands.find(({ name }) => name === message);
const cmdData = {
nodeId: node,
message: Buffer.from(msgData.code, 'hex')
};
let reason = command.verify(cmdData);
if (reason != null) {
console.log(reason)
const reason = command.verify(cmdData);
if (reason != null && debug) {
console.log(reason);
}

@@ -213,8 +204,6 @@ data = command.create({

});
let cmdBuffer = command.encode(data).finish();
const cmdBuffer = command.encode(data).finish();
if (debug) {
console.log(" ** " + message + " - " + opBuffer.toString("hex") + " - " + cmdBuffer.toString("hex"));
} else {
console.log(" ** " + message)
console.log(' ** ' + message + ' - ' + opBuffer.toString('hex') + ' - ' + cmdBuffer.toString('hex'));
}

@@ -225,8 +214,7 @@

'command' : cmdBuffer
}
};
}
function cmd_CloseSession(debug = false) {
let operation = messages.lookupType('GatewayOperation');
const operation = messages.lookupType('GatewayOperation');
let data = operation.create({

@@ -236,10 +224,10 @@ type : messages.GatewayOperation.OperationType.CloseSessionRequestType,

});
let opBuffer = operation.encode(data).finish();
const opBuffer = operation.encode(data).finish();
let command = messages.lookupType('CloseSessionRequest');
const command = messages.lookupType('CloseSessionRequest');
data = command.create({});
let cmdBuffer = command.encode(data).finish();
const cmdBuffer = command.encode(data).finish();
if (debug) {
console.log(" ** " + opBuffer.toString("hex") + " - " + cmdBuffer.toString("hex"));
console.log(' ** ' + opBuffer.toString('hex') + ' - ' + cmdBuffer.toString('hex'));
}

@@ -250,7 +238,7 @@

'command':cmdBuffer
}
};
}
function cmd_VersionRequest(debug = false) {
let operation = messages.lookupType('GatewayOperation');
const operation = messages.lookupType('GatewayOperation');
let data = operation.create({

@@ -260,10 +248,10 @@ type : messages.GatewayOperation.OperationType.VersionRequestType,

});
let opBuffer = operation.encode(data).finish();
const opBuffer = operation.encode(data).finish();
let command = messages.lookupType('VersionRequest')
const command = messages.lookupType('VersionRequest');
data = command.create({});
let cmdBuffer = command.encode(data).finish();
const cmdBuffer = command.encode(data).finish();
if (debug) {
console.log(" ** " + opBuffer.toString("hex") + " - " + cmdBuffer.toString("hex"));
console.log(' ** ' + opBuffer.toString('hex') + ' - ' + cmdBuffer.toString('hex'));
}

@@ -274,3 +262,27 @@

'command':cmdBuffer
};
}
function cmd_TimeRequest(debug = false) {
const operation = messages.lookupType('GatewayOperation');
let data = operation.create({
type : messages.GatewayOperation.OperationType.CnTimeRequestType,
reference : reference++
});
const opBuffer = operation.encode(data).finish();
const command = messages.lookupType('CnTimeRequest');
data = command.create({
setTime: 0
});
const cmdBuffer = command.encode(data).finish();
if (debug) {
console.log(' ** ' + opBuffer.toString('hex') + ' - ' + cmdBuffer.toString('hex'));
}
return {
'operation': opBuffer,
'command':cmdBuffer
};
}

@@ -287,4 +299,5 @@

cmd_CloseSession,
cmd_VersionRequest
}
cmd_VersionRequest,
cmd_TimeRequest
};
{
"name": "node-comfoairq",
"version": "0.5.4",
"version": "0.5.5",
"description": "NodeJS Zehnder ComfoAirQ implementation",

@@ -31,3 +31,3 @@ "main": "lib/comfoconnect.js",

"devDependencies": {
"eslint": "^7.0.0"
"eslint": "^7.11.0"
},

@@ -43,4 +43,5 @@ "bugs": {

"scripts": {
"test": "test/comfoTest.js"
"test": "test/comfoTest.js",
"lint": "eslint"
}
}
# node-comfoairq
Library to control a Zehnder Comfoair Q series of ventilation devices
A Zehnder Comfoconnect LAN C interface is required to make this work
A Zehnder ComfoConnect LAN C interface is required to make this work

@@ -13,2 +14,3 @@ Development of this node.js plugin is heavily inspired on the work performed by:

Revision history:
* 0.5.0 : first working version

@@ -18,9 +20,23 @@ * 0.5.1 : general bugfixes

* 0.5.3 : complete dependencies in package.json
* 0.5.4 : fix bug with registering devices
* 0.5.4 : fix bug with registering devices
* 0.5.5 : extra commands to send to the comfoconnect device
get time added
## Test Script
A test-application is provided to demonstrate the capabilities
1. Update the test/settings.json
2. Run the script
```
npm run test
```
## Range of functions
Not all functions are implemented as the plugin is designed for home automation
Only these are provided:
* start session

@@ -32,2 +48,3 @@ * keepalive

* get version
* get time
* list all registered apps

@@ -40,1 +57,32 @@ * register app

On 'received' and 'disconnect' events are provided
If a valid UUID is provided for the comfoconnect device, a discovery operation is no longer needed
## Quick-start
```javascript
const comfoconnect = require('node-comfoairq');
const settings = require(__dirname + '/settings.json');
const zehnder = new comfoconnect(settings);
zehnder.on('receive', (data) => {
console.log(JSON.stringify(data));
});
zehnder.on('disconnect', (reason) => {
if (reason.state == 'OTHER_SESSION') {
console.log('other device became active');
reconnect = true;
}
connected = false;
});
zehnder.discover();
await zehnder.StartSession(true);
// ..... do something ......
// -> find some inspiration in test\comfoTest.js
await zehnder.CloseSession();
```

@@ -1,24 +0,21 @@

'use strict'
'use strict';
const comfo = require('../lib/comfoconnect');
const zehnder = new comfo()
const settings = require(__dirname + "/settings.json");
const comfoconnect = require('../lib/comfoconnect');
const settings = require(__dirname + '/settings.json');
zehnder.settings = settings;
zehnder.discover();
const zehnder = new comfoconnect(settings);
const readline = require("readline");
const readline = require('readline');
const trmnl = readline.createInterface({
input: process.stdin,
output: process.stdout
input: process.stdin,
output: process.stdout
});
var connected = false;
var reconnect = false;
let connected = false;
let reconnect = false;
zehnder.on('receive', (data) => {
console.log(JSON.stringify(data));
});
zehnder.on('disconnect', (reason) => {

@@ -30,3 +27,3 @@ if (reason.state == 'OTHER_SESSION') {

connected = false;
})
});

@@ -38,3 +35,3 @@ function keepAlive() {

}
return
return;
}

@@ -48,6 +45,6 @@

async function restartSession() {
console.log('** attempting reconnect **')
console.log('** attempting reconnect **');
try {
let result = await zehnder.StartSession(false);
const result = await zehnder.StartSession(false);
console.log(JSON.stringify(result));

@@ -59,18 +56,17 @@

connected = true;
result = await zehnder.RegisterSensor(227);
/*
result = await zehnder.RegisterSensor(227); // SENSOR_BYPASS_STATE
console.log(JSON.stringify(result));
result = await zehnder.RegisterSensor(221);
result = await zehnder.RegisterSensor(221); // SENSOR_TEMPERATURE_SUPPLY
console.log(JSON.stringify(result));
result = await zehnder.RegisterSensor(274);
result = await zehnder.RegisterSensor(274); // SENSOR_TEMPERATURE_EXTRACT
console.log(JSON.stringify(result));
result = await zehnder.RegisterSensor(275);
result = await zehnder.RegisterSensor(275); // SENSOR_TEMPERATURE_EXHAUST
console.log(JSON.stringify(result));
result = await zehnder.RegisterSensor(276);
result = await zehnder.RegisterSensor(276); // SENSOR_TEMPERATURE_OUTDOOR
console.log(JSON.stringify(result));
*/
setTimeout(keepAlive, 5000);
}
catch (exc) {
} catch (exc) {
console.log(exc);

@@ -81,48 +77,49 @@ setTimeout(restartSession, 15000);

var waitForCommand = function () {
trmnl.question("zehnder command to test (? for help) ",async function(answer) {
if (answer == "?") {
console.log("? -- this help function\n" +
"srch -- (re)run discovery\n" +
"lapp -- List Registered Apps\n" +
"rapp -- Register App\n" +
"uapp -- UnRegister App\n" +
"info -- fetch ComfoAir version\n" +
"conn -- connect to ComfoAir unit\n" +
"sens -- register to updates on sensors\n" +
"disc -- disconnect from ComfoAir unit\n" +
"quit -- close this application\n\n" );
const waitForCommand = function() {
trmnl.question('zehnder command to test (? for help) ', async function(answer) {
if (answer == '?') {
console.log('? -- this help function\n' +
'srch -- run discovery\n' +
'lapp -- List Registered Apps\n' +
'rapp -- Register App\n' +
'uapp -- UnRegister App\n' +
'info -- fetch ComfoAir version\n' +
'conn -- connect to ComfoAir unit\n' +
'sens -- register to updates on sensors\n' +
'cmnd -- send command\n' +
'time -- fetch system time\n' +
'disc -- disconnect from ComfoAir unit\n' +
'quit -- close this application\n\n');
} else if (answer == "srch") {
console.log('(re)running discovery\n');
} else if (answer == 'srch') {
console.log('running discovery\n');
let result = await zehnder.discover();
const result = await zehnder.discover();
console.log(JSON.stringify(result));
} else if (answer == "lapp") {
} else if (answer == 'lapp') {
console.log('list registered apps\n');
let result = await zehnder.ListRegisteredApps();
const result = await zehnder.ListRegisteredApps();
console.log(JSON.stringify(result));
} else if (answer == "rapp") {
} else if (answer == 'rapp') {
console.log('register this app\n');
let result = await zehnder.RegisterApp();
const result = await zehnder.RegisterApp();
console.log(JSON.stringify(result));
} else if (answer.startsWith("uapp")) {
} else if (answer.startsWith('uapp')) {
console.log('unregister this app\n');
let uuid = answer.slice(5);
let result = await zehnder.DeRegisterApp(uuid);
const uuid = answer.slice(5);
const result = await zehnder.DeRegisterApp(uuid);
console.log(JSON.stringify(result));
} else if (answer == "info") {
} else if (answer == 'info') {
console.log('fetch ComfoAir info\n');
let result = await zehnder.VersionRequest();
const result = await zehnder.VersionRequest();
console.log(JSON.stringify(result));
} else if (answer == "conn") {
} else if (answer == 'conn') {
console.log('connect to ComfoAir unit\n');

@@ -134,57 +131,81 @@

connected = true;
/*
result = await zehnder.RegisterSensor(67); // TEMPERATURE_PROFILE
console.log(JSON.stringify(result));
result = await zehnder.RegisterSensor(227);
result = await zehnder.RegisterSensor(122); // SENSOR_FAN_SUPPLY_SPEED
console.log(JSON.stringify(result));
result = await zehnder.RegisterSensor(221);
result = await zehnder.RegisterSensor(227); // SENSOR_BYPASS_STATE
console.log(JSON.stringify(result));
result = await zehnder.RegisterSensor(274);
result = await zehnder.RegisterSensor(221); // SENSOR_TEMPERATURE_SUPPLY
console.log(JSON.stringify(result));
result = await zehnder.RegisterSensor(275);
result = await zehnder.RegisterSensor(274); // SENSOR_TEMPERATURE_EXTRACT
console.log(JSON.stringify(result));
result = await zehnder.RegisterSensor(276);
result = await zehnder.RegisterSensor(275); // SENSOR_TEMPERATURE_EXHAUST
console.log(JSON.stringify(result));
result = await zehnder.RegisterSensor(276); // SENSOR_TEMPERATURE_OUTDOOR
console.log(JSON.stringify(result));
*/
setTimeout(keepAlive, 5000);
}
catch (exc) {
} catch (exc) {
console.log(exc);
}
} else if (answer.startsWith("sens")) {
} else if (answer.startsWith('sens')) {
console.log('register to updates on sensors\n');
let sensID = answer.slice(5)
let result = await zehnder.RegisterSensor(Number(sensID));
const sensID = answer.slice(5);
if (sensID) {
const result = await zehnder.RegisterSensor(Number(sensID));
console.log(JSON.stringify(result));
} else {
console.log('Provide sensor id as parameter');
}
} else if (answer.startsWith('cmnd')) {
console.log('Sending custom command\n');
const cmndName = answer.slice(5);
if (cmndName) {
const result = await zehnder.SendCommand(1, cmndName);
console.log(JSON.stringify(result));
} else {
console.log('Provide command name as parameter');
}
} else if (answer.startsWith('time')) {
console.log('Fetching time\n');
const result = await zehnder.TimeRequest();
console.log(JSON.stringify(result));
} else if (answer == 'disc') {
console.log('disconnect from ComfoAir unit\n');
//checkSensors = true;
} else if (answer == "disc") {
console.log('disconnect from ComfoAir unit\n');
await zehnder.CloseSession();
connected = false;
} else if (answer == "quit") {
} else if (answer == 'quit') {
console.log('closing down');
await zehnder.CloseSession();
connected = false;
trmnl.close();
}
}
waitForCommand();
});
}
/*
zehnder.bridge.on('receive', () => {
console.log('test')
})*/
};
waitForCommand();
//setTimeout(getResponse, 1000);
trmnl.on('close', function() {
console.log('\nBYE BYE !!!');
process.exit(0);
});
trmnl.on("close", function() {
console.log("\nBYE BYE !!!");
process.exit(0);
});
zehnder.discover();

@@ -5,5 +5,7 @@ {

"device" : "node-comfoairq",
"multicast": "10.1.1.255",
"comfoair": "10.1.1.25",
"debug": true
}
"multicast": "192.168.1.255",
"comfoair": "192.168.1.113",
"comfoUuid": "00000000003410138001144fd71e24cc",
"debug": false,
"verbose": true
}

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