UNPKG

5.74 kBtext/coffeescriptView Raw
1_ = require 'lodash'
2async = require 'async'
3MeshbluHttp = require 'browser-meshblu-http'
4MeshbluHose = require 'meshblu-firehose-socket.io/src/firehose-socket-io.coffee'
5EventEmitter = require 'eventemitter2'
6
7class Inquisitor extends EventEmitter
8 constructor: ({meshbluConfig, @firehoseConfig, uuid}) ->
9 @meshblu = new MeshbluHttp meshbluConfig
10 @inquisitorUuid = uuid
11
12 setup: (callback) =>
13 @meshblu.device @inquisitorUuid, (error, device) =>
14 return callback error if error?
15
16 devices = device.devices
17
18 @_createSubscription @inquisitorUuid, (error) =>
19 return callback error if error?
20
21 @getStatusDevices devices, (error, statusDevices) =>
22 return callback error if error?
23 allDevices = _.union devices, statusDevices
24
25 @createSubscriptions allDevices, (error) =>
26 return callback error if error?
27 @updatePermissions allDevices, callback
28
29 connect: (callback) =>
30 @getMonitoredDevices (error, @monitoredDevices) =>
31 return callback error if error?
32 @meshblu.generateAndStoreToken @inquisitorUuid, {}, (error, response) =>
33 return callback error if error?
34 @firehose = new MeshbluHose({
35 meshbluConfig: {
36 hostname: @firehoseConfig.hostname
37 port: @firehoseConfig.port,
38 protocol: @firehoseConfig.protocol
39 uuid: @inquisitorUuid,
40 token: response.token
41 }
42 })
43
44 @firehose.on 'message', @_onMessage
45
46
47 @firehose.connect {uuid: @inquisitorUuid}, callback
48
49 _onMessage: ({metadata, data}) =>
50 @emit 'message', {metadata, data}
51 return unless _.last(metadata.route).type == 'configure.received'
52
53 statusDevice = _.last(_.initial(metadata.route)).from
54 {device} = _.find @monitoredDevices, {statusDevice}
55 device = data if device.uuid == statusDevice
56
57 emitMessage =
58 uuid: device.uuid
59 statusDevice: statusDevice
60 errors: data.errors
61 device: device
62
63 @emit 'status-update', emitMessage
64
65
66 stop: (callback) =>
67 return callback() unless @firehose?
68 @firehose.close callback
69
70 getStatusDevices: (devices, callback) =>
71 @meshblu.search {query: {uuid: $in: devices }, projection: {statusDevice: true }}, (error, newDevices) =>
72 return callback error if error?
73 statusDevices = _.compact _.map newDevices, 'statusDevice'
74 callback null, statusDevices
75
76 getMonitoredDevices: (callback) =>
77 @meshblu.listSubscriptions {subscriberUuid: @inquisitorUuid}, (error, subscriptions) =>
78 return callback error if error?
79 subscribedDevices = _.without _.map(subscriptions, 'emitterUuid'), @inquisitorUuid
80 @meshblu.search {query: {uuid: $in: subscribedDevices}}, (error, devices) =>
81 return callback error if error?
82 callback null, @mapStatusDevices devices
83
84 mapStatusDevices: (devices) =>
85 _.compact _.map devices, (device) =>
86 return if _.some devices, statusDevice: device.uuid
87 return {uuid: device.uuid, device, statusDevice: device.uuid, errors: device.errors} unless device.statusDevice?
88 statusDevice = _.find devices, uuid: device.statusDevice
89 return {uuid: device.uuid, device, statusDevice: device.statusDevice, errors: statusDevice?.errors || []}
90
91
92 createSubscriptions: (devices, callback) =>
93 async.each devices, @_createSubscription, callback
94
95 _createSubscription: (device, callback) =>
96 subscriptions = [
97 {subscriberUuid: @inquisitorUuid, emitterUuid: device, type: 'configure.received'}
98 {subscriberUuid: @inquisitorUuid, emitterUuid: device, type: 'message.received'}
99 {subscriberUuid: @inquisitorUuid, emitterUuid: device, type: 'message.sent'}
100 {subscriberUuid: @inquisitorUuid, emitterUuid: device, type: 'broadcast.sent'}
101 ]
102 async.eachSeries subscriptions, @meshblu.createSubscription, callback
103
104 updatePermissions: (devices, callback) =>
105 @meshblu.search {query: {uuid: {$in: devices}, 'meshblu.version': '2.0.0'}, projection: {uuid: true}}, (error, v2Devices) =>
106 return callback error if error?
107 v2Devices = _.map v2Devices, 'uuid'
108 v1Devices = _.difference devices, v2Devices
109 @updateV1Devices v1Devices, (error) =>
110 return callback error if error?
111 @updateV2Devices v2Devices, callback
112
113 updateV1Devices: (devices, callback) =>
114 async.each devices, @_updateV1Device, callback
115
116 _updateV1Device: (device, callback) =>
117 update =
118 $addToSet:
119 configureWhitelist: @inquisitorUuid
120 discoverWhitelist: @inquisitorUuid
121 @meshblu.updateDangerously device, update, callback
122
123 updateV2Devices: (devices, callback) =>
124 async.each devices, @_updateV2Device, callback
125
126 _updateV2Device: (device, callback) =>
127 update =
128 $addToSet:
129 'meshblu.whitelists.configure.received': uuid: @inquisitorUuid
130 'meshblu.whitelists.discover.view': uuid: @inquisitorUuid
131
132 @meshblu.updateDangerously device, update, callback
133
134 clearErrors: (uuid, callback) =>
135 update =
136 $unset:
137 errors: true
138 @meshblu.updateDangerously uuid, update, callback
139
140 getMonitoredDeviceSubscriptions: (callback) =>
141 @meshblu.listSubscriptions {subscriberUuid: @inquisitorUuid}, (error, subscriptions) =>
142 return callback error if error?
143 subscriptionQueries =
144 _(subscriptions)
145 .uniqBy('emitterUuid')
146 .reject emitterUuid: @inquisitorUuid
147 .map ({emitterUuid}) => {subscriberUuid: emitterUuid}
148 .compact()
149 .value()
150
151 async.map subscriptionQueries, @meshblu.listSubscriptions, (error, subscriptions) =>
152 return callback error, _.flatten(subscriptions)
153
154module.exports = Inquisitor