Skip to content

Commit

Permalink
feat: auto discover climates devices
Browse files Browse the repository at this point in the history
  • Loading branch information
robertsLando committed Dec 1, 2020
1 parent dd1fe56 commit 2d0167e
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 15 deletions.
9 changes: 5 additions & 4 deletions hass/configurations.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,12 @@ module.exports = {
type: 'climate',
object_id: 'climate',
discovery_payload: {
min_temp: 7,
max_temp: 30,
modes: ['off', 'auto', 'heat'],
min_temp: 5,
max_temp: 40,
temp_step: 0.5,
modes: [],
mode_state_topic: true,
mode_state_template: '{{ value_json.mode }}',
mode_state_template: '{{ value_json.value }}',
mode_command_topic: true,
current_temperature_topic: true,
current_temperature_template: '{{ value_json.value }}',
Expand Down
22 changes: 11 additions & 11 deletions hass/devices.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ const THERMOSTAT_2GIG = {
on: 1
},
setpoint_topic: {
Heat: '67-1-setpoint-1',
Cool: '67-1-setpoint-2'
1: '67-1-setpoint-1',
2: '67-1-setpoint-2'
},
default_setpoint: '67-1-setpoint-1',
discovery_payload: {
Expand Down Expand Up @@ -79,8 +79,8 @@ const STELLA_ZWAVE = {
],
mode_map: { off: 0, heat: 1, cool: 11 },
setpoint_topic: {
Comfort: '67-0-setpoint-1',
'Energy Saving': '67-0-setpoint-11'
1: '67-0-setpoint-1',
11: '67-0-setpoint-11'
},
default_setpoint: '67-0-setpoint-1',
discovery_payload: {
Expand Down Expand Up @@ -109,8 +109,8 @@ const SPIRIT_ZWAVE_PLUS = {
],
mode_map: { off: 0, heat: 1, cool: 11 },
setpoint_topic: {
Heat: '67-0-setpoint-1',
'Heat Eco': '67-0-setpoint-11'
1: '67-0-setpoint-1',
11: '67-0-setpoint-11'
},
default_setpoint: '67-0-setpoint-1',
discovery_payload: {
Expand All @@ -131,7 +131,7 @@ const DANFOSS_TRV_ZWAVE = {
type: 'climate',
object_id: 'thermostat',
values: ['49-0-Air temperature', '67-0-setpoint-1'],
setpoint_topic: { Heat: '67-0-setpoint-1' },
setpoint_topic: { 1: '67-0-setpoint-1' },
default_setpoint: '67-0-setpoint-1',
discovery_payload: {
min_temp: 4,
Expand Down Expand Up @@ -171,7 +171,7 @@ module.exports = {
off: 0,
heat: 1
},
setpoint_topic: { Heat: '67-0-setpoint-1' },
setpoint_topic: { 1: '67-0-setpoint-1' },
default_setpoint: '67-0-setpoint-1',
discovery_payload: {
min_temp: 5,
Expand All @@ -197,8 +197,8 @@ module.exports = {
],
mode_map: { off: 0, heat: 1, cool: 2 },
setpoint_topic: {
'Heat (Default)': '67-0-setpoint-1',
Cool: '67-0-setpoint-2'
1: '67-0-setpoint-1',
2: '67-0-setpoint-2'
},
default_setpoint: '67-0-setpoint-1',
discovery_payload: {
Expand Down Expand Up @@ -226,7 +226,7 @@ module.exports = {
'67-0-setpoint-2'
],
mode_map: { off: 0, heat: 1, cool: 2 },
setpoint_topic: { Heat: '67-0-setpoint-1', Cool: '67-0-setpoint-2' },
setpoint_topic: { 1: '67-0-setpoint-1', 2: '67-0-setpoint-2' },
default_setpoint: '67-0-setpoint-1',
discovery_payload: {
min_temp: 15,
Expand Down
80 changes: 80 additions & 0 deletions lib/Gateway.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,9 @@ function onNodeStatus (node) {
}
}

// check if there are climates to discover
this.discoverClimates(node)

const nodeDevices = allDevices[node.deviceId] || []
nodeDevices.forEach(device => this.discoverDevice(node, device))

Expand Down Expand Up @@ -1145,6 +1148,83 @@ Gateway.prototype.discoverDevice = function (node, hassDevice) {
}
}

/**
* Discover climate devices
*
* @param {NodeObj} node Internal node object
*/
Gateway.prototype.discoverClimates = function (node) {
// https://github.com/zwave-js/node-zwave-js/blob/master/packages/config/config/deviceClasses.json#L177
if (!node.deviceClass.generic === 0x08) { // it's a thermostat
return
}

const nodeDevices = allDevices[node.deviceId] || []

// skip if there is already a climate device
if (nodeDevices.length > 0 && nodeDevices.find(d => d.type === 'climate')) {
return
}

const setpoints = []
const temperatures = []
const modes = []

for (const vId in node.values) {
const v = node.values[vId]
if (v.commandClass === CommandClasses['Thermostat Setpoint'] && v.property === 'setpoint') {
setpoints.push(v)
} else if (v.commandClass === CommandClasses['Multilevel Sensor'] && v.property === 'Air temperature') {
temperatures.push(v)
} else if (v.commandClass === CommandClasses['Thermostat Mode'] && v.property === 'mode') {
modes.push(v)
}
}

const mode = modes[0]
const temperature = temperatures[0]

// [0, 1, 2] ---> ['off', 'heat', 'cold']
const availableModes = mode.states.map(s => s.value)

const hassModes = [ // [“auto”, “off”, “cool”, “heat”, “dry”, “fan_only”]
'off',
'heat',
'cool'
]

const config = copy(hassCfg.thermostat)

config.mode_map = {}
config.setpoint_topic = {}
config.values = [mode.id, temperature.id]

config.discovery_payload.mode_state_topic = mode.id
config.discovery_payload.current_temperature_topic = temperature.id

for (const m of availableModes) {
config.mode_map[hassModes[m]] = availableModes[m]
config.discovery_payload.modes.push(hassModes[m])
if (m > 0) { // find the mode setpoint, ignore off
const setpoint = setpoints.find(v => v.propertyKey === m)
if (setpoint) {
if (setpoint.propertyKey === 1) {
config.default_setpoint = setpoint.id
}

config.values.push(setpoint.id)
config.setpoint_topic[m] = setpoint.id
}
}
}

nodeDevices.push(config)

debug('New climate device discovered: ' + JSON.stringify(config))

allDevices[node.deviceId] = nodeDevices
}

/**
* Try to guess the best way to discover this valueId in Hass
*
Expand Down

0 comments on commit 2d0167e

Please sign in to comment.