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.

    CORS using node_helper.js for Uber and Lyft APIs

    Scheduled Pinned Locked Moved Troubleshooting
    10 Posts 4 Posters 4.6k Views 3 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.
    • kalK Offline
      kal
      last edited by kal

      Hi all,

      I have a bit of programming experience (mostly C and python) but I have never worked with javascript. I am trying to create a module to communicate with the Uber and Lyft APIs. Initially I was trying to do something like this for Lyft , but I kept getting an 'Access-Control-Allow-Origin' error.

      After some research I found this post which said that a work-around is done in node_helper.js and referenced this module.

      So, I have tried my hand at an Uber module done in that fashion, but no luck. I have put a bunch of Log.log() statements in my code but I am not seeing anything in the console to help me debug. The mirror shows the statement “Checking Uber status…”

      Here’s the module code:

      /* global Module */
      
      /* Magic Mirror
       * Module: Uber
       * 
       * based on MagicMirror work by Michael Teeuw http://michaelteeuw.nl
       * MIT Licensed.
       */
      
      Module.register("MMM-uber",{
      
      	// Default module config.
      	defaults: {
      		lat: null,
      		lng: null,
      		product_id: null,
      		client_id: null,
      		uberServerToken: null,
      
      		updateInterval: 5 * 60 * 1000, // every 5 minutes
      		animationSpeed: 1000,
      	},
      
      	// Define required scripts.
      	getScripts: function() {
      		return ["moment.js", "https://code.jquery.com/jquery-2.2.3.min.js"];
      	},
      
      	// Define required styles.
      	getStyles: function() {
      		return ["MMM-uber.css"];
      	},
      
      	start: function() {
      		Log.info("Starting module: " + this.name);
      
      		// Set locale.
      		moment.locale(config.language);
      
      		// variables that will be loaded from service
      		this.uberTime = null;
      		this.uberSurge = null;
      
      		this.loaded = false;
      		this.sendSocketNotification('CONFIG', this.config);
      	},
      
      	// unload the results from uber services
      	processUber: function(FLAG, result) {
      		var self = this;
      		Log.log("ProcessUber");
      
      		// go through the time data to find the uberX product
      		if (FLAG === "TIME"){
      			Log.log("Time");
      			Log.log(result);
      			for (var i = 0, count = result.times.length; i < count ; i++) {
      
      				var rtime = result.times[i];
      				
      				if(rtime.display_name === "uberX"){
      					// convert estimated seconds to minutes
      					this.uberTime = rtime.estimate / 60;
      					break;
      				}
      			}
      		}
      
      		// go through the price data to find the uberX product
      		else if (FLAG === "PRICE"){
      			Log.log("Price");
      			Log.log(result);
      			for( var i=0, count = result.prices.length; i< count; i++) {
      				var rprice = result.prices[i];
      
      				if(rprice.display_name === "uberX"){
      					// grab the surge pricing
      					this.uberSurge = rprice.surge_multiplier;
      					break;
      				}
      			}
      		}
      	},
      
      	// Override dom generator.
      	getDom: function() {
      		var wrapper = document.createElement("div");
      
      		var uber = document.createElement("div");
      		uber.className = "uberButton";
      		
      		var uberIcon = document.createElement("img");
      		uberIcon.className = "badge";
      		uberIcon.src = "modules/MMM-uber/UBER_API_Badges_1x_22px.png";
      
      		var uberText = document.createElement("span");
      
      		if(this.loaded) {
      			var myText = "UberX in "+ this.uberTime +" min ";
      			Log.log("ubersurge: " + this.uberSurge);
      			// only show the surge pricing if it is above 1.0
      			if(typeof this.uberSurge !== "undefined" && this.uberSurge > 1.0){
      				myText += " - " + this.uberSurge + "X surge pricing";
      			}
      			uberText.innerHTML = myText;
      		} else {
      			// Loading message
      			uberText.innerHTML = "Checking Uber status ...";
      		}
      
      		uber.appendChild(uberIcon);
      		uber.appendChild(uberText);
      		
      		wrapper.appendChild(uber);
      		return wrapper;
      	},
      
      	socketNotificationReceived: function(notification, payload) {
      		Log.log(this.name + " received a socket notification: " + notification + " - Payload: " + payload);
      		if (notification === "TIME") {
      			this.processUber("TIME", payload);
      			this.updateDom(this.config.animationSpeed)
      		}
      		else if (notification === "PRICE") {
      			this.processUber("PRICE", payload);
      			this.loaded = true;
      			this.updateDom(this.config.animationSpeed);
      		}
      	}
      
      });
      
      

      And the code in node_helper.js

      'use strict';
      
      /* Magic Mirror
       * Module: MMM-lyft
       *
       * By Kyle Kelly
       * MIT Licensed.
       */
      
      const NodeHelper = require('node_helper');
      var request = require('request');
      var moment = require('moment');
      
      module.exports = NodeHelper.create({
      
      	start: function() {
      		var self = this;
      		console.log("Starting node helper for: " + this.name);
      
      		this.started = false;
      		this.config = null;
      	},
      
      	getData: function() {
      		var self = this;
      						
      		request({
      			url: "https://api.uber.com/v1/estimates/time",
      			method: 'GET',
      			headers: {
      		        "Authorization": "Token " + self.config.uberServerToken
      		    },
      		    data: {
      		        start_latitude: self.config.lat,
      		        start_longitude: self.config.lng,
      		        product_id: self.product_id
      		    },
      		}, function (error, response, body) {
      			
      			if (!error && response.statusCode == 200) {
      				self.sendSocketNotification("TIME", body);
      			}
      		});
      
      		request({
      			url: "https://api.uber.com/v1/estimates/price",
      			method: 'GET',
      			headers: {
      				        "Authorization": "Token " + self.config.uberServerToken
      		    },
      		    data: {
      		        start_latitude: self.config.lat,
      		        start_longitude: self.config.lng,
      
      		        end_latitude: self.config.lat,
      		        end_longitude: self.config.lng
      		    },
      		}, function (error, response, body) {
      			
      			if (!error && response.statusCode == 200) {
      				self.sendSocketNotification("PRICE", body);
      			}
      		});
      
      		setTimeout(function() { self.getData(); }, this.config.updateInterval);
      	},
      
      	socketNotificationReceived: function(notification, payload) {
      		var self = this;
      		if (notification === 'CONFIG' && self.started == false) {
      			self.config = payload;
      			self.getData();
      			self.started = true;
      		}
      	}
      });
      
      

      Any help would be appreciated. Thanks!

      A 1 Reply Last reply Reply Quote 0
      • A Offline
        Anhalter42 @kal
        last edited by

        @kal are you looking at the correct console? Log.log logs to electron console, which is visible when starting MM with npm start dev (or by pressing some shortcut which I forgot; search the forum if you want to know). The terminal where you start MM is kind of useless for debugging :(

        bheplerB kalK 2 Replies Last reply Reply Quote 0
        • bheplerB Offline
          bhepler Module Developer @Anhalter42
          last edited by

          @Anhalter42 said in CORS using node_helper.js for Uber and Lyft APIs:

          (or by pressing some shortcut which I forgot; search the forum if you want to know).

          Try F12.

          1 Reply Last reply Reply Quote 1
          • cowboysdudeC Offline
            cowboysdude Module Developer
            last edited by

            As an example ONLY!

               getStuff: function(url) {
              request({
                    url: "https://www.whereever.com/stuff.json",
                    method: 'GET',
                    headers: {
                        'User-Agent': 'MagicMirror/1.0 '
                    }
              }, (error, response, body) => {
                    if (!error && response.statusCode == 200) {
               blah..blah....blah.......
            
            kalK 1 Reply Last reply Reply Quote 0
            • kalK Offline
              kal @Anhalter42
              last edited by

              @Anhalter42 I’m looking at the JavaScript console. The IP of my laptop is whitelisted, so I go to https://IP.of.Raspberry.Pi:8080 in Chrome and then go to View>Developer>JavaScript Console.

              Is there another way I can get statements to print to that console ?

              A 1 Reply Last reply Reply Quote 0
              • kalK Offline
                kal @cowboysdude
                last edited by

                @cowboysdude isn’t that what I am doing? Can you explain how your solution differs from mine?

                1 Reply Last reply Reply Quote 0
                • cowboysdudeC Offline
                  cowboysdude Module Developer
                  last edited by

                  When you request a webpage, your browser sends a number of headers to the server hosting the site that you’re visiting.

                  These headers occur during a negotiation process that helps the browser and the hosting server determine the best way to provide the requested information. The user-agent header identifies the application requesting the information from the server, typically a browser. This identification string is called the user-agent string and contains tokens that provide specific details about the program making the request.

                  kalK 1 Reply Last reply Reply Quote 0
                  • kalK Offline
                    kal @cowboysdude
                    last edited by

                    @cowboysdude I don’t think the user-agent string is required when making an HTTP request. According to the Uber API docs it doesn’t look like I need one.

                    1 Reply Last reply Reply Quote 0
                    • A Offline
                      Anhalter42 @kal
                      last edited by

                      @kal well then… I know its not helping, but it should work as you described. Not seeing anything in js console is a serious problem when developing. Did you try other browsers? If nothing appears in any browser AND on raspberry itself (with npm start dev), then something is seriously wrong…

                      1 Reply Last reply Reply Quote 0
                      • kalK Offline
                        kal
                        last edited by

                        I was able to fix this. See below for the module code

                        /* global Module */
                        
                        /* Magic Mirror
                         * Module: Uber
                         * 
                         * Shows the time and surge pricing for UberX
                         *
                         * By Kyle Kelly
                         * based on MagicMirror work by Michael Teeuw http://michaelteeuw.nl
                         * and by derickson https://github.com/derickson/MMderickson/tree/master/uber
                         * MIT Licensed.
                         */
                        
                        Module.register("MMM-uber",{
                        
                        	// Default module config.
                        	defaults: {
                        		lat: null,
                        		lng: null,
                        		ride_type: "uberX",
                        		uberServerToken: null,
                        
                        		updateInterval: 5 * 60 * 1000, // every 5 minutes
                        		animationSpeed: 1000,
                        	},
                        
                        	// Define required scripts.
                        	getScripts: function() {
                        		return ["moment.js", "https://code.jquery.com/jquery-2.2.3.min.js"];
                        	},
                        
                        	// Define required styles.
                        	getStyles: function() {
                        		return ["MMM-uber.css"];
                        	},
                        
                        	start: function() {
                        		Log.info("Starting module: " + this.name);
                        
                        		// Set locale.
                        		moment.locale(config.language);
                        
                        		// variables that will be loaded from service
                        		this.uberTime = null;
                        		this.uberSurge = null;
                        
                        		this.loaded = false;
                        		Log.log("Sending CONFIG to node_helper.js in " + this.name);
                        		Log.log("Payload: " + this.config)
                        		this.sendSocketNotification('CONFIG', this.config);
                        	},
                        
                        	// unload the results from uber services
                        	processUber: function(FLAG, result) {
                        		var self = this;
                        		Log.log("ProcessUber");
                        
                        		// go through the time data to find the uberX product
                        		if (FLAG === "TIME"){
                        			Log.log("Time:");
                        			Log.log(result);
                        			for (var i = 0, count = result.times.length; i < count ; i++) {
                        
                        				var rtime = result.times[i];
                        				
                        				if(rtime.display_name === this.config.ride_type){
                        					// convert estimated seconds to minutes
                        					this.uberTime = rtime.estimate / 60;
                        					break;
                        				}
                        			}
                        		}
                        
                        		// go through the price data to find the uberX product
                        		else if (FLAG === "PRICE"){
                        			Log.log("Price:");
                        			Log.log(result);
                        			for( var i=0, count = result.prices.length; i< count; i++) {
                        				var rprice = result.prices[i];
                        
                        				if(rprice.display_name === this.config.ride_type){
                        					// grab the surge pricing
                        					this.uberSurge = rprice.surge_multiplier;
                        					break;
                        				}
                        			}
                        		}
                        	},
                        
                        	// Override dom generator.
                        	getDom: function() {
                        		var wrapper = document.createElement("div");
                        
                        		var uber = document.createElement("div");
                        		uber.className = "uberButton";
                        		
                        		var uberIcon = document.createElement("img");
                        		uberIcon.className = "badge";
                        		uberIcon.src = "modules/MMM-uber/UBER_API_Badges_1x_22px.png";
                        
                        		var uberText = document.createElement("span");
                        
                        		if(this.loaded) {
                        			var myText = this.config.ride_type + " in "+ this.uberTime +" min ";
                        			Log.log("ubersurge: " + this.uberSurge);
                        			// only show the surge pricing if it is above 1.0
                        			if(typeof this.uberSurge !== "undefined" && this.uberSurge > 1.0){
                        				myText += " - " + this.uberSurge + "X surge pricing";
                        			}
                        			uberText.innerHTML = myText;
                        		} else {
                        			// Loading message
                        			uberText.innerHTML = "Checking Uber status ...";
                        		}
                        
                        		uber.appendChild(uberIcon);
                        		uber.appendChild(uberText);
                        		
                        		wrapper.appendChild(uber);
                        		return wrapper;
                        	},
                        
                        	socketNotificationReceived: function(notification, payload) {
                        		Log.log(this.name + " received a socket notification: " + notification + " - Payload: " + payload);
                        		if (notification === "TIME") {
                        			this.processUber("TIME", JSON.parse(payload));
                        			this.updateDom(this.config.animationSpeed)
                        		}
                        		else if (notification === "PRICE") {
                        			this.processUber("PRICE", JSON.parse(payload));
                        			this.loaded = true;
                        			this.updateDom(this.config.animationSpeed);
                        		}
                        	}
                        
                        });
                        
                        

                        and the node_helper.js code

                        'use strict';
                        
                        /* Magic Mirror
                         * Module: MMM-uber
                         *
                         * By Kyle Kelly
                         * MIT Licensed.
                         */
                        
                        const NodeHelper = require('node_helper');
                        var request = require('request');
                        var moment = require('moment');
                        
                        module.exports = NodeHelper.create({
                        
                        	start: function() {
                        		var self = this;
                        		console.log("Starting node helper for: " + this.name);
                        
                        		this.config = null;
                        	},
                        
                        	getData: function() {
                        		var self = this;
                        
                        		this.sendSocketNotification("Test", 2);
                        		this.sendSocketNotification("LATITUDE", this.config.lat);
                        		this.sendSocketNotification("LONGITUDE", this.config.lng);
                        						
                        		
                        		request({
                        			url: "https://api.uber.com/v1/estimates/time?start_latitude=" + this.config.lat + "&start_longitude=" + this.config.lng,
                        			method: 'GET',
                        			headers: {
                        		        'Authorization': 'Token ' + this.config.uberServerToken,
                        		        'Accept-Language': 'en_US',
                        		        'Content-Type': 'application/json'
                        		    },
                        		}, function (error, response, body) {
                        			
                        			if (!error && response.statusCode == 200) {
                        				self.sendSocketNotification("TIME", body);
                        			}
                        			else {
                        				self.sendSocketNotification("ERROR", "In TIME request with status code: " + response.statusCode);
                        			}
                        		});
                        
                        		request({
                        			url: "https://api.uber.com/v1/estimates/price?start_latitude=" + this.config.lat + "&start_longitude=" + this.config.lng + "&end_latitude=" + this.config.lat + "&end_longitude=" + this.config.lng,
                        			method: 'GET',
                        			headers: {
                        				'Authorization': 'Token ' + this.config.uberServerToken,
                        		        'Accept-Language': 'en_US',
                        		        'Content-Type': 'application/json'
                        		    },
                        		}, function (error, response, body) {
                        			
                        			if (!error && response.statusCode == 200) {
                        				self.sendSocketNotification("PRICE", body);
                        			}
                        			else {
                        				self.sendSocketNotification("ERROR", "In PRICE request with status code: " + response.statusCode);
                        			}
                        		});
                        
                        		setTimeout(function() { self.getData(); }, this.config.updateInterval);
                        		
                        	},
                        
                        	socketNotificationReceived: function(notification, payload) {
                        		//var self = this;
                        		this.sendSocketNotification("Test", 0);
                        		if (notification === 'CONFIG') {
                        			this.sendSocketNotification("Test", 1);
                        			this.config = payload;
                        			this.getData();
                        		}
                        	}
                        });
                        
                        
                        1 Reply Last reply Reply Quote 0

                        Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                        Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                        With your input, this post could be even better 💗

                        Register Login
                        • 1 / 1
                        • First post
                          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