hoffmation-base 0.1.1 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/.eslintrc.js +27 -27
  2. package/.github/workflows/npm-publish.yml +50 -0
  3. package/.prettierrc.js +9 -9
  4. package/LICENSE +21 -21
  5. package/index.js +1 -1
  6. package/models/connectionCallbacks.ts +13 -13
  7. package/models/daytime.ts +3 -3
  8. package/models/deviceConfig.ts +8 -8
  9. package/models/dimmerSettings.ts +5 -5
  10. package/models/iTemperaturDataPoint.ts +9 -9
  11. package/models/lampSettings.ts +5 -5
  12. package/models/ledSettings.ts +19 -19
  13. package/models/logLevel.ts +9 -9
  14. package/models/persistence/BasicRoomInfo.ts +3 -3
  15. package/models/persistence/DailyMovementCount.ts +3 -3
  16. package/models/persistence/RoomDetailInfo.ts +4 -4
  17. package/models/persistence/temperaturDataPoint.ts +12 -12
  18. package/models/persistence/todaysCount.ts +3 -3
  19. package/models/rooms/RoomBase.ts +357 -357
  20. package/models/rooms/RoomSettings/RoomSettings.ts +159 -159
  21. package/models/rooms/RoomSettings/hmIPRoomSettings.ts +53 -53
  22. package/models/rooms/RoomSettings/iRoomDefaultSettings.ts +17 -17
  23. package/models/rooms/RoomSettings/readme.md +17 -17
  24. package/models/rooms/RoomSettings/zigbeeRoomSettings.ts +51 -51
  25. package/models/rooms/iRoomImportEnforcer.ts +3 -3
  26. package/models/rooms/readme.md +11 -11
  27. package/models/temperaturSettings.ts +22 -22
  28. package/models/timeCallback.ts +90 -90
  29. package/package.json +1 -1
  30. package/server/config/config-readme.md +19 -19
  31. package/server/config/iConfig.ts +53 -53
  32. package/server/config/private/mainConfig.json +64 -64
  33. package/server/devices/DeviceInfo.ts +66 -66
  34. package/server/devices/Griffe.ts +31 -31
  35. package/server/devices/Heizgruppen.ts +91 -91
  36. package/server/devices/Rollos.ts +48 -48
  37. package/server/devices/deviceUpdater.ts +72 -72
  38. package/server/devices/devices.ts +189 -189
  39. package/server/devices/groups/fensterGroup.ts +175 -175
  40. package/server/devices/groups/heatGroup.ts +32 -32
  41. package/server/devices/groups/lampenGroup.ts +88 -88
  42. package/server/devices/groups/praesenzGroup.ts +182 -182
  43. package/server/devices/groups/smokeGroup.ts +16 -16
  44. package/server/devices/groups/sonosGroup.ts +33 -33
  45. package/server/devices/groups/tasterGroup.ts +48 -48
  46. package/server/devices/groups/waterGroup.ts +16 -16
  47. package/server/devices/hmIPDevices/Fenster.ts +114 -114
  48. package/server/devices/hmIPDevices/FensterPosition.ts +5 -5
  49. package/server/devices/hmIPDevices/TuerPosition.ts +4 -4
  50. package/server/devices/hmIPDevices/hmIpBewegung.ts +126 -126
  51. package/server/devices/hmIPDevices/hmIpDevice.ts +90 -90
  52. package/server/devices/hmIPDevices/hmIpDeviceType.ts +14 -14
  53. package/server/devices/hmIPDevices/hmIpGriff.ts +143 -143
  54. package/server/devices/hmIPDevices/hmIpHeizgruppe.ts +172 -172
  55. package/server/devices/hmIPDevices/hmIpHeizung.ts +69 -69
  56. package/server/devices/hmIPDevices/hmIpLampe.ts +119 -119
  57. package/server/devices/hmIPDevices/hmIpPraezenz.ts +99 -99
  58. package/server/devices/hmIPDevices/hmIpRoll.ts +133 -133
  59. package/server/devices/hmIPDevices/hmIpTaster.ts +82 -73
  60. package/server/devices/hmIPDevices/hmIpTherm.ts +19 -19
  61. package/server/devices/hmIPDevices/hmIpTuer.ts +115 -115
  62. package/server/devices/hmIPDevices/hmIpWippe.ts +55 -55
  63. package/server/devices/iDeviceUpdater.ts +4 -4
  64. package/server/devices/iIoBrokerDevice.ts +44 -44
  65. package/server/devices/iTaster.ts +6 -0
  66. package/server/devices/{hmIPDevices/hmIpTaste.ts → taste.ts} +84 -72
  67. package/server/devices/wledDevice.ts +124 -124
  68. package/server/devices/zigbee/ZigbeeActuator.ts +113 -113
  69. package/server/devices/zigbee/zigbeeAquaraVibra.ts +171 -171
  70. package/server/devices/zigbee/zigbeeAquaraWater.ts +94 -94
  71. package/server/devices/zigbee/zigbeeBlitzShp.ts +77 -77
  72. package/server/devices/zigbee/zigbeeDevice.ts +115 -115
  73. package/server/devices/zigbee/zigbeeDeviceType.ts +13 -13
  74. package/server/devices/zigbee/zigbeeHeimanSmoke.ts +99 -99
  75. package/server/devices/zigbee/zigbeeIkeaSteckdose.ts +31 -31
  76. package/server/devices/zigbee/zigbeeIlluActuator.ts +37 -37
  77. package/server/devices/zigbee/zigbeeIlluDimmer.ts +165 -165
  78. package/server/devices/zigbee/zigbeeIlluLampe.ts +33 -33
  79. package/server/devices/zigbee/zigbeeIlluLedRGBCCT.ts +137 -137
  80. package/server/ioBroker/connection.ts +1655 -1655
  81. package/server/ioBroker/ioBroker.main.ts +99 -99
  82. package/server/ioBroker/socketIOAuthInfo.ts +5 -5
  83. package/server/ioBroker/socketIOConnectOptions.ts +6 -6
  84. package/server/ioBroker/socketIOLogging.ts +29 -29
  85. package/server/ioBroker/socketIOVisCommand.ts +11 -11
  86. package/server/services/HTTPSOptions.ts +14 -14
  87. package/server/services/Sonos/OwnSonosDevices.ts +9 -0
  88. package/server/services/Sonos/mp3-server.ts +75 -75
  89. package/server/services/Sonos/polly-service.ts +100 -100
  90. package/server/services/Sonos/sonos-service.ts +194 -199
  91. package/server/services/Telegram/telegram-Commands.ts +237 -215
  92. package/server/services/Telegram/telegram-service.ts +171 -171
  93. package/server/services/Telegram/telegramMessageCalback.ts +11 -11
  94. package/server/services/calendar/muell-tonne.ts +82 -83
  95. package/server/services/calendar/m/303/274ll-service.ts +147 -146
  96. package/server/services/dbo/persist.ts +125 -125
  97. package/server/services/https-service.ts +71 -71
  98. package/server/services/log-service.ts +69 -69
  99. package/server/services/news-service.ts +81 -81
  100. package/server/services/settings-service.ts +15 -15
  101. package/server/services/time-callback-service.ts +223 -223
  102. package/server/services/utils/ringstorage.ts +24 -24
  103. package/server/services/utils/utils.ts +52 -52
  104. package/server/services/weather/weather-alert.ts +7 -7
  105. package/server/services/weather/weather-current.ts +26 -26
  106. package/server/services/weather/weather-daily.ts +22 -22
  107. package/server/services/weather/weather-feelsLike.ts +6 -6
  108. package/server/services/weather/weather-hourly.ts +17 -17
  109. package/server/services/weather/weather-item.ts +6 -6
  110. package/server/services/weather/weather-minutes.ts +4 -4
  111. package/server/services/weather/weather-service.ts +277 -277
  112. package/server/services/weather/weather-temp.ts +8 -8
  113. package/tsconfig.json +58 -58
