Hi!
So two years ago I needed a way to disable a device from a rule, and I’m actually still in need for this functionality. And since I now have more knowledge about the Pimatic code I was thinking about implementing this myself.
I would like to have this eventually implemented in the Pimatic core, so a good understanding on how I’m thinking to implement this and agreeing on the matter is needed.
This is what I propose:
A device which supports enable/disable would implement two actions:
actions:
enable:
description: ''
disable:
description: ''
enable: ->
if !@_enabled
@_enabled = true
@emit 'enabled', @_enabled
# Device specific things if needed
disable: ->
if @_enabled
@_enabled = false
@emit 'disabled', @_enabled
# Device specific things if needed
Then other actions in the Device would need to check if the Device is enabled and act accordingly. Like:
turnOn: ->
if @_enabled
# Device specific code
turnOff: ->
if @_enabled
# Device specific code
Then an ActionProvider and ActionHandler would be implemented to handle rules like:
when <something> then enable device <device>
when <something> then disable device <device>
This implementation would look like:
_ = require 'lodash'
M = env.matcher
class DisableDeviceActionProvider extends env.actions.ActionProvider
constructor: (@framework) ->
parseAction: (input, context) =>
# Get all devices which have a disable method
disableDevices = _(@framework.deviceManager.devices).values().filter(
(device) => device.hasAction('disable')
).value()
device = null
action = null
match = null
# Match action
# [enable, disable] device <device>
m = M(input, context)
.match(['enable', 'disable'], (m, _action) ->
m.match('device ')
.matchDevice(disableDevices, (m, _device) ->
device = _device
action = _action
match = m.getFullMatch()
)
)
# Does the action match with our syntax?
if match?
assert device?
assert action?
assert typeof match is "string"
return {
token: match
nextInput: input.substring match.length
actionHandler: new DisableDeviceActionHandler @framework, device, action
}
return null
class DisableDeviceActionHandler extends env.actions.ActionHandler
constructor: (@framework, @device, @action) ->
executeAction: (simulate) ->
return (
if simulate
if @action in ['enable', 'disable']
Promise.resolve __('would %s device %s', @action, @device.name)
else
# Error handling
else
if @action = 'enable'
@device.enable()
else if @action = 'disable'
@device.disable()
else
# Error handling
Promise.resolve __('%s device %s', @action, @device.name)
)
)
Then the last remaining part would be the GUI, greying out the specific Device. I know nothing about the GUI, however I would assume that there could be a CCS style .enabled and .disabled implemented.
What are your thoughts on this?