From c5b40e8c59ee90bd96a57ce3e1f66fa3ad301117 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 15 Nov 2021 10:49:21 -0800 Subject: [PATCH] Add an option bindAddr which can be passed to TuyaLinkWizard: specifies the interface to broadcast the device link packets on --- index.js | 6 ++++-- lib/link.js | 22 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 0ae5fdd..08b87d8 100644 --- a/index.js +++ b/index.js @@ -25,7 +25,7 @@ const TuyaLink = require('./lib/link.js'); * password: 'example-password'}); */ class TuyaLinkWizard { - constructor({email, password, region = 'us', timezone = 'America/Chicago', apiKey, apiSecret, schema} = {}) { + constructor({email, password, region = 'us', timezone = 'America/Chicago', apiKey, apiSecret, schema, bindAddr} = {}) { if (!email || !password) { throw new Error('Both email and password must be provided'); } @@ -34,6 +34,7 @@ class TuyaLinkWizard { this.password = password; this.region = region; this.timezone = timezone; + this.bindAddr = bindAddr; this.api = new TuyaContext({ baseUrl: `https://openapi.tuya${region}.com`, @@ -123,7 +124,8 @@ class TuyaLinkWizard { token: token.token, secret: token.secret, ssid, - wifiPassword}); + wifiPassword, + bindAddr: this.bindAddr}); // While UDP packets are being sent, start polling for device debug('Polling cloud for details on token...'); diff --git a/lib/link.js b/lib/link.js index 55f2615..083398b 100644 --- a/lib/link.js +++ b/lib/link.js @@ -1,6 +1,7 @@ const dgram = require('dgram'); const delay = require('delay'); const debug = require('debug')('@tuyapi/link:manual'); +const os = require('os'); /** * A lower level option for linking @@ -14,8 +15,10 @@ const debug = require('debug')('@tuyapi/link:manual'); class TuyaLink { constructor() { this.abortBroadcasting = false; + this.bindAddr = undefined; } + /** * Thin wrapper for this.sendSmartLinkStart() * and this.sendSmartLinkData(). Unless you @@ -66,6 +69,23 @@ class TuyaLink { throw new Error('Invalid WiFi password'); } + if (options.bindAddr !== undefined) + { + if (typeof options.bindAddr !== 'string') + { + throw new Error('Invalid binding address'); + } + + const interfaces = os.networkInterfaces(); + if (!Object.keys(interfaces).some(name => + !interfaces[name].some(assigned => assigned.address.toLowerCase() === options.bindAddr.toLowerCase()) + )) + { + throw new Error('Invalid binding address'); + } + this.bindAddr = options.bindAddr; + } + debug('Sending SmartLink initialization packets'); await this.sendSmartLinkStart(); @@ -335,7 +355,7 @@ class TuyaLink { this.udpClient.on('listening', function () { this.setBroadcast(true); }); - this.udpClient.bind(0); + this.udpClient.bind(0, this.bindAddr); } // 0-filled buffer