@@ -1,357 +1,357 @@
1
- import { TimeCallback } from '../timeCallback';
2
- import { HmIPDevice } from '../../server/devices/hmIPDevices/hmIpDevice';
3
- import { TasterGroup } from '../../server/devices/groups/tasterGroup';
4
- import { PraesenzGroup } from '../../server/devices/groups/praesenzGroup';
5
- import { ringStorage } from '../../server/services/utils/ringstorage';
6
- import { TelegramService } from '../../server/services/Telegram/telegram-service';
7
- import { HeatGroup } from '../../server/devices/groups/heatGroup';
8
- import { LogLevel } from '../logLevel';
9
- import { WaterGroup } from '../../server/devices/groups/waterGroup';
10
- import { ServerLogService } from '../../server/services/log-service';
11
- import { Utils } from '../../server/services/utils/utils';
12
- import { LampenGroup } from '../../server/devices/groups/lampenGroup';
13
- import { RoomSettings } from './RoomSettings/RoomSettings';
14
- import { SmokeGroup } from '../../server/devices/groups/smokeGroup';
15
- import { FensterGroup } from '../../server/devices/groups/fensterGroup';
16
- import { ZigbeeDevice } from '../../server/devices/zigbee/zigbeeDevice';
17
- import { Persist } from '../../server/services/dbo/persist';
18
- import { TimeCallbackService, TimeOfDay } from '../../server/services/time-callback-service';
19
- import { SonosService } from '../../server/services/Sonos/sonos-service';
20
- import { SonosGroup } from '../../server/devices/groups/sonosGroup';
21
-
22
- export class RoomBase {
23
- public static Rooms: { [name: string]: RoomBase } = {};
24
- public static allRooms: RoomBase[] = [];
25
- public static floors: { [level: number]: RoomBase[] } = {};
26
- public static awayModeActive: boolean = false;
27
- public static nightAlarmActive: boolean = false;
28
- public static movementHistory: ringStorage = new ringStorage(15);
29
- public FensterGroup: FensterGroup = new FensterGroup(this, []);
30
- public PraesenzGroup: PraesenzGroup = new PraesenzGroup(this, [], []);
31
- public LampenGroup: LampenGroup = new LampenGroup(this, [], [], []);
32
- public TasterGroup: TasterGroup = new TasterGroup(this, []);
33
- public SonosGroup: SonosGroup = new SonosGroup(this, []);
34
- public SmokeGroup: SmokeGroup = new SmokeGroup(this, []);
35
- public WaterGroup: WaterGroup = new WaterGroup(this, []);
36
- public HeatGroup: HeatGroup = new HeatGroup(this, []);
37
- public Settings: RoomSettings;
38
- public sonnenAufgangCallback: TimeCallback | undefined;
39
- public sonnenUntergangCallback: TimeCallback | undefined;
40
- public sonnenAufgangLichtCallback: TimeCallback | undefined;
41
- public skipNextRolloUp: boolean = false;
42
- private static _awayModeTimer: NodeJS.Timeout | undefined;
43
- private static _nightModeTimer: NodeJS.Timeout | undefined;
44
- private static _intrusionAlarmActive: boolean = false;
45
- private static _intrusionAlarmLevel: number = 0;
46
- private static _intrusionAlarmTimeout: NodeJS.Timeout | undefined;
47
-
48
- public static registerRoomForDevices(roomSettings: RoomSettings): void {
49
- if (roomSettings.hmIpSettings !== undefined) {
50
- HmIPDevice.addRoom(roomSettings.shortName, roomSettings.hmIpSettings);
51
- }
52
- if (roomSettings.zigbeeSettings !== undefined) {
53
- ZigbeeDevice.addRoom(roomSettings.shortName, roomSettings.zigbeeSettings);
54
- }
55
- }
56
-
57
- public static addToRoomList(room: RoomBase): void {
58
- RoomBase.Rooms[room.roomName] = room;
59
- }
60
-
61
- public static getAllRoomsOfFloor(floor: number): Array<RoomBase> {
62
- return this.floors[floor];
63
- }
64
-
65
- /**
66
- * Set ALl Roolos of a specific floor
67
- * !!floor -1 sets all rollos in house instead!!
68
- * @param floor the level on which all rollos shall be changed -1 equals all rooms
69
- * @param position (0 equals down, 100 up)
70
- */
71
- public static setAllRolloOfFloor(floor: number = -1, position: number = 0): void {
72
- const rooms: RoomBase[] = floor > -1 ? this.getAllRoomsOfFloor(floor) : this.allRooms;
73
- for (const room of rooms) {
74
- room.FensterGroup.allRolloToLevel(position, true);
75
- }
76
- }
77
-
78
- /**
79
- * Set ALl Lamps of a specific floor
80
- * !!floor -1 sets all lamps in house instead!!
81
- * @param floor the level on which all lamps shall be changed -1 equals all rooms
82
- * @param status
83
- */
84
- public static setAllLampsOfFloor(floor: number, status: boolean = false): void {
85
- ServerLogService.writeLog(LogLevel.Info, `Schalte alle Lampen in Etage ${floor} auf den Wert ${status}`);
86
- const rooms: RoomBase[] = floor > -1 ? this.getAllRoomsOfFloor(floor) : this.allRooms;
87
- for (const room of rooms) {
88
- room.LampenGroup.setAllLampen(status, -1, true);
89
- room.LampenGroup.setAllLED(status);
90
- room.LampenGroup.setAllStecker(status, -1, true);
91
- }
92
- }
93
-
94
- public static clearAllAlarms(): void {
95
- for (const r of RoomBase.allRooms) {
96
- if (r.WaterGroup) {
97
- r.WaterGroup.stopAlarm();
98
- }
99
- if (r.SmokeGroup) {
100
- r.SmokeGroup.stopAlarm();
101
- }
102
- }
103
- this.stopIntrusionAlarm();
104
- this.restoreRolloPosition();
105
- this.restoreLight();
106
- }
107
-
108
- public static startAwayMode(): void {
109
- SonosService.speakOnAll(`Alarmanlage wird scharfgeschaltet.`, 40);
110
- if (this._awayModeTimer) {
111
- clearTimeout(this._awayModeTimer);
112
- }
113
- this._awayModeTimer = Utils.guardedTimeout(
114
- () => {
115
- this.awayModeActive = true;
116
- this._awayModeTimer = undefined;
117
- TelegramService.inform(`Alarm ist nun scharf. Gute Reise!`);
118
- },
119
- 60000,
120
- this,
121
- );
122
- }
123
- public static startNightAlarmMode(): void {
124
- SonosService.speakOnAll(`Alarmanlage wird für die Nacht scharfgeschaltet. Gute Nacht!`, 30);
125
- if (this._nightModeTimer) {
126
- clearTimeout(this._nightModeTimer);
127
- }
128
- this._nightModeTimer = Utils.guardedTimeout(
129
- () => {
130
- this.nightAlarmActive = true;
131
- this._nightModeTimer = undefined;
132
- TelegramService.inform(`Alarm ist nun scharf. Süße Träume!`);
133
- },
134
- 60000,
135
- this,
136
- );
137
- }
138
-
139
- public static startIntrusionAlarm(room: RoomBase, device: HmIPDevice): void {
140
- const message: string = `!Potenzieller Eindringling! Bewegung in ${room.roomName} von ${device.info.fullName} festgestellt`;
141
- ServerLogService.writeLog(LogLevel.Info, message);
142
- if (!this.awayModeActive && !this.nightAlarmActive) {
143
- this.stopIntrusionAlarm();
144
- return;
145
- }
146
-
147
- Utils.guardedNewThread(() => {
148
- TelegramService.inform(message);
149
- }, this);
150
-
151
- if (this._intrusionAlarmActive) {
152
- return;
153
- }
154
- this._intrusionAlarmActive = true;
155
- this.performNextIntrusionLevel();
156
- }
157
-
158
- public static endAlarmModes(): void {
159
- if (this.awayModeActive) {
160
- TelegramService.sendMessage(TelegramService.subscribedIDs, `Alarmanalage entschärft`);
161
- SonosService.speakOnAll(`Willkommen Zuhause!`, 35);
162
- }
163
- if (this.nightAlarmActive) {
164
- TelegramService.sendMessage(TelegramService.subscribedIDs, `Nachtmodus der Alarmanlage entschärft`);
165
- SonosService.speakOnAll(`Guten Morgen!`, 30);
166
- }
167
- if (this._nightModeTimer) {
168
- clearTimeout(this._nightModeTimer);
169
- }
170
- if (this._awayModeTimer) {
171
- clearTimeout(this._awayModeTimer);
172
- }
173
- this.awayModeActive = false;
174
- this.nightAlarmActive = false;
175
-
176
- this.stopIntrusionAlarm();
177
- }
178
-
179
- public static getLastMovements(): string {
180
- return this.movementHistory.readAmount(15).join('\n');
181
- }
182
-
183
- public constructor(public roomName: string, public Einstellungen: RoomSettings) {
184
- if (Einstellungen.etage !== undefined) {
185
- const level: number = Einstellungen.etage;
186
- if (RoomBase.floors[level] === undefined) {
187
- RoomBase.floors[level] = [];
188
- }
189
- RoomBase.floors[level].push(this);
190
- }
191
- Einstellungen.room = this;
192
- this.Settings = Einstellungen;
193
- RoomBase.allRooms.push(this);
194
- }
195
-
196
- public initializeBase(): void {
197
- ServerLogService.writeLog(LogLevel.Debug, `RoomBase Init für ${this.roomName}`);
198
- this.recalcTimeCallbacks();
199
- this.PraesenzGroup.initCallbacks();
200
- this.FensterGroup.initCallbacks();
201
- this.TasterGroup.initCallbacks();
202
- }
203
-
204
- public persist(): void {
205
- Persist.addRoom(this);
206
- }
207
-
208
- public recalcTimeCallbacks(): void {
209
- const now: Date = new Date();
210
- if (this.sonnenAufgangCallback && this.Einstellungen.rolloOffset) {
211
- this.sonnenAufgangCallback.minuteOffset = this.Einstellungen.rolloOffset.sunrise;
212
- this.sonnenAufgangCallback.sunTimeOffset = this.Einstellungen.rolloOffset;
213
- this.sonnenAufgangCallback.recalcNextToDo(now);
214
- }
215
- if (this.sonnenUntergangCallback && this.Einstellungen.rolloOffset) {
216
- this.sonnenUntergangCallback.minuteOffset = this.Einstellungen.rolloOffset.sunset;
217
- this.sonnenUntergangCallback.sunTimeOffset = this.Einstellungen.rolloOffset;
218
- this.sonnenUntergangCallback.recalcNextToDo(now);
219
- }
220
- if (this.sonnenAufgangLichtCallback && this.Einstellungen.lampOffset) {
221
- this.sonnenAufgangLichtCallback.minuteOffset = this.Einstellungen.lampOffset.sunrise;
222
- this.sonnenAufgangLichtCallback.recalcNextToDo(now);
223
- }
224
- }
225
-
226
- /**
227
- * Sets the light based on the current time, rollo Position and room Settings
228
- * @param movementDependant Only turn light on if there was a movement in the same room
229
- */
230
- public setLightTimeBased(movementDependant: boolean = false): void {
231
- if (movementDependant && !this.PraesenzGroup.anyPresent()) {
232
- this.LampenGroup.switchAll(false);
233
- return;
234
- }
235
-
236
- if (!this.Einstellungen.lampOffset) {
237
- ServerLogService.writeLog(
238
- LogLevel.Alert,
239
- `Beim Aufruf von "setLightTimeBased" im Raum ${this.roomName} liegt kein Lampen Offset vor`,
240
- );
241
- return;
242
- }
243
- let timeOfDay: TimeOfDay = TimeCallbackService.dayType(this.Einstellungen.lampOffset);
244
- if (
245
- timeOfDay === TimeOfDay.Daylight &&
246
- ((this.Einstellungen.lightIfNoWindows && this.FensterGroup.fenster.length === 0) ||
247
- this.FensterGroup.fenster.some((f) => {
248
- const rolloDown: boolean = f.rollo?.currentLevel === 0;
249
- ServerLogService.writeLog(
250
- LogLevel.Debug,
251
- `Rollo ${f.rollo?.info.customName} for light in ${this.roomName} is ${rolloDown ? '' : 'not '}down`,
252
- );
253
- return rolloDown;
254
- }))
255
- ) {
256
- timeOfDay = TimeOfDay.AfterSunset;
257
- }
258
- this.LampenGroup.switchTimeConditional(timeOfDay);
259
- }
260
-
261
- public isNowLightTime(): boolean {
262
- if (!this.Einstellungen.lampOffset) {
263
- ServerLogService.writeLog(
264
- LogLevel.Alert,
265
- `Beim Aufruf von "setLightTimeBased" im Raum ${this.roomName} liegt kein Lampen Offset vor`,
266
- );
267
- return false;
268
- }
269
- let timeOfDay: TimeOfDay = TimeCallbackService.dayType(this.Einstellungen.lampOffset);
270
- if (
271
- timeOfDay === TimeOfDay.Daylight &&
272
- this.FensterGroup.fenster.some((f) => {
273
- return f.rollo?.currentLevel === 0;
274
- })
275
- ) {
276
- timeOfDay = TimeOfDay.AfterSunset;
277
- }
278
- return TimeCallbackService.darkOutsideOrNight(timeOfDay);
279
- }
280
-
281
- private static stopIntrusionAlarm() {
282
- ServerLogService.writeLog(LogLevel.Info, `Stoppe Intrusion Alarm`);
283
- if (this._intrusionAlarmTimeout) {
284
- clearTimeout(this._intrusionAlarmTimeout);
285
- }
286
- if (!this._intrusionAlarmActive) {
287
- return;
288
- }
289
- this._intrusionAlarmActive = false;
290
- this._intrusionAlarmLevel = 0;
291
- ServerLogService.writeLog(LogLevel.Alert, `Alarm wurde beendet --> Fahre Rollos in Ausgangsposition.`);
292
- this.restoreRolloPosition();
293
- this.restoreLight();
294
- }
295
-
296
- private static performNextIntrusionLevel(): void {
297
- this._intrusionAlarmTimeout = undefined;
298
- if (!this.awayModeActive && !this._intrusionAlarmActive) {
299
- return;
300
- }
301
- this._intrusionAlarmLevel += 1;
302
- let speakMessage: string;
303
- let volume = 50;
304
- let newTimeout: number = 20000;
305
- const alarmAutomaticEnd: number = 15;
306
- if (this._intrusionAlarmLevel === 1) {
307
- speakMessage = `Hallo potenzieller Eindringling! Das Alarmprotokoll ist initiiert bitte verlassen Sie umgehend das Gebäude!`;
308
- volume = 40;
309
- } else if (this._intrusionAlarmLevel === 2) {
310
- speakMessage = `Alle Rollos fahren hoch, bitte begeben Sie sich zum nächsten Ausgang`;
311
- Utils.guardedNewThread(() => {
312
- this.setAllRolloOfFloor(-1, 100);
313
- this.setAllLampsOfFloor(-1, true);
314
- }, this);
315
- } else if (this._intrusionAlarmLevel === 3) {
316
- volume = 70;
317
- speakMessage = `Verlassen Sie sofort das Gebäude! Die Behörden sind informiert`;
318
- } else if (this._intrusionAlarmLevel <= 5) {
319
- volume = 80;
320
- speakMessage = `Weitere Abwehrmaßnahmen werden eingeleitet`;
321
- } else if (this._intrusionAlarmLevel >= alarmAutomaticEnd) {
322
- this.stopIntrusionAlarm();
323
- return;
324
- } else {
325
- volume = 90;
326
- speakMessage = `Alarm. Einbrecher erkannt.`;
327
- newTimeout = 10000;
328
- }
329
- this._intrusionAlarmTimeout = Utils.guardedTimeout(
330
- () => {
331
- this.performNextIntrusionLevel();
332
- },
333
- newTimeout,
334
- this,
335
- );
336
- Utils.guardedNewThread(() => {
337
- SonosService.speakOnAll(speakMessage, volume);
338
- TelegramService.inform(
339
- `Eindringling erhielt folgende Nachricht: "${speakMessage}"\nAlarmlevel ist ${this._intrusionAlarmLevel}\t Automatisches Ende bei ${alarmAutomaticEnd}`,
340
- );
341
- }, this);
342
- }
343
-
344
- private static restoreRolloPosition(): void {
345
- const rooms: RoomBase[] = this.allRooms;
346
- for (const room of rooms) {
347
- room.FensterGroup.restoreRolloPosition();
348
- }
349
- }
350
-
351
- private static restoreLight() {
352
- const rooms: RoomBase[] = this.allRooms;
353
- for (const room of rooms) {
354
- room.setLightTimeBased(true);
355
- }
356
- }
357
- }
1
+ import { TimeCallback } from '../timeCallback';
2
+ import { HmIPDevice } from '../../server/devices/hmIPDevices/hmIpDevice';
3
+ import { TasterGroup } from '../../server/devices/groups/tasterGroup';
4
+ import { PraesenzGroup } from '../../server/devices/groups/praesenzGroup';
5
+ import { ringStorage } from '../../server/services/utils/ringstorage';
6
+ import { TelegramService } from '../../server/services/Telegram/telegram-service';
7
+ import { HeatGroup } from '../../server/devices/groups/heatGroup';
8
+ import { LogLevel } from '../logLevel';
9
+ import { WaterGroup } from '../../server/devices/groups/waterGroup';
10
+ import { ServerLogService } from '../../server/services/log-service';
11
+ import { Utils } from '../../server/services/utils/utils';
12
+ import { LampenGroup } from '../../server/devices/groups/lampenGroup';
13
+ import { RoomSettings } from './RoomSettings/RoomSettings';
14
+ import { SmokeGroup } from '../../server/devices/groups/smokeGroup';
15
+ import { FensterGroup } from '../../server/devices/groups/fensterGroup';
16
+ import { ZigbeeDevice } from '../../server/devices/zigbee/zigbeeDevice';
17
+ import { Persist } from '../../server/services/dbo/persist';
18
+ import { TimeCallbackService, TimeOfDay } from '../../server/services/time-callback-service';
19
+ import { SonosService } from '../../server/services/Sonos/sonos-service';
20
+ import { SonosGroup } from '../../server/devices/groups/sonosGroup';
21
+
22
+ export class RoomBase {
23
+ public static Rooms: { [name: string]: RoomBase } = {};
24
+ public static allRooms: RoomBase[] = [];
25
+ public static floors: { [level: number]: RoomBase[] } = {};
26
+ public static awayModeActive: boolean = false;
27
+ public static nightAlarmActive: boolean = false;
28
+ public static movementHistory: ringStorage = new ringStorage(15);
29
+ public FensterGroup: FensterGroup = new FensterGroup(this, []);
30
+ public PraesenzGroup: PraesenzGroup = new PraesenzGroup(this, [], []);
31
+ public LampenGroup: LampenGroup = new LampenGroup(this, [], [], []);
32
+ public TasterGroup: TasterGroup = new TasterGroup(this, []);
33
+ public SonosGroup: SonosGroup = new SonosGroup(this, []);
34
+ public SmokeGroup: SmokeGroup = new SmokeGroup(this, []);
35
+ public WaterGroup: WaterGroup = new WaterGroup(this, []);
36
+ public HeatGroup: HeatGroup = new HeatGroup(this, []);
37
+ public Settings: RoomSettings;
38
+ public sonnenAufgangCallback: TimeCallback | undefined;
39
+ public sonnenUntergangCallback: TimeCallback | undefined;
40
+ public sonnenAufgangLichtCallback: TimeCallback | undefined;
41
+ public skipNextRolloUp: boolean = false;
42
+ private static _awayModeTimer: NodeJS.Timeout | undefined;
43
+ private static _nightModeTimer: NodeJS.Timeout | undefined;
44
+ private static _intrusionAlarmActive: boolean = false;
45
+ private static _intrusionAlarmLevel: number = 0;
46
+ private static _intrusionAlarmTimeout: NodeJS.Timeout | undefined;
47
+
48
+ public static registerRoomForDevices(roomSettings: RoomSettings): void {
49
+ if (roomSettings.hmIpSettings !== undefined) {
50
+ HmIPDevice.addRoom(roomSettings.shortName, roomSettings.hmIpSettings);
51
+ }
52
+ if (roomSettings.zigbeeSettings !== undefined) {
53
+ ZigbeeDevice.addRoom(roomSettings.shortName, roomSettings.zigbeeSettings);
54
+ }
55
+ }
56
+
57
+ public static addToRoomList(room: RoomBase): void {
58
+ RoomBase.Rooms[room.roomName] = room;
59
+ }
60
+
61
+ public static getAllRoomsOfFloor(floor: number): Array<RoomBase> {
62
+ return this.floors[floor];
63
+ }
64
+
65
+ /**
66
+ * Set ALl Roolos of a specific floor
67
+ * !!floor -1 sets all rollos in house instead!!
68
+ * @param floor the level on which all rollos shall be changed -1 equals all rooms
69
+ * @param position (0 equals down, 100 up)
70
+ */
71
+ public static setAllRolloOfFloor(floor: number = -1, position: number = 0): void {
72
+ const rooms: RoomBase[] = floor > -1 ? this.getAllRoomsOfFloor(floor) : this.allRooms;
73
+ for (const room of rooms) {
74
+ room.FensterGroup.allRolloToLevel(position, true);
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Set ALl Lamps of a specific floor
80
+ * !!floor -1 sets all lamps in house instead!!
81
+ * @param floor the level on which all lamps shall be changed -1 equals all rooms
82
+ * @param status
83
+ */
84
+ public static setAllLampsOfFloor(floor: number, status: boolean = false): void {
85
+ ServerLogService.writeLog(LogLevel.Info, `Schalte alle Lampen in Etage ${floor} auf den Wert ${status}`);
86
+ const rooms: RoomBase[] = floor > -1 ? this.getAllRoomsOfFloor(floor) : this.allRooms;
87
+ for (const room of rooms) {
88
+ room.LampenGroup.setAllLampen(status, -1, true);
89
+ room.LampenGroup.setAllLED(status);
90
+ room.LampenGroup.setAllStecker(status, -1, true);
91
+ }
92
+ }
93
+
94
+ public static clearAllAlarms(): void {
95
+ for (const r of RoomBase.allRooms) {
96
+ if (r.WaterGroup) {
97
+ r.WaterGroup.stopAlarm();
98
+ }
99
+ if (r.SmokeGroup) {
100
+ r.SmokeGroup.stopAlarm();
101
+ }
102
+ }
103
+ this.stopIntrusionAlarm();
104
+ this.restoreRolloPosition();
105
+ this.restoreLight();
106
+ }
107
+
108
+ public static startAwayMode(): void {
109
+ SonosService.speakOnAll(`Alarmanlage wird scharfgeschaltet.`, 40);
110
+ if (this._awayModeTimer) {
111
+ clearTimeout(this._awayModeTimer);
112
+ }
113
+ this._awayModeTimer = Utils.guardedTimeout(
114
+ () => {
115
+ this.awayModeActive = true;
116
+ this._awayModeTimer = undefined;
117
+ TelegramService.inform(`Alarm ist nun scharf. Gute Reise!`);
118
+ },
119
+ 60000,
120
+ this,
121
+ );
122
+ }
123
+ public static startNightAlarmMode(): void {
124
+ SonosService.speakOnAll(`Alarmanlage wird für die Nacht scharfgeschaltet. Gute Nacht!`, 30);
125
+ if (this._nightModeTimer) {
126
+ clearTimeout(this._nightModeTimer);
127
+ }
128
+ this._nightModeTimer = Utils.guardedTimeout(
129
+ () => {
130
+ this.nightAlarmActive = true;
131
+ this._nightModeTimer = undefined;
132
+ TelegramService.inform(`Alarm ist nun scharf. Süße Träume!`);
133
+ },
134
+ 60000,
135
+ this,
136
+ );
137
+ }
138
+
139
+ public static startIntrusionAlarm(room: RoomBase, device: HmIPDevice): void {
140
+ const message: string = `!Potenzieller Eindringling! Bewegung in ${room.roomName} von ${device.info.fullName} festgestellt`;
141
+ ServerLogService.writeLog(LogLevel.Info, message);
142
+ if (!this.awayModeActive && !this.nightAlarmActive) {
143
+ this.stopIntrusionAlarm();
144
+ return;
145
+ }
146
+
147
+ Utils.guardedNewThread(() => {
148
+ TelegramService.inform(message);
149
+ }, this);
150
+
151
+ if (this._intrusionAlarmActive) {
152
+ return;
153
+ }
154
+ this._intrusionAlarmActive = true;
155
+ this.performNextIntrusionLevel();
156
+ }
157
+
158
+ public static endAlarmModes(): void {
159
+ if (this.awayModeActive) {
160
+ TelegramService.sendMessage(TelegramService.subscribedIDs, `Alarmanalage entschärft`);
161
+ SonosService.speakOnAll(`Willkommen Zuhause!`, 35);
162
+ }
163
+ if (this.nightAlarmActive) {
164
+ TelegramService.sendMessage(TelegramService.subscribedIDs, `Nachtmodus der Alarmanlage entschärft`);
165
+ SonosService.speakOnAll(`Guten Morgen!`, 30);
166
+ }
167
+ if (this._nightModeTimer) {
168
+ clearTimeout(this._nightModeTimer);
169
+ }
170
+ if (this._awayModeTimer) {
171
+ clearTimeout(this._awayModeTimer);
172
+ }
173
+ this.awayModeActive = false;
174
+ this.nightAlarmActive = false;
175
+
176
+ this.stopIntrusionAlarm();
177
+ }
178
+
179
+ public static getLastMovements(): string {
180
+ return this.movementHistory.readAmount(15).join('\n');
181
+ }
182
+
183
+ public constructor(public roomName: string, public Einstellungen: RoomSettings) {
184
+ if (Einstellungen.etage !== undefined) {
185
+ const level: number = Einstellungen.etage;
186
+ if (RoomBase.floors[level] === undefined) {
187
+ RoomBase.floors[level] = [];
188
+ }
189
+ RoomBase.floors[level].push(this);
190
+ }
191
+ Einstellungen.room = this;
192
+ this.Settings = Einstellungen;
193
+ RoomBase.allRooms.push(this);
194
+ }
195
+
196
+ public initializeBase(): void {
197
+ ServerLogService.writeLog(LogLevel.Debug, `RoomBase Init für ${this.roomName}`);
198
+ this.recalcTimeCallbacks();
199
+ this.PraesenzGroup.initCallbacks();
200
+ this.FensterGroup.initCallbacks();
201
+ this.TasterGroup.initCallbacks();
202
+ }
203
+
204
+ public persist(): void {
205
+ Persist.addRoom(this);
206
+ }
207
+
208
+ public recalcTimeCallbacks(): void {
209
+ const now: Date = new Date();
210
+ if (this.sonnenAufgangCallback && this.Einstellungen.rolloOffset) {
211
+ this.sonnenAufgangCallback.minuteOffset = this.Einstellungen.rolloOffset.sunrise;
212
+ this.sonnenAufgangCallback.sunTimeOffset = this.Einstellungen.rolloOffset;
213
+ this.sonnenAufgangCallback.recalcNextToDo(now);
214
+ }
215
+ if (this.sonnenUntergangCallback && this.Einstellungen.rolloOffset) {
216
+ this.sonnenUntergangCallback.minuteOffset = this.Einstellungen.rolloOffset.sunset;
217
+ this.sonnenUntergangCallback.sunTimeOffset = this.Einstellungen.rolloOffset;
218
+ this.sonnenUntergangCallback.recalcNextToDo(now);
219
+ }
220
+ if (this.sonnenAufgangLichtCallback && this.Einstellungen.lampOffset) {
221
+ this.sonnenAufgangLichtCallback.minuteOffset = this.Einstellungen.lampOffset.sunrise;
222
+ this.sonnenAufgangLichtCallback.recalcNextToDo(now);
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Sets the light based on the current time, rollo Position and room Settings
228
+ * @param movementDependant Only turn light on if there was a movement in the same room
229
+ */
230
+ public setLightTimeBased(movementDependant: boolean = false): void {
231
+ if (movementDependant && !this.PraesenzGroup.anyPresent()) {
232
+ this.LampenGroup.switchAll(false);
233
+ return;
234
+ }
235
+
236
+ if (!this.Einstellungen.lampOffset) {
237
+ ServerLogService.writeLog(
238
+ LogLevel.Alert,
239
+ `Beim Aufruf von "setLightTimeBased" im Raum ${this.roomName} liegt kein Lampen Offset vor`,
240
+ );
241
+ return;
242
+ }
243
+ let timeOfDay: TimeOfDay = TimeCallbackService.dayType(this.Einstellungen.lampOffset);
244
+ if (
245
+ timeOfDay === TimeOfDay.Daylight &&
246
+ ((this.Einstellungen.lightIfNoWindows && this.FensterGroup.fenster.length === 0) ||
247
+ this.FensterGroup.fenster.some((f) => {
248
+ const rolloDown: boolean = f.rollo?.currentLevel === 0;
249
+ ServerLogService.writeLog(
250
+ LogLevel.Debug,
251
+ `Rollo ${f.rollo?.info.customName} for light in ${this.roomName} is ${rolloDown ? '' : 'not '}down`,
252
+ );
253
+ return rolloDown;
254
+ }))
255
+ ) {
256
+ timeOfDay = TimeOfDay.AfterSunset;
257
+ }
258
+ this.LampenGroup.switchTimeConditional(timeOfDay);
259
+ }
260
+
261
+ public isNowLightTime(): boolean {
262
+ if (!this.Einstellungen.lampOffset) {
263
+ ServerLogService.writeLog(
264
+ LogLevel.Alert,
265
+ `Beim Aufruf von "setLightTimeBased" im Raum ${this.roomName} liegt kein Lampen Offset vor`,
266
+ );
267
+ return false;
268
+ }
269
+ let timeOfDay: TimeOfDay = TimeCallbackService.dayType(this.Einstellungen.lampOffset);
270
+ if (
271
+ timeOfDay === TimeOfDay.Daylight &&
272
+ this.FensterGroup.fenster.some((f) => {
273
+ return f.rollo?.currentLevel === 0;
274
+ })
275
+ ) {
276
+ timeOfDay = TimeOfDay.AfterSunset;
277
+ }
278
+ return TimeCallbackService.darkOutsideOrNight(timeOfDay);
279
+ }
280
+
281
+ private static stopIntrusionAlarm() {
282
+ ServerLogService.writeLog(LogLevel.Info, `Stoppe Intrusion Alarm`);
283
+ if (this._intrusionAlarmTimeout) {
284
+ clearTimeout(this._intrusionAlarmTimeout);
285
+ }
286
+ if (!this._intrusionAlarmActive) {
287
+ return;
288
+ }
289
+ this._intrusionAlarmActive = false;
290
+ this._intrusionAlarmLevel = 0;
291
+ ServerLogService.writeLog(LogLevel.Alert, `Alarm wurde beendet --> Fahre Rollos in Ausgangsposition.`);
292
+ this.restoreRolloPosition();
293
+ this.restoreLight();
294
+ }
295
+
296
+ private static performNextIntrusionLevel(): void {
297
+ this._intrusionAlarmTimeout = undefined;
298
+ if (!this.awayModeActive && !this._intrusionAlarmActive) {
299
+ return;
300
+ }
301
+ this._intrusionAlarmLevel += 1;
302
+ let speakMessage: string;
303
+ let volume = 50;
304
+ let newTimeout: number = 20000;
305
+ const alarmAutomaticEnd: number = 15;
306
+ if (this._intrusionAlarmLevel === 1) {
307
+ speakMessage = `Hallo potenzieller Eindringling! Das Alarmprotokoll ist initiiert bitte verlassen Sie umgehend das Gebäude!`;
308
+ volume = 40;
309
+ } else if (this._intrusionAlarmLevel === 2) {
310
+ speakMessage = `Alle Rollos fahren hoch, bitte begeben Sie sich zum nächsten Ausgang`;
311
+ Utils.guardedNewThread(() => {
312
+ this.setAllRolloOfFloor(-1, 100);
313
+ this.setAllLampsOfFloor(-1, true);
314
+ }, this);
315
+ } else if (this._intrusionAlarmLevel === 3) {
316
+ volume = 70;
317
+ speakMessage = `Verlassen Sie sofort das Gebäude! Die Behörden sind informiert`;
318
+ } else if (this._intrusionAlarmLevel <= 5) {
319
+ volume = 80;
320
+ speakMessage = `Weitere Abwehrmaßnahmen werden eingeleitet`;
321
+ } else if (this._intrusionAlarmLevel >= alarmAutomaticEnd) {
322
+ this.stopIntrusionAlarm();
323
+ return;
324
+ } else {
325
+ volume = 90;
326
+ speakMessage = `Alarm. Einbrecher erkannt.`;
327
+ newTimeout = 10000;
328
+ }
329
+ this._intrusionAlarmTimeout = Utils.guardedTimeout(
330
+ () => {
331
+ this.performNextIntrusionLevel();
332
+ },
333
+ newTimeout,
334
+ this,
335
+ );
336
+ Utils.guardedNewThread(() => {
337
+ SonosService.speakOnAll(speakMessage, volume);
338
+ TelegramService.inform(
339
+ `Eindringling erhielt folgende Nachricht: "${speakMessage}"\nAlarmlevel ist ${this._intrusionAlarmLevel}\t Automatisches Ende bei ${alarmAutomaticEnd}`,
340
+ );
341
+ }, this);
342
+ }
343
+
344
+ private static restoreRolloPosition(): void {
345
+ const rooms: RoomBase[] = this.allRooms;
346
+ for (const room of rooms) {
347
+ room.FensterGroup.restoreRolloPosition();
348
+ }
349
+ }
350
+
351
+ private static restoreLight() {
352
+ const rooms: RoomBase[] = this.allRooms;
353
+ for (const room of rooms) {
354
+ room.setLightTimeBased(true);
355
+ }
356
+ }
357
+ }