-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
120 lines (110 loc) · 3.51 KB
/
index.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
import dotenv from 'dotenv';
import config from 'config';
import { logger } from './utils/logger';
import { home, listenToSocket, locations } from './homely/api';
import { init } from './db/init';
import { discover } from './entities/discover';
import { Device, Home } from './models/home';
import { gateway } from './entities/gateway';
import { createDevices } from './entities/devices';
import { getAndCreateEntities } from './entities/entities';
import { createEntitiesMqtt } from './entities/create-entities-mqtt';
import {
publish,
publishEntityChanges,
} from './entities/publish-entity-changes';
import { scheduleJob } from 'node-schedule';
import { HomelyFeature } from './db';
import { HomelyAlarmStateToHomeAssistant } from './models/alarm-state';
dotenv.config();
logger.info('Starting service');
if (!process.env.MQTT_HOST) {
logger.fatal('MQTT_HOST is not defined');
process.exit();
}
if (!process.env.HOMELY_USER) {
logger.fatal('HOMELY_USER is not defined');
process.exit();
}
if (!process.env.HOMELY_PASSWORD) {
logger.fatal('HOMELY_PASSWORD is not defined');
process.exit();
}
const pollHomely = (locationId: string) => {
const schedule = config.get<string | undefined>('polling.schedule');
scheduleJob(schedule ?? '*/30 * * * *', async () => {
const homeData = await home(locationId);
await updateAndCreateEntities(homeData);
});
};
async function updateAndCreateEntities(homeData: Home) {
const { device: alarmDevice, feature: gatewayFeature } = gateway(homeData);
const devices: Array<Device> = [
alarmDevice,
...homeData.devices.map((d) => ({
...d,
homeId: homeData.locationId,
})),
];
await createDevices(devices);
const discoveredDevices = discover(homeData);
discoveredDevices.forEach((dev) =>
publish(dev.availability_topic, dev.online ? 'online' : 'offline')
);
publish(gatewayFeature.availability_topic, 'online');
await getAndCreateEntities(discoveredDevices, gatewayFeature);
await createEntitiesMqtt();
await publishEntityChanges(discoveredDevices, devices);
const alarmState = HomelyAlarmStateToHomeAssistant[homeData.alarmState];
publish(gatewayFeature.state_topic, alarmState);
}
process.on('exit', () => {
HomelyFeature.findAll({})
.then((features) => {
features.forEach((f) => {
if (f.state_topic) {
publish(f.availability_topic, 'offline');
}
});
})
.catch(() => {
/*already exiting, skip.*/
});
});
(async function () {
await init();
try {
const homes = await locations();
logger.info(`Loaded ${homes.length} homes`);
logger.debug(homes);
try {
for (const location of homes) {
const homeData = await home(location.locationId);
if (process.env.GET_LOCATION) {
logger.debug({
message: `Getting location info for ${location.name}. The process will exit afterwards`,
data: homeData,
});
process.exit(1);
}
logger.debug(`Home data retrieved from homely:
${JSON.stringify(homeData, null, 2)}`);
await updateAndCreateEntities(homeData);
pollHomely(location.locationId);
await listenToSocket(location.locationId);
}
} catch (ex) {
logger.fatal({
message: `Application encountered a fatal error and will exit.`,
error: ex,
});
process.exit();
}
} catch (ex) {
logger.fatal({
message: `Application encountered a fatal error and will exit.`,
error: ex,
});
process.exit();
}
})();