-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from jxg81/fan-only-mode-support
Fan only mode support
- Loading branch information
Showing
12 changed files
with
439 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
#test data | ||
neo.json | ||
|
||
# Ignore compiled code | ||
dist | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
import { Service, PlatformAccessory, CharacteristicValue, HAPStatus } from 'homebridge'; | ||
import { ClimateMode, FanMode, PowerState } from './types'; | ||
import { ActronQuePlatform } from './platform'; | ||
|
||
// This class represents the master controller | ||
export class FanOnlyMasterAccessory { | ||
private fanService: Service; | ||
|
||
constructor( | ||
private readonly platform: ActronQuePlatform, | ||
private readonly accessory: PlatformAccessory, | ||
) { | ||
|
||
// set accessory information | ||
this.accessory.getService(this.platform.Service.AccessoryInformation)! | ||
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'Actron') | ||
.setCharacteristic(this.platform.Characteristic.Model, this.platform.hvacInstance.type + ' FanOnlyMaster') | ||
.setCharacteristic(this.platform.Characteristic.SerialNumber, this.platform.hvacInstance.serialNo); | ||
|
||
// Get or create the fan service. | ||
this.fanService = this.accessory.getService(this.platform.Service.Fanv2) | ||
|| this.accessory.addService(this.platform.Service.Fanv2); | ||
|
||
// Set accessory display name, this is taken from discover devices in platform | ||
this.fanService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName); | ||
|
||
// register handlers for device control, references the class methods that follow for Set and Get | ||
this.fanService.getCharacteristic(this.platform.Characteristic.Active) | ||
.onSet(this.setPowerState.bind(this)) | ||
.onGet(this.getPowerState.bind(this)); | ||
|
||
this.fanService.getCharacteristic(this.platform.Characteristic.RotationSpeed) | ||
.onSet(this.setFanMode.bind(this)) | ||
.onGet(this.getFanMode.bind(this)); | ||
|
||
setInterval(() => this.softUpdateDeviceCharacteristics(), this.platform.softRefreshInterval); | ||
|
||
} | ||
|
||
// SET's are async as these need to wait on API response then cache the return value on the hvac Class instance | ||
// GET's run non async as this is a quick retrieval from the hvac class instance cache | ||
// UPDATE is run Async as this polls the API first to confirm current cache state is accurate | ||
async softUpdateDeviceCharacteristics() { | ||
this.fanService.updateCharacteristic(this.platform.Characteristic.Active, this.getPowerState()); | ||
this.fanService.updateCharacteristic(this.platform.Characteristic.RotationSpeed, this.getFanMode()); | ||
} | ||
|
||
checkHvacComms() { | ||
if (!this.platform.hvacInstance.cloudConnected) { | ||
this.platform.log.error('Master Controller is offline. Check Master Controller Internet/Wifi connection'); | ||
throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE); | ||
} | ||
} | ||
|
||
async setPowerState(value: CharacteristicValue) { | ||
this.checkHvacComms(); | ||
switch (value) { | ||
case 0: | ||
await this.platform.hvacInstance.setPowerStateOff(); | ||
break; | ||
case 1: | ||
// If the fan only mode is not running, switch climate mode to fan instead of sending power on event | ||
if (this.platform.hvacInstance.climateMode !== ClimateMode.FAN) { | ||
await this.platform.hvacInstance.setClimateModeFan(); | ||
} | ||
// If power state is not ON - Turn on | ||
if (this.platform.hvacInstance.powerState !== PowerState.ON) { | ||
await this.platform.hvacInstance.setPowerStateOn(); | ||
} | ||
break; | ||
} | ||
this.platform.log.debug('Set FanOnlyMaster Power State -> ', value); | ||
} | ||
|
||
getPowerState(): CharacteristicValue { | ||
// Check climate mode, if it is any value other than FAN then we are not in fan-only mode | ||
// If it is FAN then we need to check if the system is powered on | ||
let powerState: number; | ||
const climateMode = this.platform.hvacInstance.climateMode; | ||
switch (climateMode) { | ||
case ClimateMode.FAN: | ||
powerState = (this.platform.hvacInstance.powerState === PowerState.ON) ? 1 : 0; | ||
break; | ||
default: | ||
powerState = 0; | ||
} | ||
this.platform.log.debug('Got FanOnlyMaster Power State -> ', powerState); | ||
return powerState; | ||
} | ||
|
||
async setFanMode(value: CharacteristicValue) { | ||
this.checkHvacComms(); | ||
switch (true) { | ||
case (+value <= 10): | ||
await this.platform.hvacInstance.setFanModeAuto(); | ||
break; | ||
case (+value <= 30): | ||
await this.platform.hvacInstance.setFanModeLow(); | ||
break; | ||
case (+value <= 65): | ||
await this.platform.hvacInstance.setFanModeMedium(); | ||
break; | ||
case (+value <= 100): | ||
await this.platform.hvacInstance.setFanModeHigh(); | ||
break; | ||
} | ||
this.platform.log.debug('Set FanOnlyMaster Fan Mode 1-10:Auto, 11-30:Low, 31-65:Medium, 66-100:High -> ', value); | ||
} | ||
|
||
getFanMode(): CharacteristicValue { | ||
let currentMode: number; | ||
const fanMode = this.platform.hvacInstance.fanMode; | ||
switch (fanMode) { | ||
case FanMode.AUTO || FanMode.AUTO_CONT: | ||
currentMode = 10; | ||
break; | ||
case FanMode.LOW || FanMode.LOW_CONT: | ||
currentMode = 25; | ||
break; | ||
case FanMode.MEDIUM || FanMode.MEDIUM_CONT: | ||
currentMode = 50; | ||
break; | ||
case FanMode.HIGH || FanMode.HIGH_CONT: | ||
currentMode = 100; | ||
break; | ||
default: | ||
currentMode = 0; | ||
this.platform.log.debug('Failed To Get FanOnlyMaster Current Fan Mode -> ', fanMode); | ||
} | ||
this.platform.log.debug('Got FanOnlyMaster Current Fan Mode -> ', fanMode); | ||
return currentMode; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { Service, PlatformAccessory, CharacteristicValue, HAPStatus } from 'homebridge'; | ||
import { ClimateMode } from './types'; | ||
import { ActronQuePlatform } from './platform'; | ||
import { HvacZone } from './hvacZone'; | ||
|
||
// This class represents the zone controller | ||
export class FanOnlyZoneAccessory { | ||
private fanService: Service; | ||
|
||
constructor( | ||
private readonly platform: ActronQuePlatform, | ||
private readonly accessory: PlatformAccessory, | ||
private readonly zone: HvacZone, | ||
) { | ||
|
||
// set accessory information | ||
this.accessory.getService(this.platform.Service.AccessoryInformation)! | ||
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'Actron') | ||
.setCharacteristic(this.platform.Characteristic.Model, this.platform.hvacInstance.type + ' FanOnlyZone') | ||
.setCharacteristic(this.platform.Characteristic.SerialNumber, this.zone.sensorId); | ||
|
||
// Get or create the fan service. | ||
this.fanService = this.accessory.getService(this.platform.Service.Fanv2) | ||
|| this.accessory.addService(this.platform.Service.Fanv2); | ||
|
||
// Set accessory display name, this is taken from discover devices in platform | ||
this.fanService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName); | ||
|
||
// register handlers for device control, references the class methods that follow for Set and Get | ||
this.fanService.getCharacteristic(this.platform.Characteristic.Active) | ||
.onSet(this.setEnableState.bind(this)) | ||
.onGet(this.getEnableState.bind(this)); | ||
|
||
|
||
setInterval(() => this.softUpdateDeviceCharacteristics(), this.platform.softRefreshInterval); | ||
|
||
} | ||
|
||
// SET's are async as these need to wait on API response then cache the return value on the hvac Class instance | ||
// GET's run non async as this is a quick retrieval from the hvac class instance cache | ||
// UPDATE is run Async as this polls the API first to confirm current cache state is accurate | ||
async softUpdateDeviceCharacteristics() { | ||
this.fanService.updateCharacteristic(this.platform.Characteristic.Active, this.getEnableState()); | ||
} | ||
|
||
checkHvacComms() { | ||
if (!this.platform.hvacInstance.cloudConnected) { | ||
this.platform.log.error('Master Controller is offline. Check Master Controller Internet/Wifi connection'); | ||
throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE); | ||
} | ||
} | ||
|
||
async setEnableState(value: CharacteristicValue) { | ||
this.checkHvacComms(); | ||
switch (value) { | ||
case 0: | ||
await this.zone.setZoneDisable(); | ||
break; | ||
case 1: | ||
// If the fan only mode is not running, switch climate mode to fan instead of sending enable event | ||
if (this.platform.hvacInstance.climateMode !== ClimateMode.FAN) { | ||
await this.platform.hvacInstance.setClimateModeFan(); | ||
} | ||
// after checking mode, check if the state is enabled or not | ||
if (this.zone.zoneEnabled === false) { | ||
await this.zone.setZoneEnable(); | ||
} | ||
break; | ||
} | ||
this.platform.log.debug(`Set FanOnlyZone ${this.zone.zoneName} Enable State -> `, value); | ||
} | ||
|
||
getEnableState(): CharacteristicValue { | ||
// Check climate mode, if it is any value other than FAN then we are not in fan-only mode | ||
// If it is FAN then we need to check if the zone is enabled | ||
let enableState: number; | ||
const climateMode = this.platform.hvacInstance.climateMode; | ||
switch (climateMode) { | ||
case ClimateMode.FAN: | ||
enableState = (this.zone.zoneEnabled === true) ? 1 : 0; | ||
break; | ||
default: | ||
enableState = 0; | ||
} | ||
this.platform.log.debug(`Got FanOnlyZone ${this.zone.zoneName} Enable State -> `, enableState); | ||
return enableState; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.