diff --git a/lib/db/api.js b/lib/db/api.js index bf3f9a94..2b3548df 100644 --- a/lib/db/api.js +++ b/lib/db/api.js @@ -41,26 +41,36 @@ dbapi.saveDeviceLog = function(serial, entry) { })) } -dbapi.saveDeviceStatus = function(serial, status) { - return db.run(r.table('devices').get(serial).update({ - status: status.status - , provider: status.provider +dbapi.saveDevice = function(serial, device) { + return db.run(r.table('devices').insert({ + serial: serial + , present: true + , provider: device.provider + , status: device.status , statusChangedAt: r.now() + , createdAt: r.now() + } + , { + upsert: true })) - .then(function(stats) { - if (stats.skipped) { - return db.run(r.table('devices').insert({ - serial: serial - , provider: status.provider - , status: status.status - , statusChangedAt: r.now() - , createdAt: r.now() - })) - } - return stats +} + +dbapi.saveDeviceStatus = function(serial, status) { + return dbapi.ensureDeviceSaved(serial) + .then(function() { + return db.run(r.table('devices').get(serial).update({ + status: status + , statusChangedAt: r.now() + })) }) } +dbapi.setDeviceAbsent = function(serial) { + return db.run(r.table('devices').get(serial).update({ + present: false + })) +} + dbapi.saveDeviceIdentity = function(serial, identity) { return db.run(r.table('devices').get(serial).update({ platform: identity.platform diff --git a/lib/roles/app.js b/lib/roles/app.js index 781a1a1f..dc866dfd 100644 --- a/lib/roles/app.js +++ b/lib/roles/app.js @@ -178,6 +178,15 @@ module.exports = function(options) { .on(wire.LeaveGroupMessage, function(channel, message) { socket.emit('group.leave', message) }) + .on(wire.DevicePresentMessage, function(channel, message) { + socket.emit('device.present', message) + }) + .on(wire.DeviceAbsentMessage, function(channel, message) { + socket.emit('device.absent', message) + }) + .on(wire.DeviceStatusMessage, function(channel, message) { + socket.emit('device.status', message) + }) .handler() // Global messages diff --git a/lib/roles/device.js b/lib/roles/device.js index 132b2d69..b58a4736 100644 --- a/lib/roles/device.js +++ b/lib/roles/device.js @@ -432,8 +432,14 @@ module.exports = function(options) { } function gracefullyExit() { - log.info('Bye') - process.exit(0) + if (isGrouped()) { + leaveGroup() + Promise.delay(500).then(gracefullyExit) + } + else { + log.info('Bye') + process.exit(0) + } } process.on('SIGINT', function() { diff --git a/lib/roles/processor.js b/lib/roles/processor.js index 00f34ee4..ed0e6753 100644 --- a/lib/roles/processor.js +++ b/lib/roles/processor.js @@ -32,6 +32,18 @@ module.exports = function(options) { }) devDealer.on('message', wirerouter() + .on(wire.DevicePresentMessage, function(channel, message, data) { + dbapi.saveDevice(message.serial, message) + appDealer.send([channel, data]) + }) + .on(wire.DeviceAbsentMessage, function(channel, message, data) { + dbapi.setDeviceAbsent(message.serial) + appDealer.send([channel, data]) + }) + .on(wire.DeviceStatusMessage, function(channel, message, data) { + dbapi.saveDeviceStatus(message.serial, message.status) + appDealer.send([channel, data]) + }) .on(wire.JoinGroupMessage, function(channel, message, data) { appDealer.send([channel, data]) }) @@ -51,9 +63,6 @@ module.exports = function(options) { .on(wire.DeviceIdentityMessage, function(channel, message) { dbapi.saveDeviceIdentity(message.serial, message) }) - .on(wire.DeviceStatusMessage, function(channel, message) { - dbapi.saveDeviceStatus(message.serial, message) - }) .on(wire.ShellCommandDataMessage, function(channel, message, data) { appDealer.send([channel, data]) }) diff --git a/lib/roles/provider.js b/lib/roles/provider.js index 2c8fccb8..e6335286 100644 --- a/lib/roles/provider.js +++ b/lib/roles/provider.js @@ -60,18 +60,36 @@ module.exports = function(options) { tracker.on('add', function(device) { lists.all.push(device.id) - pushDeviceStatus(device, device.type) + push.send([ + wireutil.global + , wireutil.envelope(new wire.DevicePresentMessage( + device.id + , options.name + , wireutil.toDeviceStatus(device.type) + )) + ]) maybeConnect(device) }) tracker.on('change', function(device) { - pushDeviceStatus(device, device.type) + push.send([ + wireutil.global + , wireutil.envelope(new wire.DeviceStatusMessage( + device.id + , wireutil.toDeviceStatus(device.type) + )) + ]) maybeConnect(device) || maybeDisconnect(device) }) tracker.on('remove', function(device) { _.pull(lists.all, device.id) - pushDeviceStatus(device, 'absent') + push.send([ + wireutil.global + , wireutil.envelope(new wire.DeviceAbsentMessage( + device.id + )) + ]) maybeDisconnect(device) }) @@ -321,6 +339,12 @@ module.exports = function(options) { Array.prototype.push.apply(options.ports, worker.ports) _.pull(lists.ready, id) _.pull(lists.waiting, id) + push.send([ + wireutil.global + , wireutil.envelope(new wire.DeviceAbsentMessage( + id + )) + ]) delayedTotals() return worker } diff --git a/lib/wire/util.js b/lib/wire/util.js index c64d6eb8..a31ddf1e 100644 --- a/lib/wire/util.js +++ b/lib/wire/util.js @@ -14,7 +14,6 @@ var wireutil = { , emulator: 'ONLINE' , unauthorized: 'UNAUTHORIZED' , offline: 'OFFLINE' - , absent: 'ABSENT' }[type]] } , envelope: function(message) { @@ -106,13 +105,6 @@ var wireutil = { }) )) } -, makeDeviceStatusMessage: function(serial, type, provider) { - return wireutil.envelope(new wire.DeviceStatusMessage( - serial - , wireutil.toDeviceStatus(type) - , provider - )) - } , makeProbeMessage: function() { return wireutil.envelope(new wire.ProbeMessage()) } diff --git a/lib/wire/wire.proto b/lib/wire/wire.proto index 8b430a89..f58036dd 100644 --- a/lib/wire/wire.proto +++ b/lib/wire/wire.proto @@ -15,6 +15,8 @@ enum MessageType { ShellCommandFailMessage = 12; DeviceIdentityMessage = 13; DeviceLogMessage = 14; + DevicePresentMessage = 16; + DeviceAbsentMessage = 17; } message Envelope { @@ -36,6 +38,16 @@ message DeviceLogMessage { // Introductions +message DevicePresentMessage { + required string serial = 1; + required string provider = 2; + required DeviceStatus status = 4; +} + +message DeviceAbsentMessage { + required string serial = 1; +} + message DevicePokeMessage { required string serial = 1; required string channel = 2; @@ -45,16 +57,14 @@ message ProbeMessage { } enum DeviceStatus { - ABSENT = 1; - OFFLINE = 2; - UNAUTHORIZED = 3; - ONLINE = 4; + OFFLINE = 1; + UNAUTHORIZED = 2; + ONLINE = 3; } message DeviceStatusMessage { required string serial = 1; required DeviceStatus status = 2; - required string provider = 3; } message DeviceDisplayMessage { diff --git a/res/app/scripts/services/deviceService.js b/res/app/scripts/services/deviceService.js index 308655c1..3fd0c2df 100644 --- a/res/app/scripts/services/deviceService.js +++ b/res/app/scripts/services/deviceService.js @@ -1,13 +1,56 @@ define(['./module', 'oboe'], function(mod, oboe) { - function DevicesServiceFactory($rootScope, socketService) { + function DevicesServiceFactory($rootScope, socket) { var deviceService = { devices: [] + , devicesBySerial: {} } + function get(data) { + return deviceService.devices[deviceService.devicesBySerial[data.serial]] + } + + function insert(data, alter) { + deviceService.devicesBySerial[data.serial] = + deviceService.devices.push(data) - 1 + _.assign(data, alter) + $rootScope.$digest() + } + + function modify(data, properties) { + if (data) { + _.assign(data, properties) + $rootScope.$digest() + } + } + + function remove(data) { + var index = deviceService.devicesBySerial[data.serial] + if (index >= 0) { + deviceService.devices.splice(index, 1) + delete deviceService.devicesBySerial[data.serial] + $rootScope.$digest() + } + } + + socket.on('device.present', function(data) { + remove(data) + insert(data, { + present: true + }) + }) + + socket.on('device.status', function(data) { + modify(get(data), data) + }) + + socket.on('device.absent', function(data) { + remove(data) + }) + oboe('/api/v1/devices') .node('devices[*]', function(device) { - deviceService.devices.push(device) - $rootScope.$digest() + // We want to skip other arguments + insert(device) }) return deviceService diff --git a/res/app/scripts/services/groupService.js b/res/app/scripts/services/groupService.js index 6d07e7f8..46491d2e 100644 --- a/res/app/scripts/services/groupService.js +++ b/res/app/scripts/services/groupService.js @@ -16,6 +16,11 @@ define(['./module', 'lodash'], function(mod, _) { $rootScope.$digest() }) + socket.on('device.absent', function(data) { + _.pull(groupService.members, data.serial) + $rootScope.$digest() + }) + groupService.invite = function(requirements) { socket.emit('group.invite', requirements) }