diff --git a/CHANGELOG.md b/CHANGELOG.md
index 79a9746..938763f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## [1.0.7] - 2019-11-10
+- fix a problem with loading plugin more then once
+- fix problem with counting visible stations
+- change MVG API URL
+- fix some typos
+
## [1.0.6] - 2019-09-17
- add option to show route for regional bus
diff --git a/mvgmunich.js b/mvgmunich.js
index c5b73f1..dc0aec7 100755
--- a/mvgmunich.js
+++ b/mvgmunich.js
@@ -1,208 +1,228 @@
-/* Timetable for public transport in Munich */
-
-/*
- * Magic Mirror
- * Module: MVG Munich
- *
- * By Simon Crnko
- * MIT Licensed
- *
- */
-
-const MS_PER_MINUTE = 60000;
-const mvgAPI = "https://www.mvg.de/api";
-Module.register("mvgmunich", {
- // Default module configuration
- defaults: {
- maxEntries: 8, // maximum number of results shown on UI
- updateInterval: MS_PER_MINUTE, // update every 60 seconds
- apiBase: mvgAPI + "/fahrinfo/departure/",
- stationQuery: mvgAPI + "/fahrinfo/location/queryWeb?q=",
- haltestelle: "Hauptbahnhof", // default departure station
- haltestelleId: 0,
- haltestelleName: "",
- ignoreStations: [], // list of destination to be ignored in the list
- timeToWalk: 0, // walking time to the station
- showWalkingTime: false, // if the walking time should be included and the starting time is displayed
- showTrainDepartureTime: true,
- trainDepartureTimeFormat: "relative",
- walkingTimeFormat: "relative",
- showIcons: true,
- transportTypesToShow: {
- "ubahn": true,
- "sbahn": true,
- "regional_bus": true,
- "bus": true,
- "tram": true
- }
- },
-
- getStyles: function() {
- return ["mvgmunich.css"];
- },
-
- // Load translations files
- getTranslations: function() {
- return {
- en: "translations/en.json",
- de: "translations/de.json"
- };
- },
-
- start: function() {
- var self = this;
- Log.info("Starting module: " + this.name);
- this.loaded = false;
- this.getData();
- setInterval(function() {
- self.updateDom();
- }, this.config.updateInterval);
- },
-
- /*
- * getData
- * function call getData function in node_helper.js
- */
- getData: function() {
- // get first stationId based on station name
- this.sendSocketNotification("GETSTATION", this.config);
- },
-
- // Override dom generator.
- getDom: function() {
- var wrapperTable = document.createElement("div");
- if (this.config.haltestelle === "") {
- wrapperTable.className = "dimmed light small";
- wrapperTable.innerHTML = "Please set value for 'Haltestelle'.";
- }
- if (!this.loaded) {
- wrapperTable.className = "dimmed light small";
- wrapperTable.innerHTML = "Loading data from MVG ...";
- return wrapperTable;
- }
- var wrapperTable = document.createElement("table");
- wrapperTable.className = "small";
- wrapperTable.innerHTML = this.dataRequest;
- return wrapperTable;
- },
-
- getHtml: function(jsonObject) {
- var htmlText = "";
-
- for (var i = 0, len = jsonObject.departures.length; i < this.config.maxEntries; i++) {
- // get one item from api result
- var apiResultItem = jsonObject.departures[i];
- // get transport type
- var transportType = apiResultItem.product.toLocaleLowerCase();
-
- // check if we should show data of this transport type
- // check if current station is not part of the ignore list
- if (!this.config.transportTypesToShow[transportType] ||
- this.config.ignoreStations.includes(apiResultItem.destination)) {
- continue;
- }
-
- htmlText += "
";
- // check if user want's icons
- htmlText += this.showIcons(apiResultItem.product, this.config.showIcons);
- // add transport number
- htmlText += "" + apiResultItem.label + " | ";
- // add last station aka direction
- htmlText += "" + apiResultItem.destination + " | ";
- // check if user want's to see departure time
- htmlText += this.showDepartureTime(apiResultItem.departureTime, this.config);
- // check if user want's to see walking time
- htmlText += this.showWalkingTime(apiResultItem.departureTime);
- htmlText += "
";
- }
-
- return htmlText;
- },
-
- showIcons(product, showIcons) {
- // if (Object.is(showIcons, true)) {
- if(showIcons)
- return " | ";
- return "";
- },
-
- showWalkingTime: function (departureTime) {
- var htmlText = "";
- if (this.config.showWalkingTime) {
- htmlText += " / ";
- var startWalkingTime = new Date(departureTime - this.config.timeToWalk * MS_PER_MINUTE);
- // check what kind of walking time user wants (absolute / relative)
- if(this.config.walkingTimeFormat == "absolute") {
- htmlText += this.getAbsoluteTime(startWalkingTime);
- } else if (this.config.walkingTimeFormat == "relative") {
- htmlText += this.getRelativeTime(startWalkingTime);
- } else {
- htmlText += "walkingTimeFormat config is wrong"
- }
- htmlText += " | ";
- }
- return htmlText;
- },
-
- showDepartureTime: function (departureTime, config) {
- var htmlText = "";
- if(config.showTrainDepartureTime) {
- // add departure time
- htmlText += "";
- var departureTime = new Date(departureTime)
-
- // check what kind of time user wants (absolute / relative)
- if(config.trainDepartureTimeFormat == "absolute") {
- htmlText += this.getAbsoluteTime(departureTime);
- } else if (config.trainDepartureTimeFormat == "relative") {
- htmlText += this.getRelativeTime(departureTime);
- } else {
- htmlText += "trainDepartureTimeFormat config is wrong"
- }
- htmlText += " | ";
- }
- return htmlText;
- },
-
- getAbsoluteTime: function(time) {
- var hoursStr = (time.getHours() < 10 ? '0' : '') + time.getHours();
- var minutesStr = (time.getMinutes() < 10 ? '0' : '') + time.getMinutes();
-
- return hoursStr + ":" + minutesStr;
- },
-
- getRelativeTime: function(time) {
- var timingForStartWalking = Math.floor((time.getTime() - new Date().getTime()) / 1000 / 60);
- return (timingForStartWalking <=0
- ? this.translate("JETZT")
- : this.translate("IN") + " " + timingForStartWalking + " " + this.translate("MIN"));
- },
-
- // Override getHeader method.
- getHeader: function() {
- return this.data.header + " Munich: " + this.config.haltestelleName;
- },
-
- socketNotificationReceived: function(notification, payload) {
- if (notification === "UPDATE") {
- this.dataRequest = this.getHtml(payload);
- this.loaded = true;
- this.updateDom();
- }
- if (notification === "ERROR") {
- this.dataRequest = payload;
- this.loaded = true;
- this.updateDom();
- }
- if (notification === "ERROR_NO_STATION") {
- this.dataRequest = this.translate("NO_STATION");
- this.loaded = true;
- this.updateDom();
- }
- if (notification === "STATION") {
- this.config.haltestelleName = payload.name;
- this.config.haltestelleId = payload.id
- this.sendSocketNotification("GETDATA", this.config);
- }
- }
-});
+/* Timetable for public transport in Munich */
+
+/*
+ * Magic Mirror
+ * Module: MVG Munich
+ *
+ * By Simon Crnko
+ * MIT Licensed
+ *
+ */
+
+const MS_PER_MINUTE = 60000;
+const mvgAPI = "https://www.mvg.de/api";
+Module.register("mvgmunich", {
+ // Default module configuration
+ defaults: {
+ maxEntries: 8, // maximum number of results shown on UI
+ updateInterval: MS_PER_MINUTE, // update every 60 seconds
+ apiBase: mvgAPI + "/fahrinfo/departure/",
+ stationQuery: mvgAPI + "/fahrinfo/location/queryWeb?q=",
+ haltestelle: "Hauptbahnhof", // default departure station
+ haltestelleId: 0,
+ haltestelleName: "",
+ ignoreStations: [], // list of destination to be ignored in the list
+ timeToWalk: 0, // walking time to the station
+ showWalkingTime: false, // if the walking time should be included and the starting time is displayed
+ showTrainDepartureTime: true,
+ trainDepartureTimeFormat: "relative",
+ walkingTimeFormat: "relative",
+ showIcons: true,
+ transportTypesToShow: {
+ "ubahn": true,
+ "sbahn": true,
+ "regional_bus": true,
+ "bus": true,
+ "tram": true
+ }
+ },
+
+ getStyles: function () {
+ return ["mvgmunich.css"];
+ },
+
+ // Load translations files
+ getTranslations: function () {
+ return {
+ en: "translations/en.json",
+ de: "translations/de.json"
+ };
+ },
+
+ start: function () {
+ this.resultData = [];
+ Log.info("Starting module: " + this.name + ", identifier: " + this.identifier);
+ if (this.config.haltestelle !== "") {
+ this.sendSocketNotification("GET_STATION_INFO", this.config);
+ }
+ },
+
+ /*
+ * getData
+ * function call getData function in node_helper.js
+ *
+ */
+ getData: function () {
+ const self = this;
+ self.sendSocketNotification("GET_DEPARTURE_DATA", self.config);
+ setInterval(function () {
+ self.sendSocketNotification("GET_DEPARTURE_DATA", self.config);
+ }, self.config.updateInterval);
+ },
+
+ // Override dom generator.
+ getDom: function () {
+ let wrapperTable = document.createElement("div");
+ if (this.config.haltestelle === "") {
+ wrapperTable.className = "dimmed light small";
+ wrapperTable.innerHTML = "Please set value for 'Haltestelle'.";
+ return wrapperTable;
+ }
+ // console.log("this.resultData: {}", this.resultData);
+ if (this.resultData === []) {
+ wrapperTable.className = "dimmed light small";
+ wrapperTable.innerHTML = "Loading data from MVG ...";
+ return wrapperTable;
+ }
+ wrapperTable = document.createElement("table");
+ wrapperTable.className = "small";
+ wrapperTable.innerHTML = this.resultData[this.config.haltestelle];
+ return wrapperTable;
+ },
+
+ getHtml: function (jsonObject) {
+ let htmlText = "";
+
+ // console.log("payload.maxEntries: " + payload.maxEntries);
+ let visibleLines = 0;
+ for (let i = 0; i < jsonObject.departures.length; i++) {
+ if (visibleLines >= this.config.maxEntries) {
+ break;
+ }
+ // get one item from api result
+ const apiResultItem = jsonObject.departures[i];
+ // get transport type
+ const transportType = apiResultItem.product.toLocaleLowerCase();
+
+ // console.log("transportType: " + transportType);
+ // console.log("apiResultItem.destination: " + apiResultItem.destination);
+ // console.log("apiResultItem.departureTime: " + apiResultItem.departureTime);
+
+ // check if we should show data of this transport type
+ // check if current station is not part of the ignore list
+ if (!this.config.transportTypesToShow[transportType] ||
+ this.config.ignoreStations.includes(apiResultItem.destination)) {
+ continue;
+ }
+
+ htmlText += "";
+ // check if user want's icons
+ htmlText += this.showIcons(apiResultItem.product, this.config.showIcons);
+ // add transport number
+ htmlText += "" + apiResultItem.label + " | ";
+ // add last station aka direction
+ htmlText += "" + apiResultItem.destination + " | ";
+ // check if user want's to see departure time
+ htmlText += this.showDepartureTime(apiResultItem.departureTime);
+ // check if user want's to see walking time
+ htmlText += this.showWalkingTime(apiResultItem.departureTime);
+ htmlText += "
";
+ visibleLines++;
+ }
+ // console.log("htmlText: " + "haltestelle: " + payload.haltestelle + " - " + htmlText);
+ return htmlText;
+ },
+
+ showIcons: function (product, showIcons) {
+ // console.log("Show icons: ", showIcons);
+ let icons = "";
+ if (showIcons) {
+ icons = " | ";
+ }
+ // console.log("Icons content: {}", icons);
+ return icons;
+ },
+
+ showWalkingTime: function (departureTime) {
+ let htmlText = "";
+ if (this.config.showWalkingTime) {
+ htmlText += " / ";
+ const startWalkingTime = new Date(departureTime - this.config.timeToWalk * MS_PER_MINUTE);
+ // check what kind of walking time user wants (absolute / relative)
+ if (this.config.walkingTimeFormat === "absolute") {
+ htmlText += this.getAbsoluteTime(startWalkingTime);
+ } else if (this.config.walkingTimeFormat === "relative") {
+ htmlText += this.getRelativeTime(startWalkingTime);
+ } else {
+ htmlText += "walkingTimeFormat config is wrong";
+ }
+ htmlText += " | ";
+ }
+ return htmlText;
+ },
+
+ showDepartureTime: function (departureTime) {
+ let htmlText = "";
+ if (this.config.showTrainDepartureTime) {
+ // add departure time
+ htmlText += "";
+ const departureDate = new Date(departureTime);
+ // console.log("departureDate: " + departureDate);
+ // check what kind of time user wants (absolute / relative)
+ if (this.config.trainDepartureTimeFormat === "absolute") {
+ htmlText += this.getAbsoluteTime(departureDate);
+ } else if (this.config.trainDepartureTimeFormat === "relative") {
+ htmlText += this.getRelativeTime(departureDate);
+ } else {
+ htmlText += "trainDepartureTimeFormat config is wrong";
+ }
+ htmlText += " | ";
+ }
+ return htmlText;
+ },
+
+ getAbsoluteTime: function (time) {
+ let hoursStr = (time.getHours() < 10 ? "0" : "") + time.getHours();
+ let minutesStr = (time.getMinutes() < 10 ? "0" : "") + time.getMinutes();
+
+ return hoursStr + ":" + minutesStr;
+ },
+
+ getRelativeTime: function (time) {
+ const timingForStartWalking = Math.floor((time.getTime() - new Date().getTime()) / 1000 / 60);
+ return (timingForStartWalking <= 0
+ ? this.translate("JETZT")
+ : this.translate("IN") + " " + timingForStartWalking + " " + this.translate("MIN"));
+ },
+
+ // Override getHeader method.
+ getHeader: function () {
+ if (this.config.haltestelle !== "" || this.config.haltestelleName !== "") {
+ return this.data.header + " Munich: " +
+ (this.config.haltestelleName === "" ? this.config.haltestelle : this.config.haltestelleName);
+ }
+ return "";
+ },
+
+ socketNotificationReceived: function (notification, payload) {
+ // console.log("Notification in mvgmunich: " + notification + " - " + payload);
+ // console.log("this.config.haltestelle: " + this.config.haltestelle);
+ // console.log("payload.transport: " + payload.transport);
+ switch (notification) {
+ case "UPDATE_DEPARTURE_INFO":
+ this.resultData[payload.haltestelle] = this.getHtml(payload.transport);
+ break;
+ case "UPDATE_STATION":
+ if (this.config.haltestelle === payload.haltestelle) {
+ this.config.haltestelleId = payload.haltestelleId;
+ this.config.haltestelleName = payload.haltestelleName;
+ }
+ this.getHeader();
+ this.getData();
+ break;
+ default:
+ Log.error();
+ }
+ this.updateDom();
+ }
+});
diff --git a/node_helper.js b/node_helper.js
index 17b4cf1..2af1a36 100755
--- a/node_helper.js
+++ b/node_helper.js
@@ -7,10 +7,10 @@
*
*/
-var NodeHelper = require("node_helper");
-var request = require("request");
-var urlencode = require('urlencode');
-var globals = {
+const NodeHelper = require("node_helper");
+const request = require("request");
+const urlencode = require("urlencode");
+const globals = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json, text/javascript, */*; q=0.01",
@@ -23,82 +23,83 @@ var globals = {
module.exports = NodeHelper.create({
- start: function() {
- this.config = null;
- },
-
- socketNotificationReceived: function(notification, payload) {
+ socketNotificationReceived: function (notification, payload) {
+ // console.log("Notification in node_helper: " + notification + " - " + payload);
const self = this;
- this.config = payload;
- if (notification === "GETDATA") {
- self.getDepartureInfo();
- self.scheduleUpdate(this.config.updateInterval);
- }
- if (notification === "GETSTATION") {
- self.getStationInfo();
+ switch (notification) {
+ case "GET_STATION_INFO":
+ self.getStationInfo(payload);
+ break;
+ case "GET_DEPARTURE_DATA":
+ self.getDepartureInfo(payload);
+ break;
+ default:
+ console.error("Switch item {} is missing", notification);
}
},
- getDepartureInfo: function() {
- var self = this;
-
+ getDepartureInfo: function (payload) {
+ const self = this;
+ // console.log("Haltestelle: {} URL: {}", payload.haltestelle, payload.apiBase + payload.haltestelleId + "?footway=" + payload.timeToWalk);
request({
headers: globals,
- uri: self.config.apiBase + self.config.haltestelleId + "?footway=" + self.config.timeToWalk,
+ uri: payload.apiBase + payload.haltestelleId + "?footway=" + payload.timeToWalk,
method: "GET",
gzip: true
- }, function(error, response, body) {
+ }, function (error, response, body) {
+ // console.log("Response: " + response);
+ // console.log("Body: " + body);
if (error) {
// Error while reading departure data ...
+ console.error("Error while reading departure info", error);
self.sendSocketNotification("ERROR", "Error while reading data: " + error.message);
} else {
// body is the decompressed response body
- var jsonObject = JSON.parse(body);
- self.sendSocketNotification("UPDATE", jsonObject);
+ try {
+ // console.log("haltestelle: {} Body: {}", payload.haltestelle, body);
+ // console.log("haltestelle: {} jsonObject: {}", payload.haltestelle, jsonObject);
+ // payload.transport = self.getHtml(JSON.parse(body), payload);
+ payload.transport = JSON.parse(body);
+ self.sendSocketNotification("UPDATE_DEPARTURE_INFO", payload);
+ } catch (e) {
+ console.error("Error while parsing and sending departure info", e);
+ self.sendSocketNotification("ERROR_NO_DEPARTURE_DATA", "");
+ }
}
});
},
- getStationInfo: function() {
- var self = this;
-
+ getStationInfo: function (payload) {
+ const self = this;
+ // console.log("Station info Query: {}", payload.stationQuery + urlencode(payload.haltestelle));
request({
headers: globals,
- uri: self.config.stationQuery + urlencode(self.config.haltestelle),
+ uri: payload.stationQuery + urlencode(payload.haltestelle),
method: "GET",
gzip: true
- }, function(error, response, body) {
+ }, function (error, response, body) {
if (error) {
- // Error while reading departure data ...
+ // Error while reading station data ...
+ console.error("Error while reading station data", error);
self.sendSocketNotification("ERROR", "Error while reading data: " + error.message);
} else {
// body is the decompressed response body
try {
- var jsonObject = JSON.parse(body);
- if(jsonObject.locations[0].id === undefined) {
+ const jsonObject = JSON.parse(body);
+ if (jsonObject.locations[0].id === undefined) {
self.sendSocketNotification("ERROR_NO_STATION", "");
- } else
- self.sendSocketNotification("STATION", jsonObject.locations[0]);
+ } else {
+ // console.log("json: {}", jsonObject.locations[0]);
+ payload.haltestelleId = jsonObject.locations[0].id;
+ payload.haltestelleName = jsonObject.locations[0].name;
+ self.sendSocketNotification("UPDATE_STATION", payload);
+ }
} catch (e) {
- self.sendSocketNotification("ERROR_NO_STATION", "");
+ console.error("Error while parsing and sending station info", e);
+ self.sendSocketNotification("ERROR_NO_STATION", "");
}
}
});
},
- /* 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;
- }
- nextLoad = nextLoad;
- var self = this;
- setInterval(function() {
- self.getDepartureInfo();
- }, nextLoad);
- }
});
diff --git a/package.json b/package.json
index 25a2bc0..ffb67a0 100644
--- a/package.json
+++ b/package.json
@@ -1,23 +1,24 @@
{
- "name": "MMM-mvgmunich",
- "version": "1.0.6",
- "description": "",
- "main": "mvgmunich.js",
- "author": "Simon Crnko",
- "license": "MIT",
- "homepage": "https://github.com/mrVragec/MMM-mvgmunich",
- "keywords": [
- "magic mirror",
- "public transport",
- "mvv",
- "mvg"
- ],
- "repository": {
- "type": "git",
- "url": "https://github.com/mrVragec/MMM-mvgmunich"
- },
- "contributors": "",
- "dependencies": {
- "urlencode":"~1.1.0"
- }
+ "name": "MMM-mvgmunich",
+ "version": "1.0.7",
+ "description": "",
+ "main": "mvgmunich.js",
+ "author": "Simon Crnko",
+ "license": "MIT",
+ "homepage": "https://github.com/mrVragec/MMM-mvgmunich",
+ "keywords": [
+ "magic mirror",
+ "public transport",
+ "mvv",
+ "mvg"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/mrVragec/MMM-mvgmunich"
+ },
+ "contributors": "",
+ "dependencies": {
+ "request": "^2.88.0",
+ "urlencode": "~1.1.0"
+ }
}