pimatic-dooya
Version:
Pimatic plugin to control motorized blinds equipped with Dooya tubular motors
138 lines (117 loc) • 3.71 kB
text/coffeescript
module.exports = (env) ->
# Require the bluebird promise library
Promise = env.require 'bluebird'
# Require the [cassert library](https://github.com/rhoot/cassert).
assert = env.require 'cassert'
t = env.require('decl-api').types
M = env.matcher
rpio = require 'rpio'
class Dooya extends env.plugins.Plugin
# ####init()
# The `init` function is called by the framework to ask your plugin to initialise.
#
# #####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) =>
deviceConf = require './device-config-schema'
@framework.deviceManager.registerDeviceClass('DooyaRemote', {
configDef: deviceConf.DooyaRemote,
createCallback: (config) => new DooyaRemoteDevice(config, @, deviceConf.DooyaRemote)
})
class DooyaRemoteDevice extends env.devices.ShutterController
constructor: (@config, @plugin, @deviceConf) ->
@id = @config.id
@name = @config.name
@remoteId = @config.remoteId || @deviceConf.remoteId
@pin = @plugin.config.pin
# keep the state of the pin so that devices
# do not hog the GPIO unnecesseraly
@opened = false
# codes for supported commands
@cmd = {
wakeup: 17,
up: 30,
wakedown: 51,
down: 60,
stop: 85
}
# latency for different pulses
@lut = {
HSTART: 4830,
LSTART: 1535,
LSHORT: 415,
HSHORT: 340,
LLONG: 750,
HLONG: 685,
CMDDELAY: 9,
DELAY: 15
}
rpio.open(@pin, rpio.OUTPUT)
rpio.usleep(10) #first call has lag
@opened = true
super()
moveToPosition: (position) ->
moveUp = () ->
return new Promise (resolve, reject) =>
@send(@cmd.wakeup, 3)
rpio.msleep(@lut.DELAY)
@send(@cmd.up, 3)
resolve()
moveDown = () ->
return new Promise (resolve, reject) =>
@send(@cmd.wakedown, 3)
rpio.msleep(@lut.DELAY)
@send(@cmd.down, 3)
resolve()
if position == 'up'
return moveUp()
else if position == 'down'
return moveDown()
else
throw new Error('unsupported position ' + position)
stop: () ->
return new Promise (resolve, reject) =>
@send(@cmd.stop, 3)
resolve()
destroy: () ->
rpio.close(@pin)
@opened = false
super()
_pulse: (cmd, bit) ->
level = cmd & (1 << bit)
if level
rpio.write(@pin, 1)
rpio.usleep(@lut.HLONG)
rpio.write(@pin, 0)
rpio.usleep(@lut.LSHORT)
else
rpio.write(@pin, 1)
rpio.usleep(@lut.HSHORT)
rpio.write(@pin, 0)
rpio.usleep(@lut.LLONG)
send: (cmd, repeat) ->
if not @opened
rpio.open(@pin, rpio.OUTPUT)
rpio.usleep(10) #first call has lag
rpio.write(@pin, 1)
rpio.usleep(@lut.HSTART)
rpio.write(@pin, 0)
rpio.usleep(@lut.LSTART)
# send remote id
@_pulse @remoteId, bit for bit in [31..0]
# send command
@_pulse cmd, bit for bit in [7..0]
repeat--
if repeat
rpio.msleep(@lut.CMDDELAY)
@send(cmd, repeat)
# ###Finally
# Create a instance of my plugin
dooya = new Dooya
# and return it to the framework.
return dooya