Skip to content

Commit

Permalink
Improving discovery with update event and model info
Browse files Browse the repository at this point in the history
  • Loading branch information
aholstenson committed Apr 17, 2017
1 parent f51ab5d commit b679ed8
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 40 deletions.
3 changes: 2 additions & 1 deletion cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ if(args.discover) {
const browser = new Browser(60);
browser.on('available', reg => {
console.log('Device ID:', reg.id);
console.log('Address:', reg.address);
console.log('Model:', reg.model || 'Unknown');
console.log('Address:', reg.address + (reg.hostname ? ' (' + reg.hostname + ')' : ''));
console.log('Token:', reg.token);
console.log();
});
Expand Down
40 changes: 37 additions & 3 deletions lib/discovery.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@

const dgram = require('dgram');
const dns = require('dns');
const EventEmitter = require('events').EventEmitter;

const infoFromHostname = require('./infoFromHostname');
const Packet = require('./packet');

const PORT = 54321;
Expand Down Expand Up @@ -63,7 +65,7 @@ class Browser {

_search() {
this._packet.handshake();
const data = this._packet.raw;
const data = Buffer.from(this._packet.raw);
this._socket.send(data, 0, data.length, PORT, '255.255.255.255');

if(this.cacheTime / 3 > 500) {
Expand All @@ -75,14 +77,46 @@ class Browser {
}

_addService(service) {
const added = ! this._services[service.id];
const existing = this._services[service.id];

this._services[service.id] = service;
service.lastSeen = Date.now();

if(added) {
if(existing) {
// This is an existing device, skip extra discovery
if(existing.address !== service.address) {
this._events.emit('update', service);
}

return;
}

let added = false;
const add = () => {
if(added) return;
added = true;

this._events.emit('available', service);
}

// Give us five seconds to try resolve some extras for new devices
setTimeout(add, 5000);

dns.lookupService(service.address, service.port, (err, hostname) => {
if(err || ! hostname) {
add();
return;
}

service.hostname = hostname;
const info = infoFromHostname(hostname);
if(info) {
service.type = info.type;
service.model = info.model;
}

add();
});
}

_removeService(name) {
Expand Down
39 changes: 3 additions & 36 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,8 @@
const Discovery = require('./discovery');
const Device = require('./device');

const AirPurifier = require('./devices/air-purifier');
const Switch = require('./devices/switch');
const Vacuum = require('./devices/vacuum');
const Gateway = require('./devices/gateway');

const devices = {
'zhimi.airpurifier.m1': AirPurifier,
'zhimi.airpurifier.v1': AirPurifier,
'zhimi.airpurifier.v2': AirPurifier,
'zhimi.airpurifier.v6': AirPurifier,

'chuangmi.plug.m1': Switch,
'chuangmi.plug.v1': Switch,
'chuangmi.plug.v2': Switch,

'rockrobo.vacuum.v1': Vacuum,

'lumi.gateway.v2': Gateway,
'lumi.gateway.v3': Gateway,
};

module.exports.Device = Device;
module.exports.devices = devices;
const models = module.exports.models = require('./models');

/**
* Resolve a device from the given options.
Expand Down Expand Up @@ -67,7 +46,7 @@ module.exports.device = function(options) {
const createDevice = module.exports.createDevice = function(options) {
if(! options.address) throw new Error('Address to device is required');

const d = devices[options.model];
const d = models[options.model];
let device;
if(! d) {
device = new Device(options);
Expand All @@ -81,19 +60,7 @@ const createDevice = module.exports.createDevice = function(options) {
/**
* Extract information about a device from its hostname on the local network.
*/
module.exports.infoFromHostname = function(hostname) {
const m = /(.+)_miio(\d+)/g.exec(hostname);
if(! m) return null;

const model = m[1].replace(/-/g, '.');

const device = devices[model];
return {
model: model,
type: (device && device.TYPE) || 'generic',
id: m[2]
};
};
module.exports.infoFromHostname = require('./infoFromHostname.js');

module.exports.browser = function(options) {
const cacheTime = options && options.cacheTime ? options.cacheTime : 1800;
Expand Down
17 changes: 17 additions & 0 deletions lib/infoFromHostname.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

const models = require('./models');

module.exports = function(hostname) {
// Extract info via hostname structure
const m = /(.+)_miio(\d+)/g.exec(hostname);
if(! m) return null;

const model = m[1].replace(/-/g, '.');

const device = models[model];
return {
model: model,
type: (device && device.TYPE) || 'generic',
id: m[2]
};
}
23 changes: 23 additions & 0 deletions lib/models.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Mapping from models into high-level devices.
*/
const AirPurifier = require('./devices/air-purifier');
const Switch = require('./devices/switch');
const Vacuum = require('./devices/vacuum');
const Gateway = require('./devices/gateway');

module.exports = {
'zhimi.airpurifier.m1': AirPurifier,
'zhimi.airpurifier.v1': AirPurifier,
'zhimi.airpurifier.v2': AirPurifier,
'zhimi.airpurifier.v6': AirPurifier,

'chuangmi.plug.m1': Switch,
'chuangmi.plug.v1': require('./devices/chuangmi.plug.v1'),
'chuangmi.plug.v2': Switch,

'rockrobo.vacuum.v1': Vacuum,

'lumi.gateway.v2': Gateway,
'lumi.gateway.v3': Gateway,
};

0 comments on commit b679ed8

Please sign in to comment.