Skip to content

Commit

Permalink
Adding new way to discover and connect to devices
Browse files Browse the repository at this point in the history
  • Loading branch information
aholstenson committed Apr 9, 2017
1 parent 956d7b1 commit 2d23e57
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 18 deletions.
74 changes: 61 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,18 @@ npm install --save miio
const miio = require('miio');
```

Create a handle to the device:
Resolve a handle to the device:

```javascript
// Create a device - with a model to get a more specific device instance
const device = miio.createDevice({
token: 'token-as-hex', // Token of device
model: 'zhimi.airpurifier.m1',
address: '192.168.100.8'
});
// Resolve a device, resolving the token automatically if possible
miio.device({ address: '192.168.100.8' })
.then(console.log)
.catch(console.error);

// Create a new generic device by skipping the model
const device = miio.createDevice({
token: 'token-as-hex', // Token of device
address: '192.168.100.8'
});
// Resolve a device, specifying the token (see below for how to get the token)
miio.device({ address: '192.168.100.8', token: 'token-as-hex' })
.then(console.log)
.catch(console.error);
```

Call methods to interact with the device:
Expand Down Expand Up @@ -88,7 +85,44 @@ token of those devices.

## Discovering devices

Devices use mDNS for discovery, but this library does not contain a mDNS
Use `miio.browser()` to look for devices on the local network. This method of
discovery will tell you directly if a device reveals its token and can be
auto-connected to. It will not tell you the model of devices until they are
connected to via `miio.device()`.

Example:

```javascript
const browser = miio.browser({
cacheTime: 300 // 5 minutes. Default is 1800 seconds (30 minutes)
});

const devices = {};
browser.on('available', reg => {
if(! reg.token) {
console.log(reg.id, 'hides its token');
return;
}

miio.device(reg)
.then(device => {
devices[reg.id] = device;

// Do something useful with the device
})
.catch(handleErrorProperlyHere);
});

browser.on('unavailable', reg => {
const device = devices[reg.id];
if(! device) return;

device.destroy();
delete devices[reg.id];
})
```

You can also use mDNS for discovery, but this library does not contain a mDNS
implementation. You can choose a mDNS-implementation suitable for your
needs. Devices announce themselves via `_miio._udp` and should work for most
devices, in certain cases you might need to restart your device to make it
Expand Down Expand Up @@ -138,6 +172,20 @@ Currently implemented devices are:
See [documentation for devices](devices.md) for information about the API for each
type.

## Advanced: Skip model and token checks

The `miio.device` function will return a promise that checks that we can
communicate with the device and what model it is. If you wish to skip this
step and just create a reference to a device use `miio.createDevice`:

```javascript
const device = miio.createDevice({
address: '192.168.100.8',
token: 'token-as-hex',
model: 'zhimi.airpurifier.m1'
});
```

## Advanced: Device management

Get information and update the wireless settings of devices via the management
Expand Down
9 changes: 6 additions & 3 deletions discovery.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,17 @@ class Browser {
this._socket.on('message', (msg, rinfo) => {
const buf = Buffer.from(msg);
this._packet.raw = buf;
let token = this._packet.checksum.toString('hex');
if(token.match(/^[fF]+$/)) {
token = null;
}

this._addService({
id: this._packet.deviceId,
address: rinfo.address,
port: rinfo.port,
token: this._packet.checksum.toString('hex')
token: token
});

// TODO: Is there any way to discover the model of the device?
});

this._searchHandle = setInterval(this._search.bind(this), this.cacheTime / 3);
Expand Down
28 changes: 26 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,39 @@ module.exports.Device = Device;
module.exports.devices = devices;

/**
* Create a device from from the given options. This will either create a
* Resolve a device from the given options.
*
* Options:
* * `address`, **required** the address to the device as an IP or hostname
* * `port`, optional port number, if not specified the default 54391 will be used
* * `token`, optional token of the device
*/
module.exports.device = function(options) {
// Create a temporary device and fetch info from device
const temp = new Device(options);
return temp.call('miIO.info')
.then(data => {
temp.destroy();
return createDevice({
address: options.address,
port: options.port,
model: data.model,
token: data.token
});
});
};

/**
* Create a device from the given options. This will either create a
* specific device if the type is known, or a generic device if it is unknown.
*
* Options:
* * `address`, **required** the address to the device as an IP or hostname
* * `port`, optional port number, if not specified the default 54391 will be used
* * `model`, optional model if known, allows a more specific type to be returned
* * `token`, optional token of the device
*/
module.exports.createDevice = 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];
Expand Down

0 comments on commit 2d23e57

Please sign in to comment.