hoffmation-base 0.0.1
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.
- package/.eslintrc.js +27 -0
- package/.prettierrc.js +9 -0
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/index.js +1 -0
- package/models/connectionCallbacks.ts +13 -0
- package/models/daytime.ts +3 -0
- package/models/deviceConfig.ts +8 -0
- package/models/dimmerSettings.ts +5 -0
- package/models/lampSettings.ts +5 -0
- package/models/ledSettings.ts +19 -0
- package/models/logLevel.ts +9 -0
- package/models/persistence/BasicRoomInfo.ts +3 -0
- package/models/persistence/DailyMovementCount.ts +3 -0
- package/models/persistence/RoomDetailInfo.ts +4 -0
- package/models/persistence/temperaturDataPoint.ts +12 -0
- package/models/persistence/todaysCount.ts +3 -0
- package/models/rooms/RoomBase.ts +357 -0
- package/models/rooms/RoomSettings/RoomSettings.ts +159 -0
- package/models/rooms/RoomSettings/hmIPRoomSettings.ts +53 -0
- package/models/rooms/RoomSettings/iRoomDefaultSettings.ts +17 -0
- package/models/rooms/RoomSettings/readme.md +18 -0
- package/models/rooms/RoomSettings/zigbeeRoomSettings.ts +51 -0
- package/models/rooms/iRoomImportEnforcer.ts +3 -0
- package/models/rooms/readme.md +11 -0
- package/models/temperaturSettings.ts +22 -0
- package/models/timeCallback.ts +90 -0
- package/package.json +57 -0
- package/server/config/config-readme.md +19 -0
- package/server/config/iConfig.ts +53 -0
- package/server/devices/DeviceInfo.ts +66 -0
- package/server/devices/Griffe.ts +31 -0
- package/server/devices/Heizgruppen.ts +91 -0
- package/server/devices/Rollos.ts +48 -0
- package/server/devices/deviceUpdater.ts +72 -0
- package/server/devices/devices.ts +189 -0
- package/server/devices/groups/fensterGroup.ts +175 -0
- package/server/devices/groups/heatGroup.ts +32 -0
- package/server/devices/groups/lampenGroup.ts +88 -0
- package/server/devices/groups/praesenzGroup.ts +182 -0
- package/server/devices/groups/smokeGroup.ts +16 -0
- package/server/devices/groups/sonosGroup.ts +33 -0
- package/server/devices/groups/tasterGroup.ts +48 -0
- package/server/devices/groups/waterGroup.ts +16 -0
- package/server/devices/hmIPDevices/Fenster.ts +114 -0
- package/server/devices/hmIPDevices/FensterPosition.ts +5 -0
- package/server/devices/hmIPDevices/TuerPosition.ts +4 -0
- package/server/devices/hmIPDevices/hmIpBewegung.ts +126 -0
- package/server/devices/hmIPDevices/hmIpDevice.ts +90 -0
- package/server/devices/hmIPDevices/hmIpDeviceType.ts +14 -0
- package/server/devices/hmIPDevices/hmIpGriff.ts +143 -0
- package/server/devices/hmIPDevices/hmIpHeizgruppe.ts +172 -0
- package/server/devices/hmIPDevices/hmIpHeizung.ts +69 -0
- package/server/devices/hmIPDevices/hmIpLampe.ts +119 -0
- package/server/devices/hmIPDevices/hmIpPraezenz.ts +99 -0
- package/server/devices/hmIPDevices/hmIpRoll.ts +133 -0
- package/server/devices/hmIPDevices/hmIpTaste.ts +72 -0
- package/server/devices/hmIPDevices/hmIpTaster.ts +73 -0
- package/server/devices/hmIPDevices/hmIpTherm.ts +19 -0
- package/server/devices/hmIPDevices/hmIpTuer.ts +115 -0
- package/server/devices/hmIPDevices/hmIpWippe.ts +55 -0
- package/server/devices/iDeviceUpdater.ts +4 -0
- package/server/devices/iIoBrokerDevice.ts +44 -0
- package/server/devices/wledDevice.ts +124 -0
- package/server/devices/zigbee/ZigbeeActuator.ts +113 -0
- package/server/devices/zigbee/zigbeeAquaraVibra.ts +171 -0
- package/server/devices/zigbee/zigbeeAquaraWater.ts +94 -0
- package/server/devices/zigbee/zigbeeBlitzShp.ts +77 -0
- package/server/devices/zigbee/zigbeeDevice.ts +115 -0
- package/server/devices/zigbee/zigbeeDeviceType.ts +13 -0
- package/server/devices/zigbee/zigbeeHeimanSmoke.ts +99 -0
- package/server/devices/zigbee/zigbeeIkeaSteckdose.ts +31 -0
- package/server/devices/zigbee/zigbeeIlluActuator.ts +37 -0
- package/server/devices/zigbee/zigbeeIlluDimmer.ts +165 -0
- package/server/devices/zigbee/zigbeeIlluLampe.ts +33 -0
- package/server/devices/zigbee/zigbeeIlluLedRGBCCT.ts +137 -0
- package/server/ioBroker/connection.ts +1655 -0
- package/server/ioBroker/ioBroker.main.ts +99 -0
- package/server/ioBroker/socketIOAuthInfo.ts +5 -0
- package/server/ioBroker/socketIOConnectOptions.ts +6 -0
- package/server/ioBroker/socketIOLogging.ts +29 -0
- package/server/ioBroker/socketIOVisCommand.ts +11 -0
- package/server/services/HTTPSOptions.ts +14 -0
- package/server/services/Sonos/mp3-server.ts +75 -0
- package/server/services/Sonos/polly-service.ts +100 -0
- package/server/services/Sonos/sonos-service.ts +199 -0
- package/server/services/Telegram/telegram-Commands.ts +215 -0
- package/server/services/Telegram/telegram-service.ts +171 -0
- package/server/services/Telegram/telegramMessageCalback.ts +11 -0
- package/server/services/calendar/m/303/274ll-service.ts +224 -0
- package/server/services/dbo/persist.ts +125 -0
- package/server/services/https-service.ts +71 -0
- package/server/services/log-service.ts +69 -0
- package/server/services/news-service.ts +81 -0
- package/server/services/settings-service.ts +23 -0
- package/server/services/time-callback-service.ts +223 -0
- package/server/services/utils/ringstorage.ts +24 -0
- package/server/services/utils/utils.ts +52 -0
- package/server/services/weather/weather-alert.ts +7 -0
- package/server/services/weather/weather-current.ts +26 -0
- package/server/services/weather/weather-daily.ts +22 -0
- package/server/services/weather/weather-feelsLike.ts +6 -0
- package/server/services/weather/weather-hourly.ts +17 -0
- package/server/services/weather/weather-item.ts +6 -0
- package/server/services/weather/weather-minutes.ts +4 -0
- package/server/services/weather/weather-service.ts +277 -0
- package/server/services/weather/weather-temp.ts +8 -0
- package/tsconfig.json +59 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import TelegramBot from 'node-telegram-bot-api';
|
|
2
|
+
import { Devices } from '../../devices/devices';
|
|
3
|
+
import { TelegramService } from './telegram-service';
|
|
4
|
+
import { TelegramMessageCallback } from './telegramMessageCalback';
|
|
5
|
+
import { Griffe } from '../../devices/Griffe';
|
|
6
|
+
import { Heizgruppen } from '../../devices/Heizgruppen';
|
|
7
|
+
import { Rolladen } from '../../devices/Rollos';
|
|
8
|
+
import { ZigbeeAquaraVibra } from '../../devices/zigbee/zigbeeAquaraVibra';
|
|
9
|
+
import { ZigbeeDeviceType } from '../../devices/zigbee/zigbeeDeviceType';
|
|
10
|
+
import { RoomBase } from '../../../models/rooms/RoomBase';
|
|
11
|
+
import { SonosService } from '../Sonos/sonos-service';
|
|
12
|
+
|
|
13
|
+
export class TelegramCommands {
|
|
14
|
+
private static devices: Devices;
|
|
15
|
+
|
|
16
|
+
public static initialize(pDevices: Devices): void {
|
|
17
|
+
TelegramCommands.devices = pDevices;
|
|
18
|
+
TelegramService.addMessageCallback(
|
|
19
|
+
new TelegramMessageCallback(
|
|
20
|
+
'AlarmStop',
|
|
21
|
+
/\/stop_alarm/,
|
|
22
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
23
|
+
if (m.from === undefined) return false;
|
|
24
|
+
RoomBase.clearAllAlarms();
|
|
25
|
+
TelegramService.sendMessage(
|
|
26
|
+
[m.from.id],
|
|
27
|
+
'Alle ausgelösten Wasser-/Rauchmelder und Eindringlingsalarme wurden gestoppt.',
|
|
28
|
+
);
|
|
29
|
+
return true;
|
|
30
|
+
},
|
|
31
|
+
'Eine Möglichkeit bei Fehlalarm den Alarm abzuschalten',
|
|
32
|
+
),
|
|
33
|
+
);
|
|
34
|
+
TelegramService.addMessageCallback(
|
|
35
|
+
new TelegramMessageCallback(
|
|
36
|
+
'AwayModeStart',
|
|
37
|
+
/\/away_mode_start/,
|
|
38
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
39
|
+
if (m.from === undefined) return false;
|
|
40
|
+
RoomBase.startAwayMode();
|
|
41
|
+
TelegramService.inform('Der Abwesenheitsmodus ist initiiert');
|
|
42
|
+
return true;
|
|
43
|
+
},
|
|
44
|
+
'Eine Möglichkeit die Alarmanlage scharfzuschalten',
|
|
45
|
+
),
|
|
46
|
+
);
|
|
47
|
+
TelegramService.addMessageCallback(
|
|
48
|
+
new TelegramMessageCallback(
|
|
49
|
+
'NightAlarmMode',
|
|
50
|
+
/\/nightalarm_mode_start/,
|
|
51
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
52
|
+
if (m.from === undefined) return false;
|
|
53
|
+
RoomBase.startNightAlarmMode();
|
|
54
|
+
TelegramService.inform('Der Nachtmodus ist initiiert');
|
|
55
|
+
return true;
|
|
56
|
+
},
|
|
57
|
+
'Alarmanlage für die Nacht scharf schalten',
|
|
58
|
+
),
|
|
59
|
+
);
|
|
60
|
+
TelegramService.addMessageCallback(
|
|
61
|
+
new TelegramMessageCallback(
|
|
62
|
+
'AlarmModesEnd',
|
|
63
|
+
/\/alarm_modes_end/,
|
|
64
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
65
|
+
if (m.from === undefined) return false;
|
|
66
|
+
RoomBase.endAlarmModes();
|
|
67
|
+
TelegramService.sendMessage([m.from.id], 'Der Abwesenheitsmodus ist deaktiviert.');
|
|
68
|
+
return true;
|
|
69
|
+
},
|
|
70
|
+
'Alarmanlage nach Abwesenheit/Nacht entschärfen',
|
|
71
|
+
),
|
|
72
|
+
);
|
|
73
|
+
TelegramService.addMessageCallback(
|
|
74
|
+
new TelegramMessageCallback(
|
|
75
|
+
'LastMovements',
|
|
76
|
+
/\/check_movement/,
|
|
77
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
78
|
+
if (m.from === undefined) return false;
|
|
79
|
+
TelegramService.sendMessage(
|
|
80
|
+
[m.from.id],
|
|
81
|
+
`Im Folgenden sind die letzten Bewegungen\n${RoomBase.getLastMovements()}`,
|
|
82
|
+
);
|
|
83
|
+
return true;
|
|
84
|
+
},
|
|
85
|
+
'Gibt die letzten Bewegungen inkl. ihrer Uhrzeit aus.',
|
|
86
|
+
),
|
|
87
|
+
);
|
|
88
|
+
TelegramService.addMessageCallback(
|
|
89
|
+
new TelegramMessageCallback(
|
|
90
|
+
'TelegramTest',
|
|
91
|
+
/\/test/,
|
|
92
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
93
|
+
if (m.from === undefined) return false;
|
|
94
|
+
TelegramService.sendMessage([m.from.id], 'Hallo, ich bin der HoffMation Bot.');
|
|
95
|
+
return true;
|
|
96
|
+
},
|
|
97
|
+
'Eine Möglichkeit die Verknüpfung mit dem HoffMation Bot zu testen',
|
|
98
|
+
),
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
TelegramService.addMessageCallback(
|
|
102
|
+
new TelegramMessageCallback(
|
|
103
|
+
'RolloObenCheck',
|
|
104
|
+
/\/check_rollo/,
|
|
105
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
106
|
+
if (m.from === undefined) return false;
|
|
107
|
+
TelegramService.sendMessage([m.from.id], Rolladen.getRolladenPosition());
|
|
108
|
+
return true;
|
|
109
|
+
},
|
|
110
|
+
'Gibt die Positionen der Rollos aus, warnt über offene Rollos und nennt die nächsten Fahrten',
|
|
111
|
+
),
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
TelegramService.addMessageCallback(
|
|
115
|
+
new TelegramMessageCallback(
|
|
116
|
+
'FensterCheck',
|
|
117
|
+
/\/check_fenster/,
|
|
118
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
119
|
+
if (m.from === undefined) return false;
|
|
120
|
+
TelegramService.sendMessage([m.from.id], Griffe.getGriffPosition());
|
|
121
|
+
return true;
|
|
122
|
+
},
|
|
123
|
+
'Gibt die Positionen der Fenstergriffe aus und warnt somit über offene Fenster',
|
|
124
|
+
),
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
TelegramService.addMessageCallback(
|
|
128
|
+
new TelegramMessageCallback(
|
|
129
|
+
'HeizungCheck',
|
|
130
|
+
/\/check_temperatur/,
|
|
131
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
132
|
+
if (m.from === undefined) return false;
|
|
133
|
+
TelegramService.sendMessage([m.from.id], Heizgruppen.getInfo());
|
|
134
|
+
return true;
|
|
135
|
+
},
|
|
136
|
+
'Gibt die Namen und aktuellen Werte sämtlicher Heizgruppen aus (aktuelle Temperatur, Soll Temperatur, Ventilstellung).',
|
|
137
|
+
),
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
TelegramService.addMessageCallback(
|
|
141
|
+
new TelegramMessageCallback(
|
|
142
|
+
'HeizungError',
|
|
143
|
+
/\/temperatur_error/,
|
|
144
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
145
|
+
if (m.from === undefined) return false;
|
|
146
|
+
TelegramService.sendMessage([m.from.id], Heizgruppen.getProblems());
|
|
147
|
+
return true;
|
|
148
|
+
},
|
|
149
|
+
'Zeigt Differenzen zwischen Heizungen und den jeweiligen Heizgruppen auf',
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
TelegramService.addMessageCallback(
|
|
154
|
+
new TelegramMessageCallback(
|
|
155
|
+
'HeizungCheckOne',
|
|
156
|
+
/\/check_1_temperatur.*/,
|
|
157
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
158
|
+
if (m.from === undefined) return false;
|
|
159
|
+
TelegramService.sendMessage([m.from.id], await Heizgruppen.getSpecificInfo(m.text));
|
|
160
|
+
return true;
|
|
161
|
+
},
|
|
162
|
+
`Gibt den Verlauf der in \\"\\" übergebenen Heizgruppe aus.`,
|
|
163
|
+
/\/check_1_temperatur/,
|
|
164
|
+
),
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
TelegramService.addMessageCallback(
|
|
168
|
+
new TelegramMessageCallback(
|
|
169
|
+
'AllRolloDown',
|
|
170
|
+
/\/all_rollo_down/,
|
|
171
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
172
|
+
if (m.from === undefined) return false;
|
|
173
|
+
RoomBase.setAllRolloOfFloor(-1, 0);
|
|
174
|
+
TelegramService.sendMessage([m.from.id], `Es werden alle Rollos heruntergefahren`);
|
|
175
|
+
return true;
|
|
176
|
+
},
|
|
177
|
+
`Fährt alle rollos runter`,
|
|
178
|
+
),
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
TelegramService.addMessageCallback(
|
|
182
|
+
new TelegramMessageCallback(
|
|
183
|
+
'VibrationSensitivity',
|
|
184
|
+
/\/set_vibration_sensitivity/,
|
|
185
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
186
|
+
if (m.from === undefined) return false;
|
|
187
|
+
for (const id in Devices.Zigbee) {
|
|
188
|
+
const d = Devices.Zigbee[id];
|
|
189
|
+
if (d.deviceType === ZigbeeDeviceType.ZigbeeAquaraVibra) {
|
|
190
|
+
(d as ZigbeeAquaraVibra).setSensitivity(2);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
TelegramService.sendMessage([m.from.id], 'Abgeschlossen');
|
|
194
|
+
return true;
|
|
195
|
+
},
|
|
196
|
+
`Setzt alle Vibrationsensoren auf High`,
|
|
197
|
+
),
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
TelegramService.addMessageCallback(
|
|
201
|
+
new TelegramMessageCallback(
|
|
202
|
+
'SonosTest',
|
|
203
|
+
/\/perform_sonos_test/,
|
|
204
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
205
|
+
if (m.from === undefined) return false;
|
|
206
|
+
SonosService.speakTestMessageOnEachDevice();
|
|
207
|
+
TelegramService.sendMessage([m.from.id], 'Testnachricht gesprochen --> Führe weiteren Test durch');
|
|
208
|
+
SonosService.checkAll();
|
|
209
|
+
return true;
|
|
210
|
+
},
|
|
211
|
+
`Spiele eine kurze Nachricht auf allen Sonos Geräten um diese zu identifizieren`,
|
|
212
|
+
),
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import TelegramBot from 'node-telegram-bot-api';
|
|
2
|
+
import { ServerLogService } from '../log-service';
|
|
3
|
+
import { TelegramMessageCallback } from './telegramMessageCalback';
|
|
4
|
+
import { LogLevel } from '../../../models/logLevel';
|
|
5
|
+
import { iTelegramSettings } from '../../config/iConfig';
|
|
6
|
+
export class TelegramService {
|
|
7
|
+
public static subscribedIDs: number[];
|
|
8
|
+
|
|
9
|
+
private static token: string;
|
|
10
|
+
private static active: boolean = false;
|
|
11
|
+
private static bot: TelegramBot;
|
|
12
|
+
private static allowedIDs: number[];
|
|
13
|
+
private static settings: iTelegramSettings | undefined = undefined;
|
|
14
|
+
private static restartTimeout: NodeJS.Timeout | undefined = undefined;
|
|
15
|
+
|
|
16
|
+
private static callbacks: { [name: string]: TelegramMessageCallback } = {};
|
|
17
|
+
|
|
18
|
+
public static addMessageCallback(pCallback: TelegramMessageCallback, reset: boolean = false): void {
|
|
19
|
+
if (!reset) {
|
|
20
|
+
TelegramService.callbacks[pCallback.name] = pCallback;
|
|
21
|
+
}
|
|
22
|
+
TelegramService.bot.onText(pCallback.identifier, (msg) => {
|
|
23
|
+
if (!TelegramService.checkAuthorized(msg)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
pCallback.callback(msg);
|
|
27
|
+
});
|
|
28
|
+
ServerLogService.writeLog(
|
|
29
|
+
LogLevel.Debug,
|
|
30
|
+
`Telegram Callback mit Namen ${pCallback.name} für Nachrichten mit "${pCallback.identifier}" hinzugefügt`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public static initialize(settings?: iTelegramSettings): void {
|
|
35
|
+
if (!settings && this.settings === undefined) {
|
|
36
|
+
this.active = false;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (settings) {
|
|
41
|
+
this.settings = settings;
|
|
42
|
+
ServerLogService.telegramLevel = settings.logLevel;
|
|
43
|
+
this.token = settings.telegramToken;
|
|
44
|
+
this.allowedIDs = settings.allowedIDs;
|
|
45
|
+
this.subscribedIDs = settings.subscribedIDs;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.active = true;
|
|
49
|
+
this.bot = new TelegramBot(this.token, { polling: true, webHook: false });
|
|
50
|
+
this.bot.on('polling_error', (e) => {
|
|
51
|
+
/*
|
|
52
|
+
if (!this.reinitiliazeWithTimeout()) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
*/
|
|
56
|
+
ServerLogService.writeLog(LogLevel.Debug, `Telegram Polling Error: ${e.message}`);
|
|
57
|
+
ServerLogService.writeLog(LogLevel.Trace, `Telegram Polling Error stack: ${e.stack}`);
|
|
58
|
+
});
|
|
59
|
+
TelegramService.addMessageCallback(
|
|
60
|
+
new TelegramMessageCallback(
|
|
61
|
+
'helpCommand',
|
|
62
|
+
/\/help/,
|
|
63
|
+
async (m: TelegramBot.Message): Promise<boolean> => {
|
|
64
|
+
if (m.from === undefined) return true;
|
|
65
|
+
const message: string[] = [];
|
|
66
|
+
message.push('Im folgenden ist eine Liste sämtlicher Kommandos:\n');
|
|
67
|
+
for (const cName in TelegramService.callbacks) {
|
|
68
|
+
const telegramCb: TelegramMessageCallback = TelegramService.callbacks[cName];
|
|
69
|
+
message.push(
|
|
70
|
+
`${telegramCb.identifier.toString().replace(/\//g, '').replace(/\\/g, '')} - ${telegramCb.helpMessage}`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
TelegramService.sendMessage([m.from?.id], message.join('\n'));
|
|
74
|
+
return true;
|
|
75
|
+
},
|
|
76
|
+
`Gibt eine Liste mit sämtlichen Kommandos aus`,
|
|
77
|
+
),
|
|
78
|
+
);
|
|
79
|
+
TelegramService.inform(`(Re-)Initialisierung abgeschlossen`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public static publishCommands(): void {
|
|
83
|
+
const commands: TelegramBot.BotCommand[] = [];
|
|
84
|
+
for (const cName in TelegramService.callbacks) {
|
|
85
|
+
const telegramCb: TelegramMessageCallback = TelegramService.callbacks[cName];
|
|
86
|
+
const commandIdentifier: string = (
|
|
87
|
+
telegramCb.identifierForCommandList !== undefined ? telegramCb.identifierForCommandList : telegramCb.identifier
|
|
88
|
+
)
|
|
89
|
+
.toString()
|
|
90
|
+
.replace(/\//g, '')
|
|
91
|
+
.replace(/\\/g, '');
|
|
92
|
+
commands.push({ command: commandIdentifier, description: telegramCb.helpMessage });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
ServerLogService.writeLog(LogLevel.Debug, `New Telegram Commands: "${JSON.stringify(commands)}"`);
|
|
96
|
+
TelegramService.bot.setMyCommands(commands);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public static inform(message: string): void {
|
|
100
|
+
this.sendMessage(this.subscribedIDs, message);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public static sendMessage(ids: number[], message: string): void {
|
|
104
|
+
if (!TelegramService.active) {
|
|
105
|
+
// We can't use Log Service here, as it might result in a recursion
|
|
106
|
+
console.log(`Telegram message ${message} wasn't send as TelegramService is inactive`);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
for (const id of ids) {
|
|
111
|
+
this.bot.sendMessage(id, message).catch((r) => {
|
|
112
|
+
ServerLogService.writeLog(LogLevel.Warn, `Send Telegram Message to ${id} failed: ${r}`);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public static checkAuthorized(msg: TelegramBot.Message): boolean {
|
|
118
|
+
if (msg.from !== undefined && this.allowedIDs.includes(msg.from?.id)) {
|
|
119
|
+
ServerLogService.writeLog(LogLevel.Debug, `Authorisierte Telegram Message erhalten: ${JSON.stringify(msg)}`);
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
ServerLogService.writeLog(LogLevel.Alert, `Fremden Telegram Nutzer erkannt. Nachricht "${JSON.stringify(msg)}"`);
|
|
124
|
+
TelegramService.sendMessage(
|
|
125
|
+
[msg.chat.id],
|
|
126
|
+
"Hello stranger,\nExcuse me, but you're not yet on the guest list.\nPlease contact our manager.\nHave a great day",
|
|
127
|
+
);
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/*
|
|
132
|
+
private static reinitialize(): void {
|
|
133
|
+
ServerLogService.writeLog(LogLevel.Info, `Reinitialize Telegram Bot: Stop Polling`);
|
|
134
|
+
this.bot
|
|
135
|
+
.startPolling({ restart: true })
|
|
136
|
+
.then(() => {
|
|
137
|
+
this.restartTimeout = undefined;
|
|
138
|
+
this.resetMessageCallbacks();
|
|
139
|
+
ServerLogService.writeLog(LogLevel.Debug, `Reinitialization of Telegram finished.`);
|
|
140
|
+
})
|
|
141
|
+
.catch((e) => {
|
|
142
|
+
ServerLogService.writeLog(LogLevel.Info, `Can't start polling: ${e}`);
|
|
143
|
+
TelegramService.reinitiliazeWithTimeout(true);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public static reinitiliazeWithTimeout(force: boolean = false): boolean {
|
|
148
|
+
if (this.restartTimeout !== undefined && !force) {
|
|
149
|
+
return false;
|
|
150
|
+
} else if (force && this.restartTimeout !== undefined) {
|
|
151
|
+
clearTimeout(this.restartTimeout);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
this.restartTimeout = Utils.guardedTimeout(
|
|
155
|
+
() => {
|
|
156
|
+
this.reinitialize();
|
|
157
|
+
},
|
|
158
|
+
10000,
|
|
159
|
+
this,
|
|
160
|
+
);
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
*/
|
|
164
|
+
|
|
165
|
+
public static resetMessageCallbacks(): void {
|
|
166
|
+
TelegramService.bot.clearTextListeners();
|
|
167
|
+
for (const name in TelegramService.callbacks) {
|
|
168
|
+
this.addMessageCallback(TelegramService.callbacks[name]);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import TelegramBot from 'node-telegram-bot-api';
|
|
2
|
+
|
|
3
|
+
export class TelegramMessageCallback {
|
|
4
|
+
public constructor(
|
|
5
|
+
public name: string,
|
|
6
|
+
public identifier: RegExp,
|
|
7
|
+
public callback: (message: TelegramBot.Message) => Promise<boolean>,
|
|
8
|
+
public helpMessage: string,
|
|
9
|
+
public identifierForCommandList?: RegExp,
|
|
10
|
+
) {}
|
|
11
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { async, VEvent } from 'node-ical';
|
|
2
|
+
import { ServerLogService } from '../log-service';
|
|
3
|
+
import { OwnSonosDevice, SonosService } from '../Sonos/sonos-service';
|
|
4
|
+
import { TelegramService } from '../Telegram/telegram-service';
|
|
5
|
+
import { TimeCallbackService } from '../time-callback-service';
|
|
6
|
+
import { LogLevel } from '../../../models/logLevel';
|
|
7
|
+
import { TimeCallback, TimeCallbackType } from '../../../models/timeCallback';
|
|
8
|
+
import { iMuellSettings } from '../../config/iConfig';
|
|
9
|
+
import { Utils } from '../utils/utils';
|
|
10
|
+
|
|
11
|
+
export class MuellTonne {
|
|
12
|
+
public static oneDay: number = 1000 * 60 * 60 * 24;
|
|
13
|
+
public nextDate: Date | undefined = undefined;
|
|
14
|
+
public dates: Date[] = [];
|
|
15
|
+
|
|
16
|
+
public constructor(public name: string, public ownSonosDevice?: OwnSonosDevice) {
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public sortDates(): void {
|
|
20
|
+
this.dates = this.dates.sort((a, b) => a.getTime() - b.getTime());
|
|
21
|
+
this.removePassedDates();
|
|
22
|
+
ServerLogService.writeLog(
|
|
23
|
+
LogLevel.Info,
|
|
24
|
+
`Die "${this.name}" ist das nächste mal am ${this.nextDate.toLocaleDateString('de-DE')} zu leeren`,
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public removePassedDates(): void {
|
|
29
|
+
const todayMidnight: number = new Date().setHours(0, 0, 0, 0);
|
|
30
|
+
while (this.dates.length > 0 && this.dates[0].getTime() < todayMidnight) {
|
|
31
|
+
this.dates.shift();
|
|
32
|
+
}
|
|
33
|
+
this.nextDate = this.dates[0];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public check(): void {
|
|
37
|
+
this.removePassedDates();
|
|
38
|
+
if (this.nextDate === undefined) {
|
|
39
|
+
ServerLogService.writeLog(LogLevel.Alert, `Die Mülltonne mit dem Namen ${this.name} hat keine nächste Abholung!`);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const todayMidnight: number = new Date().setHours(0, 0, 0, 0);
|
|
43
|
+
const tomorowMidnight: number = todayMidnight + MuellTonne.oneDay;
|
|
44
|
+
const tomorowAfterMidnight: number = tomorowMidnight + MuellTonne.oneDay;
|
|
45
|
+
const nextTimestamp: number = this.nextDate.getTime();
|
|
46
|
+
|
|
47
|
+
const daysTilNextEvent: number = (nextTimestamp - todayMidnight) / MuellTonne.oneDay;
|
|
48
|
+
ServerLogService.writeLog(
|
|
49
|
+
LogLevel.Info,
|
|
50
|
+
`Die Mülltonne mit dem Namen ${this.name} wird in ${daysTilNextEvent} Tagen das nächste Mal abgeholt.`,
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
if (nextTimestamp >= tomorowAfterMidnight) {
|
|
54
|
+
ServerLogService.writeLog(
|
|
55
|
+
LogLevel.Trace,
|
|
56
|
+
`Die Mülltonne mit dem Namen ${this.name} wird erst nach Übermorgen abgeholt`,
|
|
57
|
+
);
|
|
58
|
+
return; // Es ist noch lange hin
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (nextTimestamp >= tomorowMidnight) {
|
|
62
|
+
const message = `Die Mülltonne mit dem Namen ${this.name} wird morgen abgeholt!`;
|
|
63
|
+
TelegramService.inform(message);
|
|
64
|
+
|
|
65
|
+
if (this.ownSonosDevice) {
|
|
66
|
+
SonosService.speakOnDevice(message, this.ownSonosDevice, 30);
|
|
67
|
+
}
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (nextTimestamp >= todayMidnight) {
|
|
72
|
+
if (new Date().getHours() > 10) {
|
|
73
|
+
const message = `Die Mülltonne mit dem Namen ${this.name} wurde heute abgeholt, Mülltonne zurückstellen!`;
|
|
74
|
+
TelegramService.inform(message);
|
|
75
|
+
if (this.ownSonosDevice) {
|
|
76
|
+
SonosService.speakOnDevice(message, this.ownSonosDevice, 30);
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
const message = `Die Mülltonne mit dem Namen ${this.name} wird heute abgeholt!`;
|
|
80
|
+
TelegramService.inform(message);
|
|
81
|
+
if (this.ownSonosDevice) {
|
|
82
|
+
SonosService.speakOnDevice(message, this.ownSonosDevice, 30);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export class MuellService {
|
|
91
|
+
public static alleTonnen: Array<{ name: string; date: Date }> = [];
|
|
92
|
+
public static blaueTonne: MuellTonne;
|
|
93
|
+
public static graueTonne: MuellTonne;
|
|
94
|
+
public static gelbeTonne: MuellTonne;
|
|
95
|
+
public static brauneTonne: MuellTonne;
|
|
96
|
+
public static updateTimeCallback: TimeCallback;
|
|
97
|
+
public static checkTimeCallback: TimeCallback;
|
|
98
|
+
private static lastCheck: Date = new Date(0);
|
|
99
|
+
private static _calendarURL: string;
|
|
100
|
+
private static _active: boolean = false;
|
|
101
|
+
|
|
102
|
+
public static months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
103
|
+
|
|
104
|
+
public static intialize(config: iMuellSettings): void {
|
|
105
|
+
this._active = true;
|
|
106
|
+
this._calendarURL = config.calendarURL;
|
|
107
|
+
this.updateTimeCallback = new TimeCallback(
|
|
108
|
+
'MuelltonnenServiceUpdater',
|
|
109
|
+
TimeCallbackType.TimeOfDay,
|
|
110
|
+
() => {
|
|
111
|
+
this.updateCalendar(false);
|
|
112
|
+
},
|
|
113
|
+
0,
|
|
114
|
+
2,
|
|
115
|
+
0,
|
|
116
|
+
);
|
|
117
|
+
TimeCallbackService.addCallback(this.updateTimeCallback);
|
|
118
|
+
|
|
119
|
+
this.checkTimeCallback = new TimeCallback(
|
|
120
|
+
'MuelltonnenServiceChecker',
|
|
121
|
+
TimeCallbackType.TimeOfDay,
|
|
122
|
+
() => {
|
|
123
|
+
this.checkAll();
|
|
124
|
+
},
|
|
125
|
+
0,
|
|
126
|
+
18,
|
|
127
|
+
0,
|
|
128
|
+
);
|
|
129
|
+
TimeCallbackService.addCallback(this.checkTimeCallback);
|
|
130
|
+
|
|
131
|
+
this.updateCalendar();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public static updateCalendar(checkAfterwards: boolean = true): void {
|
|
135
|
+
ServerLogService.writeLog(LogLevel.Debug, `Muell Service wird nun initialisiert`);
|
|
136
|
+
async.fromURL(this._calendarURL).then((data) => {
|
|
137
|
+
this.gelbeTonne = new MuellTonne('Gelbe Tonne');
|
|
138
|
+
this.graueTonne = new MuellTonne('Graue Tonne');
|
|
139
|
+
this.blaueTonne = new MuellTonne('Blaue Tonne');
|
|
140
|
+
this.brauneTonne = new MuellTonne('Braune Tonne');
|
|
141
|
+
this.alleTonnen = [];
|
|
142
|
+
const todayMidnight: number = new Date().setHours(0, 0, 0, 0);
|
|
143
|
+
for (const k in data) {
|
|
144
|
+
if (!data.hasOwnProperty(k)) {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (data[k].type !== 'VEVENT') {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const ev = data[k] as VEvent;
|
|
153
|
+
ServerLogService.writeLog(
|
|
154
|
+
LogLevel.DeepTrace,
|
|
155
|
+
`${ev.summary} is in ${ev.location} on the ${ev.start.getDate()} of ${
|
|
156
|
+
this.months[ev.start.getMonth()]
|
|
157
|
+
} at ${ev.start.toLocaleTimeString('en-GB')}`,
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
if (ev.start.getTime() < todayMidnight) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
this.alleTonnen.push({name: ev.summary, date: ev.start});
|
|
165
|
+
switch (ev.summary) {
|
|
166
|
+
case this.gelbeTonne.name:
|
|
167
|
+
this.gelbeTonne.dates.push(ev.start);
|
|
168
|
+
break;
|
|
169
|
+
case this.graueTonne.name:
|
|
170
|
+
this.graueTonne.dates.push(ev.start);
|
|
171
|
+
break;
|
|
172
|
+
case this.blaueTonne.name:
|
|
173
|
+
this.blaueTonne.dates.push(ev.start);
|
|
174
|
+
break;
|
|
175
|
+
case this.brauneTonne.name:
|
|
176
|
+
this.brauneTonne.dates.push(ev.start);
|
|
177
|
+
break;
|
|
178
|
+
default:
|
|
179
|
+
ServerLogService.writeLog(LogLevel.Warn, `Unbekannte Mülltonne (${ev.summary})`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
this.gelbeTonne.sortDates();
|
|
184
|
+
this.graueTonne.sortDates();
|
|
185
|
+
this.blaueTonne.sortDates();
|
|
186
|
+
this.brauneTonne.sortDates();
|
|
187
|
+
this.alleTonnen = this.alleTonnen.sort((a, b) => a.date.getTime() - b.date.getTime());
|
|
188
|
+
if (checkAfterwards) {
|
|
189
|
+
this.checkAll();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
public static checkAll(pRetries: number = 10): void {
|
|
195
|
+
if (!this._active) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const now: Date = new Date();
|
|
200
|
+
if (now.getTime() - this.lastCheck.getTime() < 60000 && now.getDate() === this.lastCheck.getDate()) {
|
|
201
|
+
ServerLogService.writeLog(LogLevel.Trace, `MüllService.checkAll: Skipped weil wir gerade erst geprüft hatten.`);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (this.gelbeTonne === undefined) {
|
|
206
|
+
if (pRetries > 0) {
|
|
207
|
+
ServerLogService.writeLog(LogLevel.Warn, `Der Müllservice ist noch nicht bereit --> warten`);
|
|
208
|
+
Utils.guardedTimeout(() => {
|
|
209
|
+
MuellService.checkAll(pRetries - 1);
|
|
210
|
+
}, 1000);
|
|
211
|
+
} else {
|
|
212
|
+
ServerLogService.writeLog(LogLevel.Error, `Der Müllservice ist trotz Warten nicht bereit --> Abbruch`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
this.lastCheck = now;
|
|
219
|
+
this.gelbeTonne.check();
|
|
220
|
+
this.graueTonne.check();
|
|
221
|
+
this.blaueTonne.check();
|
|
222
|
+
this.brauneTonne.check();
|
|
223
|
+
}
|
|
224
|
+
}
|