diff --git a/lib/http_server.js b/lib/http_server.js index f1b764f..924f9bf 100644 --- a/lib/http_server.js +++ b/lib/http_server.js @@ -84,6 +84,10 @@ var ZettaHttpServer = module.exports = function(zettaInstance, options) { name = decodeURI(name); self.zetta.log.emit('log', 'http_server', 'Websocket connection for peer "' + name + '" established.'); + // Include ._env and ._loader on websocket, allows argo formatters to work used in virtual_device build actions. + var host = ws.upgradeReq.headers['host'] + self.wireUpWebSocketForEvent(ws, host, '/servers/' + name); + if (self.peers[name] && self.peers[name].state !== PeerSocket.DISCONNECTED) { // peer already connected or connecting ws.close(4000, 'peer already connected'); diff --git a/lib/virtual_device.js b/lib/virtual_device.js index f1c81a0..dbcd57f 100644 --- a/lib/virtual_device.js +++ b/lib/virtual_device.js @@ -3,6 +3,7 @@ var util = require('util'); var ReadableStream = require('stream').Readable; var EventEmitter = require('events').EventEmitter; var rels = require('zetta-rels'); +var buildDeviceActions = require('./api_formats/siren/device.siren').buildActions; var VirtualStream = module.exports = function(topic, socket, options) { ReadableStream.call(this, options); @@ -41,6 +42,10 @@ var VirtualDevice = module.exports = function(entity, peerSocket) { }); this._socket.on(logTopic, function(data) { + // Format data.actions to siren action format + data.actions = buildDeviceActions(data.properties.id, self._socket.ws._env, self._socket.ws._loader, data.transitions); + delete data.transitions; + self._update(data); self._eventEmitter.emit(data.transition); }); diff --git a/test/test_virtual_device.js b/test/test_virtual_device.js index c5c5080..3b7b03f 100644 --- a/test/test_virtual_device.js +++ b/test/test_virtual_device.js @@ -91,6 +91,31 @@ describe('Virtual Device', function() { }); }); + it('_update should always be called with data.actions in proper format', function(done) { + var called = 0; + var orig = vdevice._update; + vdevice._update = function(data) { + called++; + assert(Array.isArray(data.actions)); + data.actions.forEach(function(action) { + assert(action.class); + assert(action.name); + assert(action.method); + assert(action.href); + assert(action.fields); + }); + orig.apply(vdevice, arguments); + + // _update is called twice on transitions. Once for the return of the transition http POST and again + // for the log topic update. + if (called === 2) { + done(); + } + }; + + vdevice.call('change'); + }); + it('call should work without arguments', function(done) { vdevice.call('change', function(err) { assert.equal(err, null);