Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BugFix for 'Loading...' issue #34

Open
Stephan3555 opened this issue Jan 14, 2019 · 1 comment
Open

BugFix for 'Loading...' issue #34

Stephan3555 opened this issue Jan 14, 2019 · 1 comment

Comments

@Stephan3555
Copy link

Hi guys,
stumbled over the "Loading..." issue by myself. A short debug session revealed that if the distance is too short, google suggests 'walking'. Unfortunately the google API dont specify 'departure_time' and 'arrival_time' for 'walking'. Hence the code run in an undefined parameter and quits.

I fixed this issue (in a really dirty way) to get it going for me. If you run in the same mistake just replace the MMM-LocalTransport.js with the following code:

/* global Module */
/* Magic Mirror
 * Module: MMM-LocalTransport
 *
 * By Christopher Fenner https://github.com/CFenner
 * style options by Lasse Wollatz
 * MIT Licensed.
 */
Module.register('MMM-LocalTransport', {
  defaults: {
    maximumEntries: 3,
    displayStationLength: 0,
    displayWalkType: 'short',
    displayArrival: true,
    maxWalkTime: 10,
    fade: true,
    fadePoint: 0.1,
    showColor: true,
    maxModuleWidth: 0,
    animationSpeed: 1,
    updateInterval: 5,
    language: config.language,
    units: config.units,
    timeFormat: config.timeFormat,
    mode: 'transit',
    traffic_model: 'best_guess',
    departure_time: 'now',
    alternatives: true,
    apiBase: 'https://maps.googleapis.com/',
    apiEndpoint: 'maps/api/directions/json',
    debug: false
  },
  start: function() {
    Log.info('Starting module: ' + this.name);
    this.loaded = false;
    this.url = this.config.apiBase + this.config.apiEndpoint + this.getParams();
    var d = new Date();
    this.lastupdate = d.getTime() - 2 * this.config.updateInterval * 60 * 1000;
    this.update();
    // refresh every 0.25 minutes
    setInterval(
        this.update.bind(this),
        15 * 1000);
  },
  update: function() {
    //updateDOM
    var dn = new Date();
    if (dn.getTime() - this.lastupdate >= this.config.updateInterval * 60 * 1000){
        //perform main update
        //request routes from Google

	Log.info(this.config.apiBase + this.config.apiEndpoint + this.getParams());

        this.sendSocketNotification(
            'LOCAL_TRANSPORT_REQUEST', {
                id: this.identifier,
                url: this.config.apiBase + this.config.apiEndpoint + this.getParams()
            }
        );
        if (this.config.debug){
          this.sendNotification("SHOW_ALERT", { timer: 3000, title: "LOCAL TRANSPORT", message: "special update"});
        }
        this.lastupdate = dn.getTime();
    }else{
        //perform minor update
        //only update time
        if (this.config.debug){
          this.sendNotification("SHOW_ALERT", {timer: 3000, title: "LOCAL TRANSPORT", message: "normal update"});
        }
        this.loaded = true;
        this.updateDom(); //this.updateDom(this.config.animationSpeed * 1000)
    }
  },
  getParams: function() {
    var params = '?';
    params += 'mode=' + this.config.mode;
    params += '&origin=' + this.config.origin;
    params += '&destination=' + this.config.destination;
    params += '&key=' + this.config.api_key;
    params += '&traffic_model=' + this.config.traffic_model;
    params += '&departure_time=now';
    params += '&alternatives=true';
    return params;
  },
  renderLeg: function(wrapper, leg){
    /* renderLeg
     * creates HTML element for one leg of a route
     */

    /*
    * If Distance is too short, Google suggests walking. Therefore 'deparure' and 'arrival'
    * are not set by the google API. Have to calculate by myself
    */
    if(leg.departure_time === undefined){
	var depature = new Date();
    	var arrival = new Date() + leg.duration.value;
    } else {
	var depature = leg.departure_time.value * 1000;
	var arrival = leg.arrival_time.value * 1000;
    }

    //var depadd = leg.start_address;
    var span = document.createElement("div");
    span.className = "small bright";
    span.innerHTML = moment(depature).locale(this.config.language).fromNow();
    // span.innerHTML += "from " + depadd;
    if (this.config.displayArrival && this.config.timeFormat === 24){
        span.innerHTML += " ("+this.translate("ARRIVAL")+": " + moment(arrival).format("H:mm") + ")";
    }else if(this.config.displayArrival){
        span.innerHTML += " ("+this.translate("ARRIVAL")+": " + moment(arrival).format("h:mm") + ")";
    }
    // span.innerHTML += this.translate('TRAVEL_TIME') + ": ";
    // span.innerHTML += moment.duration(moment(arrival).diff(depature, 'minutes'), 'minutes').humanize();
    wrapper.appendChild(span);
  },
  renderStep: function(wrapper, step){
    /* renderStep
     * creates HTML element for one step of a leg
     */
    if(step.travel_mode === "WALKING"){
        /*this step is not public transport but walking*/
        var duration = step.duration.value;
        if (duration >= (this.config.maxWalkTime*60)){
            /*if time of walking is longer than
             *specified, mark this route to be skipped*/
            wrapper.innerHTML = "too far";
        }else if(this.config.displayWalkType != 'none'){
            /*if walking and walking times should be
             *specified, add symbol and time*/
            var img = document.createElement("img");
            if(this.config.showColor){
                img.className = "symbol";
            }else{
                img.className = "symbol bw";
            }
            img.src = "http://maps.gstatic.com/mapfiles/transit/iw2/6/walk.png";
            //img.src = "/localtransport/walk.png"; //needs to be saved in localtransport/public/walk.png
            wrapper.appendChild(img)
            var span = document.createElement("span");
            span.innerHTML = moment.duration(duration, 'seconds').locale(this.config.language).humanize();
            if(this.config.displayWalkType === 'short'){
                span.innerHTML = span.innerHTML.replace(this.translate("MINUTE_PL"),this.translate("MINUTE_PS"));
                span.innerHTML = span.innerHTML.replace(this.translate("MINUTE_SL"),this.translate("MINUTE_SS"));
                span.innerHTML = span.innerHTML.replace(this.translate("SECOND_PL"),this.translate("SECOND_PS"));
            }
            span.className = "xsmall dimmed";
            wrapper.appendChild(span);
        }else{
            /*skip walking*/
            return;
        }
    }else{
        /*if this is a transit step*/
        var details = step.transit_details;
        if(details) {
            /*add symbol of transport vehicle*/
            var img = document.createElement("img");
            if(this.config.showColor){
                img.className = "symbol";
            }else{
                img.className = "symbol bw";
            }
            /* get symbol online*/
            img.src = details.line.vehicle.local_icon || ("http:" + details.line.vehicle.icon);
            /* can provide own symbols under /localtransport/public/*.png */
            //img.src = "/localtransport/" + details.line.vehicle.name + ".png";
            img.alt = "[" + details.line.vehicle.name +"]";
            wrapper.appendChild(img);
            /*add description*/
            var span = document.createElement("span");
            /* add line name*/
            span.innerHTML = details.line.short_name || details.line.name;
            if (this.config.displayStationLength > 0){
                /* add departure stop (shortened)*/
                span.innerHTML += " ("+this.translate("FROM")+" " + this.shorten(details.departure_stop.name, this.config.displayStationLength) + ")";
            }else if (this.config.displayStationLength === 0){
                /* add departure stop*/
                span.innerHTML += " ("+this.translate("FROM")+" " + details.departure_stop.name + ")";
            }
            if (this.config.debug){
                /* add vehicle type for debug*/
                span.innerHTML += " [" + details.line.vehicle.name +"]";
            }
            span.className = "xsmall dimmed";
            wrapper.appendChild(span);
        }
    }
  },
  socketNotificationReceived: function(notification, payload) {
    if (notification === 'LOCAL_TRANSPORT_RESPONSE' && payload.id === this.identifier) {
        Log.info('received' + notification);
        if(payload.data && payload.data.status === "OK"){
            this.info = payload.data;
            this.loaded = true;
            this.updateDom(this.config.animationSpeed * 1000);
        }
    }
  },
  getStyles: function() {
    return ["localtransport.css"];
  },
  getScripts: function() {
        return ["moment.js"];
  },
  getTranslations: function() {
    return {
        de: "i18n/de.json",
        en: "i18n/en.json",
        sv: "i18n/sv.json",
        fr: "i18n/fr.json"
    };
  },
  getDom: function() {
    /* main function creating HTML code to display*/
    var wrapper = document.createElement("div");
    if (!this.loaded) {
        /*if not loaded, display message*/
        wrapper.innerHTML = this.translate("LOADING_CONNECTIONS");
        wrapper.className = "small dimmed";
    }else{
        /*create an unsorted list with each
         *route alternative being a new list item*/
        //var udt = document.createElement("div");
        //udt.innerHTML = moment().format("HH:mm:ss") + " (" +  this.lastupdate + ")";
        //wrapper.appendChild(udt);
        var ul = document.createElement("ul");
        var Nrs = 0; //number of routes
        var routeArray = []; //array of all alternatives for later sorting
        for(var routeKey in this.info.routes) {
            /*each route describes a way to get from A to Z*/
            //if(Nrs >= this.config.maxAlternatives){
            //  break;
            //}
	    Log.info("Routkey: " + routeKey);
            var route = this.info.routes[routeKey];
            var li = document.createElement("li");
            li.className = "small";
            var arrival = 0;
            if (this.config.maxModuleWidth > 0){
              li.style.width = this.config.maxModuleWidth + "px";
            }
            for(var legKey in route.legs) {
                var leg = route.legs[legKey];
               
                /*
    		* If Distance is too short, Google suggests walking. Therefore 'arrival' 
		* is not set by the google API. Have to calculate by myself
   		*/

		if (leg.arrival_time === undefined){
			arrival = new Date() + leg.duration.value;
		} else {
			arrival = leg.arrival_time.value;
		}
//		arrival = leg.arrival_time.value;
                var tmpwrapper = document.createElement("text");
                for(var stepKey in leg.steps) {
                    /*each leg consists of several steps
                     *e.g. (1) walk from A to B, then
                           (2) take the bus from B to C and then
                           (3) walk from C to Z*/
                    var step = leg.steps[stepKey];
                    this.renderStep(tmpwrapper, step);
                    if (tmpwrapper.innerHTML === "too far"){
                        //walking distance was too long -> skip this option
                        break;
                    }
                }
                if (tmpwrapper.innerHTML === "too far"){
                    //walking distance was too long -> skip this option
                    li.innerHTML = "too far";
                    break;
                }
                this.renderLeg(li, leg);
                li.appendChild(tmpwrapper);
            }
            if (li.innerHTML !== "too far"){
                routeArray.push({"arrival":arrival,"html":li});
                Nrs += 1;
            }
        }

        /*sort the different alternative routes by arrival time*/
        routeArray.sort(function(a, b) {
            return parseFloat(a.arrival) - parseFloat(b.arrival);
        });
        /*only show the first few options as specified by "maximumEntries"*/
        routeArray = routeArray.slice(0, this.config.maximumEntries);

        /*create fade effect and append list items to the list*/
        var e = 0;
        Nrs = routeArray.length;
        for(var dataKey in routeArray) {
            var routeData = routeArray[dataKey];
            var routeHtml = routeData.html;
            // Create fade effect.
            if (this.config.fade && this.config.fadePoint < 1) {
                if (this.config.fadePoint < 0) {
                    this.config.fadePoint = 0;
                }
                var startingPoint = Nrs * this.config.fadePoint;
                var steps = Nrs - startingPoint;
                if (e >= startingPoint) {
                    var currentStep = e - startingPoint;
                    routeHtml.style.opacity = 1 - (1 / steps * currentStep);
                }
            }
            ul.appendChild(routeHtml);
            e += 1;
        }
        wrapper.appendChild(ul);
    }
    return wrapper;
  },
  shorten: function(string, maxLength) {
    /*shorten
     *shortens a string to the number of characters specified*/
    if (string.length > maxLength) {
        return string.slice(0,maxLength) + "&hellip;";
    }
    return string;
  }

});

I am not doing a pull request because I think the owner abandoned the project already.

Greetings,
Stephan

@GHLasse
Copy link
Contributor

GHLasse commented Feb 24, 2019

Hi Stephan,
If you can fix this in my version (https://github.com/GHLasse/MagicMirror-LocalTransport-Module) I am happy to pull it there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants