-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgpio.coffee
165 lines (128 loc) · 4.52 KB
/
gpio.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
155
156
157
158
159
160
161
162
163
164
165
module.exports = (env) ->
# pimatic imports.
Promise = env.require 'bluebird'
assert = env.require 'cassert'
_ = env.require 'lodash'
Gpio = require('onoff').Gpio
class GpioPlugin extends env.plugins.Plugin
init: (app, @framework, @config) ->
deviceConfigDef = require("./device-config-schema")
@framework.deviceManager.registerDeviceClass("GpioPresence", {
configDef: deviceConfigDef.GpioPresence,
createCallback: (config, lastState) => new GpioPresence(config, lastState)
})
@framework.deviceManager.registerDeviceClass("GpioContact", {
configDef: deviceConfigDef.GpioContact,
createCallback: (config, lastState) => new GpioContact(config, lastState)
})
@framework.deviceManager.registerDeviceClass("GpioSwitch", {
configDef: deviceConfigDef.GpioSwitch,
createCallback: (config, lastState) => new GpioSwitch(config, lastState)
})
plugin = new GpioPlugin
class GpioSwitch extends env.devices.PowerSwitch
constructor: (@config, lastState) ->
@name = @config.name
@id = @config.id
if @config.defaultState?
@_state = @config.defaultState
else
@_state = lastState?.state?.value or false
stateToSet = (if @config.inverted then not @_state else @_state)
options =
debounceTimeout: @config.debounceTimeout if @config.debounceTimeout?
@gpio = new Gpio @config.gpio, (if stateToSet then "high" else "low"), options
super()
destroy: () ->
@gpio.unwatchAll()
@gpio.unexport()
super()
getState: () ->
if @_state? then Promise.resolve @_state
@gpio.read().then( (value) =>
_state = (if value is 1 then yes else no)
if @config.inverted then @_state = not _state
else @_state = _state
return @_state
)
changeStateTo: (state) ->
assert state is on or state is off
if @config.inverted then _state = not state
else _state = state
@gpio.write(if _state then 1 else 0).then( () =>
@_setState(state)
)
# ##GpioContact Sensor
class GpioContact extends env.devices.ContactSensor
constructor: (@config, lastState) ->
@id = @config.id
@name = @config.name
options =
debounceTimeout: @config.debounceTimeout if @config.debounceTimeout?
@gpio = new Gpio(@config.gpio, 'in', 'both', options)
@_contact = lastState?.contact?.value or false
@_readContactValue().catch( (error) =>
env.logger.error error.message
env.logger.debug error.stack
)
@gpio.watch (err, value) =>
if err?
env.logger.error err.message
env.logger.debug err.stack
else
@_setContactValue value
super()
destroy: () ->
@gpio.unwatchAll()
@gpio.unexport()
super()
_setContactValue: (value) ->
assert value is 1 or value is 0
state = (if value is 1 then yes else no)
if @config.inverted then state = not state
@_setContact state
_readContactValue: ->
@gpio.read().then( (value) =>
@_setContactValue value
return @_contact
)
getContact: () -> if @_contact? then Promise.resolve(@_contact) else @_readContactValue()
# ##GpioPresence Sensor
class GpioPresence extends env.devices.PresenceSensor
constructor: (@config, lastState) ->
@id = @config.id
@name = @config.name
options =
debounceTimeout: @config.debounceTimeout if @config.debounceTimeout?
@gpio = new Gpio(@config.gpio, 'in', 'both', options)
@_presence = lastState?.presence?.value or false
@_readPresenceValue().catch( (error) =>
env.logger.error error.message
env.logger.debug error.stack
)
@gpio.watch (err, value) =>
if err?
env.logger.error err.message
env.logger.debug err.stack
else
@_setPresenceValue value
super()
destroy: () ->
@gpio.unwatchAll()
@gpio.unexport()
super()
_setPresenceValue: (value) ->
assert value is 1 or value is 0
state = (if value is 1 then yes else no)
if @config.inverted then state = not state
@_setPresence state
_readPresenceValue: ->
@gpio.read().then( (value) =>
@_setPresenceValue value
return @_presence
)
getPresence: () -> if @_presence? then Promise.resolve(@_presence) else @_readPresenceValue()
# For testing...
plugin.GpioSwitch = GpioSwitch
plugin.GpioPresence = GpioPresence
return plugin