-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathpimatic-ifttt.coffee
154 lines (118 loc) · 4.32 KB
/
pimatic-ifttt.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# https://github.com/fcingolani/node-ifttt
module.exports = (env) ->
# Require the [bluebird](https://github.com/petkaantonov/bluebird) promise library.
Promise = env.require 'bluebird'
# Require the [cassert library](https://github.com/rhoot/cassert).
assert = env.require 'cassert'
# Matcher for autocompletion of rules
M = env.matcher
# Utility library [lodash](http://lodash.com).
_ = env.require 'lodash'
# ###IFTTTPlugin class
class IFTTTPlugin extends env.plugins.Plugin
# ####init()
#
# #####params:
# * `app` is the [express] instance the framework is using.
# * `framework` the framework itself
# * `config` the properties the user specified as config for your plugin in the `plugins`
# section of the config.json file
#
#
init: (app, @framework, @config) =>
deviceConfigDef = require("./device-config-schema")
# Add the predicate provider to enable the following rules:
# IF my-ifttt-device is triggered
# IF my-ifttt-device is waiting
@framework.ruleManager.addPredicateProvider(new IFTTTTriggerPredicateProvider(@framework))
@framework.deviceManager.registerDeviceClass("IFTTTDevice", {
configDef: deviceConfigDef.IFTTTDevice,
createCallback: (config) =>
device = new IFTTTDevice(config)
return device
})
# ###IFTTTDevice class
class IFTTTDevice extends env.devices.Device
_triggerState: false
actions:
trigger:
description: "triggers the switch"
attributes:
triggerState:
description: "state of the trigger"
type: "boolean"
labels: ['triggered', 'waiting']
# Default Device constructor
constructor: (@config) ->
@name = @config.name
@id = @config.id
super()
# This action-method is dynamically added to the REST API. Use
# http://<URL:PORT>/api/device/<device-id>/trigger
trigger: ->
@_setTriggerState(true)
@_setTriggerState(false)
_setTriggerState: (value) ->
if @_triggerState is value then return
@_triggerState = value
@emit 'triggerState', value
getTriggerState: -> Promise.resolve(@_triggerState)
# ###IFTTTTriggerPredicateProvider class
class IFTTTTriggerPredicateProvider extends env.predicates.PredicateProvider
constructor: (@framework) ->
parsePredicate: (input, context) ->
# Get all IFTTTDevices to apply the predicate.
iftttDevices =
_(@framework.deviceManager.devices).values()
.filter((device) => device instanceof IFTTTDevice).value()
device = null
negated = null
match = null
# Autocomplete filter used by matcher.
iftttFilter = (v) => v.trim() in ["triggered", "waiting"]
M(input, context)
.matchDevice(iftttDevices, (next, d) =>
next.match(" is")
.match([" triggered", " waiting"], {acFilter: iftttFilter},(m,s) =>
# Already had a match with another device?
if device? and device.id isnt d.id
context?.addError(""""#{input.trim()}" is ambiguous.""")
return
device = d
negated = (s.trim() is "waiting")
match = m.getFullMatch()
)
)
if match?
assert device?
assert negated?
assert typeof match is "string"
return {
token: match
nextInput: input.substring(match.length)
predicateHandler: new IFTTTTriggerPredicateHandler(device, negated)
}
else
return null
# ###IFTTTTriggerPredicateProvider class
class IFTTTTriggerPredicateHandler extends env.predicates.PredicateHandler
constructor: (@device, @negated) ->
setup: ->
@triggerListener = (p) =>
@emit 'change', (if @negated then not p else p)
@device.on 'triggerState', @triggerListener
super()
getValue: ->
@device.getUpdatedAttributeValue('triggerState').then(
(p) => (if @negated then not p else p)
)
destroy: ->
@device.removeListener "triggerState", @triggerListener
super()
getType: -> 'state'
# ###Finally
# Create a instance of the plugin...
ifttt = new IFTTTPlugin
ifttt.IFTTTDevice = IFTTTDevice
# ...and return it to the framework.
return ifttt