generated from mantinedev/next-pages-template
-
-
Notifications
You must be signed in to change notification settings - Fork 258
/
entity-state.ts
123 lines (101 loc) · 4.19 KB
/
entity-state.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { TRPCError } from '@trpc/server';
import Consola from 'consola';
import { ZodError, z } from 'zod';
import { createTRPCRouter, protectedProcedure } from '../../trpc';
import { findAppProperty } from '~/tools/client/app-properties';
import { getConfig } from '~/tools/config/getConfig';
import { HomeAssistantSingleton } from '~/tools/singleton/HomeAssistantSingleton';
import { ISmartHomeEntityStateWidget } from '~/widgets/smart-home/entity-state/entity-state.widget';
export const smartHomeEntityStateRouter = createTRPCRouter({
retrieveStatus: protectedProcedure
.input(
z.object({
configName: z.string(),
// TODO: passing entity ID directly can be unsafe
entityId: z.string().regex(/^[A-Za-z0-9-_\.]+$/),
}),
)
.query(async ({ input }) => {
const config = getConfig(input.configName);
const instances = config.apps.filter((app) => app.integration?.type == 'homeAssistant');
for (const instance of instances) {
const url = new URL(instance.url);
const client = HomeAssistantSingleton.getOrSet(url, findAppProperty(instance, 'apiKey'));
const state = await client.getEntityState(input.entityId);
if (!state.success) {
if (!(state.error instanceof ZodError)) {
continue;
}
throw new TRPCError({
code: 'NOT_IMPLEMENTED',
message: `Unable to handle Home Assistant entity state. This may be due to malformed response or unknown entity type. Check log for details`,
});
}
if (!state.data) {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: `Home Assistant: Unable to connect to app '${instance.id}'. Check logs for details`,
});
}
return state.data;
}
return null;
}),
triggerAutomation: protectedProcedure
.input(z.object({
widgetId: z.string(),
configName: z.string(),
})).mutation(async ({ input }) => {
const config = getConfig(input.configName);
const widget = config.widgets.find(widget => widget.id === input.widgetId) as ISmartHomeEntityStateWidget | null;
if (!widget) {
Consola.error(`Referenced widget ${input.widgetId} does not exist on backend.`);
throw new TRPCError({
code: 'CONFLICT',
message: 'Referenced widget does not exist on backend',
});
}
if (!widget.properties.automationId || widget.properties.automationId.length < 1) {
Consola.error(`Referenced widget ${input.widgetId} does not have the required property set.`);
throw new TRPCError({
code: 'CONFLICT',
message: 'Referenced widget does not have the required property',
});
}
const instances = config.apps.filter((app) => app.integration?.type == 'homeAssistant');
for (const instance of instances) {
const url = new URL(instance.url);
const client = HomeAssistantSingleton.getOrSet(url, findAppProperty(instance, 'apiKey'));
const state = await client.triggerAutomation(widget.properties.automationId);
if (state) {
return true;
}
}
return false;
}),
triggerToggle: protectedProcedure
.input(z.object({
widgetId: z.string(),
configName: z.string()
})).mutation(async ({ input }) => {
const config = getConfig(input.configName);
const widget = config.widgets.find(widget => widget.id === input.widgetId) as ISmartHomeEntityStateWidget | null;
if (!widget) {
Consola.error(`Referenced widget ${input.widgetId} does not exist on backend.`);
throw new TRPCError({
code: 'CONFLICT',
message: 'Referenced widget does not exist on backend',
});
}
const instances = config.apps.filter((app) => app.integration?.type == 'homeAssistant');
for (const instance of instances) {
const url = new URL(instance.url);
const client = HomeAssistantSingleton.getOrSet(url, findAppProperty(instance, 'apiKey'));
const state = await client.triggerToggle(widget.properties.entityId);
if (state) {
return true;
}
}
return false;
}),
});