• Recent
  • Tags
  • Unsolved
  • Solved
  • MagicMirror² Repository
  • Documentation
  • 3rd-Party-Modules
  • Donate
  • Discord
  • Register
  • Login
MagicMirror Forum
  • Recent
  • Tags
  • Unsolved
  • Solved
  • MagicMirror² Repository
  • Documentation
  • 3rd-Party-Modules
  • Donate
  • Discord
  • Register
  • Login
A New Chapter for MagicMirror: The Community Takes the Lead
Read the statement by Michael Teeuw here.

MM & Google Maps Traffic

Scheduled Pinned Locked Moved Troubleshooting
16 Posts 4 Posters 15.9k Views 5 Watching
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    birdy
    last edited by birdy Aug 27, 2017, 2:25 PM Aug 27, 2017, 2:24 PM

    Hi all,

    I was looking in the forum and internet, but couldn’t find a solution. Did anyone on you managed to show the google maps route (from A to B) and trafic?

    Like this (example from this forum):
    alt text.

    I (hope i did) intalled the module MMM-googlemaps. Sometimes I read I need an iFrame, sometimes: it won’t work with an iFrame.
    My code:

    //		{
    		   module: "MMM-googlemaps",
    		   position: 'bottom_right',
    		   config: {
    		       apikey: '*my API*',
    			origin: 'Köln,+Deutschland',
    			destination: 'Essen,+Deutschland',
    			mode: driving,
    		   }
    		},
    

    Thx for your support!
    Birdy

    S 1 Reply Last reply Aug 27, 2017, 7:24 PM Reply Quote 0
    • M Offline
      Mirrorolentia
      last edited by Aug 27, 2017, 4:03 PM

      Yes! I did it with the MMM-Traffic module. A bit of hacks and unclean code 😑 but yeah was able to get it working. Will try to share the same

      1 Reply Last reply Reply Quote 0
      • M Offline
        Mirrorolentia
        last edited by Aug 27, 2017, 5:07 PM

        /* global Module */

        /* Magic Mirror

        • Module: MMM-Traffic
        • By Sam Lewis https://github.com/SamLewis0602
        • MIT Licensed.
          */

        Module.register(‘MMM-Traffic’, {

        defaults: {
            api_key: '',
            mode: 'driving',
            interval: 300000, //all modules use milliseconds
            origin: '',
            destination: '',
            mon_destination: '',
            tues_destination: '',
            wed_destination: '',
            thurs_destination: '',
            fri_destination: '',
            traffic_model: 'best_guess',
            departure_time: 'now',
            arrival_time: '',
            loadingText: 'Loading commute...',
            prependText: 'Current commute is',
            changeColor: false,
            limitYellow: 10,
            limitRed: 30,
            showGreen: true,
            language: config.language,
            show_summary: true,
            showWeekend: true,
            allTime: true,
            startHr: 7,
            endHr: 22,
            avoid:'',
              summaryText:'via',
              leaveByText:'Leave by',
              arriveByText:'to arrive by',
            hideOffHours: false,
        },
        setLocalParams: function(){
        	// These parameters are populated mostly 
        	// by node_helper
            this.loaded = false;
            this.mapLoaded= false;
            this.leaveBy = '';
            this.symbols = {
                'driving': 'fa fa-car',
                'walking': 'fa fa-odnoklassniki',
                'bicycling': 'fa fa-bicycle',
                'transit': 'fa fa-train'
            };
            this.commute = '';
            this.summary = '';
        },
        start: function() {
            Log.info('Starting module: ' + this.name);
            if (this.data.classes === 'MMM-Traffic') {
              this.data.classes = 'bright medium';
            }
            this.loaded = false;
            this.mapLoaded= false;
            this.leaveBy = '';
            var myURL = 'https://maps.googleapis.com/maps/api/directions/json' + this.getParams();  
            console.log("Querying with loc = " + myURL);
            this.url = encodeURI('https://maps.googleapis.com/maps/api/directions/json' + this.getParams());
            this.symbols = {
                'driving': 'fa fa-car',
                'walking': 'fa fa-odnoklassniki',
                'bicycling': 'fa fa-bicycle',
                'transit': 'fa fa-train'
            };
            this.commute = '';
            this.summary = '';
            this.updateCommute(this);
        },
        // Handler for notifications from any other module asking for 
        // TRAFFFIC update.
        // This will invoke updateCommute with new source and destination
        // TODO: The new source and destination will continue to get displayed untill
        // it is reset. Will try to revert that
        notificationReceived: function(notification, payload, sender){
        	Log.log(notification+" received from "+sender);
        	var myURL = "";
        	if(notification === "TRAFFIC_ACTION_NEEDED"){
        		console.log("Received new traffic update request for start: "+payload.start_location+" end:"+payload.end_location);
        		myURL = 'https://maps.googleapis.com/maps/api/directions/json' + 
        			    this.getParam_specific(payload.start_location, payload.end_location);
        		console.log("Querying with "+myURL);
        	    this.url = encodeURI(myURL);
        		this.updateCommute(this);
        	}
        },
        
        updateCommute: function(self) {
        	console.log("updateCommute called");
            timeConfig = {
              showWeekend:    self.config.showWeekend,
              allTime:        self.config.allTime,
              startHr:        self.config.startHr,
              endHr:          self.config.endHr
            };
        
            if (self.config.arrival_time.length == 4) {
              self.sendSocketNotification('LEAVE_BY', {'url':self.url, 'arrival':self.config.arrival_time, 'timeConfig':timeConfig});
            } else {
              self.sendSocketNotification('TRAFFIC_URL', {'url':self.url, 'timeConfig':timeConfig});
            }
            setTimeout(self.updateCommute, self.config.interval, self);
        },
        getStyles: function() {
            return ['traffic.css', 'font-awesome.css'];
        },
        createMap_area: function(start_location, end_location){
        	console.log("createMap_area invoked");
        	if(document.getElementById('map'))
        	{
        		console.log("Map Div available "+start_location.lat);
        		var map_options = {
        			center: new google.maps.LatLng(start_location.lat, start_location.lng),
        			zoom: 20,
                    size: '300x300',
        			panControl: true,
        			mapTypeControl: false,
        			panControlOptions: {
        				position: google.maps.ControlPosition.RIGHT_CENTER
        			},
        			zoomControl: true,
        			zoomControlOptions: {
        				style: google.maps.ZoomControlStyle.LARGE,
        				position: google.maps.ControlPosition.RIGHT_CENTER
        			},
        			scaleControl: false,
        			streetViewControl: false,
        			streetViewControlOptions: {
        				position: google.maps.ControlPosition.RIGHT_CENTER
        			}
        		};
        	    // map div is added to document.body
            	var map = new google.maps.Map(document.getElementById("map"), map_options);
        
        		var start_bound = new google.maps.LatLng(start_location.lat, start_location.lng);
        
        		var end_bound = new google.maps.LatLng(end_location.lat, end_location.lng);
        		var marker = new google.maps.Marker({
        			position: start_bound,
        			map: map
        		});
        
        		var marker = new google.maps.Marker({
        			position: end_bound,
        			map: map
        		})
        
        		var bounds = new google.maps.LatLngBounds();
        		bounds.extend(start_bound);
        		bounds.extend(end_bound);
        		map.fitBounds(bounds);
        		// the preserveViewport is almost mandatory to prevent zoom/pan out of the screen
               var directionsDisplay = new google.maps.DirectionsRenderer({
                   map: map,
        		   zoom: 20,
        		   preserveViewport: true
               });
        	   directionsDisplay.setMap(map);
        
               // Set destination, origin and travel mode.
               var request = {
                 destination: end_location,
                 origin: start_location,
                 travelMode: 'DRIVING'
               };
               // Pass the directions request to the directions service.
               var directionsService = new google.maps.DirectionsService();
               directionsService.route(request, function(response, status) {
                   if (status == 'OK') {
                       // Display the route on the map.
                       directionsDisplay.setDirections(response);
                   }
               }); 
               // Pass the directions request to the directions service.
        	   this.mapLoaded = true;
        	}
        	return document.getElementById('map');
        },
        createMap: function(){
            var wrapper = document.createElement('div');
            wrapper.style.height = this.config.height;
            wrapper.style.width = this.config.width;
        	wrapper.setAttribute("id", "map");
            
            // This script is appended to the main body
            var outer_script = document.createElement("script");
            outer_script.type = "text/javascript";
            outer_script.src = "https://maps.googleapis.com/maps/api/js?key=" + this.config.api_key;
        	outer_script.setAttribute("async","");
        	outer_script.setAttribute("defer","");
            document.body.appendChild(outer_script);
            outer_script.onload = function(){
        		console.log("Added the map script to document body");
            }
            return wrapper; 
        },
        
        
        getDom: function() {
            var wrapper = document.createElement("div");
            var commuteInfo = document.createElement('div');
            var routeName = document.createElement('div');
            // Map display 
        
            if (!this.loaded) {
                console.log("[MMM-Traffic]Pre-loading invoked");
                //wrapper.innerHTML = this.config.loadingText;
        		// Invoke adding the Google Maps base script to the dcoument.body
        		// It needs to be invoked only once.
                wrapper.appendChild(this.createMap());
                 
                return wrapper;
            }
        
            if ((this.commute == '' || this.commute == '--') && this.config.hideOffHours && !this.config.allTime) {
                wrapper.innerHTML = '';
                return wrapper;
            }
            // Obtain start/end co-ordinates
            var start_loc = this.start_location;
            var end_loc = this.end_location;
            console.log("Start lat "+start_loc.lat+" long "+start_loc.lng); 
            wrapper.appendChild(this.createMap_area(this.start_location, this.end_location));
        
        
            //symbol
            var symbol = document.createElement('span');
            symbol.className = this.symbols[this.config.mode] + ' symbol';
            commuteInfo.appendChild(symbol);
            
        
            if (this.config.arrival_time == '') {
              //commute time
              var trafficInfo = document.createElement('span');
              trafficInfo.innerHTML = this.config.prependText + ' ' + this.commute;
              commuteInfo.appendChild(trafficInfo);
        
              //routeName
              if (this.config.route_name) {
                routeName.className = 'dimmed small';
                if (this.summary.length > 0 && this.config.show_summary){
                  routeName.innerHTML = this.config.route_name + ' ' + this.config.summaryText + ' ' + this.summary;
                } else {
                  routeName.innerHTML = this.config.route_name;
                }
              }
            } else {
              //leave-by time
              var trafficInfo = document.createElement('span');
              trafficInfo.innerHTML = this.config.leaveByText + ' ' + this.leaveBy;
              commuteInfo.appendChild(trafficInfo);
        
              //routeName
              if (this.config.route_name) {
                routeName.className = 'dimmed small';
                if (this.summary.length > 0 && this.config.show_summary){
                  routeName.innerHTML = this.config.route_name + ' ' + this.config.summaryText + ' ' + this.summary + ' ' + this.config.arriveByText + ' ' + this.config.arrival_time.substring(0,2) + ":" + this.config.arrival_time.substring(2,4);
                } else {
              console.log(typeof this.config.arrival_time );
                  routeName.innerHTML = this.config.route_name + ' ' + this.config.arriveByText + ' ' + this.config.arrival_time.substring(0,2) + ":" + this.config.arrival_time.substring(2,4);
                }
              }
            }
        
            //change color if desired
            if (this.config.changeColor) {
              if (this.trafficComparison >= 1 + (this.config.limitRed / 100)) {
                commuteInfo.className += ' red';
              } else if (this.trafficComparison >= 1 + (this.config.limitYellow / 100)) {
                commuteInfo.className += ' yellow';
              } else if (this.config.showGreen) {
                commuteInfo.className += ' green';
              }
            }
        
            wrapper.appendChild(commuteInfo);
            wrapper.appendChild(routeName);
            return wrapper;
        },
        getParam_specific: function(origin, destination){
            var params = '?';
            params += 'mode=' + this.config.mode;
            params += '&origin=' + origin;
            params += '&destination=' + destination;
            params += '&key=' + this.config.api_key;
            params += '&traffic_model=' + this.config.traffic_model;
            params += '&language=' + this.config.language;
            if (this.config.avoid.length > 0) {
              params += '&avoid=' + this.config.avoid;
            }
            return params;
        },
        
        getParams: function() {
            var params = '?';
            params += 'mode=' + this.config.mode;
            params += '&origin=' + this.config.origin;
            params += '&destination=' + this.getTodaysDestination();
            params += '&key=' + this.config.api_key;
            params += '&traffic_model=' + this.config.traffic_model;
            params += '&language=' + this.config.language;
            if (this.config.avoid.length > 0) {
              params += '&avoid=' + this.config.avoid;
            }
            return params;
        },
        
        getTodaysDestination: function() {
            var todays_destination = "";
            switch (new Date().getDay()) {
              case 1:
                todays_destination = this.config.mon_destination;
                break;
              case 2:
                todays_destination = this.config.tues_destination;
                break;
              case 3:
                todays_destination = this.config.wed_destination; 
                break;
              case 4:
                todays_destination = this.config.thurs_destination;
                break;
              case 5:
                todays_destination = this.config.fri_destination;
                break;
              default:
                //to handle Sat and Sun (GoogleAPI may raise error if no destination set)   
                todays_destination = this.config.destination; 
            }
        
            if(todays_destination === ""){ //if no weekday destinations defined in config.js, set to default
                todays_destination = this.config.destination;           
            }
        
            return todays_destination;
        },
        
        socketNotificationReceived: function(notification, payload) {
            this.leaveBy = '';
            this.start_location = payload.start_location;
            this.end_location = payload.end_location;
            if (notification === 'TRAFFIC_COMMUTE' && payload.url === this.url) {
                Log.info('received TRAFFIC_COMMUTE');
                this.commute = payload.commute;
                this.summary = payload.summary;
                this.trafficComparison = payload.trafficComparison;
                this.loaded = true;
                this.updateDom(1000);
            } else if (notification === 'TRAFFIC_TIMING' && payload.url === this.url) {
                Log.info('received TRAFFIC_TIMING');
                this.leaveBy = payload.commute;
                this.commute = payload.commute; //support for hideOffHours
                this.summary = payload.summary;
                this.loaded = true;
                this.updateDom(1000);
            }
        }
        

        });

        M 1 Reply Last reply Aug 27, 2017, 5:11 PM Reply Quote 1
        • M Offline
          Mirrorolentia @Mirrorolentia
          last edited by Mirrorolentia Aug 27, 2017, 5:19 PM Aug 27, 2017, 5:11 PM

          Please install the MMM-Traffic module and replace the MMM-Traffic.js with the above code.
          Below is a sample entry in config.js

          {
                      module: 'MMM-Traffic',
                      position: 'top_left',
                      classes: 'dimmed medium', //optional, default is 'bright medium', only applies to commute info not route_name
                      config: {
                          api_key: '', // Your Google Maps API_KEY needs to go here
                          mode: 'driving',
                          origin: '',
                          destination: '',
                          mon_destination: '',
                          arrival_time: '', //optional, but needs to be in 24 hour time if used.
                          route_name: 'Home to Work',
                          changeColor: true,
                          showGreen: false,
                          limitYellow: 5, //Greater than 5% of journey time due to traffic
                          limitRed: 20, //Greater than 20% of journey time due to traffic
                          traffic_model: 'best_guess',
                          interval: 60000, //2 minutes
                          showWeekend: true,
                          allTime: true,
                          width: '300px',
                          height: '300px'
                      }
                  },
          
          1 Reply Last reply Reply Quote 1
          • M Offline
            Mirrorolentia
            last edited by Aug 27, 2017, 5:18 PM

            There are two catches which I will try to correct:

            1. The Google Maps have their own lifecycle which I could not align with MM module’s. So you may not see the map in the first instance but it will get uploaded within the next interval (as configured in config.interval).
            2. The Maps div element keeps getting refreshed after every interval which is a bit irritating :(
            D 1 Reply Last reply Aug 28, 2017, 6:23 AM Reply Quote 0
            • S Offline
              strawberry 3.141 Project Sponsor Module Developer @birdy
              last edited by Aug 27, 2017, 7:24 PM

              @birdy you are missing quotes around the drivin mode, should be mode: 'driving'

              Please create a github issue if you need help, so I can keep track

              1 Reply Last reply Reply Quote 0
              • D Offline
                devtech8 @Mirrorolentia
                last edited by Aug 28, 2017, 6:23 AM

                @Mirrorolentia - I was thinking of trying this too, but looks like you have made some progress. I hope to dig into what you have later this week. I had seen some further customization I would like to add when time allows. Thanks for the work on this!

                M 1 Reply Last reply Aug 28, 2017, 7:38 AM Reply Quote 0
                • M Offline
                  Mirrorolentia @devtech8
                  last edited by Aug 28, 2017, 7:38 AM

                  @devtech8
                  Sure that would be great! Thanks!

                  1 Reply Last reply Reply Quote 0
                  • B Offline
                    birdy
                    last edited by Aug 28, 2017, 9:45 AM

                    @Mirrorolentia - wow, thx!! I will test it later :) can’t await

                    1 Reply Last reply Reply Quote 0
                    • B Offline
                      birdy
                      last edited by Aug 29, 2017, 3:42 PM

                      so, as a complete noobie, I just pasted the code (adding Google Api key) in both files.

                      I can see, there is a gap in the corner (I hope for the map) and if I get you correctly, the map will load “soon”(?).

                      Thank you one more time and will keep u posted.

                      Cheers
                      Birdy

                      M 1 Reply Last reply Aug 29, 2017, 3:57 PM Reply Quote 0
                      • 1
                      • 2
                      • 1 / 2
                      1 / 2
                      • First post
                        10/16
                        Last post
                      Enjoying MagicMirror? Please consider a donation!
                      MagicMirror created by Michael Teeuw.
                      Forum managed by Sam, technical setup by Karsten.
                      This forum is using NodeBB as its core | Contributors
                      Contact | Privacy Policy