Created
October 31, 2017 02:36
-
-
Save amirburbea/d6b677665bbb98a4db97f84b36659813 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { createSocket } = require('dgram'), | |
{ EventEmitter } = require('events'), | |
regex = /^AMXB<-UUID=GlobalCache_([\dA-F]{12})>/, | |
MULTICAST_ADDRESS = '239.255.250.250'; | |
class GlobalCacheDiscovery extends EventEmitter { | |
/** | |
* Discover Global Cache devices. | |
* @param {string} identifier - An optional Global Cache identifier to limit multicast results to. | |
*/ | |
discover(identifier) { | |
const socket = createSocket('udp4'), | |
timeout = global.setTimeout(() => this.stop(), 60500), | |
devices = {}; | |
socket | |
.on('error', error => { | |
this.emit('error', error); | |
global.clearTimeout(timeout); | |
this.stop(); | |
}) | |
.on('close', () => { | |
socket.removeAllListeners(); | |
global.clearTimeout(timeout); | |
this.socket = undefined; | |
this.emit('end'); | |
}) | |
.on('message', (msg, rinfo) => { | |
const matches = regex.exec(msg); | |
if (!matches) { | |
return; | |
} | |
const [, id] = matches, { address } = rinfo; | |
if (devices[id] !== address) { | |
devices[id] = address; | |
if (!identifier || id === identifier) { | |
this.emit('device', id, devices); | |
} | |
} | |
if (identifier && !id.localeCompare(identifier, undefined, { sensitivity: 'accent' })) { | |
global.clearTimeout(timeout); | |
this.stop(); | |
} | |
}); | |
socket.bind(9131, undefined, () => (this.socket = socket).addMembership(MULTICAST_ADDRESS)); | |
} | |
stop() { | |
const { socket } = this; | |
if (socket) { | |
socket.dropMembership(MULTICAST_ADDRESS); | |
socket.close(); | |
} | |
} | |
} | |
// DEMO | |
const finder = new GlobalCacheDiscovery(); | |
finder.on('device', (addedIdentifier, devices) => { | |
// Obviously you'll be interacting with the GC device by IP address. | |
// That said, a user may have multiple GC devices in their home, and the IP address may be assigned by DHCP. | |
// Find it again, by looking for a specific identifier (which can also be passed as a parameter to the `discover` method). | |
console.log(addedIdentifier, devices[addedIdentifier]); | |
finder.stop(); | |
}); | |
finder.on('end', () => finder.removeAllListeners()); | |
finder.discover(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment