update for partial polling, add grist
This commit is contained in:
4
package-lock.json
generated
4
package-lock.json
generated
@@ -28,8 +28,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@dpu/shared": {
|
"node_modules/@dpu/shared": {
|
||||||
"version": "1.8.1",
|
"version": "1.8.4",
|
||||||
"resolved": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git#27dc6f2b1214b8e2aff65de510caea402c2f88db",
|
"resolved": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git#ff4248961b97a84bfdbeed85cd83b007332378ac",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/ws": "^8.18.1",
|
"@types/ws": "^8.18.1",
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
|
|||||||
@@ -35,13 +35,13 @@ export class GristService extends BaseService<GristClient> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getTodayAsId(date = new Date()) {
|
private getTodayAsId(date = new Date()) {
|
||||||
const start = new Date(date.getFullYear(), 0, 0);
|
const start = new Date(date.getFullYear(), 0, 0);
|
||||||
const diff = date.getTime() - start.getTime();
|
const diff = date.getTime() - start.getTime();
|
||||||
return Math.floor(diff / 86400000);
|
return Math.floor(diff / 86400000);
|
||||||
}
|
}
|
||||||
|
|
||||||
transformToPersonalGoals(
|
private transformToPersonalGoals(
|
||||||
obj: Record<string, unknown>,
|
obj: Record<string, unknown>,
|
||||||
): GristRecord_PersonalGoals {
|
): GristRecord_PersonalGoals {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,28 +1,40 @@
|
|||||||
import {
|
import {
|
||||||
|
type API_HA_DeskPosition,
|
||||||
BaseService,
|
BaseService,
|
||||||
|
type ComponentUpdate,
|
||||||
type FullInformation,
|
type FullInformation,
|
||||||
|
type GristRecord_PersonalGoals,
|
||||||
type HomeAssistantDeskPositionResult,
|
type HomeAssistantDeskPositionResult,
|
||||||
type ServiceResult,
|
type ServiceResult,
|
||||||
type TidalGetCurrent,
|
type TidalGetCurrent,
|
||||||
type WsService,
|
type WsService,
|
||||||
} from "@dpu/shared";
|
} from "@dpu/shared";
|
||||||
import { logInfo, logWarning } from "@dpu/shared/dist/logger.js";
|
import { logInfo, logWarning } from "@dpu/shared/dist/logger.js";
|
||||||
|
import type { GristService } from "../grist/service";
|
||||||
import type { HomeAssistantService } from "../homeassistant/service";
|
import type { HomeAssistantService } from "../homeassistant/service";
|
||||||
import type { TidalService } from "../tidal/service";
|
import type { TidalService } from "../tidal/service";
|
||||||
|
|
||||||
export class HomepageService extends BaseService<null> {
|
export class HomepageService extends BaseService<null> {
|
||||||
|
private gristService: GristService;
|
||||||
private haService: HomeAssistantService;
|
private haService: HomeAssistantService;
|
||||||
private tidalService: TidalService;
|
private tidalService: TidalService;
|
||||||
private wsService: WsService;
|
private wsService: WsService;
|
||||||
private pollingInterval: ReturnType<typeof setInterval> | null = null;
|
private pollingIntervals: ReturnType<typeof setInterval>[] = [];
|
||||||
private lastPoll: FullInformation | null = null;
|
private lastPoll: FullInformation = {
|
||||||
|
ha_desk_position: null,
|
||||||
|
ha_temp: null,
|
||||||
|
tidal_current: null,
|
||||||
|
grist_personal_goals: null,
|
||||||
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
gristService: GristService,
|
||||||
haService: HomeAssistantService,
|
haService: HomeAssistantService,
|
||||||
tidalService: TidalService,
|
tidalService: TidalService,
|
||||||
wsService: WsService,
|
wsService: WsService,
|
||||||
) {
|
) {
|
||||||
super(null);
|
super(null);
|
||||||
|
this.gristService = gristService;
|
||||||
this.haService = haService;
|
this.haService = haService;
|
||||||
this.tidalService = tidalService;
|
this.tidalService = tidalService;
|
||||||
this.wsService = wsService;
|
this.wsService = wsService;
|
||||||
@@ -31,23 +43,21 @@ export class HomepageService extends BaseService<null> {
|
|||||||
|
|
||||||
async getFullInformation(): Promise<ServiceResult<FullInformation | string>> {
|
async getFullInformation(): Promise<ServiceResult<FullInformation | string>> {
|
||||||
try {
|
try {
|
||||||
const [desk, temp, song] = await Promise.all([
|
const [desk, temp, tidal, personal_goals] = await Promise.all([
|
||||||
this.haService.getDeskPosition(),
|
this._getDesk(),
|
||||||
this.haService.getTemperatureText(),
|
this._getTemp(),
|
||||||
this.tidalService.getSong(),
|
this._getTidal(),
|
||||||
|
this._getGristPG(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const result = {
|
return this.getSuccessfulResult(
|
||||||
ha_desk_position: desk.successful
|
this.updateFull({
|
||||||
? this.haService.convertPosResultToApiAnswer(
|
ha_desk_position: desk,
|
||||||
desk.result as HomeAssistantDeskPositionResult,
|
ha_temp: temp,
|
||||||
)
|
tidal_current: tidal,
|
||||||
: null,
|
grist_personal_goals: personal_goals,
|
||||||
ha_temp: temp.successful ? temp.result : null,
|
}),
|
||||||
tidal_current: song ? (song.result as TidalGetCurrent) : null,
|
);
|
||||||
};
|
|
||||||
|
|
||||||
return this.getSuccessfulResult(this.updateLastPoll(result));
|
|
||||||
} catch {
|
} catch {
|
||||||
const error_message = "error getting all information";
|
const error_message = "error getting all information";
|
||||||
logWarning(error_message);
|
logWarning(error_message);
|
||||||
@@ -55,35 +65,40 @@ export class HomepageService extends BaseService<null> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLastPoll(newPoll: FullInformation) {
|
private async _getDesk(): Promise<API_HA_DeskPosition | null> {
|
||||||
const updates = [];
|
const desk = await this.haService.getDeskPosition();
|
||||||
if (
|
return desk.successful
|
||||||
this.lastPoll?.ha_desk_position?.is_standing !==
|
? this.haService.convertPosResultToApiAnswer(
|
||||||
newPoll.ha_desk_position?.is_standing
|
desk.result as HomeAssistantDeskPositionResult,
|
||||||
) {
|
)
|
||||||
updates.push({
|
: null;
|
||||||
component: "ha_desk_position",
|
|
||||||
data: newPoll.ha_desk_position,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.lastPoll?.ha_temp !== newPoll.ha_temp) {
|
private async _getTemp(): Promise<string | null> {
|
||||||
updates.push({
|
const temp = await this.haService.getTemperatureText();
|
||||||
component: "ha_temp",
|
return temp.successful ? temp.result : null;
|
||||||
data: newPoll.ha_temp,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
private async _getTidal(): Promise<TidalGetCurrent | null> {
|
||||||
this.lastPoll?.tidal_current?.title !== newPoll.tidal_current?.title ||
|
const tidal = await this.tidalService.getSong();
|
||||||
this.lastPoll?.tidal_current?.status !== newPoll.tidal_current?.status
|
return tidal ? (tidal.result as TidalGetCurrent) : null;
|
||||||
) {
|
|
||||||
updates.push({
|
|
||||||
component: "tidal_current",
|
|
||||||
data: newPoll.tidal_current,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _getGristPG(): Promise<GristRecord_PersonalGoals | null> {
|
||||||
|
const personal_goals = await this.gristService.getToday();
|
||||||
|
return personal_goals.successful
|
||||||
|
? (personal_goals.result as GristRecord_PersonalGoals)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFull(newPoll: FullInformation): FullInformation {
|
||||||
|
const updates: ComponentUpdate[] = [];
|
||||||
|
|
||||||
|
this.updateHaDesk(newPoll.ha_desk_position, updates);
|
||||||
|
this.updateHaTemp(newPoll.ha_temp, updates);
|
||||||
|
this.updateTidal(newPoll.tidal_current, updates);
|
||||||
|
this.updateGristPG(newPoll.grist_personal_goals, updates);
|
||||||
|
|
||||||
if (updates.length > 0) {
|
if (updates.length > 0) {
|
||||||
logInfo("Updating clients");
|
logInfo("Updating clients");
|
||||||
this.wsService.broadcast({
|
this.wsService.broadcast({
|
||||||
@@ -92,16 +107,117 @@ export class HomepageService extends BaseService<null> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastPoll = newPoll;
|
|
||||||
return newPoll;
|
return newPoll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updatePartial(components: string[]): Promise<void> {
|
||||||
|
const updates: ComponentUpdate[] = [];
|
||||||
|
for (const component of components) {
|
||||||
|
switch (component) {
|
||||||
|
case "desk": {
|
||||||
|
this.updateHaDesk(await this._getDesk(), updates);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "temp":
|
||||||
|
this.updateHaTemp(await this._getTemp(), updates);
|
||||||
|
break;
|
||||||
|
case "tidal":
|
||||||
|
this.updateTidal(await this._getTidal(), updates);
|
||||||
|
break;
|
||||||
|
case "grist":
|
||||||
|
this.updateGristPG(await this._getGristPG(), updates);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.wsService.broadcast({
|
||||||
|
type: "update",
|
||||||
|
data: updates,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateHaDesk(
|
||||||
|
new_ha_desk_position: API_HA_DeskPosition | null,
|
||||||
|
updates: ComponentUpdate[],
|
||||||
|
): void {
|
||||||
|
if (
|
||||||
|
this.lastPoll.ha_desk_position?.is_standing !==
|
||||||
|
new_ha_desk_position?.is_standing
|
||||||
|
) {
|
||||||
|
this.lastPoll.ha_desk_position = new_ha_desk_position;
|
||||||
|
updates.push({
|
||||||
|
component: "ha_desk_position",
|
||||||
|
data: new_ha_desk_position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private 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({
|
||||||
|
component: "ha_temp",
|
||||||
|
data: new_ha_temp,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateTidal(
|
||||||
|
new_tidal_current: TidalGetCurrent | null,
|
||||||
|
updates: ComponentUpdate[],
|
||||||
|
): void {
|
||||||
|
if (
|
||||||
|
this.lastPoll.tidal_current?.title !== new_tidal_current?.title ||
|
||||||
|
this.lastPoll.tidal_current?.artists !== new_tidal_current?.artists ||
|
||||||
|
this.lastPoll.tidal_current?.status !== new_tidal_current?.status ||
|
||||||
|
this.lastPoll.tidal_current?.volume !== new_tidal_current?.volume
|
||||||
|
) {
|
||||||
|
this.lastPoll.tidal_current = new_tidal_current;
|
||||||
|
updates.push({
|
||||||
|
component: "tidal_current",
|
||||||
|
data: new_tidal_current,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateGristPG(
|
||||||
|
new_grist_personal_goals: GristRecord_PersonalGoals | null,
|
||||||
|
updates: ComponentUpdate[],
|
||||||
|
): void {
|
||||||
|
if (
|
||||||
|
this.lastPoll.grist_personal_goals?.went_outside !==
|
||||||
|
new_grist_personal_goals?.went_outside ||
|
||||||
|
this.lastPoll.grist_personal_goals?.standing !==
|
||||||
|
new_grist_personal_goals?.standing ||
|
||||||
|
this.lastPoll.grist_personal_goals?.steps !==
|
||||||
|
new_grist_personal_goals?.steps ||
|
||||||
|
this.lastPoll.grist_personal_goals?.pushups !==
|
||||||
|
new_grist_personal_goals?.pushups ||
|
||||||
|
this.lastPoll.grist_personal_goals?.squats !==
|
||||||
|
new_grist_personal_goals?.squats ||
|
||||||
|
this.lastPoll.grist_personal_goals?.leg_raises !==
|
||||||
|
new_grist_personal_goals?.leg_raises ||
|
||||||
|
this.lastPoll.grist_personal_goals?.stairs !==
|
||||||
|
new_grist_personal_goals?.stairs
|
||||||
|
) {
|
||||||
|
this.lastPoll.grist_personal_goals = new_grist_personal_goals;
|
||||||
|
updates.push({
|
||||||
|
component: "grist_personal_goals",
|
||||||
|
data: new_grist_personal_goals,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
listenForClientChange(): void {
|
listenForClientChange(): void {
|
||||||
this.wsService.onClientChange((clients: number) => {
|
this.wsService.onClientChange((clients: number) => {
|
||||||
if (clients === 0) {
|
if (clients === 0) {
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
} else {
|
} else {
|
||||||
if (!this.pollingInterval) {
|
if (this.pollingIntervals.length === 0) {
|
||||||
this.startPolling();
|
this.startPolling();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,17 +226,24 @@ export class HomepageService extends BaseService<null> {
|
|||||||
|
|
||||||
startPolling(): void {
|
startPolling(): void {
|
||||||
logInfo("Polling started");
|
logInfo("Polling started");
|
||||||
this.pollingInterval = setInterval(() => {
|
|
||||||
logInfo("Polling now");
|
const config: [string[], number][] = [
|
||||||
this.getFullInformation();
|
[["tidal"], 20_000],
|
||||||
}, 30000);
|
[["desk"], 60_000],
|
||||||
|
[["temp", "grist"], 600_000],
|
||||||
|
];
|
||||||
|
|
||||||
|
this.pollingIntervals = config.map(([components, interval]) =>
|
||||||
|
setInterval(() => {
|
||||||
|
logInfo(`Polling ${components.join(", ")}`);
|
||||||
|
this.updatePartial(components);
|
||||||
|
}, interval),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
stopPolling(): void {
|
stopPolling(): void {
|
||||||
logInfo("Polling ended");
|
logInfo("Polling ended");
|
||||||
if (this.pollingInterval) {
|
this.pollingIntervals.forEach(clearInterval);
|
||||||
clearInterval(this.pollingInterval);
|
this.pollingIntervals = [];
|
||||||
this.pollingInterval = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user