diff --git a/drizzle/20241104190811_lucia.sql b/drizzle/20241104190811_lucia.sql new file mode 100644 index 0000000..691820a --- /dev/null +++ b/drizzle/20241104190811_lucia.sql @@ -0,0 +1,19 @@ +CREATE TABLE IF NOT EXISTS "sessions" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "expires_at" timestamp with time zone NOT NULL +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "users" ( + "id" text PRIMARY KEY NOT NULL, + "age" integer, + "username" text NOT NULL, + "password_hash" text NOT NULL, + CONSTRAINT "users_username_unique" UNIQUE("username") +); +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "sessions" ADD CONSTRAINT "sessions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/drizzle/20250614083214_lucia.sql b/drizzle/20250614083214_lucia.sql deleted file mode 100644 index 5b65242..0000000 --- a/drizzle/20250614083214_lucia.sql +++ /dev/null @@ -1,43 +0,0 @@ -CREATE TABLE "floors" ( - "floor" integer PRIMARY KEY NOT NULL, - "url" text NOT NULL, - "image" text -); ---> statement-breakpoint -CREATE TABLE "plans" ( - "floor" integer PRIMARY KEY NOT NULL, - "plan" json NOT NULL -); ---> statement-breakpoint -CREATE TABLE "sensor_data" ( - "uuid" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, - "sensor" text NOT NULL, - "temperature" real NOT NULL, - "humidity" real NOT NULL, - "pressure" real NOT NULL, - "altitude" real NOT NULL, - "time" timestamp with time zone DEFAULT now() NOT NULL -); ---> statement-breakpoint -CREATE TABLE "sensors" ( - "id" text PRIMARY KEY NOT NULL, - "user" text NOT NULL -); ---> statement-breakpoint -CREATE TABLE "sessions" ( - "id" text PRIMARY KEY NOT NULL, - "user_id" text NOT NULL, - "expires_at" timestamp with time zone NOT NULL -); ---> statement-breakpoint -CREATE TABLE "users" ( - "id" text PRIMARY KEY NOT NULL, - "age" integer, - "username" text NOT NULL, - "password_hash" text NOT NULL, - CONSTRAINT "users_username_unique" UNIQUE("username") -); ---> statement-breakpoint -ALTER TABLE "sensor_data" ADD CONSTRAINT "sensor_data_sensor_sensors_id_fk" FOREIGN KEY ("sensor") REFERENCES "public"."sensors"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint -ALTER TABLE "sensors" ADD CONSTRAINT "sensors_user_users_id_fk" FOREIGN KEY ("user") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint -ALTER TABLE "sessions" ADD CONSTRAINT "sessions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action; \ No newline at end of file diff --git a/drizzle/meta/20241104190811_snapshot.json b/drizzle/meta/20241104190811_snapshot.json new file mode 100644 index 0000000..13d527c --- /dev/null +++ b/drizzle/meta/20241104190811_snapshot.json @@ -0,0 +1,103 @@ +{ + "id": "4b3474a3-7de5-4b99-878e-f839b53c52f7", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "age": { + "name": "age", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password_hash": { + "name": "password_hash", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_username_unique": { + "name": "users_username_unique", + "nullsNotDistinct": false, + "columns": ["username"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/drizzle/meta/20250614083214_snapshot.json b/drizzle/meta/20250614083214_snapshot.json deleted file mode 100644 index 129a3c6..0000000 --- a/drizzle/meta/20250614083214_snapshot.json +++ /dev/null @@ -1,261 +0,0 @@ -{ - "id": "23f11c9d-f98b-4321-aca4-54ec7fc4eece", - "prevId": "00000000-0000-0000-0000-000000000000", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.floors": { - "name": "floors", - "schema": "", - "columns": { - "floor": { - "name": "floor", - "type": "integer", - "primaryKey": true, - "notNull": true - }, - "url": { - "name": "url", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "image": { - "name": "image", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.plans": { - "name": "plans", - "schema": "", - "columns": { - "floor": { - "name": "floor", - "type": "integer", - "primaryKey": true, - "notNull": true - }, - "plan": { - "name": "plan", - "type": "json", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.sensor_data": { - "name": "sensor_data", - "schema": "", - "columns": { - "uuid": { - "name": "uuid", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "sensor": { - "name": "sensor", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "temperature": { - "name": "temperature", - "type": "real", - "primaryKey": false, - "notNull": true - }, - "humidity": { - "name": "humidity", - "type": "real", - "primaryKey": false, - "notNull": true - }, - "pressure": { - "name": "pressure", - "type": "real", - "primaryKey": false, - "notNull": true - }, - "altitude": { - "name": "altitude", - "type": "real", - "primaryKey": false, - "notNull": true - }, - "time": { - "name": "time", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "sensor_data_sensor_sensors_id_fk": { - "name": "sensor_data_sensor_sensors_id_fk", - "tableFrom": "sensor_data", - "tableTo": "sensors", - "columnsFrom": ["sensor"], - "columnsTo": ["id"], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.sensors": { - "name": "sensors", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user": { - "name": "user", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "sensors_user_users_id_fk": { - "name": "sensors_user_users_id_fk", - "tableFrom": "sensors", - "tableTo": "users", - "columnsFrom": ["user"], - "columnsTo": ["id"], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.sessions": { - "name": "sessions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "sessions_user_id_users_id_fk": { - "name": "sessions_user_id_users_id_fk", - "tableFrom": "sessions", - "tableTo": "users", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.users": { - "name": "users", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "age": { - "name": "age", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "username": { - "name": "username", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "password_hash": { - "name": "password_hash", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "users_username_unique": { - "name": "users_username_unique", - "nullsNotDistinct": false, - "columns": ["username"] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - } - }, - "enums": {}, - "schemas": {}, - "sequences": {}, - "roles": {}, - "policies": {}, - "views": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index c0eeced..2c97128 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -5,8 +5,8 @@ { "idx": 0, "version": "7", - "when": 1749889934943, - "tag": "20250614083214_lucia", + "when": 1730747291671, + "tag": "20241104190811_lucia", "breakpoints": true } ] diff --git a/package.json b/package.json index fb9ac4e..75383b6 100644 --- a/package.json +++ b/package.json @@ -68,8 +68,6 @@ "@node-rs/argon2": "^2.0.2", "@oslojs/crypto": "^1.0.1", "@oslojs/encoding": "^1.1.0", - "d3-scale": "^4.0.2", - "d3-shape": "^3.2.0", "drizzle-orm": "^0.43.1", "mqtt": "^5.13.1", "postgres": "^3.4.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c8adcf8..7918f60 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,12 +17,6 @@ importers: '@oslojs/encoding': specifier: ^1.1.0 version: 1.1.0 - d3-scale: - specifier: ^4.0.2 - version: 4.0.2 - d3-shape: - specifier: ^3.2.0 - version: 3.2.0 drizzle-orm: specifier: ^0.43.1 version: 0.43.1(postgres@3.4.5) diff --git a/src/lib/server/db/schema.js b/src/lib/server/db/schema.js index e048caa..0ae02ed 100644 --- a/src/lib/server/db/schema.js +++ b/src/lib/server/db/schema.js @@ -34,7 +34,7 @@ export const sensors = pgTable("sensors", { }); export const sensorData = pgTable("sensor_data", { - uuid: uuid().primaryKey().defaultRandom(), + uuid: uuid().primaryKey(), sensor: text("sensor") .references(() => sensors.id) .notNull(), @@ -42,5 +42,4 @@ export const sensorData = pgTable("sensor_data", { humidity: real().notNull(), pressure: real().notNull(), altitude: real().notNull(), - time: timestamp({ withTimezone: true, mode: "date" }).notNull().defaultNow(), }); diff --git a/src/lib/server/mqtt-devices.js b/src/lib/server/mqtt-devices.js deleted file mode 100644 index ad0b62d..0000000 --- a/src/lib/server/mqtt-devices.js +++ /dev/null @@ -1,33 +0,0 @@ -let connectedDevices = new Map(); -let deviceSensorData = new Map(); - -export { connectedDevices, deviceSensorData }; - -function cleanupDevices() { - const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000); - let updated = false; - - for (const [deviceId, device] of connectedDevices.entries()) { - if (device.lastSeen < fiveMinutesAgo && device.status === "online") { - connectedDevices.set(deviceId, { ...device, status: "offline" }); - updated = true; - } - } - - return updated; -} - -export function getCurrentDevices() { - cleanupDevices(); - return Array.from(connectedDevices.values()).map((device) => { - const sensorData = deviceSensorData.get(device.id); - return { - ...device, - sensorData: sensorData || null, - }; - }); -} - -export function getDeviceSensorData(deviceId) { - return deviceSensorData.get(deviceId) || null; -} diff --git a/src/routes/(app)/[slug]/+page.server.ts b/src/routes/(app)/[slug]/+page.server.ts index 119d062..4488322 100644 --- a/src/routes/(app)/[slug]/+page.server.ts +++ b/src/routes/(app)/[slug]/+page.server.ts @@ -2,69 +2,36 @@ import { db } from "$lib/server/db"; import * as table from "$lib/server/db/schema"; import { eq } from "drizzle-orm"; import type { PageServerLoad } from "./$types"; -import { getDeviceSensorData } from "$lib/server/mqtt-devices.js"; +import { connect } from "mqtt"; export const load: PageServerLoad = async ({ params }) => { - const floorNumber = Number(params.slug); - - const floorData = await db.select({ - floor: table.floors.floor, - url: table.floors.url - }).from(table.floors).where(eq(table.floors.floor, floorNumber)); - - if (floorData.length > 0 && floorData[0].url && floorData[0].url !== "/") { - try { - const config = JSON.parse(floorData[0].url); - - if (config.devices) { - config.devices = config.devices.map(device => { - const sensorData = getDeviceSensorData(device.id); - return { - ...device, - sensorData: sensorData - }; - }); - } - - return { - slug: params.slug, - floorConfig: config, - hasConfig: true - }; - } catch (e) { - console.error("Error parsing floor configuration:", e); + { + const floor_cnt = await db.select({ floor: table.plans.floor, json: table.plans.plan }).from(table.plans).where(eq(table.plans.floor, params.slug)); + if (floor_cnt.length == 0) { + await db.insert(table.plans).values({ floor: params.slug, plan: { + "regions": [ + { "start": { "x": 100, "y": 100 }, "end": { "x": 400, "y": 100 } }, + { "start": { "x": 400, "y": 100 }, "end": { "x": 400, "y": 300 } }, + { "start": { "x": 400, "y": 300 }, "end": { "x": 100, "y": 300 } }, + { "start": { "x": 100, "y": 300 }, "end": { "x": 100, "y": 100 } } + ], + "doors": [ + { "location": { "x": 240, "y": 100 }, "width": 50, "rotation": 0 } + ], + "furnitures": [ + { + "minBound": { "x": 150, "y": 150 }, + "maxBound": { "x": 200, "y": 200 }, + "equipName": "Table", + "xPlacement": 150, + "yPlacement": 150, + "rotation": 0 + } + ] + }}); } + } - - const floor_cnt = await db.select({ floor: table.plans.floor, json: table.plans.plan }).from(table.plans).where(eq(table.plans.floor, params.slug)); - if (floor_cnt.length == 0) { - await db.insert(table.plans).values({ floor: params.slug, plan: { - "regions": [ - { "start": { "x": 100, "y": 100 }, "end": { "x": 400, "y": 100 } }, - { "start": { "x": 400, "y": 100 }, "end": { "x": 400, "y": 300 } }, - { "start": { "x": 400, "y": 300 }, "end": { "x": 100, "y": 300 } }, - { "start": { "x": 100, "y": 300 }, "end": { "x": 100, "y": 100 } } - ], - "doors": [ - { "location": { "x": 240, "y": 100 }, "width": 50, "rotation": 0 } - ], - "furnitures": [ - { - "minBound": { "x": 150, "y": 150 }, - "maxBound": { "x": 200, "y": 200 }, - "equipName": "Table", - "xPlacement": 150, - "yPlacement": 150, - "rotation": 0 - } - ] - }}); - } - const floor_ = await db.select({ floor: table.plans.floor, json: table.plans.plan }).from(table.plans).where(eq(table.plans.floor, params.slug)); - return { - slug: params.slug, - floor: floor_, - hasConfig: false - }; + return { slug: params.slug, floor: floor_ }; }; diff --git a/src/routes/(app)/[slug]/+page.svelte b/src/routes/(app)/[slug]/+page.svelte index 45c60c6..2f90051 100644 --- a/src/routes/(app)/[slug]/+page.svelte +++ b/src/routes/(app)/[slug]/+page.svelte @@ -1,76 +1,43 @@ -
MQTT Status: {mqttMessage}
-Loading statistics...
-Error loading statistics
-Please try again later
-No data available
-- Statistics will appear once sensor data is collected -
-No data available
-- No data found for the selected time period -
-