pimatic-johnny-five
Version:
Pimatic Plugin for Johnny Five, a Robotics and IoT programming framework.
233 lines (209 loc) • 8.12 kB
text/coffeescript
# Class UniPiUpdateManager
module.exports = (env) ->
Promise = env.require 'bluebird'
_ = env.require 'lodash'
events = require 'events'
util = require 'util'
five = require('johnny-five')
commons = require('pimatic-plugin-commons')(env)
class ExpanderBoardMapper
constructor: () ->
= false
= .debug || false
= .id
= commons.base @, "ExpanderBoard"
if not .controller?
throw new Error "Missing controller property for expander board"
= new Promise((resolve, reject) =>
=
=
if .board.isReady
else
.board.once "ready",
.board.once "error",
)
.catch (error) =>
.error error
_boardReadyHandler: (resolve, reject) ->
return () =>
expanderOptions =
controller: .controller
board: .board
if .address?
expanderOptions.address = parseInt .address
try
= new five.Board.Virtual({
io: new five.Expander(expanderOptions),
board: .board
})
catch error
return reject new Error "Expander board initialization failed: #{error}"
.board.removeListener "error", if ?
.remote = false
.debug "Board Ready"
= true
resolve
_boardNotReadyHandler: (resolve, reject) ->
return (error) =>
.board.removeListener "ready", if ?
.rejectWithErrorString(reject, error)
boardReady: () ->
return new Promise( (resolve, reject) =>
Promise.settle([])
.then () =>
if
resolve
else
.rejectWithErrorString(reject, new Error "Board not ready")
.catch (error) =>
.rejectWithErrorString(reject, error)
)
releasePin: (pin, controller) ->
# nothing to do
class BoardWrapper extends five.Board
constructor: (opts) ->
super(opts)
= false
= opts.debug || false
= commons.base @, "Board"
= new Promise((resolve, reject) =>
=
=
if
else
"ready",
"error",
"message", (event) =>
.debug "Message received:", event.message
"error", (error) =>
.error "Board not ready:", error.message.replace("\n", "")
"ready", =>
.debug "Board Ready"
)
_boardReadyHandler: (resolve, reject) ->
return () =>
= true
"error", if ?
resolve
_boardNotReadyHandler: (resolve, reject) ->
return (error) =>
"ready", if ?
.rejectWithError(reject, error)
boardReady: () ->
return new Promise( (resolve, reject) =>
Promise.settle([])
.then () =>
if
resolve @
else
.rejectWithError(reject, new Error "Board not ready")
.catch (error) =>
.rejectWithError(reject, error)
)
releasePin: (pin, controller) ->
if not _.isEmpty pin
checkController = not _.isEmpty controller
for index, slot of
if checkController
match = slot.controller? and slot.controller is controller
else
match = true
if slot.value is pin and slot.type is 'pin' and match
.splice index, 1
break
class BoardManager extends events.EventEmitter
constructor: (, plugin) ->
= {}
= plugin.config.debug || false
= commons.base @, "BoardManager"
= false
super()
boardConfigs = .boards
if boardConfigs? and boardConfigs.length isnt 0
defaultBoardConfig =
debug:
repl: false
timeout: 40000
for boardConfig in .boards
if boardConfig.id?
try
[boardConfig.id] =
.debug "Created board #{boardConfig.id}"
catch e
.error "Creation of board #{boardConfig.id} raised exception:" + e
else
.error "Invalid plugin configuration. Missing board id"
else
.error "Invalid plugin configuration. No boards configured"
plugin.framework.once 'destroy', (context) =>
promise = new Promise( (resolve, reject) =>
.info "pimatic is shutting down"
if
(require('pigpio').terminate)()
.info "pigpio terminated"
= false
resolve()
)
context.waitForIt promise
createBoard: (options) ->
switch options.boardType || 'arduino'
when 'arduino' then (
if options.port? and options.baudrate?
fiveModule = require.cache[require.resolve 'johnny-five']
SerialPort = fiveModule.require 'serialport'
options.port = new SerialPort(options.port, {baudrate: options.baudrate})
= new BoardWrapper options
)
when 'raspi-io' then (
unless
= true
.info "pigpio hardwareRevision #{(require('pigpio')).hardwareRevision()}"
(require('pigpio').initialize)()
.info "pigpio initialized"
raspi = require 'raspi-io'
raspiOptions =
enableSoftPwm: true
if options.address?
try
raspiOptions = _.assign({}, JSON.parse(options.address), raspiOptions)
catch e
env.logger.error "Property address does not contain stringified JSON options for raspi-io - ignored."
= new BoardWrapper(_.assign({}, options, {io: new raspi(raspiOptions)}))
)
when 'particle-io' then (
Particle = require 'particle-io'
= new BoardWrapper(_.assign({}, options, {io: new Particle({
token: options.token, deviceId: options.deviceId })}))
)
when 'etherport' then (
EtherPort = require 'etherport'
= new BoardWrapper(_.assign({}, options, {port: new EtherPort({
port: options.port, reset: options.port || false})}))
)
when 'etherport-client', 'esp8266' then (
EtherPortClient = require('etherport-client').EtherPortClient
= new BoardWrapper(_.assign({}, options, {
port: new EtherPortClient({
port: options.port,
host: options.address
})
}))
)
when 'expander' then (
parentBoard = options.port
= new ExpanderBoardMapper(_.assign({}, options, {board: parentBoard}))
)
else
throw new Error "Unsupported boardType #{options.boardType}"
return
getBoard: (id) ->
if [id]
board=[id]
if board?
return board
else
error = new Error "Board not found"
.error error
throw error