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 3.9k 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
                        • 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