homebridge-deconz
Version:
Homebridge plugin for deCONZ
206 lines (182 loc) • 6.4 kB
JavaScript
// homebridge-deconz/lib/DeconzService/AirPurifier.js
// Copyright © 2022-2026 Erik Baauw. All rights reserved.
//
// Homebridge plugin for deCONZ.
import { DeconzService } from '../DeconzService/index.js'
import '../DeconzService/SensorsResource.js'
class FilterMaintenance extends DeconzService.SensorsResource {
constructor (accessory, resource, params = {}) {
params.Service = accessory.Services.hap.FilterMaintenance
super(accessory, resource, params)
this.addCharacteristicDelegate({
key: 'filterChange',
Characteristic: this.Characteristics.hap.FilterChangeIndication
})
if (
resource.body.config.filterlifetime !== undefined &&
resource.body.state.filterruntime !== undefined
) {
this.addCharacteristicDelegate({
key: 'filterLifeLevel',
Characteristic: this.Characteristics.hap.FilterLifeLevel,
unit: '%'
})
this.addCharacteristicDelegate({
key: 'resetFilter',
Characteristic: this.Characteristics.hap.ResetFilterIndication,
props: { adminOnlyAccess: [this.Characteristic.Access.WRITE] },
value: 0
}).on('didSet', async (value, fromHomeKit) => {
await this.put('/config', { filterlifetime: 6 * 30 * 24 * 60 })
})
this.values.filterLifeTime = resource.body.config.filterlifetime
}
this.update(resource.body, resource.rpath)
}
updateState (state) {
if (this.values.filterLifeTime != null && state.filterruntime != null) {
this.values.filterLifeLevel = 100 - Math.round(
100 * state.filterruntime / this.values.filterLifeTime
)
}
if (state.replacefilter != null) {
this.values.filterChange = state.replacefilter
? this.Characteristics.hap.FilterChangeIndication.CHANGE_FILTER
: this.Characteristics.hap.FilterChangeIndication.FILTER_OK
}
}
updateConfig (config) {
if (config.filterlifetime != null) {
this.values.filterLifeTime = config.filterlifetime
}
}
}
/**
* @memberof DeconzService
*/
class AirPurifier extends DeconzService.SensorsResource {
constructor (accessory, resource, params = {}) {
params.Service = accessory.Services.hap.AirPurifier
super(accessory, resource, params)
this.addCharacteristicDelegate({
key: 'active',
Characteristic: this.Characteristics.hap.Active
}).on('didSet', async (value, fromHomeKit) => {
if (fromHomeKit) {
await this.put('/config', { mode: this.modeValue(value) })
}
})
this.addCharacteristicDelegate({
key: 'currentState',
Characteristic: this.Characteristics.hap.CurrentAirPurifierState
})
this.addCharacteristicDelegate({
key: 'targetState',
Characteristic: this.Characteristics.hap.TargetAirPurifierState
}).on('didSet', async (value, fromHomeKit) => {
if (fromHomeKit) {
await this.put('/config', { mode: this.modeValue(null, value) })
}
})
this.addCharacteristicDelegate({
key: 'rotationSpeed',
Characteristic: this.Characteristics.hap.RotationSpeed,
unit: '%'
}).on('didSet', async (value, fromHomeKit) => {
if (fromHomeKit) {
await this.put('/config', { mode: this.modeValue(null, null, value) })
}
})
if (resource.body.state.airquality !== undefined) {
this.airQualityService = new DeconzService.AirQuality(accessory, resource, {
linkedServiceDelegate: this
})
}
if (resource.body.state.replacefilter !== undefined) {
this.filterService = new FilterMaintenance(accessory, resource, {
linkedServiceDelegate: this
})
}
if (resource.body.state.deviceruntime !== undefined) {
// TODO
}
if (resource.body.config.ledindication !== undefined) {
// TODO
}
if (resource.body.config.locked !== undefined) {
this.addCharacteristicDelegate({
key: 'lockPhysicalControls',
Characteristic: this.Characteristics.hap.LockPhysicalControls
}).on('didSet', async (value, fromHomeKit) => {
if (fromHomeKit) {
await this.put('/config', {
locked: value === this.Characteristics.hap.LockPhysicalControls
.CONTROL_LOCK_ENABLED
})
}
})
}
super.addCharacteristicDelegates()
this.update(resource.body, resource.rpath)
}
modeValue (
active = this.values.active,
targetState = this.values.targetState,
rotationSpeed = this.values.rotationSpeed
) {
if (active === this.Characteristics.hap.Active.INACTIVE) {
return 'off'
}
if (
targetState === this.Characteristics.hap.TargetAirPurifierState.AUTO ||
rotationSpeed === 0
) {
return 'auto'
}
return 'speed_' + Math.round(rotationSpeed / 20)
}
updateState (state) {
if (state.speed != null) {
this.values.active = state.speed > 0
? this.Characteristics.hap.Active.ACTIVE
: this.Characteristics.hap.Active.INACTIVE
this.values.currentState = state.speed === 0
? this.Characteristics.hap.CurrentAirPurifierState.INACTIVE
: this.Characteristics.hap.CurrentAirPurifierState.PURIFYING_AIR
this.values.rotationSpeed = state.speed
}
super.updateState(state)
if (this.airQualityService != null) {
this.airQualityService.updateState(state)
}
if (this.filterService != null) {
this.filterService.updateState(state)
}
}
updateConfig (config) {
if (config.filterlifetime != null) {
this.values.filterLifeTime = config.filterlifetime
}
if (config.ledindication != null) {
// TODO
}
if (config.locked != null) {
this.values.lockPhysicalControls = config.locked
? this.Characteristics.hap.LockPhysicalControls.CONTROL_LOCK_ENABLED
: this.Characteristics.hap.LockPhysicalControls.CONTROL_LOCK_DISABLED
}
if (config.mode != null) {
this.values.targetState = config.mode === 'auto'
? this.Characteristics.hap.TargetAirPurifierState.AUTO
: this.Characteristics.hap.TargetAirPurifierState.MANUAL
}
super.updateConfig(config)
if (this.airQualityService != null) {
this.airQualityService.updateConfig(config)
}
if (this.filterService != null) {
this.filterService.updateConfig(config)
}
}
}
DeconzService.AirPurifier = AirPurifier