-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmicroflo.coffee
181 lines (146 loc) · 4.62 KB
/
microflo.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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
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 if graph
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