add buzzer code field
All checks were successful
Build and push image for doorman / docker (push) Successful in 1m39s

This commit is contained in:
Martin Dimitrov 2024-07-06 19:22:50 -07:00
parent c1f068f5aa
commit 81699c7bf4
7 changed files with 99 additions and 39 deletions

View File

@ -7,7 +7,7 @@
"bun-types": "latest" "bun-types": "latest"
}, },
"scripts": { "scripts": {
"prepare-client-serverless": "bun --filter 'doorman-client' build && cp -fr packages/client/dist/* packages/serverless/assets/ && cp -f packages/serverless/assets/index.html packages/serverless/assets/assets/index.html", "prepare-client-serverless": "bun --filter 'doorman-client' build && rm -rf packages/serverless/assets/* && mkdir packages/serverless/assets/assets && cp -fr packages/client/dist/* packages/serverless/assets/ && cp -f packages/serverless/assets/index.html packages/serverless/assets/assets/index.html",
"deploy-serverless": "bun run prepare-client-serverless && bun --filter 'serverless' deploy" "deploy-serverless": "bun run prepare-client-serverless && bun --filter 'serverless' deploy"
}, },
"peerDependencies": { "peerDependencies": {

View File

@ -19,11 +19,6 @@ const router = createBrowserRouter([
path: "", path: "",
loader: doorpageloader, loader: doorpageloader,
element: <DoorPage /> element: <DoorPage />
},
{
path: "door/:door",
loader: doorpageloader,
element: <DoorPage />,
} }
] ]
} }

View File

@ -6,8 +6,10 @@ import OtpInput from 'react-otp-input';
import type { IDoorResponse } from "../../../server/src/types/IDoorResponse"; import type { IDoorResponse } from "../../../server/src/types/IDoorResponse";
import { CountdownBar } from "../components/CountdownBar"; import { CountdownBar } from "../components/CountdownBar";
export async function loader({ params }: any) { export async function loader({ params, request }: any) {
const response = await fetch(params.door ? `/api/door/info?door=${params.door}`: `/api/door/info`).then(res => res.json()); const door = new URL(request.url).searchParams.get('door');
const response = await fetch(`/api/door/info?door=${door}`).then(res => res.json());
console.log(response); console.log(response);
@ -241,8 +243,8 @@ export function DoorPage() {
width: '2rem', width: '2rem',
fontSize: '2rem', fontSize: '2rem',
}} }}
value={'2207'} value={doorResponse.buzzerCode}
numInputs={4} numInputs={doorResponse.buzzerCode.length}
onChange={() => null} onChange={() => null}
renderSeparator={() => <span>-</span>} renderSeparator={() => <span>-</span>}
renderInput={(props) => <input readOnly {...props} />} renderInput={(props) => <input readOnly {...props} />}

View File

@ -1,7 +1,5 @@
import { IAuthMode } from "./IAuthMode";
export interface IDoorResponse { export interface IDoorResponse {
id: string, id: string,
authModes: IAuthMode[];
timeout: number; timeout: number;
} buzzerCode: string;
};

View File

@ -13,27 +13,29 @@ exports.handler = async function(context, event, callback) {
return callback(null, response); return callback(null, response);
} }
if (!context['FIXED_PIN_' + door.toUpperCase()]) { const ddbPath = Runtime.getFunctions()['common/ddb'].path;
const ddb = require(ddbPath);
const client = ddb.createDDBClient(context);
const config = await client.send(ddb.getDoorConfigCommand(door));
if (!config.Item) {
response.setStatusCode(404); response.setStatusCode(404);
return callback(null, response); return callback(null, response);
} }
let correctPin = context['FIXED_PIN_' + door.toUpperCase()]; let correctPin = config.Item.pin.S;
if (correctPin !== pin) { if (correctPin !== pin) {
response.setStatusCode(401); response.setStatusCode(401);
return callback(null, response); return callback(null, response);
} }
const ddbPath = Runtime.getFunctions()['common/ddb'].path;
const ddb = require(ddbPath);
const client = ddb.createDDBClient(context);
const fingerprint = { const fingerprint = {
method: "PIN", method: "PIN",
userAgent: event.request.headers['user-agent'], userAgent: event.request.headers['user-agent'],
}; };
const timeout = context['OPEN_TIMEOUT_' + door.toUpperCase()] || 60; const timeout = config.Item.timeout.N;
await client.send(ddb.setLockStatusCommand(door, timeout, fingerprint)) await client.send(ddb.setLockStatusCommand(door, timeout, fingerprint))
.then(async (item) => { .then(async (item) => {

View File

@ -5,9 +5,10 @@
exports.handler = async function(context, event, callback) { exports.handler = async function(context, event, callback) {
const response = new Twilio.Response(); const response = new Twilio.Response();
const door = event.door || context.DEFAULT_DOOR; let door = event.door;
const buzzer = event.buzzer?.slice(-10);
if (!door) { if (!door && !buzzer) {
response.setStatusCode(400); response.setStatusCode(400);
return callback(null, response); return callback(null, response);
} }
@ -16,24 +17,58 @@ exports.handler = async function(context, event, callback) {
const ddb = require(ddbPath); const ddb = require(ddbPath);
const client = ddb.createDDBClient(context); const client = ddb.createDDBClient(context);
const timeout = context['OPEN_TIMEOUT_' + door.toUpperCase()] || 60; if (buzzer) {
door = await client.send(ddb.getDoorAliasCommand(buzzer))
.then(async (alias) => {
if (!alias.Item) {
response
.setStatusCode(404)
.appendHeader('Content-Type', 'application/json')
.setBody({ err: "This buzzer is not registered" });
return undefined;
}
return alias.Item.name.S;
});
}
await client.send(ddb.getLockStatusCommand(door)) if (door) {
.then(async (lock) => { const config = await client.send(ddb.getDoorConfigCommand(door));
const status = ddb.isLockOpen(lock) ? "OPEN": "CLOSED";
if (!config.Item) {
response response
.setStatusCode(200) .setStatusCode(404)
.appendHeader('Content-Type', 'application/json') .appendHeader('Content-Type', 'application/json')
.setBody({ id: door, timeout, status }); .setBody({ err: "This buzzer is not registered properly" });
} else {
}).catch((e) => { if (buzzer) {
console.log(e); response
response .setStatusCode(200)
.setStatusCode(500) .appendHeader('Content-Type', 'application/json')
.appendHeader('Content-Type', 'application/json') .setBody({
.setBody({ err: e }); buzzer,
}); door,
await client.destroy(); fallbackNumbers: config.Item.fallbackNumbers.SS,
return callback(null, response); });
} else {
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: config.Item.timeout.N, status, buzzerCode: config.Item.buzzerCode.S });
}).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

@ -24,6 +24,34 @@ exports.getLockStatusCommand = (door) => {
}); });
}; };
exports.getDoorAliasCommand = (buzzerNumber) => {
return new GetItemCommand({
TableName: "doorman",
Key: {
"PK": {
S: buzzerNumber,
},
"SK": {
S: "alias",
}
},
});
};
exports.getDoorConfigCommand = (door) => {
return new GetItemCommand({
TableName: "doorman",
Key: {
"PK": {
S: `door-${door}`,
},
"SK": {
S: "config",
},
},
});
};
exports.isLockOpen = (lock) => { exports.isLockOpen = (lock) => {
// ttl is a UTC ms time for how long it is unlocked // ttl is a UTC ms time for how long it is unlocked
const ttl = lock.Item?.TTL?.N || 0; const ttl = lock.Item?.TTL?.N || 0;