Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the fan accessory with two speed ability for Shelly 2 and 2.5 #240

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f13ae1e
Create basic-garage-door-opener.js
MichaelVdheeren Mar 1, 2020
2f70e47
Update garage-door-openers.js
MichaelVdheeren Mar 1, 2020
391064c
Update basic-garage-door-opener.js
MichaelVdheeren Mar 1, 2020
73e4f61
changed to garage-door-switch
MichaelVdheeren Jun 1, 2020
3ee6017
added the garage door switch
MichaelVdheeren Jun 1, 2020
4dbba6a
Change from garageDoorSwitch to GarageDoorOpener
MichaelVdheeren Mar 7, 2021
4325eae
Remove unused property isSwitchedOn from garageDoorSwitch
MichaelVdheeren Mar 7, 2021
cecb408
Remove unnecessary get handlers
MichaelVdheeren Mar 7, 2021
ad9abf9
Fix reference to error-handlers module
MichaelVdheeren Mar 7, 2021
c96e0e9
Adapt to the way services setup is handled now
MichaelVdheeren Mar 7, 2021
2c312d4
Adapt to the way services setup is handled now - continued
MichaelVdheeren Mar 7, 2021
83969d8
Adapt to the way services setup is handled now - continued
MichaelVdheeren Mar 7, 2021
7a85268
Remove calling updateGarageDoorState when we set the switch
MichaelVdheeren Mar 8, 2021
69895c0
add the fan accessory with two speed ability for Shelly 2 and 2.5
MichaelVdheeren Jan 1, 2021
18d82dc
fix to ensure speed is correctly set when activating again
MichaelVdheeren Jan 1, 2021
e9be45a
fix console logging for state changes of the properties
MichaelVdheeren Jan 1, 2021
cacef87
remove unnecessary logging
MichaelVdheeren Jan 1, 2021
ce6e1e5
fix an issue where Siri would return 2%
MichaelVdheeren Jan 1, 2021
336cbe0
fix issues after recent updates of service setup
MichaelVdheeren Mar 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,11 @@ interface of a device, under *Settings -> Device info -> Device ID*.
*Applies to Shelly 1, 1PM, 2 and 2.5 in relay mode, 4Pro, EM, Plug and Plug S.*
* `"type"` - sets the type of accessory the device is identified as. Available
types are `"contactSensor"`, `"motionSensor"`, `"occupancySensor"`,
`"outlet"`, `"switch"` (default) and `"valve"`.
`"outlet"`, `"switch"` (default), `"fan"` and `"valve"`.

#### Additional Shelly 2 and 2.5 switch configurations
*Applies to Shelly 2 and 2.5 in relay mode*
* `"type"` - sets the type of accessory the device is identified as. If the fan type is set, each of the outputs triggers a different fan speed.

#### Shelly 2.5 configurations
* `"type"` - in roller mode, the device can be identified as either `"door"`,
Expand Down
190 changes: 190 additions & 0 deletions abilities/garage-door-switch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
const { handleFailedRequest } = require('../util/error-handlers')

module.exports = homebridge => {
const { Ability } = require('./base')(homebridge)
const Characteristic = homebridge.hap.Characteristic
const Service = homebridge.hap.Service

class GarageDoorSwitchAbility extends Ability {
/**
* @param {string} switchProperty - The device property to trigger the
* garage door to open or close.
* @param {string} stateProperty - The device property used to indicate the
* garage door is closed.
* @param {function} setSwitch - A function that updates the device's switch
* state. Must return a Promise.
*/
constructor(switchProperty, stateProperty, setSwitch) {
super()
this._switchProperty = switchProperty
this._stateProperty = stateProperty
this._setSwitch = setSwitch
this._targetState = null
}

get service() {
return this.platformAccessory.getService(Service.GarageDoorOpener)
}

get state() {
return this.device[this._stateProperty] || 0
}

get currentState() {
const CDS = Characteristic.CurrentDoorState

if (this.state > 0) {
return CDS.CLOSED
}

return CDS.OPEN
}

get targetState() {
if (this._targetState !== null) {
return this._targetState
}

const CDS = Characteristic.CurrentDoorState
const TDS = Characteristic.TargetDoorState
const cs = this.currentState
return cs === CDS.OPEN || cs === CDS.OPENING ? TDS.OPEN : TDS.CLOSED
}

_createService() {
const CDS = Characteristic.CurrentDoorState
const TDS = Characteristic.TargetDoorState

return new Service.GarageDoorOpener()
.setCharacteristic(CDS, this.currentState)
.setCharacteristic(TDS, TDS.CLOSED)
.setCharacteristic(Characteristic.ObstructionDetected, false)
}

_setupEventHandlers() {
super._setupEventHandlers()

// This is the handler to catch HomeKit events
this.service
.getCharacteristic(Characteristic.TargetDoorState)
.on('set', this._targetDoorStateSetHandler.bind(this))

// This is the handler to catch device events
// This one is always correct!
this.device
.on(
'change:' + this._stateProperty,
this._stateChangeHandler,
this
)
}

/**
* Handles changes from HomeKit to the TargetDoorState characteristic.
*/
async _targetDoorStateSetHandler(newValue, callback, context) {
const d = this.device

// If the context is shelly then this is an internal update
// to ensure that homekit is in sync with the current status
// If not, we really trigger the switch
if (context === 'shelly') {
callback()
return
}

this._targetState = newValue

this.log.debug(
'Target homekit state is',
newValue
)

this.log.debug(
'Setting',
this._switchProperty,
'of device',
d.type,
d.id,
'to',
true
)

try {
await this._setSwitch(true)
callback()
} catch (e) {
handleFailedRequest(
this.log,
d,
e,
'Failed to set ' + this._switchProperty
)
callback(e)
}
}

/**
* Handles changes from the device to the state property.
* This means either the garage door just closed or it has started to open.
*/
_stateChangeHandler(newValue) {
this.log.debug(
this._stateProperty,
'of device',
this.device.type,
this.device.id,
'changed to',
newValue
)

this.updateGarageDoorState()
}

updateGarageDoorState() {
const CDS = Characteristic.CurrentDoorState
const TDS = Characteristic.TargetDoorState

if (this.currentState === CDS.CLOSED) {
this.service
.getCharacteristic(TDS)
.setValue(TDS.CLOSED, null, 'shelly')
this.service
.setCharacteristic(CDS, CDS.CLOSING)

setTimeout(() => {
this.service
.setCharacteristic(CDS, CDS.CLOSED)
}, 1000)
} else {
this.service
.getCharacteristic(TDS)
.setValue(TDS.OPEN, null, 'shelly')
this.service
.setCharacteristic(CDS, CDS.OPENING)

setTimeout(() => {
this.service
.setCharacteristic(CDS, CDS.OPEN)
}, 1000)
}
}

getState(callback) {
callback(null, this.currentState)
}

detach() {
this.device
.removeListener(
'change:' + this._stateProperty,
this._stateChangeHandler,
this
)

super.detach()
}
}

return GarageDoorSwitchAbility
}
Loading