Read the statement by Michael Teeuw here.
CORS using node_helper.js for Uber and Lyft APIs
-
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!
-
@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 :( -
@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.
-
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.......
-
@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 ?
-
@cowboysdude isn’t that what I am doing? Can you explain how your solution differs from mine?
-
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.
-
@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.
-
@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… -
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(); } } });