feat: restructure backend with Elysia framework and add MQTT adapter
- Updated .gitignore to exclude generated files and database - Modified package.json to change dev script and add new dependencies - Removed src/index.ts and created app.ts for Elysia server initialization - Added environment variable configuration in config/env.ts - Implemented MQTT adapter in adapter/mqtt.ts for message handling - Created Prisma client in prisma/client.ts and defined schema in prisma/schema.prisma - Added seeding script in prisma/seed.ts for measurement points - Established logging utility in utils/logger.ts for structured logging - Created bed router in routes/bed.ts for handling bed-related routes
This commit is contained in:
parent
b76d6b99ee
commit
a767dc3635
14 changed files with 801 additions and 14 deletions
5
prisma/client.ts
Normal file
5
prisma/client.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { PrismaClient } from "~/generated/prisma";
|
||||
|
||||
const db = new PrismaClient()
|
||||
|
||||
export default db;
|
81
prisma/schema.prisma
Normal file
81
prisma/schema.prisma
Normal file
|
@ -0,0 +1,81 @@
|
|||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
output = "../generated/prisma"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model MeasurementPoint {
|
||||
id String @id @default(cuid())
|
||||
sensorId String @unique // e.g., "head-1", "back-2"
|
||||
label String // e.g., "Head Left", "Upper Back Center"
|
||||
zone String // e.g., "head", "back", "shoulders"
|
||||
x Int // X coordinate on bed layout
|
||||
y Int // Y coordinate on bed layout
|
||||
pin Int // Hardware pin number
|
||||
|
||||
// Threshold configuration
|
||||
warningThreshold Int // Pressure value that triggers warning
|
||||
alarmThreshold Int // Pressure value that triggers alarm
|
||||
warningDelayMs Int // Delay before warning escalates to alarm
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relations
|
||||
data MeasurementPointData[]
|
||||
alerts Alert[]
|
||||
}
|
||||
|
||||
model MeasurementPointData {
|
||||
id String @id @default(cuid())
|
||||
measurementPointId String
|
||||
|
||||
// Sensor reading data
|
||||
value Int // Analog sensor value (0-4095)
|
||||
|
||||
// Timestamps
|
||||
timestamp DateTime @default(now())
|
||||
time String // Formatted time string
|
||||
|
||||
// Relations
|
||||
measurementPoint MeasurementPoint @relation(fields: [measurementPointId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([measurementPointId, timestamp])
|
||||
}
|
||||
|
||||
enum AlertType {
|
||||
WARNING
|
||||
ALARM
|
||||
}
|
||||
|
||||
model Alert {
|
||||
id String @id @default(cuid())
|
||||
measurementPointId String
|
||||
|
||||
// Alert details
|
||||
type AlertType
|
||||
value Int // Sensor value that triggered alert
|
||||
threshold Int // Threshold that was exceeded
|
||||
|
||||
// Alert state
|
||||
acknowledged Boolean @default(false)
|
||||
silenced Boolean @default(false)
|
||||
|
||||
// Timing
|
||||
startTime DateTime @default(now())
|
||||
endTime DateTime?
|
||||
|
||||
// Relations
|
||||
measurementPoint MeasurementPoint @relation(fields: [measurementPointId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([measurementPointId, startTime])
|
||||
@@index([type, acknowledged])
|
||||
}
|
219
prisma/seed.ts
Normal file
219
prisma/seed.ts
Normal file
|
@ -0,0 +1,219 @@
|
|||
import db from "./client";
|
||||
|
||||
async function main() {
|
||||
console.log('Seeding MeasurementPoints...');
|
||||
|
||||
// Delete existing measurement points
|
||||
await db.measurementPoint.deleteMany();
|
||||
|
||||
// Create measurement points based on API sensor configuration
|
||||
const measurementPoints = [
|
||||
// Head area - Higher thresholds due to critical nature, faster escalation
|
||||
{
|
||||
sensorId: "head-1",
|
||||
label: "Head Left",
|
||||
zone: "head",
|
||||
x: 45,
|
||||
y: 15,
|
||||
pin: 2,
|
||||
warningThreshold: 3000,
|
||||
alarmThreshold: 3500,
|
||||
warningDelayMs: 30000 // 30 seconds
|
||||
},
|
||||
{
|
||||
sensorId: "head-2",
|
||||
label: "Head Right",
|
||||
zone: "head",
|
||||
x: 55,
|
||||
y: 15,
|
||||
pin: 3,
|
||||
warningThreshold: 3000,
|
||||
alarmThreshold: 3500,
|
||||
warningDelayMs: 30000 // 30 seconds
|
||||
},
|
||||
|
||||
// Shoulder area - Moderate thresholds, medium escalation time
|
||||
{
|
||||
sensorId: "shoulder-1",
|
||||
label: "Left Shoulder",
|
||||
zone: "shoulders",
|
||||
x: 35,
|
||||
y: 25,
|
||||
pin: 4,
|
||||
warningThreshold: 2800,
|
||||
alarmThreshold: 3200,
|
||||
warningDelayMs: 45000 // 45 seconds
|
||||
},
|
||||
{
|
||||
sensorId: "shoulder-2",
|
||||
label: "Right Shoulder",
|
||||
zone: "shoulders",
|
||||
x: 65,
|
||||
y: 25,
|
||||
pin: 5,
|
||||
warningThreshold: 2800,
|
||||
alarmThreshold: 3200,
|
||||
warningDelayMs: 45000 // 45 seconds
|
||||
},
|
||||
|
||||
// Upper back - Moderate thresholds, 1 minute escalation
|
||||
{
|
||||
sensorId: "back-1",
|
||||
label: "Upper Back Left",
|
||||
zone: "back",
|
||||
x: 40,
|
||||
y: 35,
|
||||
pin: 6,
|
||||
warningThreshold: 2500,
|
||||
alarmThreshold: 3000,
|
||||
warningDelayMs: 60000 // 1 minute
|
||||
},
|
||||
{
|
||||
sensorId: "back-2",
|
||||
label: "Upper Back Center",
|
||||
zone: "back",
|
||||
x: 50,
|
||||
y: 35,
|
||||
pin: 7,
|
||||
warningThreshold: 2500,
|
||||
alarmThreshold: 3000,
|
||||
warningDelayMs: 60000 // 1 minute
|
||||
},
|
||||
{
|
||||
sensorId: "back-3",
|
||||
label: "Upper Back Right",
|
||||
zone: "back",
|
||||
x: 60,
|
||||
y: 35,
|
||||
pin: 8,
|
||||
warningThreshold: 2500,
|
||||
alarmThreshold: 3000,
|
||||
warningDelayMs: 60000 // 1 minute
|
||||
},
|
||||
|
||||
// Lower back/Hip area - Lower thresholds, 90 second escalation
|
||||
{
|
||||
sensorId: "hip-1",
|
||||
label: "Left Hip",
|
||||
zone: "hips",
|
||||
x: 35,
|
||||
y: 50,
|
||||
pin: 9,
|
||||
warningThreshold: 2200,
|
||||
alarmThreshold: 2800,
|
||||
warningDelayMs: 90000 // 90 seconds
|
||||
},
|
||||
{
|
||||
sensorId: "hip-2",
|
||||
label: "Lower Back",
|
||||
zone: "hips",
|
||||
x: 50,
|
||||
y: 50,
|
||||
pin: 10,
|
||||
warningThreshold: 2200,
|
||||
alarmThreshold: 2800,
|
||||
warningDelayMs: 90000 // 90 seconds
|
||||
},
|
||||
{
|
||||
sensorId: "hip-3",
|
||||
label: "Right Hip",
|
||||
zone: "hips",
|
||||
x: 65,
|
||||
y: 50,
|
||||
pin: 11,
|
||||
warningThreshold: 2200,
|
||||
alarmThreshold: 2800,
|
||||
warningDelayMs: 90000 // 90 seconds
|
||||
},
|
||||
|
||||
// Thigh area - Lower thresholds, 2 minute escalation
|
||||
{
|
||||
sensorId: "thigh-1",
|
||||
label: "Left Thigh",
|
||||
zone: "legs",
|
||||
x: 40,
|
||||
y: 65,
|
||||
pin: 12,
|
||||
warningThreshold: 2000,
|
||||
alarmThreshold: 2500,
|
||||
warningDelayMs: 120000 // 2 minutes
|
||||
},
|
||||
{
|
||||
sensorId: "thigh-2",
|
||||
label: "Right Thigh",
|
||||
zone: "legs",
|
||||
x: 60,
|
||||
y: 65,
|
||||
pin: 13,
|
||||
warningThreshold: 2000,
|
||||
alarmThreshold: 2500,
|
||||
warningDelayMs: 120000 // 2 minutes
|
||||
},
|
||||
|
||||
// Calf area (mock sensors - no pin) - Lower thresholds, 2.5 minute escalation
|
||||
{
|
||||
sensorId: "calf-1",
|
||||
label: "Left Calf",
|
||||
zone: "legs",
|
||||
x: 40,
|
||||
y: 75,
|
||||
pin: null,
|
||||
warningThreshold: 1800,
|
||||
alarmThreshold: 2200,
|
||||
warningDelayMs: 150000 // 2.5 minutes
|
||||
},
|
||||
{
|
||||
sensorId: "calf-2",
|
||||
label: "Right Calf",
|
||||
zone: "legs",
|
||||
x: 60,
|
||||
y: 75,
|
||||
pin: null,
|
||||
warningThreshold: 1800,
|
||||
alarmThreshold: 2200,
|
||||
warningDelayMs: 150000 // 2.5 minutes
|
||||
},
|
||||
|
||||
// Feet (mock sensors - no pin) - Lowest thresholds, 3 minute escalation
|
||||
{
|
||||
sensorId: "feet-1",
|
||||
label: "Left Foot",
|
||||
zone: "feet",
|
||||
x: 45,
|
||||
y: 85,
|
||||
pin: null,
|
||||
warningThreshold: 1500,
|
||||
alarmThreshold: 1800,
|
||||
warningDelayMs: 180000 // 3 minutes
|
||||
},
|
||||
{
|
||||
sensorId: "feet-2",
|
||||
label: "Right Foot",
|
||||
zone: "feet",
|
||||
x: 55,
|
||||
y: 85,
|
||||
pin: null,
|
||||
warningThreshold: 1500,
|
||||
alarmThreshold: 1800,
|
||||
warningDelayMs: 180000 // 3 minutes
|
||||
}
|
||||
];
|
||||
|
||||
// Insert all measurement points
|
||||
for (const point of measurementPoints) {
|
||||
await db.measurementPoint.create({
|
||||
data: point
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`Created ${measurementPoints.length} measurement points`);
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await db.$disconnect();
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue