-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
HmIP-STH/STHD configurable as Thermostat or Sensor (Close #190)
- Loading branch information
1 parent
4471cd1
commit 5db5f18
Showing
3 changed files
with
173 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,167 @@ | ||
module.exports = require('./hmip-stho'); | ||
const Accessory = require('./lib/accessory'); | ||
|
||
module.exports = class HmipWth extends Accessory { | ||
init(config, node) { | ||
const {bridgeConfig, ccu} = node; | ||
const {hap} = bridgeConfig; | ||
|
||
const levels = {}; | ||
let level = 0; | ||
let valueSetpoint; | ||
let setpointMode; | ||
let target; | ||
let serviceThermostat; | ||
|
||
function targetState() { | ||
// 0=off, 1=heat, 3=auto | ||
switch (setpointMode) { | ||
case 1: | ||
// Manu | ||
target = valueSetpoint > 4.5 ? 1 : 0; | ||
break; | ||
default: | ||
// Auto / Party | ||
target = 3; | ||
} | ||
|
||
return target; | ||
} | ||
|
||
function currentState() { | ||
// 0=off, 1=heat | ||
return level > 0 ? 1 : 0; | ||
} | ||
|
||
function updateHeatingCoolingState() { | ||
serviceThermostat.update('CurrentHeatingCoolingState', currentState()); | ||
serviceThermostat.update('TargetHeatingCoolingState', targetState()); | ||
} | ||
|
||
if (this.option('Thermostat')) { | ||
|
||
const links = ccu.getLinks(config.iface, config.description.ADDRESS + ':3') || []; | ||
node.debug(config.name + ' linked to ' + JSON.stringify(links)); | ||
|
||
serviceThermostat = this.addService('Thermostat', config.name); | ||
const subtypeThermostat = serviceThermostat.subtype; | ||
|
||
serviceThermostat | ||
.setProps('CurrentTemperature', {minValue: -40, maxValue: 80}) | ||
.get('CurrentTemperature', config.deviceAddress + ':1.ACTUAL_TEMPERATURE') | ||
|
||
.setProps('TargetTemperature', {minValue: 4.5, maxValue: 30.5, minStep: 0.5}) | ||
.get('TargetTemperature', config.deviceAddress + ':1.SET_POINT_TEMPERATURE', value => { | ||
valueSetpoint = value; | ||
updateHeatingCoolingState(); | ||
return value; | ||
}) | ||
.set('TargetTemperature', config.deviceAddress + ':1.SET_POINT_TEMPERATURE') | ||
|
||
.setProps('CurrentHeatingCoolingState', {validValues: [0, 1], maxValue: 1}) | ||
.get('CurrentHeatingCoolingState', config.deviceAddress + ':1.LEVEL', () => { | ||
setTimeout(() => { | ||
updateHeatingCoolingState(); | ||
}, 1000); | ||
return currentState(); | ||
}) | ||
|
||
.setProps('TargetHeatingCoolingState', {validValues: [0, 1, 3]}) | ||
.get('TargetHeatingCoolingState', config.deviceAddress + ':1.SET_POINT_TEMPERATURE', () => { | ||
setTimeout(() => { | ||
updateHeatingCoolingState(); | ||
}, 1000); | ||
return targetState(); | ||
}) | ||
.set('TargetHeatingCoolingState', (value, callback) => { | ||
// 0=off, 1=heat, 3=auto | ||
if (value === 0) { | ||
const params = { | ||
CONTROL_MODE: 1, | ||
SET_POINT_TEMPERATURE: 4.5 | ||
}; | ||
node.debug('set ' + config.name + ' (' + subtypeThermostat + ') TargetHeatingCoolingState ' + value + ' -> ' + config.description.ADDRESS + ':1 ' + JSON.stringify(params)); | ||
|
||
ccu.methodCall(config.iface, 'putParamset', [config.description.ADDRESS + ':1', 'VALUES', params]) | ||
.then(() => { | ||
callback(); | ||
}).catch(() => { | ||
callback(new Error(hap.HAPServer.Status.SERVICE_COMMUNICATION_FAILURE)); | ||
}); | ||
} else if (value === 1) { | ||
const params = { | ||
CONTROL_MODE: 1, | ||
SET_POINT_TEMPERATURE: 21 | ||
}; | ||
node.debug('set ' + config.name + ' (' + subtypeThermostat + ') TargetHeatingCoolingState ' + value + ' -> ' + config.description.ADDRESS + ':1 ' + JSON.stringify(params)); | ||
ccu.methodCall(config.iface, 'putParamset', [config.description.ADDRESS + ':1', 'VALUES', params]) | ||
.then(() => { | ||
callback(); | ||
}).catch(() => { | ||
callback(new Error(hap.HAPServer.Status.SERVICE_COMMUNICATION_FAILURE)); | ||
}); | ||
} else { | ||
node.debug('set ' + config.name + ' (' + subtypeThermostat + ') TargetHeatingCoolingState ' + value + ' -> ' + config.description.ADDRESS + ':1.CONTROL_MODE ' + (value === 3 ? 0 : 1)); | ||
ccu.setValue(config.iface, config.description.ADDRESS + ':1', 'CONTROL_MODE', value === 3 ? 0 : 1) | ||
.then(() => { | ||
callback(); | ||
}).catch(() => { | ||
callback(new Error(hap.HAPServer.Status.SERVICE_COMMUNICATION_FAILURE)); | ||
}); | ||
} | ||
}); | ||
|
||
links.forEach(link => { | ||
const valveStateDevice = link.split(':')[0]; | ||
const datapointLevel = config.iface + '.' + valveStateDevice + ':1.LEVEL'; | ||
this.subscribe(datapointLevel, value => { | ||
levels[datapointLevel] = value; | ||
let max = 0; | ||
Object.keys(levels).forEach(dp => { | ||
if (levels[dp] > max) { | ||
max = levels[dp]; | ||
} | ||
}); | ||
if (level !== max) { | ||
level = max; | ||
node.debug('update ' + config.name + ' level ' + level); | ||
updateHeatingCoolingState(); | ||
} | ||
}); | ||
}); | ||
|
||
this.subscribe(config.deviceAddress + ':1.SET_POINT_MODE', value => { | ||
setpointMode = value; | ||
node.debug('update ' + config.name + ' setpointMode ' + setpointMode); | ||
updateHeatingCoolingState(); | ||
}); | ||
|
||
if (this.option('BoostSwitch')) { | ||
this.addService('Switch', 'Boost ' + config.name, 'Boost') | ||
.set('On', (value, callback) => { | ||
this.ccuSetValue(config.deviceAddress + ':1.BOOST_MODE', value, callback); | ||
links.forEach(link => { | ||
const linkedDevice = link.split(':')[0]; | ||
this.ccuSetValue(config.iface + '.' + linkedDevice + ':1.BOOST_MODE', value); | ||
}); | ||
}) | ||
.get('On', config.deviceAddress + ':1.BOOST_MODE'); | ||
} | ||
} else { | ||
this.addService('TemperatureSensor', config.name) | ||
.setProps('CurrentTemperature', {minValue: -40, maxValue: 80}) | ||
.get('CurrentTemperature', config.deviceAddress + ':1.ACTUAL_TEMPERATURE'); | ||
} | ||
|
||
this.addService('BatteryService', config.name) | ||
.get('StatusLowBattery', config.deviceAddress + ':0.LOW_BAT', (value, c) => { | ||
return value ? c.BATTERY_LEVEL_LOW : c.BATTERY_LEVEL_NORMAL; | ||
}) | ||
.get('BatteryLevel', config.deviceAddress + ':0.OPERATING_VOLTAGE', this.percent) | ||
.update('ChargingState', 2); | ||
|
||
if (this.option('HumiditySensor')) { | ||
this.addService('HumiditySensor', config.name) | ||
.get('CurrentRelativeHumidity', config.deviceAddress + ':1.HUMIDITY'); | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
module.exports = require('./hmip-stho'); | ||
module.exports = require('./hmip-sth'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters