UNPKG

fbp-protocol-client

Version:
182 lines (146 loc) 4.72 kB
Base = require './base' microflo = require 'microflo' parseQueryString = (queryString) -> queries = queryString.split "&" params = {} queries.forEach (query, i) -> kv = query.split '=' params[kv[0]] = kv[1] return params parseAddress = (address) -> info = type: null device: null baudrate: "9600" if address.indexOf('serial://') == 0 info.type = 'serial' if address.indexOf('simulator://') == 0 info.type = 'simulator' if info.type start = address.indexOf('://')+'://'.length end = address.indexOf('?') end = address.length if end < 0 d = address.substring start, end info.device = d if d queryStart = address.indexOf('?') if queryStart != -1 query = address.substring queryStart+1 params = parseQueryString query for k, v of params info[k] = v return info # TODO: make this runtime be for every device that supports the same FBCS protocol as MicroFlo class MicroFloRuntime extends Base constructor: (definition) -> @connecting = false @buffer = [] @container = null # MicroFlo things @runtime = null @on 'connected', @updatecontainer super definition isConnected: -> @runtime isnt null getElement: -> @container setParentElement: (parent) -> @container = document.createElement 'container' parent.appendChild @container setMain: (graph) -> if @graph # Unsubscribe from previous main graph @graph.removeListener 'changeProperties', @updatecontainer # Update contents on property changes graph.on 'changeProperties', @updatecontainer super graph openComm: () -> getRuntime = null info = parseAddress @getAddress() if info.type == 'serial' getRuntime = (callback) => microflo.serial.openTransport info.device, parseInt(info.baudrate), (err, transport) -> return callback err if err dev = new microflo.runtime.Runtime transport if process?.env? and process.env['MICROFLO_COMPONENT_MAP'] fs = require 'fs' filename = process.env['MICROFLO_COMPONENT_MAP'] dev.library.definition = JSON.parse fs.readFileSync(filename) return callback null, dev else if info.type == 'simulator' getRuntime = (callback) => build = require 'microflo-emscripten' sim = new microflo.simulator.RuntimeSimulator build.runtime sim.library.definition = build.library # TODO: should be passed/looked up automatically sim.start() #sim.device.graph = sim.graph return callback null, sim getRuntime (err, runtime) => return @emit 'error', err if err runtime.on 'message', (response) => @onMessage { data: response } runtime.device.open () => @connecting = false if err console.log 'MicroFlo error:', err @emit 'error', err return @runtime = runtime # Perform capability discovery @sendRuntime 'getruntime', {} @emit 'status', online: true label: 'connected' @emit 'connected' @flush() connect: -> return if @connecting @connecting = true transport = runtime?.transport @runtime?.stop() @runtime = null # Make sure serial transport is closed before reopening if transport transport.close () => @openComm() else f = () => @openComm() setTimeout f, 0 disconnect: -> onClosed = (success) => @runtime = null @emit 'status', online: false label: 'disconnected' @emit 'disconnected' if @runtime @runtime.transport.close onClosed else onClosed false updatecontainer: => return unless @container # Set an ID for targeting purposes @container.id = 'preview-container' send: (protocol, command, payload) -> msg = protocol: protocol command: command payload: payload if @connecting @buffer.push msg return try @runtime.handleMessage msg catch e console.log e.stack console.log e onMessage: (message) => switch message.data.protocol when 'runtime' then @recvRuntime message.data.command, message.data.payload when 'graph' then @recvGraph message.data.command, message.data.payload when 'network' then @recvNetwork message.data.command, message.data.payload when 'component' then @recvComponent message.data.command, message.data.payload flush: -> for item in @buffer @send item.protocol, item.command, item.payload @buffer = [] module.exports = MicroFloRuntime MicroFloRuntime.parseAddress = parseAddress