change to ddb instead of redis
All checks were successful
Build and push image for doorman / docker (push) Successful in 1m0s

This commit is contained in:
Martin Dimitrov 2024-07-06 13:40:06 -07:00
parent 17cd5e08d0
commit c1f068f5aa
6 changed files with 21868 additions and 71 deletions

21755
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,17 +2,7 @@
* Try to unlock the door with auth mode
*/
const redis = require('redis');
function doorStatusKey(id) {
return concatKeys("doors", id, 'open');
}
function concatKeys(...keys) {
return keys.join(':');
}
exports.handler = function(context, event, callback) {
exports.handler = async function(context, event, callback) {
const response = new Twilio.Response();
let door = event.door;
@ -35,23 +25,22 @@ exports.handler = function(context, event, callback) {
return callback(null, response);
}
let client = redis.createClient({ url: context.REDIS_CONNECT_URL });
client.connect()
.then(async () => {
const statusKey = doorStatusKey(door);
const fingerprint = { method: "PIN" };
const timeout = context['OPEN_TIMEOUT_' + door.toUpperCase()] || 60;
const ddbPath = Runtime.getFunctions()['common/ddb'].path;
const ddb = require(ddbPath);
const client = ddb.createDDBClient(context);
await client.set(statusKey, JSON.stringify(fingerprint));
await client.expire(statusKey, timeout);
await client.quit();
const fingerprint = {
method: "PIN",
userAgent: event.request.headers['user-agent'],
};
const timeout = context['OPEN_TIMEOUT_' + door.toUpperCase()] || 60;
await client.send(ddb.setLockStatusCommand(door, timeout, fingerprint))
.then(async (item) => {
response
.setStatusCode(200)
.appendHeader('Content-Type', 'application/json')
.setBody({ msg: `Opened the door "${door}" for ${timeout}s` });
return callback(null, response);
}).catch((e) => {
console.log(e);
response
@ -59,4 +48,6 @@ exports.handler = function(context, event, callback) {
.appendHeader('Content-Type', 'application/json')
.setBody({ err: e });
});
await client.destroy();
return callback(null, response);
};

View File

@ -2,40 +2,31 @@
* Try to get door info
*/
const redis = require('redis');
function doorStatusKey(id) {
return concatKeys("doors", id, 'open');
}
function concatKeys(...keys) {
return keys.join(':');
}
exports.handler = function(context, event, callback) {
exports.handler = async function(context, event, callback) {
const response = new Twilio.Response();
let door = event.door || context.DEFAULT_DOOR;
const door = event.door || context.DEFAULT_DOOR;
if (!door) {
response.setStatusCode(400);
return callback(null, response);
}
const ddbPath = Runtime.getFunctions()['common/ddb'].path;
const ddb = require(ddbPath);
const client = ddb.createDDBClient(context);
const timeout = context['OPEN_TIMEOUT_' + door.toUpperCase()] || 60;
let client = redis.createClient({ url: context.REDIS_CONNECT_URL });
client.connect()
.then(async () => {
const status = await client.get(doorStatusKey(door)) ? "OPEN": "CLOSED";
await client.quit();
await client.send(ddb.getLockStatusCommand(door))
.then(async (lock) => {
const status = ddb.isLockOpen(lock) ? "OPEN": "CLOSED";
response
.setStatusCode(200)
.appendHeader('Content-Type', 'application/json')
.setBody({ id: door, timeout, status });
return callback(null, response);
}).catch((e) => {
console.log(e);
response
@ -43,4 +34,6 @@ exports.handler = function(context, event, callback) {
.appendHeader('Content-Type', 'application/json')
.setBody({ err: e });
});
await client.destroy();
return callback(null, response);
};

View File

@ -2,33 +2,27 @@
* Try to update door status
*/
const redis = require('redis');
function doorStatusKey(id) {
return concatKeys("doors", id, 'open');
}
function concatKeys(...keys) {
return keys.join(':');
}
exports.handler = function(context, event, callback) {
exports.handler = async function(context, event, callback) {
const response = new Twilio.Response();
let door = event.door;
const door = event.door;
if (!door) {
response.setStatusCode(400);
return callback(null, response);
}
let client = redis.createClient({ url: context.REDIS_CONNECT_URL });
client.connect()
.then(async () => {
const isOpen = await client.get(doorStatusKey(door));
const ddbPath = Runtime.getFunctions()['common/ddb'].path;
const ddb = require(ddbPath);
const client = ddb.createDDBClient(context);
await client.send(ddb.getLockStatusCommand(door))
.then(async (lock) => {
const isOpen = ddb.isLockOpen(lock);
if (isOpen) {
const fingerprint = JSON.parse(isOpen);
const fingerprint = JSON.parse(lock.Item.fingerprint.S);
response
.setStatusCode(200)
@ -37,10 +31,9 @@ exports.handler = function(context, event, callback) {
status: "OPEN",
fingerprint,
});
await client.getDel(doorStatusKey(door));
await client.quit();
return callback(null, response);
await client.send(ddb.clearLockStatusCommand(lock));
return;
}
response
@ -50,12 +43,14 @@ exports.handler = function(context, event, callback) {
status: "CLOSED",
});
return callback(null, response);
}).catch((e) => {
console.log(e);
response
.setStatusCode(500)
.appendHeader('Content-Type', 'application/json')
.setBody({ err: e });
});;
});
await client.destroy();
return callback(null, response);
};

View File

@ -0,0 +1,65 @@
const { DynamoDBClient, GetItemCommand, DeleteItemCommand, PutItemCommand } = require("@aws-sdk/client-dynamodb");
exports.createDDBClient = (context) => {
return new DynamoDBClient({
region: "us-east-1" ,
credentials: {
accessKeyId: context.AWS_ACCESS_KEY,
secretAccessKey: context.AWS_SECRET_ACCESS_KEY,
},
});
};
exports.getLockStatusCommand = (door) => {
return new GetItemCommand({
TableName: "doorman",
Key: {
"PK": {
S: door,
},
"SK": {
S: "lock",
}
},
});
};
exports.isLockOpen = (lock) => {
// ttl is a UTC ms time for how long it is unlocked
const ttl = lock.Item?.TTL?.N || 0;
return ttl > Date.now();
};
exports.clearLockStatusCommand = (lock) => {
return new DeleteItemCommand({
TableName: "doorman",
Key: {
"PK": {
S: lock.Item.PK.S,
},
"SK": {
S: "lock",
}
}
});
};
exports.setLockStatusCommand = (door, timeoutSeconds, fingerprintObj) => {
return new PutItemCommand({
TableName: "doorman",
Item: {
"PK": {
S: door,
},
"SK": {
S: "lock",
},
"TTL": {
N: `${Date.now() + timeoutSeconds * 1000}`,
},
"fingerprint": {
S: JSON.stringify(fingerprintObj),
}
}
});
};

View File

@ -5,14 +5,12 @@
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "twilio-run",
"deploy": "twilio-run deploy --service-name doorman --environment=prod",
"clean": "rm -rf assets/* functions/*"
"deploy": "twilio-run deploy --service-name doorman --environment=prod"
},
"dependencies": {
"twilio": "^3.56",
"@aws-sdk/client-dynamodb": "^3.609.0",
"@twilio/runtime-handler": "1.3.0",
"qrcode": "^1.5.3",
"redis": "^4.6.8"
"twilio": "^3.56"
},
"devDependencies": {
"twilio-run": "^3.5.4"