Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
support multi instance nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
mike182uk committed Dec 5, 2019
1 parent 3bcbf4b commit 0901f4c
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 13 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ If you do not have a `platforms` section in your Homebridge config you will need
`accessories` is where you will map a ZWave node to a HomeKit accessory. To define an accessory the information needed is:

- `zwaveNodeId` - the ID of the node in the ZWave network that this accessory is for
- `zwaveNodeInstance` - the instance on the node (for a node with multiple instances)
- `displayName` - the name that will be used for this accessory
- `homekitCategory` - the type of accessory HomeKit will see this accessory as. Supported categories are:
- `Outlet`
Expand Down
27 changes: 19 additions & 8 deletions lib/AccessoryManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,14 @@ class AccessoryManager {
})

// Update the accessory information service with the latest ZWave node information
const zwaveNodeId = accessoryConfig.zwaveNodeId
const { zwaveNodeId, zwaveNodeInstance } = accessoryConfig

this._zwave.onNodeReady(zwaveNodeId, zwaveNode => {
this._accessoryReadyState = READY_STATE_READY

const { value: serialNumber } = this._zwave.findNodeValue(zwaveNodeId, {
class_id: COMMAND_CLASS_MANUFACTURER_SPECIFIC,
instance: zwaveNodeInstance,
index: MANUFACTURER_SPECIFIC_INDEX_SERIAL_NUMBER
})

Expand Down Expand Up @@ -253,13 +254,14 @@ class AccessoryManager {
*/
_configureMotionSensorService () {
const accessoryDisplayName = this._accessory.displayName
const zwaveNodeId = this._accessoryConfig.zwaveNodeId
const { zwaveNodeId, zwaveNodeInstance } = this._accessoryConfig

const service = this._getService(this._hapService.MotionSensor)
const motionDetectedCharacteristic = service.getCharacteristic(this._hapCharacteristic.MotionDetected)
const statusTamperedCharacteristic = service.getCharacteristic(this._hapCharacteristic.StatusTampered)
const zwaveNodeValueCriteria = {
commandClass: COMMAND_CLASS_ALARM,
valueInstance: zwaveNodeInstance,
valueIndex: ALARM_INDEX_HOME_SECURITY
}
const zwaveNodeValueResolver = this._makeZwaveNodeValueResolver(zwaveNodeValueCriteria)
Expand Down Expand Up @@ -349,7 +351,7 @@ class AccessoryManager {
*/
_configureBatteryService () {
const accessoryDisplayName = this._accessory.displayName
const zwaveNodeId = this._accessoryConfig.zwaveNodeId
const { zwaveNodeId, zwaveNodeInstance } = this._accessoryConfig

const batteryService = this._getService(this._hapService.BatteryService)
const batteryLevelCharacteristic = batteryService.getCharacteristic(this._hapCharacteristic.BatteryLevel)
Expand Down Expand Up @@ -390,16 +392,19 @@ class AccessoryManager {
const statusLowBatteryCharacteristicZwaveNodeValueResolver = () => {
const { value: batteryLevel } = this._zwave.findNodeValue(zwaveNodeId, {
class_id: COMMAND_CLASS_BATTERY,
instance: zwaveNodeInstance,
index: BATTERY_INDEX_LEVEL
})

const { value: currentPowerMode } = this._zwave.findNodeValue(zwaveNodeId, {
class_id: COMMAND_CLASS_CONFIGURATION,
instance: zwaveNodeInstance,
index: CONFIGURATION_INDEX_CURRENT_POWER_MODE
})

const { value: minBatteryLevel } = this._zwave.findNodeValue(zwaveNodeId, {
class_id: COMMAND_CLASS_CONFIGURATION,
instance: zwaveNodeInstance,
index: CONFIGURATION_INDEX_LOW_BATTERY
})

Expand All @@ -423,6 +428,7 @@ class AccessoryManager {
const batteryLevelCharacteristicZwaveNodeValueId = this._zwave.generateNodeValueId({
nodeId: zwaveNodeId,
commandClass: COMMAND_CLASS_BATTERY,
valueInstance: zwaveNodeInstance,
valueIndex: BATTERY_INDEX_LEVEL
})

Expand All @@ -436,11 +442,13 @@ class AccessoryManager {
// Check if we need to update the "Status Low Battery" characteristic
const { value: currentPowerMode } = this._zwave.findNodeValue(zwaveNodeId, {
class_id: COMMAND_CLASS_CONFIGURATION,
instance: zwaveNodeInstance,
index: CONFIGURATION_INDEX_CURRENT_POWER_MODE
})

const { value: minBatteryLevel } = this._zwave.findNodeValue(zwaveNodeId, {
class_id: COMMAND_CLASS_CONFIGURATION,
instance: zwaveNodeInstance,
index: CONFIGURATION_INDEX_LOW_BATTERY
})

Expand Down Expand Up @@ -546,15 +554,16 @@ class AccessoryManager {
/**
* Create a ZWave node value resolver
*
* @param {{commandClass: number, valueIndex: number}} zwaveNodeValueCriteria
* @param {{commandClass: number, valueInstance: number, valueIndex: number}} zwaveNodeValueCriteria
* @returns {Function}
*/
_makeZwaveNodeValueResolver ({ commandClass, valueIndex }) {
_makeZwaveNodeValueResolver ({ commandClass, valueInstance, valueIndex }) {
return () => {
const zwaveNodeId = this._accessoryConfig.zwaveNodeId
const { zwaveNodeId, zwaveNodeInstance } = this._accessoryConfig

const { value } = this._zwave.findNodeValue(zwaveNodeId, {
class_id: commandClass,
instance: valueInstance || zwaveNodeInstance,
index: valueIndex
})

Expand All @@ -577,11 +586,12 @@ class AccessoryManager {
) {
return (value, done) => {
const accessoryDisplayName = this._accessoryConfig.displayName
const zwaveNodeId = this._accessoryConfig.zwaveNodeId
const { zwaveNodeId, zwaveNodeInstance } = this._accessoryConfig
const newValue = valueFilter(value)
const nodeValueId = this._zwave.generateNodeValueId({
nodeId: zwaveNodeId,
commandClass,
valueInstance: zwaveNodeInstance,
valueIndex
})

Expand Down Expand Up @@ -616,10 +626,11 @@ class AccessoryManager {
valueFilter = v => v
) {
const accessoryDisplayName = this._accessoryConfig.displayName
const zwaveNodeId = this._accessoryConfig.zwaveNodeId
const { zwaveNodeId, zwaveNodeInstance } = this._accessoryConfig
const nodeValueId = this._zwave.generateNodeValueId({
nodeId: zwaveNodeId,
commandClass,
valueInstance: zwaveNodeInstance,
valueIndex
})

Expand Down
19 changes: 18 additions & 1 deletion lib/Platform.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ module.exports = (pluginName, platformName, homebridge) => {
this._accessories = new Map()
this._redundantCachedAccessories = []

// Set default config values
this._setConfigDefaults()

// Validate the config - We validate the config here so that configureAccessory
// will not get executed if the config is invalid
try {
Expand Down Expand Up @@ -98,6 +101,7 @@ module.exports = (pluginName, platformName, homebridge) => {
_validateConfig () {
const accessoryConfigSchema = Joi.object().keys({
zwaveNodeId: Joi.number().integer().required(),
zwaveNodeInstance: Joi.number().integer().optional(),
displayName: Joi.string().required(),
homekitCategory: Joi.string().valid(['Outlet', 'Sensor', 'Switch']).required(),
homekitServices: Joi.array()
Expand Down Expand Up @@ -134,6 +138,19 @@ module.exports = (pluginName, platformName, homebridge) => {
Joi.assert(this._config, configSchema)
}

/**
* Set default config values
*/
_setConfigDefaults () {
this._config.accessories = this._config.accessories.map(accessoryConfig => {
if (!accessoryConfig.zwaveNodeInstance) {
accessoryConfig.zwaveNodeInstance = 1
}

return accessoryConfig
})
}

/**
* Initialize the platform
*/
Expand Down Expand Up @@ -226,7 +243,7 @@ module.exports = (pluginName, platformName, homebridge) => {
* @returns {string}
*/
_generateAccessoryUUID (accessoryConfig) {
return homebridge.hap.uuid.generate(`${accessoryConfig.zwaveNodeId}-${accessoryConfig.displayName}`)
return homebridge.hap.uuid.generate(`${accessoryConfig.zwaveNodeId}-${accessoryConfig.zwaveNodeInstance}-${accessoryConfig.displayName}`)
}
}

Expand Down
4 changes: 0 additions & 4 deletions lib/ZWave.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ class ZWave {
* @returns {Object}
*/
findNodeValue (nodeId, criteria) {
// For convenience, assume instance is 1 unless told otherwise
criteria = Object.assign({ instance: 1 }, criteria)

const node = this._nodes.get(nodeId)

return Array.from(node.values.values())
Expand Down Expand Up @@ -122,7 +119,6 @@ class ZWave {
* @returns {string}
*/
generateNodeValueId ({ nodeId, commandClass, valueInstance, valueIndex }) {
valueInstance = valueInstance || 1
valueIndex = valueIndex || 0

return `${nodeId}-${commandClass}-${valueInstance}-${valueIndex}`
Expand Down

0 comments on commit 0901f4c

Please sign in to comment.