From de0c5c35e03d6d9c3bb4e31d7b606108c082cb5c Mon Sep 17 00:00:00 2001 From: Harrison Goscenski Date: Wed, 7 Feb 2024 22:17:29 -0600 Subject: [PATCH 1/4] Initial attempt at naive debounce for login api --- .env.sample | 8 ++++++++ .gitignore | 3 ++- example/index.js | 46 +++++++++++++++++++++++++++++++-------------- src/index.js | 49 +++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 84 insertions(+), 22 deletions(-) create mode 100644 .env.sample diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..22142f9 --- /dev/null +++ b/.env.sample @@ -0,0 +1,8 @@ +USERNAME=username +PASSWORD=password +KEY_ID=keyId +API_KEY=apiKey +PERSIST_PATH=./scratch +LOG_LEVEL=debug +API_LOG_ENABLED=true +LOCAL_DEV=true \ No newline at end of file diff --git a/.gitignore b/.gitignore index 65bc0c3..57137dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules/* example/node_modules/* -example/scratch/* \ No newline at end of file +example/scratch/* +.env \ No newline at end of file diff --git a/example/index.js b/example/index.js index a357e1e..3765212 100644 --- a/example/index.js +++ b/example/index.js @@ -1,22 +1,40 @@ -//const WyzeAPI = require('../src/index') // Local Debug -const WyzeAPI = require("wyze-api") -const Logger = require("@ptkdev/logger"); +let WyzeAPI = null; +if (process.env.LOCAL_DEV) { + WyzeAPI = require('../src/index'); // Local Debug +} else { + WyzeAPI = require("wyze-api"); +} +const Logger = require("@ptkdev/logger"); const logger = new Logger(); const options = { - username: "username", - password: "password", - keyId: "keyId", - apiKey: "apiKey", - persistPath: "./scratch", - logLevel: "debug", - apiLogEnabled: true + username: process.env.USERNAME, + password: process.env.PASSWORD, + keyId: process.env.KEY_ID, + apiKey: process.env.API_KEY, + persistPath: process.env.PERSIST_PATH, + logLevel: process.env.LOG_LEVEL, + apiLogEnabled: process.env.API_LOG_ENABLED, } -const wyze = new WyzeAPI(options,logger) +const wyze = new WyzeAPI(options, logger); - ; (async () => { +async function loginCheck(iterations = 2) { + var count = 0; + while (count < iterations) { + await wyze.maybeLogin(); + wyze.access_token = ""; + count += 1; + } +} +async function deviceListCheck() { const devices = await wyze.getDeviceList() - logger.debug(JSON.stringify(devices)) - })() + logger.debug(JSON.stringify(devices)) +} + + +(async () => { + // await deviceListCheck(); + await loginCheck(); +})() diff --git a/src/index.js b/src/index.js index 5da6ac8..b906fb6 100644 --- a/src/index.js +++ b/src/index.js @@ -3,10 +3,11 @@ const fs = require("fs").promises; const path = require("path"); const getUuid = require("uuid-by-string"); -const payloadFactory = require("./payloadFactory"); -const crypto = require("./crypto"); -const constants = require("./constants"); -const util = require("./util"); +const payloadFactory = require('./payloadFactory'); +const crypto = require('./crypto'); +const constants = require('./constants'); +const util = require('./util'); +const { time } = require('console'); module.exports = class WyzeAPI { constructor(options, log) { @@ -54,6 +55,9 @@ module.exports = class WyzeAPI { this.dumpData = false; // Set this to true to log the Wyze object data blob one time at startup. + this.lastLoginAttempt = 0; + this.loginAttemptDebounceMilliseconds = 1000; + // Token is good for 216,000 seconds (60 hours) but 48 hours seems like a reasonable refresh interval 172800 if (this.refreshTokenTimerEnabled === true) { setInterval(this.refreshToken.bind(this), 172800); @@ -202,7 +206,38 @@ module.exports = class WyzeAPI { } if (!this.access_token) { - await this.login(); + let now = new Date().getTime(); + // check if the last login attempt occurred too recently + if (this.apiLogEnabled) this.log.debug("Last login " + this.lastLoginAttempt + " debounce " + this.loginAttemptDebounceMilliseconds + " now " + now); + if (this.lastLoginAttempt + this.loginAttemptDebounceMilliseconds < now) { + // reset loginAttemptDebounceMilliseconds if last attempted login occurred more than 12 hours ago + if (this.lastLoginAttempt - now > 60 * 1000 * 60 * 12) { + this.loginAttemptDebounceMilliseconds = 1000; + } else { + // max debounce of 5 minutes + this.loginAttemptDebounceMilliseconds = Math.min(this.loginAttemptDebounceMilliseconds * 2, 1000 * 60 * 5); + } + + this.lastLoginAttempt = now; + await this.login(); + } else { + this.log.warning("Attempting to login before debounce has cleared, waiting " + this.loginAttemptDebounceMilliseconds / 1000 + " seconds"); + + var waitTime = 0; + while (waitTime < this.loginAttemptDebounceMilliseconds) { + await this.sleep(2); + waitTime = waitTime + 5000; + if (this.access_token) { + break; + } + } + + if (!this.access_token) { + this.lastLoginAttempt = now; + this.loginAttemptDebounceMilliseconds = Math.min(this.loginAttemptDebounceMilliseconds * 2, 1000 * 60 * 5); + await this.login(); + } + } } } @@ -1416,7 +1451,7 @@ module.exports = class WyzeAPI { return Math.max(min, Math.min(number, max)); } - sleep(ms) { - return new Promise((resolve) => setTimeout(resolve, ms * 1000)); + sleep(seconds) { + return new Promise((resolve) => setTimeout(resolve, seconds * 1000)); } }; From c6f687d6725ccab5744ed9ea1edb2848f2b1ddbe Mon Sep 17 00:00:00 2001 From: Harrison Goscenski Date: Wed, 7 Feb 2024 22:19:25 -0600 Subject: [PATCH 2/4] Disable both examples by default --- example/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/index.js b/example/index.js index 3765212..f8099a6 100644 --- a/example/index.js +++ b/example/index.js @@ -36,5 +36,5 @@ async function deviceListCheck() { (async () => { // await deviceListCheck(); - await loginCheck(); + // await loginCheck(); })() From 05968475d9899e068998740c3f46ed7fa92fd9c1 Mon Sep 17 00:00:00 2001 From: Harrison Goscenski Date: Wed, 7 Feb 2024 22:30:50 -0600 Subject: [PATCH 3/4] gixed error in tabulating waitTime --- example/index.js | 2 +- src/index.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/example/index.js b/example/index.js index f8099a6..22278d4 100644 --- a/example/index.js +++ b/example/index.js @@ -36,5 +36,5 @@ async function deviceListCheck() { (async () => { // await deviceListCheck(); - // await loginCheck(); + // await loginCheck(4); })() diff --git a/src/index.js b/src/index.js index b906fb6..106051a 100644 --- a/src/index.js +++ b/src/index.js @@ -201,7 +201,7 @@ module.exports = class WyzeAPI { } async maybeLogin() { - if (!this.access_token) { + if (false && !this.access_token) { await this._loadPersistedTokens(); } @@ -226,7 +226,7 @@ module.exports = class WyzeAPI { var waitTime = 0; while (waitTime < this.loginAttemptDebounceMilliseconds) { await this.sleep(2); - waitTime = waitTime + 5000; + waitTime = waitTime + 2000; if (this.access_token) { break; } From 5efe84f823d7a1a2f0ca3b86d8686b1e0eea4480 Mon Sep 17 00:00:00 2001 From: Harrison Goscenski Date: Wed, 7 Feb 2024 22:31:33 -0600 Subject: [PATCH 4/4] removing debugging conditional --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 106051a..082fc2c 100644 --- a/src/index.js +++ b/src/index.js @@ -201,7 +201,7 @@ module.exports = class WyzeAPI { } async maybeLogin() { - if (false && !this.access_token) { + if (!this.access_token) { await this._loadPersistedTokens(); }