diff --git a/lib/roles/device.js b/lib/roles/device.js index fdd86883..132b2d69 100644 --- a/lib/roles/device.js +++ b/lib/roles/device.js @@ -26,6 +26,7 @@ module.exports = function(options) { , display = Object.create(null) , vendor = Object.create(null) , solo = wireutil.makePrivateChannel() + , group = null , channels = new ChannelManager() , vitals = new Vitals() , ports = { @@ -82,8 +83,9 @@ module.exports = function(options) { // Unsubscribe from temporary channels when they timeout channels.on('timeout', function(channel) { log.info('Channel "%s" timed out', channel) - sub.unsubscribe(channel) - push.send([channel, wireutil.makeLeaveGroupMessage(options.serial)]) + if (channel === group) { + leaveGroup() + } }) // Closure of vital functionality @@ -334,24 +336,16 @@ module.exports = function(options) { channels.keepalive(channel) }) .on(wire.GroupMessage, function(channel, message) { - var groupChannel = message.channel - if (devutil.matchesRequirements(identity, message.requirements)) { - channels.register(groupChannel, message.timeout) - log.info('Subscribing to group channel "%s"', groupChannel) - sub.subscribe(groupChannel) - push.send([groupChannel, - wireutil.makeJoinGroupMessage(options.serial)]) + if (!isGrouped() && + devutil.matchesRequirements(identity, message.requirements)) { + joinGroup(message.channel, message.timeout) } channels.keepalive(channel) }) .on(wire.UngroupMessage, function(channel, message) { - var groupChannel = message.channel - if (devutil.matchesRequirements(identity, message.requirements)) { - channels.unregister(groupChannel) - log.info('Unsubscribing from group channel "%s"', groupChannel) - sub.unsubscribe(groupChannel) - push.send([groupChannel, - wireutil.makeLeaveGroupMessage(options.serial)]) + if (isGrouped() && + devutil.matchesRequirements(identity, message.requirements)) { + leaveGroup() } channels.keepalive(channel) }) @@ -413,6 +407,26 @@ module.exports = function(options) { wireutil.makeDevicePokeMessage(options.serial, solo)]) } + function isGrouped() { + return !!group + } + + function joinGroup(channel, timeout) { + log.info('Subscribing to group channel "%s"', channel) + channels.register(channel, timeout) + sub.subscribe(channel) + push.send([channel, wireutil.makeJoinGroupMessage(options.serial)]) + group = channel + } + + function leaveGroup() { + log.info('Unsubscribing from group channel "%s"', group) + channels.unregister(group) + sub.unsubscribe(group) + push.send([group, wireutil.makeLeaveGroupMessage(options.serial)]) + group = null + } + function selfDestruct() { process.exit(1) } diff --git a/lib/wire/channelmanager.js b/lib/wire/channelmanager.js index 3349d7d9..c96c4972 100644 --- a/lib/wire/channelmanager.js +++ b/lib/wire/channelmanager.js @@ -21,8 +21,10 @@ ChannelManager.prototype.register = function(id, timeout) { ChannelManager.prototype.unregister = function(id) { var channel = this.channels[id] - delete this.channels[id] - clearTimeout(channel.timer) + if (channel) { + delete this.channels[id] + clearTimeout(channel.timer) + } } ChannelManager.prototype.keepalive = function(id) {