meshblu-server-websocket
Version:
Websocket Protocol Adapter for Meshblu
143 lines (119 loc) • 5.9 kB
text/coffeescript
_ = require 'lodash'
async = require 'async'
debug = require('debug')('meshblu-server-websocket:websocket-handler')
MeshbluWebsocket = require 'meshblu-websocket'
AuthenticateHandler = require './handlers/authenticate-handler'
UpdateAsHandler = require './handlers/update-as-handler'
UpdateHandler = require './handlers/update-handler'
WhoamiHandler = require './handlers/whoami-handler'
SendMessageHandler = require './handlers/send-message-handler'
GetAuthorizedSubscriptionTypesHandler = require './handlers/get-authorized-subscription-types-handler'
class WebsocketHandler
constructor: ({, , , }) ->
=
authenticate: AuthenticateHandler
identity:
message: SendMessageHandler
subscriptionlist:
update: UpdateHandler
updateas: UpdateAsHandler
whoami: WhoamiHandler
subscribe:
unsubscribe:
initialize: =>
.on 'message',
.on 'close',
= .build()
.on 'message', (channel, message) =>
'message', message
.on 'config', (channel, message) =>
'config', message
.on 'data', (channel, message) =>
'data', message
handlerHandler: (handlerClass) =>
(data) =>
requestQueue = 'request'
responseQueue = 'response'
handler = new handlerClass {, , , requestQueue, responseQueue}
handler.do data, (error, type, response) =>
return error.message, [type, data], 500 if error?
type, response
# Event Listeners
onClose: =>
?.close()
?.close()
onMessage: (event) =>
event.data, (error, type, data) =>
return error.message, event.data, 500 if error?
debug 'onMessage', error, type, data
return [type] data if [type]?
.send type, data if ?
onSubscribe: (data) =>
data.types ?= ['broadcast', 'received', 'sent']
data.types.push 'config'
data.types.push 'data'
requestQueue = 'request'
responseQueue = 'response'
handler = new GetAuthorizedSubscriptionTypesHandler {, , , requestQueue, responseQueue}
handler.do data, (error, type, response) =>
async.each response.types, (type, next) =>
.subscribe {type, uuid: data.uuid}, next
onUnsubscribe: (data) =>
data.types ?= ['broadcast', 'received', 'sent']
requestQueue = 'request'
responseQueue = 'response'
handler = new GetAuthorizedSubscriptionTypesHandler {, , , requestQueue, responseQueue}
handler.do data, (error, type, response) =>
async.each response.types, (type, next) =>
.unsubscribe {type, uuid: data.uuid}, next
# API endpoints
onIdentity: (authData) =>
= _.pick authData, 'uuid', 'token'
request =
metadata:
auth:
jobType: 'Authenticate'
.do 'request', 'response', request, (error, response) =>
return 'error', status: 502, message: "Bad Gateway" if error?
return 'error', status: 504, message: 'Gateway Timeout' unless response?
{code,status} = response.metadata
return 'notReady', message: status, status: code unless code == 204
, (error) =>
return 'notReady', status: 502, message: 'Bad Gateway' if error?
'ready', message: status, status: code
async.each ['received', 'config', 'data'], (type, next) =>
.subscribe {type, uuid: .uuid}, next
subscriptionList: =>
request = metadata: {jobType: 'SubscriptionList'}
.do 'request', 'response', request, (error, jobResponse) =>
return 'error', status: 502, message: 'Bad Gateway', frame: ['subscriptionlist'] if error?
{metadata,rawData} = jobResponse
return 'error', status: metadata.code, message: metadata.status if metadata.code != 200
'subscriptionlist', JSON.parse(rawData)
# Helpers
connectUpstream: (authData, callback) =>
options = _.extend {}, authData,
= new MeshbluWebsocket options
.on 'whoami', (data) => 'whoami', data
.on 'device', (data) => 'device', data
.on 'devices', (data) => 'devices', data
.on 'mydevices', (data) => 'mydevices', data
.on 'registered', (data) => 'registered', data
.on 'updated', (data) => 'updated', data
.on 'unregistered', (data) => 'unregistered', data
.on 'error', (error) =>
delete
'error', message: error.message, code: 502
.close()
.connect callback
parseFrame: (frame, callback) =>
try frame = JSON.parse frame
return callback null, frame... if _.isArray(frame) && frame.length
callback new Error 'invalid frame, must be in the form of [type, data]'
sendFrame: (type, data) =>
debug 'sendFrame', type, data
frame = [type, data]
.send JSON.stringify(frame) if type?
sendError: (message, frame, code) =>
'error', message: message, frame: frame, status: code
module.exports = WebsocketHandler