Compare commits

..

5 Commits

Author SHA1 Message Date
Darius
197fda9ad9 fix timezone issues 2026-03-06 01:30:05 +01:00
Darius
6e61cff231 steps private => public 2026-03-05 20:18:42 +01:00
Darius
4d7efaf6dc bugfix import 2026-03-05 20:00:46 +01:00
Darius
4569d786d8 status => stats 2026-03-05 19:52:24 +01:00
Darius
963c0ca9a6 status => stats 2026-03-05 19:48:53 +01:00
9 changed files with 139 additions and 127 deletions

160
package-lock.json generated
View File

@@ -33,8 +33,8 @@
}
},
"node_modules/@dpu/shared": {
"version": "1.9.9",
"resolved": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git#d73d98068a779569e3be375f077de1e63f9efa9c",
"version": "1.10.0",
"resolved": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git#1fcc02ef1f29d72a035042180f29a80f4351c19c",
"dependencies": {
"@types/ws": "^8.18.1",
"axios": "^1.7.9",
@@ -749,27 +749,6 @@
"ws": "^8.16.0"
}
},
"node_modules/@isaacs/balanced-match": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
"license": "MIT",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/@isaacs/brace-expansion": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz",
"integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==",
"license": "MIT",
"dependencies": {
"@isaacs/balanced-match": "^4.0.1"
},
"engines": {
"node": "20 || >=22"
}
},
"node_modules/@lukeed/ms": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz",
@@ -803,9 +782,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.10.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.12.tgz",
"integrity": "sha512-68e+T28EbdmLSTkPgs3+UacC6rzmqrcWFPQs1C8mwJhI/r5Uxr0yEuQotczNRROd1gq30NGxee+fo0rSIxpyAw==",
"version": "24.11.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.11.0.tgz",
"integrity": "sha512-fPxQqz4VTgPI/IQ+lj9r0h+fDR66bzoeMGHp8ASee+32OSGIkeASsoZuJixsQoVef1QJbeubcPBxKk22QVoWdw==",
"license": "MIT",
"dependencies": {
"undici-types": "~7.16.0"
@@ -827,9 +806,9 @@
"license": "MIT"
},
"node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
@@ -875,9 +854,19 @@
}
},
"node_modules/avvio": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/avvio/-/avvio-9.1.0.tgz",
"integrity": "sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==",
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/avvio/-/avvio-9.2.0.tgz",
"integrity": "sha512-2t/sy01ArdHHE0vRH5Hsay+RtCZt3dLPji7W7/MMOCEgze5b7SNDC4j5H6FnVgPkI1MTNFGzHdHrVXDDl7QSSQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "MIT",
"dependencies": {
"@fastify/error": "^4.0.0",
@@ -885,9 +874,9 @@
}
},
"node_modules/axios": {
"version": "1.13.5",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz",
"integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
"version": "1.13.6",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz",
"integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.11",
@@ -895,6 +884,15 @@
"proxy-from-env": "^1.1.0"
}
},
"node_modules/balanced-match": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
"license": "MIT",
"engines": {
"node": "18 || 20 || >=22"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -949,6 +947,18 @@
"readable-stream": "^3.4.0"
}
},
"node_modules/brace-expansion": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
"integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
},
"engines": {
"node": "18 || 20 || >=22"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
@@ -1120,9 +1130,9 @@
}
},
"node_modules/dotenv": {
"version": "17.2.4",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.4.tgz",
"integrity": "sha512-mudtfb4zRB4bVvdj0xRo+e6duH1csJRM8IukBqfTRvHotn9+LBXB8ynAidP9zHqoRC/fsllXgk4kCKlR21fIhw==",
"version": "17.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
"integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
@@ -1330,9 +1340,9 @@
"license": "BSD-3-Clause"
},
"node_modules/fastify": {
"version": "5.7.4",
"resolved": "https://registry.npmjs.org/fastify/-/fastify-5.7.4.tgz",
"integrity": "sha512-e6l5NsRdaEP8rdD8VR0ErJASeyaRbzXYpmkrpr2SuvuMq6Si3lvsaVy5C+7gLanEkvjpMDzBXWE5HPeb/hgTxA==",
"version": "5.8.1",
"resolved": "https://registry.npmjs.org/fastify/-/fastify-5.8.1.tgz",
"integrity": "sha512-y0kicFvvn7CYWoPOVLOcvn4YyKQz03DIY7UxmyOy21/J8eXm09R+tmb+tVDBW5h+pja30cHI5dqUcSlvY86V2A==",
"funding": [
{
"type": "github",
@@ -1355,7 +1365,7 @@
"fast-json-stringify": "^6.0.0",
"find-my-way": "^9.0.0",
"light-my-request": "^6.0.0",
"pino": "^10.1.0",
"pino": "^9.14.0 || ^10.1.0",
"process-warning": "^5.0.0",
"rfdc": "^1.3.1",
"secure-json-parse": "^4.0.0",
@@ -1426,9 +1436,9 @@
"license": "MIT"
},
"node_modules/find-my-way": {
"version": "9.4.0",
"resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-9.4.0.tgz",
"integrity": "sha512-5Ye4vHsypZRYtS01ob/iwHzGRUDELlsoCftI/OZFhcLs1M0tkGPcXldE80TAZC5yYuJMBPJQQ43UHlqbJWiX2w==",
"version": "9.5.0",
"resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-9.5.0.tgz",
"integrity": "sha512-VW2RfnmscZO5KgBY5XVyKREMW5nMZcxDy+buTOsL+zIPnBlbKm+00sgzoQzq1EVh4aALZLfKdwv6atBGcjvjrQ==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
@@ -1562,17 +1572,17 @@
"license": "MIT"
},
"node_modules/glob": {
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/glob/-/glob-13.0.1.tgz",
"integrity": "sha512-B7U/vJpE3DkJ5WXTgTpTRN63uV42DseiXXKMwG14LQBXmsdeIoHAPbU/MEo6II0k5ED74uc2ZGTC6MwHFQhF6w==",
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz",
"integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==",
"license": "BlueOak-1.0.0",
"dependencies": {
"minimatch": "^10.1.2",
"minipass": "^7.1.2",
"path-scurry": "^2.0.0"
"minimatch": "^10.2.2",
"minipass": "^7.1.3",
"path-scurry": "^2.0.2"
},
"engines": {
"node": "20 || >=22"
"node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -1770,9 +1780,9 @@
"license": "MIT"
},
"node_modules/lru-cache": {
"version": "11.2.5",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz",
"integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==",
"version": "11.2.6",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz",
"integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==",
"license": "BlueOak-1.0.0",
"engines": {
"node": "20 || >=22"
@@ -1842,15 +1852,15 @@
}
},
"node_modules/minimatch": {
"version": "10.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.2.tgz",
"integrity": "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==",
"version": "10.2.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
"integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/brace-expansion": "^5.0.1"
"brace-expansion": "^5.0.2"
},
"engines": {
"node": "20 || >=22"
"node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -1866,10 +1876,10 @@
}
},
"node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
"integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=16 || 14 >=14.17"
}
@@ -1936,16 +1946,16 @@
"license": "BlueOak-1.0.0"
},
"node_modules/path-scurry": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz",
"integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
"integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
},
"engines": {
"node": "20 || >=22"
"node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -2136,12 +2146,12 @@
"license": "MIT"
},
"node_modules/rimraf": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz",
"integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==",
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz",
"integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==",
"license": "BlueOak-1.0.0",
"dependencies": {
"glob": "^13.0.0",
"glob": "^13.0.3",
"package-json-from-dist": "^1.0.1"
},
"bin": {
@@ -2288,9 +2298,9 @@
}
},
"node_modules/sonic-boom": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz",
"integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==",
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz",
"integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==",
"license": "MIT",
"dependencies": {
"atomic-sleep": "^1.0.0"

View File

@@ -6,6 +6,8 @@ export const Config = {
api_key: process.env.API_KEY,
port: process.env.PORT || "8080",
timezone: process.env.TIMEZONE || "Europe/Berlin",
gadgetbridge: {
db_path:
process.env.GADGETBRIDGE_DB_PATH || "src/gadgetbridge/db/Gadgetbridge.db",

View File

@@ -1,11 +1,7 @@
import { watchFile } from "node:fs";
import type { StepRow } from "@dpu/shared";
import Database from "better-sqlite3";
export type StepRow = {
date: string;
steps: number;
};
export class GadgetbridgeClient {
private db: Database.Database;
private readonly dbPath: string;
@@ -29,29 +25,32 @@ export class GadgetbridgeClient {
return db;
}
getStepsPerDay(fromTimestamp: number, toTimestamp: number): StepRow[] {
getStepsPerDay(fromTimestamp: number, toTimestamp: number, utcOffset: string): StepRow[] {
const stmt = this.db.prepare(`
SELECT date, SUM(steps) AS steps
FROM (
SELECT
DATE(TIMESTAMP, 'unixepoch', 'localtime') AS date,
DATE(TIMESTAMP, 'unixepoch', ?) AS date,
STEPS AS steps
FROM HUAMI_EXTENDED_ACTIVITY_SAMPLE
WHERE TIMESTAMP >= ? AND TIMESTAMP < ?
UNION ALL
SELECT date, steps
FROM old.steps
WHERE date >= DATE(?, 'unixepoch', 'localtime')
AND date < DATE(?, 'unixepoch', 'localtime')
WHERE date >= DATE(?, 'unixepoch', ?)
AND date < DATE(?, 'unixepoch', ?)
)
GROUP BY date
ORDER BY date
`);
return stmt.all(
utcOffset,
fromTimestamp,
toTimestamp,
fromTimestamp,
utcOffset,
toTimestamp,
utcOffset,
) as StepRow[];
}
}

View File

@@ -4,7 +4,7 @@ import type { GadgetbridgeService } from "./service.js";
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
export async function privateGadgetbridgeRoutes(
export async function publicGadgetbridgeRoutes(
fastify: FastifyInstance,
{ gadgetbridgeService }: { gadgetbridgeService: GadgetbridgeService },
) {
@@ -34,13 +34,7 @@ export async function privateGadgetbridgeRoutes(
async (request, reply) => {
const { from, to } = request.query as any;
const fromDate = new Date(`${from}T00:00:00`);
const toDate = new Date(`${to}T00:00:00`);
const service_result = gadgetbridgeService.getStepsForTimespan(
fromDate,
toDate,
);
const service_result = gadgetbridgeService.getStepsForTimespan(from, to);
if (!service_result.successful) {
reply.code(418);

View File

@@ -1,17 +1,24 @@
import { BaseService, type ServiceResult } from "@dpu/shared";
import type { GadgetbridgeClient, StepRow } from "./client.js";
import { BaseService, type ServiceResult, type StepRow } from "@dpu/shared";
import { DateTime } from "luxon";
import { Config } from "../config.js";
import type { GadgetbridgeClient } from "./client.js";
export class GadgetbridgeService extends BaseService<GadgetbridgeClient> {
getStepsForTimespan(
from: Date,
to: Date,
): ServiceResult<StepRow[] | string> {
getStepsForTimespan(from: string, to: string): ServiceResult<StepRow[] | string> {
try {
const fromTs = Math.floor(from.getTime() / 1000);
// Add one day to make `to` inclusive
const toTs = Math.floor(to.getTime() / 1000) + 86400;
const tz = Config.timezone;
const fromDt = DateTime.fromISO(from, { zone: tz }).startOf("day");
const toDt = DateTime.fromISO(to, { zone: tz }).startOf("day").plus({ days: 1 });
const rows = this.getClient().getStepsPerDay(fromTs, toTs);
const fromTs = Math.floor(fromDt.toSeconds());
const toTs = Math.floor(toDt.toSeconds());
const offsetMinutes = fromDt.offset;
const sign = offsetMinutes >= 0 ? "+" : "-";
const abs = Math.abs(offsetMinutes);
const utcOffset = `${sign}${String(Math.floor(abs / 60)).padStart(2, "0")}:${String(abs % 60).padStart(2, "0")}`;
const rows = this.getClient().getStepsPerDay(fromTs, toTs, utcOffset);
return this.getSuccessfulResult(rows);
} catch (error) {
return this.getErrorResult(

View File

@@ -3,7 +3,7 @@ import {
type GristRecord_PersonalGoals,
type HA_Update,
type HomeAssistantEntity,
StatusComponent,
StatsComponent,
type TidalGetCurrent,
} from "@dpu/shared";
import type { FastifyInstance, FastifyReply } from "fastify";
@@ -36,7 +36,7 @@ export async function privateHomepageRoutes(
{
preHandler: verifyAPIKey,
schema: {
description: "Update information for component on dpu status page",
description: "Update information for component on dpu stats page",
tags: ["homepage"],
body: z.custom<GristRecord_PersonalGoals>(),
response: {
@@ -56,7 +56,7 @@ export async function privateHomepageRoutes(
}
const service_result = await hpService.updatePartial([
{
component: StatusComponent.GRIST_PERSONAL_GOALS,
component: StatsComponent.GRIST_PERSONAL_GOALS,
data: gristService.transformToPersonalGoals(record),
},
]);
@@ -75,7 +75,7 @@ export async function privateHomepageRoutes(
{
preHandler: verifyAPIKey,
schema: {
description: "Update information for component on dpu status page",
description: "Update information for component on dpu stats page",
tags: ["homepage"],
body: z.custom<unknown>(),
response: {
@@ -100,7 +100,7 @@ export async function privateHomepageRoutes(
switch (ha_update.entity_id) {
case Config.homeassistant.id_sensor_desk_binary: {
updates.push({
component: StatusComponent.HA_DESK_POSITION,
component: StatsComponent.HA_DESK_POSITION,
data: haService.convertPosResultToApiAnswer(
haService.convertHaEntityToPosResult(ha_entity),
),
@@ -109,7 +109,7 @@ export async function privateHomepageRoutes(
}
case Config.homeassistant.id_sensor_roomtemp:
updates.push({
component: StatusComponent.HA_TEMP,
component: StatsComponent.HA_TEMP,
data: ha_entity.state,
});
break;
@@ -132,7 +132,7 @@ export async function privateHomepageRoutes(
{
preHandler: verifyAPIKey,
schema: {
description: "Update information for component on dpu status page",
description: "Update information for component on dpu stats page",
tags: ["homepage"],
body: z.custom<TidalGetCurrent>(),
response: {
@@ -148,7 +148,7 @@ export async function privateHomepageRoutes(
const update = request.body as TidalGetCurrent;
const service_result = await hpService.updatePartial([
{
component: StatusComponent.TIDAL_CURRENT,
component: StatsComponent.TIDAL_CURRENT,
data: update,
},
]);

View File

@@ -7,7 +7,7 @@ import {
type GristRecord_PersonalGoals,
type HomeAssistantDeskPositionResult,
type ServiceResult,
StatusComponent,
StatsComponent,
type TidalGetCurrent,
type WsService,
} from "@dpu/shared";
@@ -75,11 +75,11 @@ export class HomepageService extends BaseService<null> {
try {
const [desk, temp, tidal, personal_goals] = await this._getAll();
const updates: ComponentUpdate[] = [
createComponentUpdate(StatusComponent.HA_DESK_POSITION, desk),
createComponentUpdate(StatusComponent.HA_TEMP, temp),
createComponentUpdate(StatusComponent.TIDAL_CURRENT, tidal),
createComponentUpdate(StatsComponent.HA_DESK_POSITION, desk),
createComponentUpdate(StatsComponent.HA_TEMP, temp),
createComponentUpdate(StatsComponent.TIDAL_CURRENT, tidal),
createComponentUpdate(
StatusComponent.GRIST_PERSONAL_GOALS,
StatsComponent.GRIST_PERSONAL_GOALS,
personal_goals,
),
];
@@ -171,26 +171,26 @@ export class HomepageService extends BaseService<null> {
const updates: ComponentUpdate[] = [];
for (const component of components) {
switch (component.component) {
case StatusComponent.HA_DESK_POSITION: {
case StatsComponent.HA_DESK_POSITION: {
this.updateHaDesk(
(component.data as API_HA_DeskPosition) ?? (await this._getDesk()),
updates,
);
break;
}
case StatusComponent.HA_TEMP:
case StatsComponent.HA_TEMP:
this.updateHaTemp(
(component.data as string) ?? (await this._getTemp()),
updates,
);
break;
case StatusComponent.TIDAL_CURRENT:
case StatsComponent.TIDAL_CURRENT:
this.updateTidal(
(component.data as TidalGetCurrent) ?? (await this._getTidal()),
updates,
);
break;
case StatusComponent.GRIST_PERSONAL_GOALS:
case StatsComponent.GRIST_PERSONAL_GOALS:
this.updateGristPG(
(component.data as GristRecord_PersonalGoals) ??
(await this._getGristPG()),
@@ -220,7 +220,7 @@ export class HomepageService extends BaseService<null> {
this.lastPoll.ha_desk_position = new_ha_desk_position;
updates.push(
createComponentUpdate(
StatusComponent.HA_DESK_POSITION,
StatsComponent.HA_DESK_POSITION,
new_ha_desk_position,
),
);
@@ -230,7 +230,7 @@ export class HomepageService extends BaseService<null> {
updateHaTemp(new_ha_temp: string | null, updates: ComponentUpdate[]): void {
if (this.lastPoll.ha_temp !== new_ha_temp) {
this.lastPoll.ha_temp = new_ha_temp;
updates.push(createComponentUpdate(StatusComponent.HA_TEMP, new_ha_temp));
updates.push(createComponentUpdate(StatsComponent.HA_TEMP, new_ha_temp));
}
}
@@ -246,7 +246,7 @@ export class HomepageService extends BaseService<null> {
) {
this.lastPoll.tidal_current = new_tidal_current;
updates.push(
createComponentUpdate(StatusComponent.TIDAL_CURRENT, new_tidal_current),
createComponentUpdate(StatsComponent.TIDAL_CURRENT, new_tidal_current),
);
}
}
@@ -274,7 +274,7 @@ export class HomepageService extends BaseService<null> {
this.lastPoll.grist_personal_goals = new_grist_personal_goals;
updates.push(
createComponentUpdate(
StatusComponent.GRIST_PERSONAL_GOALS,
StatsComponent.GRIST_PERSONAL_GOALS,
new_grist_personal_goals,
),
);

View File

@@ -20,7 +20,7 @@ import { SwaggerTheme, SwaggerThemeNameEnum } from "swagger-themes";
import { z } from "zod";
import { Config } from "./config.js";
import { GadgetbridgeClient } from "./gadgetbridge/client.js";
import { privateGadgetbridgeRoutes } from "./gadgetbridge/private-routes.js";
import { publicGadgetbridgeRoutes } from "./gadgetbridge/public-routes.js";
import { GadgetbridgeService } from "./gadgetbridge/service.js";
import { GristClient } from "./grist/client.js";
import { privateGristRoutes } from "./grist/private-routes.js";
@@ -178,7 +178,7 @@ async function verifyAPIKey(
// Register routes
await publicServer.register(publicWsRoutes, { wsService, hpService });
await privateServer.register(privateGadgetbridgeRoutes, {
await publicServer.register(publicGadgetbridgeRoutes, {
gadgetbridgeService,
});
await privateServer.register(privateGristRoutes, { gristService });

View File

@@ -13,7 +13,7 @@ export async function publicWsRoutes(
},
) {
fastify.get(
"/dpu/status/events",
"/dpu/stats/events",
{
schema: {
description: "Register for WebSocket events",
@@ -25,7 +25,7 @@ export async function publicWsRoutes(
(socket, _request) => {
wsService.addClient(socket);
socket.send(JSON.stringify({ type: "message", data: "Connected" }));
hpService.sendFullInformationToSocket(socket)
hpService.sendFullInformationToSocket(socket);
logInfo(`Connection for client established`);
socket.on("close", () => {