iobroker.comfoairq
Advanced tools
Comparing version 0.0.2 to 0.0.3
{ | ||
"common": { | ||
"name": "comfoairq", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"news": { | ||
"0.0.3": { | ||
"en": "Bugfixes", | ||
"de": "Bugfixes" | ||
}, | ||
"0.0.2": { | ||
@@ -21,4 +25,4 @@ "en": "First connection", | ||
"desc": { | ||
"en": "Zehnder ComfoAirQ over ComfoConnect LAN C", | ||
"de": "Zehnder ComfoAirQ über ComfoConnect LAN C" | ||
"en": "Zehnder ComfoAirQ over ComfoConnect LAN C (e.g. Q350)", | ||
"de": "Zehnder ComfoAirQ über ComfoConnect LAN C (z.B. Q350)" | ||
}, | ||
@@ -54,3 +58,6 @@ "authors": [ | ||
}, | ||
"native": {}, | ||
"native": { | ||
"pin": "0000", | ||
"port": "56747" | ||
}, | ||
"objects": [], | ||
@@ -78,4 +85,280 @@ "instanceObjects": [ | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "version", | ||
"type": "channel", | ||
"common": { | ||
"name": "Version information" | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "version.comfonet", | ||
"type": "state", | ||
"common": { | ||
"name": "ComfoNET version", | ||
"role": "value", | ||
"type": "string", | ||
"read": true, | ||
"write": false | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "version.gateway", | ||
"type": "state", | ||
"common": { | ||
"name": "Gateway version", | ||
"role": "value", | ||
"type": "string", | ||
"read": true, | ||
"write": false | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "version.serial", | ||
"type": "state", | ||
"common": { | ||
"name": "Serial number", | ||
"role": "value", | ||
"type": "string", | ||
"read": true, | ||
"write": false | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command", | ||
"type": "channel", | ||
"common": { | ||
"name": "Commands" | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.fanModeAway", | ||
"type": "state", | ||
"common": { | ||
"name": "Fan Mode Away", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.fanModeLow", | ||
"type": "state", | ||
"common": { | ||
"name": "Fan Mode Low", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.fanModeMedium", | ||
"type": "state", | ||
"common": { | ||
"name": "Fan Mode Medium", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.fanModeHigh", | ||
"type": "state", | ||
"common": { | ||
"name": "Fan Mode High", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.fanBoost10m", | ||
"type": "state", | ||
"common": { | ||
"name": "Fan Boost 10 minutes", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.fanBoost20m", | ||
"type": "state", | ||
"common": { | ||
"name": "Fan Boost 20 minutes", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.fanBoost30m", | ||
"type": "state", | ||
"common": { | ||
"name": "Fan Boost 30 minutes", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.fanBoostEnd", | ||
"type": "state", | ||
"common": { | ||
"name": "Fan Boost end", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.modeAuto", | ||
"type": "state", | ||
"common": { | ||
"name": "Mode Auto", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.modeManual", | ||
"type": "state", | ||
"common": { | ||
"name": "Mode Auto", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.ventmodeSupply", | ||
"type": "state", | ||
"common": { | ||
"name": "Vent mode Supply", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.ventmodeBalance", | ||
"type": "state", | ||
"common": { | ||
"name": "Vent mode Balance", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.tempprofNormal", | ||
"type": "state", | ||
"common": { | ||
"name": "Temperature profile normal", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.tempprofCool", | ||
"type": "state", | ||
"common": { | ||
"name": "Temperature profile cool", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.tempprofWarm", | ||
"type": "state", | ||
"common": { | ||
"name": "Temperature profile warm", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.bypassOn", | ||
"type": "state", | ||
"common": { | ||
"name": "Bypass on", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.bypassOff", | ||
"type": "state", | ||
"common": { | ||
"name": "Bypass off", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "command.bypassAuto", | ||
"type": "state", | ||
"common": { | ||
"name": "Bypass auto", | ||
"role": "button", | ||
"type": "boolean", | ||
"read": false, | ||
"write": true | ||
}, | ||
"native": {} | ||
}, | ||
{ | ||
"_id": "sensor", | ||
"type": "channel", | ||
"common": { | ||
"name": "Sensor" | ||
}, | ||
"native": {} | ||
} | ||
] | ||
} |
304
main.js
@@ -7,5 +7,4 @@ /* jshint -W097 */ | ||
const utils = require('@iobroker/adapter-core'); | ||
const comfoconnect = require('node-comfoairq/lib/comfoconnect'); | ||
const comfoconnect = require('comfoairq'); | ||
const adapterName = require('./package.json').name.split('.').pop(); | ||
const util = require('util'); | ||
@@ -23,4 +22,42 @@ class Comfoairq extends utils.Adapter { | ||
this.connected = false; | ||
this.uuid = '20200428000000000000000009080408'; | ||
this.deviceName = 'iobroker'; | ||
this.zehnder = null; | ||
this.sensors = []; | ||
this.sensorUnits = { | ||
117: '%', | ||
118: '%', | ||
119: 'm³/h', | ||
120: 'm³/h', | ||
121: 'rpm', | ||
122: 'rpm', | ||
128: 'W', | ||
129: 'kWh', | ||
130: 'kWh', | ||
144: 'kWh', | ||
145: 'kWh', | ||
146: 'W', | ||
192: 'days', | ||
209: '°C', | ||
213: 'W', | ||
214: 'kWh', | ||
215: 'kWh', | ||
216: 'W', | ||
217: 'kWh', | ||
218: 'kWh', | ||
221: '°C', | ||
227: '%', | ||
274: '°C', | ||
275: '°C', | ||
276: '°C', | ||
290: '%', | ||
291: '%', | ||
292: '%', | ||
294: '%' | ||
}; | ||
this.on('ready', this.onReady.bind(this)); | ||
@@ -32,43 +69,145 @@ this.on('stateChange', this.onStateChange.bind(this)); | ||
async onReady() { | ||
const that = this; | ||
this.setState('info.connection', false, true); | ||
this.zehnder = new comfoconnect( | ||
{ | ||
"pin": parseInt(this.config.pin), | ||
"uuid" : "20200428000000000000000009080408", | ||
"device" : "iobroker", | ||
"multicast": "192.168.1.255", | ||
"comfoair": this.config.host, | ||
"comfoUuid": this.config.uuid, | ||
"debug": true, | ||
"logger": this.log.debug | ||
// Get active sensors by configuration | ||
for (const key of Object.keys(this.config)) { | ||
if (key.indexOf('sensor_') === 0 && this.config[key]) { | ||
this.sensors.push(Number(key.slice(7))); | ||
} | ||
); | ||
} | ||
this.log.debug('register receive handler...'); | ||
this.zehnder.on('receive', (data) => { | ||
that.log.debug('received: ' + JSON.stringify(data)); | ||
/* | ||
this.getForeignObjectAsync('system.adapter.' + this.namespace).then(data => { | ||
this.log.debug('Current configuration: ' + JSON.stringify(data)); | ||
}); | ||
*/ | ||
this.log.debug('register disconnect handler...'); | ||
this.zehnder.on('disconnect', (reason) => { | ||
if (reason.state == 'OTHER_SESSION') { | ||
that.log.warn('Other session started'); | ||
if (this.config.host && this.config.port && this.config.uuid) { | ||
if (this.sensors.length > 0) { | ||
this.log.debug('Active sensors by configuration: ' + JSON.stringify(this.sensors)); | ||
this.zehnder = new comfoconnect( | ||
{ | ||
'uuid' : this.uuid, | ||
'device' : this.deviceName, | ||
'comfoair': this.config.host, | ||
'port': Number(this.config.port), | ||
'comfouuid': this.config.uuid, | ||
'pin': parseInt(this.config.pin), | ||
'debug': false, | ||
'logger': this.log.debug | ||
} | ||
); | ||
this.log.debug('register receive handler...'); | ||
this.zehnder.on('receive', async (data) => { | ||
this.log.debug('received: ' + JSON.stringify(data)); | ||
if (data && data.result.error == 'OK') { | ||
if (data.kind == 40) { // 40 = CnRpdoNotification | ||
const sensorId = data.result.data.pdid; | ||
const sensorName = data.result.data.name; | ||
const sensorNameClean = this.cleanNamespace(sensorName.replace('SENSOR', '')); | ||
const sensorValue = data.result.data.data; | ||
const unit = Object.prototype.hasOwnProperty.call(this.sensorUnits, sensorId) ? this.sensorUnits[sensorId] : ''; | ||
await this.setObjectNotExistsAsync('sensor.' + sensorNameClean, { | ||
type: 'state', | ||
common: { | ||
name: sensorName + ' (' + sensorId + ')', | ||
type: 'string', | ||
role: 'value', | ||
unit: unit, | ||
read: true, | ||
write: false | ||
}, | ||
native: {} | ||
}); | ||
this.setState('sensor.' + sensorNameClean, {val: sensorValue, ack: true}); | ||
} else if (data.kind == 68) { // 68 = VersionConfirm | ||
this.setState('version.comfonet', {val: data.result.data.comfoNetVersion, ack: true}); | ||
this.setState('version.serial', {val: data.result.data.serialNumber, ack: true}); | ||
this.setState('version.gateway', {val: data.result.data.gatewayVersion, ack: true}); | ||
} | ||
} | ||
}); | ||
this.log.debug('register disconnect handler...'); | ||
this.zehnder.on('disconnect', (reason) => { | ||
if (reason.state == 'OTHER_SESSION') { | ||
this.log.warn('Other session started: ' + JSON.stringify(reason)); | ||
} | ||
this.setState('info.connection', false, true); | ||
}); | ||
this.log.debug('register the app...'); | ||
const registerAppResult = await this.zehnder.RegisterApp(); | ||
this.log.debug('registerAppResult: ' + JSON.stringify(registerAppResult)); | ||
// Start the session | ||
this.log.debug('startSession'); | ||
const startSessionResult = await this.zehnder.StartSession(true); | ||
this.log.debug('startSessionResult:' + JSON.stringify(startSessionResult)); | ||
for (let i = 0; i < this.sensors.length; i++) { | ||
const registerResult = await this.zehnder.RegisterSensor(this.sensors[i]); | ||
this.log.debug('Registered sensor "' + this.sensors[i] + '" with result: ' + JSON.stringify(registerResult)); | ||
} | ||
this.zehnder.VersionRequest(); | ||
this.setState('info.connection', true, true); | ||
this.connected = true; | ||
this.subscribeStates('*'); | ||
} else { | ||
this.log.warn('No active sensors found in configuration - stopping'); | ||
} | ||
}); | ||
} else { | ||
// Dicover Zehnder devices | ||
this.log.warn('Device information not configured - starting discovery'); | ||
this.log.debug('register the app...'); | ||
let result = await this.zehnder.RegisterApp(); | ||
this.log.debug('registerAppResult: ' + JSON.stringify(result)); | ||
this.zehnder = new comfoconnect( | ||
{ | ||
'uuid' : this.uuid, | ||
'device' : this.deviceName, | ||
'port': Number(this.config.port), | ||
'debug': false, | ||
'logger': this.log.debug | ||
} | ||
); | ||
try { | ||
const discoverResult = await this.zehnder.discover('172.16.255.255'); | ||
this.log.info('Device discovery finished: ' + JSON.stringify(discoverResult)); | ||
} catch (ex) { | ||
this.log.error('error while discovery: ' + JSON.stringify(ex)); | ||
} | ||
} | ||
} | ||
cleanNamespace(id) { | ||
return id | ||
.trim() | ||
.replace(/\s/g, '_') // Replace whitespaces with underscores | ||
.replace(/[^\p{Ll}\p{Lu}\p{Nd}]+/gu, '_') // Replace not allowed chars with underscore | ||
.replace(/[_]+$/g, '') // Remove underscores end | ||
.replace(/^[_]+/g, '') // Remove underscores beginning | ||
.replace(/_+/g, '_') // Replace multiple underscores with one | ||
.toLowerCase() | ||
.replace(/_([a-z])/g, (m, w) => { | ||
return w.toUpperCase(); | ||
}); | ||
} | ||
onUnload(callback) { | ||
try { | ||
//await this.zehnder.CloseSession(); | ||
this.zehnder.CloseSession(); | ||
this.zehnder = null; | ||
this.setState('info.connection', false, true); | ||
callback(); | ||
@@ -86,8 +225,105 @@ } catch (e) { | ||
onStateChange(id, state) { | ||
if (state) { | ||
// The state was changed | ||
this.log.info(`state ${id} changed: ${state.val} (ack = ${state.ack})`); | ||
} else { | ||
// The state was deleted | ||
this.log.info(`state ${id} deleted`); | ||
if (id && state && !state.ack) { | ||
this.log.debug(`state ${id} changed: ${state.val} (ack = ${state.ack})`); | ||
if (this.connected) { | ||
const matches = id.match(new RegExp(this.namespace + '.command.([a-zA-Z0-9]+)')); | ||
if (matches) { | ||
const command = matches[1]; | ||
switch (command) { | ||
case 'fanModeAway': | ||
this.log.debug('Sending command: FAN_MODE_AWAY'); | ||
this.zehnder.SendCommand(1, 'FAN_MODE_AWAY'); | ||
break; | ||
case 'fanModeLow': | ||
this.log.debug('Sending command: FAN_MODE_LOW'); | ||
this.zehnder.SendCommand(1, 'FAN_MODE_LOW'); | ||
break; | ||
case 'fanModeMedium': | ||
this.log.debug('Sending command: FAN_MODE_MEDIUM'); | ||
this.zehnder.SendCommand(1, 'FAN_MODE_MEDIUM'); | ||
break; | ||
case 'fanModeHigh': | ||
this.log.debug('Sending command: FAN_MODE_HIGH'); | ||
this.zehnder.SendCommand(1, 'FAN_MODE_HIGH'); | ||
break; | ||
case 'fanBoost10m': | ||
this.log.debug('Sending command: FAN_BOOST_10M'); | ||
this.zehnder.SendCommand(1, 'FAN_BOOST_10M'); | ||
break; | ||
case 'fanBoost20m': | ||
this.log.debug('Sending command: FAN_BOOST_20M'); | ||
this.zehnder.SendCommand(1, 'FAN_BOOST_20M'); | ||
break; | ||
case 'fanBoost30m': | ||
this.log.debug('Sending command: FAN_BOOST_30M'); | ||
this.zehnder.SendCommand(1, 'FAN_BOOST_30M'); | ||
break; | ||
case 'fanBoostEnd': | ||
this.log.debug('Sending command: FAN_BOOST_END'); | ||
this.zehnder.SendCommand(1, 'FAN_BOOST_END'); | ||
break; | ||
case 'modeAuto': | ||
this.log.debug('Sending command: MODE_AUTO'); | ||
this.zehnder.SendCommand(1, 'MODE_AUTO'); | ||
break; | ||
case 'modeManual': | ||
this.log.debug('Sending command: MODE_MANUAL'); | ||
this.zehnder.SendCommand(1, 'MODE_MANUAL'); | ||
break; | ||
case 'ventmodeSupply': | ||
this.log.debug('Sending command: VENTMODE_SUPPLY'); | ||
this.zehnder.SendCommand(1, 'VENTMODE_SUPPLY'); | ||
break; | ||
case 'ventmodeBalance': | ||
this.log.debug('Sending command: VENTMODE_BALANCE'); | ||
this.zehnder.SendCommand(1, 'VENTMODE_BALANCE'); | ||
break; | ||
case 'tempprofNormal': | ||
this.log.debug('Sending command: TEMPPROF_NORMAL'); | ||
this.zehnder.SendCommand(1, 'TEMPPROF_NORMAL'); | ||
break; | ||
case 'tempprofCool': | ||
this.log.debug('Sending command: TEMPPROF_COOL'); | ||
this.zehnder.SendCommand(1, 'TEMPPROF_COOL'); | ||
break; | ||
case 'tempprofWarm': | ||
this.log.debug('Sending command: TEMPPROF_WARM'); | ||
this.zehnder.SendCommand(1, 'TEMPPROF_WARM'); | ||
break; | ||
case 'bypassOn': | ||
this.log.debug('Sending command: BYPASS_ON'); | ||
this.zehnder.SendCommand(1, 'BYPASS_ON'); | ||
break; | ||
case 'bypassOff': | ||
this.log.debug('Sending command: BYPASS_OFF'); | ||
this.zehnder.SendCommand(1, 'BYPASS_OFF'); | ||
break; | ||
case 'bypassAuto': | ||
this.log.debug('Sending command: BYPASS_AUTO'); | ||
this.zehnder.SendCommand(1, 'BYPASS_AUTO'); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
@@ -94,0 +330,0 @@ } |
{ | ||
"name": "iobroker.comfoairq", | ||
"version": "0.0.2", | ||
"description": "Connect your Zehnder ComfoAirQ over ComfoConnect LAN C", | ||
"version": "0.0.3", | ||
"description": "ioBroker ComfoAirQ Adapter", | ||
"author": { | ||
@@ -12,2 +12,5 @@ "name": "Matthias Kleine", | ||
"keywords": [ | ||
"ioBroker", | ||
"Smart Home", | ||
"home automation", | ||
"KWL", | ||
@@ -20,7 +23,7 @@ "Zehnder", | ||
"type": "git", | ||
"url": "git@github.com:klein0r/ioBroker.comfoairq.git" | ||
"url": "https://github.com/klein0r/ioBroker.comfoairq" | ||
}, | ||
"dependencies": { | ||
"@iobroker/adapter-core": "^2.4.0", | ||
"node-comfoairq": "^0.5.2" | ||
"comfoairq": "^0.6.1" | ||
}, | ||
@@ -42,3 +45,3 @@ "devDependencies": { | ||
"gulp": "^4.0.2", | ||
"mocha": "^8.0.1", | ||
"mocha": "^8.2.1", | ||
"proxyquire": "^2.1.3", | ||
@@ -45,0 +48,0 @@ "sinon": "^9.0.2", |
@@ -17,2 +17,6 @@ ![Logo](admin/comfoairq.png) | ||
*Tested with ComfoAirQ 350* | ||
**Important:** ComfoConnect LAN C supports just 1 single client. You cannot use the ComfoControl App and the ioBroker adapter at the same time! | ||
## Credits | ||
@@ -22,3 +26,3 @@ | ||
* herrJones (https://github.com/herrJones/node-comfoairq) | ||
* Jan Van Belle (https://github.com/herrJones/node-comfoairq) | ||
* Michael Arnauts (https://github.com/michaelarnauts/comfoconnect) | ||
@@ -29,2 +33,10 @@ * Marco Hoyer (https://github.com/marco-hoyer/zcan) and its forks on github (djwlindenaar, decontamin4t0R) | ||
### 0.0.3 | ||
* (klein0r) Subscribe to sensors | ||
* (klein0r) Units for sensor values | ||
* (klein0r) Get version information | ||
* (klein0r) Control fan speed | ||
* (klein0r) Control fan boost | ||
### 0.0.2 | ||
@@ -31,0 +43,0 @@ |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
60588
460
69
1
+ Addedcomfoairq@^0.6.1
+ Addedcomfoairq@0.6.2(transitive)
+ Addedieee754@1.2.1(transitive)
+ Addedpbf@3.2.1(transitive)
+ Addedprotocol-buffers-schema@3.6.0(transitive)
+ Addedresolve-protobuf-schema@2.1.0(transitive)
- Removednode-comfoairq@^0.5.2
- Removednode-comfoairq@0.5.9(transitive)