-
Notifications
You must be signed in to change notification settings - Fork 0
/
MMM-Departures.js
264 lines (231 loc) · 9.48 KB
/
MMM-Departures.js
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
/* global Module */
/* Magic Mirror
* Module: MMM-Departures
*
* By Bengt Giger
* MIT Licensed.
*/
Module.register('MMM-Departures', {
defaults: {
apiUrl: 'http://transportrest-sbiermann.rhcloud.com/departureFHEM',
absoluteTime: true,
maxElements: 5,
initialLoadDelay: 1000,
updateInterval: 30 * 60 * 1000, // every 30 minutes
debug: false,
},
getStyles: function () {
return ["MMM-Departures.css"];
},
// Method is called when all modules are loaded an the system is ready to boot up
start: function() {
var self = this;
Log.info('Starting module: ' + this.name);
this.updateTimer = null;
this.lastUpdate = NaN;
this.scheduleUpdate(this.config.initialLoadDelay);
setInterval(function() {
self.updateDom();
}, 30000);
},
/* scheduleUpdate()
* Schedule next update.
*
* argument delay number - Milliseconds before next update. If empty, this.config.updateInterval is used.
*/
scheduleUpdate: function (delay) {
var nextLoad = this.config.updateInterval;
if (typeof delay !== 'undefined' && delay >= 0) {
nextLoad = delay;
}
var self = this;
clearTimeout(this.updateTimer);
// Timer to fetch new data
this.updateTimer = setTimeout(function () {
self.sendSocketNotification('GETDATA', self.config);
// Log.log('Departures new data fetched...');
}, nextLoad);
},
// Override socket notification handler.
// Module notifications from node_helper
socketNotificationReceived: function(notification, payload) {
if (notification === 'DATARECEIVED') {
for (var i = 0; i < this.config.stations.length; i++){
if (this.config.stations[i].stationId == payload.id) {
this.config.stations[i].departures = payload.departures;
this.loaded = true;
}
}
this.lastUpdate = Date.now();
this.updateDom();
this.scheduleUpdate(this.config.updateInterval);
}
},
leadingZero: function(num) {
num = (num < 10 ? '0' : '' )+ num;
return num;
},
// Filter departures
filterPassedDepartures: function(departures, minutesSinceUpdate, threshold) {
var filteredDepartures = [];
for (var i = 0; i < departures.length; i++) {
if (parseInt(departures[i][2], 10) - minutesSinceUpdate > 0) {
if (parseInt(departures[i][2], 10) - minutesSinceUpdate >= threshold) {
filteredDepartures.push(station.departures[i]);
}
}
}
return filteredDepartures;
},
filterIncludedLines: function(departures, wantedLines ) {
var filteredDepartures = [];
for (var i = 0; i < departures.length; i++) {
for (var j = 0; j < wantedLines.length; j++) {
if (wantedLines[j] == departures[i][0]) {
filteredDepartures.push(departures[i]);
}
}
}
return filteredDepartures;
},
filterExcludedLines: function(departures, unwantedLines ) {
var filteredDepartures = [];
for (var i = 0; i < departures.length; i++) {
for (var j = 0; j < unwantedLines.length; j++) {
if (unwantedLines[j] != departures[i][0]) {
filteredDepartures.push(departures[i]);
}
}
}
return filteredDepartures;
},
filterDepartures: function(departures, station, minutesSinceUpdate) {
if (station.hasOwnProperty("hideBelow")) {
departures = this.filterPassedDepartures(departures, minutesSinceUpdate, station.hideBelow);
} else {
departures = this.filterPassedDepartures(departures, minutesSinceUpdate, 0);
}
// Filter wanted/unwanted lines
if (station.hasOwnProperty("includeLines")) {
departures = this.filterIncludedLines(departures, station.includeLines);
}
if (station.hasOwnProperty("excludeLines")) {
departures = this.filterExcludedLines(departures, station.excludeLines);
}
return departures;
},
// Update the information on screen
getDom: function() {
var self = this;
// global config check
if ( ! this.config.hasOwnProperty("provider")) {
var errorWrapper = document.createElement("div");
errorWrapper.className = "small";
errorWrapper.innerHTML = "MMM-Departures: No provider set";
return errorWrapper;
}
if ( ! this.config.hasOwnProperty("stations")) {
var errorWrapper = document.createElement("div");
errorWrapper.className = "small";
errorWrapper.innerHTML = "MMM-Departures: No station set";
return errorWrapper;
}
if (this.config.debug) { Log.log("Stations defined: " + this.config.stations.length) };
if (!this.loaded) {
if (this.config.debug) { Log.log("State: module not completely loaded yet") };
var wrapper = document.createElement("div");
wrapper.innerHTML = this.translate("LOADING");
wrapper.className = "small dimmed";
return wrapper;
}
var wrapper = document.createElement("table");
wrapper.className = "small";
// Now iterate over defined stations
for (var si = 0; si < this.config.stations.length; si++) {
station = this.config.stations[si];
if (this.config.debug) { Log.log("Processing station " + station.stationName) };
// station config check
if (station.hasOwnProperty("includeLines") && station.hasOwnProperty("excludeLines")) {
var stationRowWrapper = document.createElement("tr");
var stationWrapper = document.createElement("td");
stationWrapper.setAttribute("colspan", "3");
stationWrapper.innerHTML = station.stationName + ": only one of 'includeLines' and 'excludeLines' allowed";
stationRowWrapper.appendChild(stationWrapper);
wrapper.append(stationRowWrapper);
if (this.config.debug) { Log.log("- Processing stopped: both 'includeLines' and 'excludeLines' used") };
break;
}
var minutesSinceUpdate = Math.round((Date.now() - this.lastUpdate)/60000);
// Process only stations with departures
if (station.hasOwnProperty("departures") && station.departures.length > 0) {
// Filter departures, eliminate if too late to reach or even passed
var activeDepartures = station.departures;
activeDepartures = this.filterDepartures(activeDepartures, station, minutesSinceUpdate);
// station may be not ready yet during startup
try {
var departuresShown = Math.min(this.config.maxElements, station.departures.length);
} catch (e) {
departuresShown = this.config.maxElements;
}
if (this.config.debug) { Log.log("- Departures found: " + departuresShown) };
// Build departure table: header with station name
var stationRowNameWrapper = document.createElement("tr");
// stationRowNameWrapper.className = "small";
var stationNameWrapper = document.createElement("td");
//stationNameWrapper.className = "bright";
stationNameWrapper.className = "heading";
stationNameWrapper.setAttribute("colspan", "3");
stationNameWrapper.innerHTML = station.stationName;
var stationRowWrapper = document.createElement("tr");
stationRowWrapper.appendChild(stationNameWrapper);
stationRowWrapper.appendChild(document.createElement("td"));
stationRowWrapper.appendChild(document.createElement("td"));
wrapper.appendChild(stationRowWrapper);
// Now list departures
for (var i = 0; i < departuresShown; i++) {
if (this.config.debug) { Log.log("-- Processing departure: " + activeDepartures[i]) };
var departureWrapper = document.createElement("tr");
// Fade out last 2 entries (only if more than 2 entries...)
if (departuresShown > 2) {
if (i == departuresShown - 2) {
departureWrapper.setAttribute("style", "opacity: 0.777777");
} else if (i == departuresShown - 1) {
departureWrapper.setAttribute("style", "opacity: 0.444444");
}
}
// Split departure info into table fields
for (var j = 0; j < 3; j++) {
var departureInfoWrapper = document.createElement("td");
// first 2 fields with spacer
if (j < 2) {
// cut destination station if configured
if (j == 1 && this.config.hasOwnProperty("maxDestinationLength")) {
departureInfoWrapper.innerHTML = activeDepartures[i][j].substr(0, this.config.maxDestinationLength) + " ";
} else {
departureInfoWrapper.innerHTML = activeDepartures[i][j] + " ";
}
departureInfoWrapper.className = "align-left";
}
// time field
if (j == 2) {
if (this.config.absoluteTime) {
// Calculate absolute time
var now = new Date();
var departureTime = new Date();
departureTime.setTime(now.getTime() + parseInt(activeDepartures[i][j],10)*1000*60)
departureInfoWrapper.innerHTML = departureTime.getHours() + ":" + this.leadingZero(departureTime.getMinutes());
} else {
// Correction for relative time since some time passed since data update
departureInfoWrapper.innerHTML = parseInt(parseInt(activeDepartures[i][j],10)-minutesSinceUpdate)+"m";
}
departureInfoWrapper.className = "align-right";
}
departureWrapper.appendChild(departureInfoWrapper);
}
wrapper.appendChild(departureWrapper);
}
}
}
return wrapper;
},
});