Skip to content

Commit

Permalink
add command queue with delays
Browse files Browse the repository at this point in the history
  • Loading branch information
trembon committed Dec 12, 2023
1 parent ff3b30f commit 318e120
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 6 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ Basic example of the configuration (config.json) file.
"server": {
"port": 3000,
"deviceReconnectWait": 5000,
"refreshTime": 60000
"refreshTime": 60000,
"sendCommandDelay": 5000
},
"webhooks": ["http://localhost:4321/webhook"],
"devices": [
Expand Down
3 changes: 2 additions & 1 deletion config.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"server": {
"port": 3000,
"deviceReconnectWait": 5000,
"refreshTime": 60000
"refreshTime": 60000,
"sendCommandDelay": 5000
},
"webhooks": ["http://localhost:4321/webhook"],
"devices": [
Expand Down
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
"author": "Christopher Jansson",
"license": "MIT",
"dependencies": {
"async-lock": "^1.4.0",
"express": "^4.18.2",
"node-fetch": "^3.3.0",
"tuyapi": "github:codetheweb/tuyapi"
},
"devDependencies": {
"@types/async-lock": "^1.4.2",
"@types/express": "^4.17.17",
"@vercel/ncc": "^0.36.1",
"nodemon": "^2.0.20",
Expand Down
59 changes: 59 additions & 0 deletions src/action-queue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import AsyncLock from "async-lock";
import ActiveDevice from "./active-device";
import Configuration from "./configuration";
import {
ITuyaMultipleProperties,
ITuyaSingleProperty,
} from "./interfaces/tuya";

let processQueueTimeout = undefined;
let queue: QueueItem[] = [];

let lock = new AsyncLock();

const queueAction = (
device: ActiveDevice,
data: ITuyaMultipleProperties | ITuyaSingleProperty
) => {
lock.acquire("processQueue", () => {
queue.push({ device, data });
startTimeout();
});
};

const startTimeout = () => {
lock.acquire("processQueueTimeout", () => {
if (!processQueueTimeout) {
processQueueTimeout = setTimeout(
processQueueItem,
Configuration.instance.server().sendCommandDelay
);
}
});
};

const processQueueItem = async () => {
let queueItem: QueueItem;
await lock.acquire("processQueue", () => {
queueItem = queue.pop();
});

if (queueItem) {
await queueItem.device.set(queueItem.data);
}

await lock.acquire("processQueueTimeout", () => {
processQueueTimeout = undefined;
});

if (queueItem) {
startTimeout();
}
};

interface QueueItem {
device: ActiveDevice;
data: ITuyaMultipleProperties | ITuyaSingleProperty;
}

export default queueAction;
1 change: 1 addition & 0 deletions src/active-device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export default class ActiveDevice {
return;
}

Logger.Debug(`${this.tuya.device.id} - sending command`, data);
let response = await this.tuya.set(data);
return response ? response.dps : {};
}
Expand Down
9 changes: 5 additions & 4 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Logger from "./logger";
import processDevices from "./process-devices";
import PublicDevice from "./public-device.model";
import refreshDevices from "./refresh-devices";
import queueAction from "./action-queue";

Logger.Info(`Starting`);

Expand Down Expand Up @@ -87,8 +88,8 @@ app.post("/devices/:deviceId/send", async (req, res) => {
}
}

let result = await device.set(<ITuyaSingleProperty>action);
res.json(result);
queueAction(device, <ITuyaSingleProperty>action);
res.sendStatus(200);
} else if (action.hasOwnProperty("data")) {
for (var key in action) {
if (action.hasOwnProperty(key) && key !== "data") {
Expand All @@ -97,8 +98,8 @@ app.post("/devices/:deviceId/send", async (req, res) => {
}

action.multiple = true;
let result = await device.set(<ITuyaMultipleProperties>action);
res.json(result);
queueAction(device, <ITuyaMultipleProperties>action);
res.sendStatus(200);
} else {
res.sendStatus(400);
}
Expand Down
1 change: 1 addition & 0 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default class Configuration {
server: {
port: 3000,
deviceReconnectWait: 5000,
sendCommandDelay: 5000,
},
webhooks: [],
devices: [],
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/config/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export default interface IConfigServer {
port: number;
deviceReconnectWait: number;
refreshTime?: number;
sendCommandDelay: number;
}

0 comments on commit 318e120

Please sign in to comment.