Skip to content

Commit

Permalink
HmIP-STH/STHD configurable as Thermostat or Sensor (Close #190)
Browse files Browse the repository at this point in the history
  • Loading branch information
hobbyquaker committed Jan 2, 2020
1 parent 4471cd1 commit 5db5f18
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 2 deletions.
168 changes: 167 additions & 1 deletion homematic-devices/hmip-sth.js
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');
}
}
};
2 changes: 1 addition & 1 deletion homematic-devices/hmip-sthd.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
module.exports = require('./hmip-stho');
module.exports = require('./hmip-sth');
5 changes: 5 additions & 0 deletions nodes/redmatic-homekit-homematic-devices.html
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,11 @@

case 'hmip-sth':
case 'hmip-sthd':
addOption(addr, 'Thermostat');
addOption(addr, 'BoostSwitch');
addOption(addr, 'HumiditySensor');
break;

case 'hmip-stho-a':
case 'hmip-stho':
addOption(addr, 'HumiditySensor');
Expand Down

0 comments on commit 5db5f18

Please sign in to comment.