Read the statement by Michael Teeuw here.
MM & Google Maps Traffic
-
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):
.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 -
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
-
/* 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); } }
});
-
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' } },
-
There are two catches which I will try to correct:
- 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).
- The Maps div element keeps getting refreshed after every interval which is a bit irritating :(
-
@birdy you are missing quotes around the drivin mode, should be
mode: 'driving'
-
@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!
-
@devtech8
Sure that would be great! Thanks! -
@Mirrorolentia - wow, thx!! I will test it later :) canât await
-
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