Skip to content

Commit 985ef29

Browse files
committed
Add actuator state (3EF0) and richer config for relays
1 parent 30bc53e commit 985ef29

3 files changed

Lines changed: 62 additions & 9 deletions

File tree

src/config.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ class Config {
1010

1111
rawConfig.forEach((site) => {
1212
this.allControllers[site.controller] = {
13-
zones: site.zones
13+
zones: site.zones,
14+
relays: site.relays
1415
};
1516

1617
Object.getOwnPropertyNames(site.devices).forEach((addr) => {
@@ -20,6 +21,22 @@ class Config {
2021
zoneName: site.zones[site.devices[addr].zone]
2122
});
2223
});
24+
25+
if (site.relays) {
26+
if (site.relays.dhw) {
27+
this.allDevices[site.relays.dhw] = Object.freeze({
28+
name: 'Hot Water',
29+
subsystem: 'dhw'
30+
});
31+
}
32+
33+
if (site.relays.boiler) {
34+
this.allDevices[site.relays.boiler] = Object.freeze({
35+
name: 'Boiler',
36+
subsystem: 'boiler'
37+
});
38+
}
39+
}
2340
});
2441
}
2542

src/decoders/actuator-state.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
export default function(m) {
2+
if (m.isRequest()) { return null; }
3+
if (!((m.isReply() && m.addr[0].isOpenTherm() && m.addr[1].isSiteController()) ||
4+
(m.isInformation() && m.addr[0].isRelay() && m.addr[0].isConfigured()))) {
5+
return null;
6+
}
7+
if (m.length % 3 !== 0) { throw new Error('ACTUATOR_STATE payload length incorrect'); }
8+
9+
function readBit(byte, bit) {
10+
// eslint-disable-next-line no-bitwise
11+
return (byte & (1 << bit)) >> bit;
12+
}
13+
14+
const result = {
15+
decoded: {
16+
type: 'ACTUATOR_STATE',
17+
device: m.addr[0].describe()
18+
}
19+
};
20+
21+
if (m.length >= 3) {
22+
m.skip(1);
23+
result.decoded.modulation = m.readUInt8() / 200;
24+
m.skip(1);
25+
}
26+
27+
if (m.length >= 6) {
28+
const state = m.readUInt8();
29+
result.decoded.ch = readBit(state, 1) * 100;
30+
result.decoded.dhw = readBit(state, 2) * 100;
31+
result.decoded.flame = readBit(state, 3) * 100;
32+
result.decoded.cooling = readBit(state, 4) * 100;
33+
m.skip(2);
34+
}
35+
36+
if (m.length >= 9) {
37+
result.decoded.chEnabled = readBit(m.readUInt8(), 0);
38+
result.decoded.chSetpoint = m.readUInt8();
39+
m.skip(1);
40+
}
41+
42+
return result;
43+
}

src/decoders/index.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import heatDemand from './heat-demand';
44
import setpoint from './setpoint';
55
import dhwTemp from './dhw-temp';
66
import zoneWindow from './zone-window';
7+
import actuatorState from './actuator-state';
78

89
function externalSensor() {
910
return {
@@ -85,14 +86,6 @@ function actuatorCheck() {
8586
};
8687
}
8788

88-
function actuatorState() {
89-
return {
90-
decoded: {
91-
type: 'ACTUATOR_STATE'
92-
}
93-
};
94-
}
95-
9689
export default {
9790
'0002': externalSensor,
9891
'0004': zoneName,

0 commit comments

Comments
 (0)