diff --git a/.gitignore b/.gitignore index fd51909..29c9fa4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/ -.lock-waf* \ No newline at end of file +.lock-waf* +node_modules/ \ No newline at end of file diff --git a/subway.svg b/subway.svg new file mode 100644 index 0000000..a43974c --- /dev/null +++ b/subway.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + diff --git a/watchapps/subway.pdc b/watchapps/subway.pdc new file mode 100644 index 0000000..7e943bb Binary files /dev/null and b/watchapps/subway.pdc differ diff --git a/watchapps/transit/package-lock.json b/watchapps/transit/package-lock.json new file mode 100644 index 0000000..08ea001 --- /dev/null +++ b/watchapps/transit/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "transit", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + } + } +} diff --git a/watchapps/transit/package.json b/watchapps/transit/package.json index 287a14f..f8f5e78 100644 --- a/watchapps/transit/package.json +++ b/watchapps/transit/package.json @@ -2,9 +2,13 @@ "name": "transit", "author": "MakeAwesomeHappen", "version": "1.0.0", - "keywords": ["pebble-app"], + "keywords": [ + "pebble-app" + ], "private": true, - "dependencies": {}, + "dependencies": { + "bluebird": "^3.7.2" + }, "pebble": { "displayName": "transit", "uuid": "00c6f98f-276e-4045-8078-8326f09b982f", @@ -25,7 +29,8 @@ "Stop_Next_Time_Minutes", "Stop_Destination", "Stop_Color", - "Stop_Highlight" + "Stop_Highlight", + "RefreshMenu" ], "resources": { "media": [] diff --git a/watchapps/transit/src/c/main.c b/watchapps/transit/src/c/main.c index 1006bc1..376e7b4 100644 --- a/watchapps/transit/src/c/main.c +++ b/watchapps/transit/src/c/main.c @@ -4,6 +4,13 @@ // setup pebblekitjs to add stop static void inbox_received_callback(DictionaryIterator *iterator, void *context) { // message keys are Stop_Name, Stop_Next_Time_Minutes, Stop_Destination, Stop_Color, Stop_Highlight_Color + + Tuple *refresh_menu_tuple = dict_find(iterator, MESSAGE_KEY_RefreshMenu); + if (refresh_menu_tuple) { + refresh_menu(); + return; + } + Tuple *name_tuple = dict_find(iterator, MESSAGE_KEY_Stop_Name); Tuple *next_time_tuple = dict_find(iterator, MESSAGE_KEY_Stop_Next_Time_Minutes); Tuple *destination_tuple = dict_find(iterator, MESSAGE_KEY_Stop_Destination); @@ -24,8 +31,7 @@ static void inbox_received_callback(DictionaryIterator *iterator, void *context) // Add the stop to the list - transit_add_stop(name, next_time, destination, color, highlight_color); - + transit_add_stop(name, next_time, destination, color, highlight_color); } // on fail diff --git a/watchapps/transit/src/c/transit.c b/watchapps/transit/src/c/transit.c index ae842b3..e9d71f8 100644 --- a/watchapps/transit/src/c/transit.c +++ b/watchapps/transit/src/c/transit.c @@ -2,7 +2,7 @@ #include "transit.h" #include "scrolling_menu.h" -#define MAX_STOPS 10 +#define MAX_STOPS 90 static Window *s_main_window; static MenuLayer *s_menu_layer; @@ -133,9 +133,10 @@ void transit_add_stop(char *name, int next_time_minutes, char *destination, GCol menu_items[s_num_stops].subtext = destination; menu_items[s_num_stops].flags = ITEM_FLAG_TWO_LINER; - s_num_stops++; - - // Refresh the menu layer to reflect changes - menu_layer_reload_data(s_menu_layer); + s_num_stops++; } } + +void refresh_menu(void) { + menu_layer_reload_data(s_menu_layer); +} diff --git a/watchapps/transit/src/c/transit.h b/watchapps/transit/src/c/transit.h index 42772cc..26f64e6 100644 --- a/watchapps/transit/src/c/transit.h +++ b/watchapps/transit/src/c/transit.h @@ -16,4 +16,5 @@ typedef struct { void transit_init(void); void transit_deinit(void); void transit_add_stop(char *name, int next_time_minutes, char *destination, GColor color, GColor highlight_color); +void refresh_menu(void); MenuItem* getMenuItem(WindowData* window_data, int index); diff --git a/watchapps/transit/src/pkjs/index.js b/watchapps/transit/src/pkjs/index.js index 92e1c17..a8a0a0c 100644 --- a/watchapps/transit/src/pkjs/index.js +++ b/watchapps/transit/src/pkjs/index.js @@ -1,18 +1,15 @@ // send appmessages with stops -var sender = require("./sender") +var sender = require("./sender"); +var transit = require("./transit"); Pebble.addEventListener("ready", function(e) { - console.log("Hello world! - Sent from your javascript application."); - // send a dummy stop with name, next time minutes, destination, color and color highlight - // message keys are Stop_Name, Stop_Next_Time_Minutes, Stop_Destination, Stop_Color, Stop_Color_Highlight - var multistop_test = [ - {"name": "Test Stop 1", "time": 5, "destination": "Test Destination 1", "color": 0xAAAAAA, "highlight": 0xFFFFFF}, - {"name": "Test Stop 2", "time": 10, "destination": "Test Destination 2", "color": 0xAAAAAA, "highlight": 0xFFFFFF}, - {"name": "Test Stop 3", "time": 15, "destination": "Test Destination 3", "color": 0xAAAAAA, "highlight": 0xFFFFFF} - ]; - sender.sendMultiStop(multistop_test); + transit.data().then(function(data) { + sender.sendMultiStop(data); + }).catch(function(err) { + console.log("Error: " + err); + }); } ); diff --git a/watchapps/transit/src/pkjs/sender.js b/watchapps/transit/src/pkjs/sender.js index d360a42..2b45d45 100644 --- a/watchapps/transit/src/pkjs/sender.js +++ b/watchapps/transit/src/pkjs/sender.js @@ -1,4 +1,4 @@ -function sendStop(name, time, destination, color, highlight) { +function sendStop(name, time, destination, color, highlight, send_refresh) { console.log("Sending stop: " + name + " in " + time + " minutes to " + destination + " with color " + color + " and highlight " + highlight); Pebble.sendAppMessage({"Stop_Name": name, "Stop_Next_Time_Minutes": time, "Stop_Destination": destination, "Stop_Color": color, "Stop_Highlight": highlight}, function(e) { @@ -8,15 +8,35 @@ function sendStop(name, time, destination, color, highlight) { console.log("Failed to send message with transactionId = " + e.data.transactionId + " Error is: " + e.error.message); } ); + + if (send_refresh) { + sendRefreshMenu(); + } +} + +function sendRefreshMenu() { + console.log("Sending refresh menu"); + Pebble.sendAppMessage({"RefreshMenu": 1}, + function(e) { + console.log("Sent message with transactionId = " + e.data.transactionId); + }, + function(e) { + console.log("Failed to send message with transactionId = " + e.data.transactionId + " Error is: " + e.error.message); + } + ); } function sendMultiStop(stops) { + console.log(JSON.stringify(stops)); + console.log(typeof stops) + // stops = JSON.parse(stops); for (var i = 0; i < stops.length; i++) { - sendStop(stops[i].name, stops[i].time, stops[i].destination, stops[i].color, stops[i].highlight); - setTimeout(function() { - console.log("Sent stop " + i); - }, 100); // just enough time for the pebble to not get overwhelmed + console.log(JSON.stringify(stops[i])); + sendStop(stops[i].name, stops[i].time, stops[i].destination, stops[i].color, stops[i].highlight, false); + console.log("Sent stop " + i); } + sendRefreshMenu(); + } module.exports = { diff --git a/watchapps/transit/src/pkjs/transit.js b/watchapps/transit/src/pkjs/transit.js index e69de29..63e84e4 100644 --- a/watchapps/transit/src/pkjs/transit.js +++ b/watchapps/transit/src/pkjs/transit.js @@ -0,0 +1,118 @@ +var Promise = require('bluebird'); + +// Variables +var root = "https://external.transitapp.com/v3"; +var api_key = ""; +var lat = 38.8977; // TOTALLY not the White House +var lng = -77.0365; + +function convertHex(hex) { + // Convert hex color code (#RRGGBB) to integer (0xRRGGBB) + return parseInt(hex.substring(1), 16); +} + +function hexToRGB(hex) { + // Convert hex color code to RGB + var r = parseInt(hex.substring(1, 3), 16); + var g = parseInt(hex.substring(3, 5), 16); + var b = parseInt(hex.substring(5, 7), 16); + return [r, g, b]; +} + +function RGBToHex(r, g, b) { + // Convert RGB to hex color code + return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); +} + + +function darkenColor(color) { + // Darken color by 20% + var r = (color >> 16) & 0xFF; + var g = (color >> 8) & 0xFF; + var b = color & 0xFF; + r = Math.round(r * 0.8); + g = Math.round(g * 0.8); + b = Math.round(b * 0.8); + return (r << 16) | (g << 8) | b; +} + +function unixToMinutes(unix) { + // Convert Unix time to minutes + var date = new Date(unix * 1000); + var hours = date.getHours(); + var minutes = date.getMinutes(); + return hours * 60 + minutes; +} + +// Function to get data and print it +function data() { + return new Promise(function(resolve, reject) { + var url = root + "/public/nearby_routes?lat=" + lat + "&lon=" + lng + "&max_distance=500"; + var xhr = new XMLHttpRequest(); + xhr.open("GET", url, true); + xhr.setRequestHeader("apiKey", api_key); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4 && xhr.status === 200) { + var data = JSON.parse(xhr.responseText); + console.log(data); + var pebble = []; + // Iterate through the routes and print the required details + for (var i = 0; i < data.routes.length; i++) { + // if departure time is undefined, skip this route + try { + if (data.routes[i].itineraries[0].schedule_items[0].departure_time === undefined) { + continue; + } + } catch (e) { + continue; + } + var route_short_name = data.routes[i].route_short_name ? data.routes[i].route_short_name : "N/A"; + var mode_name = data.routes[i].mode_name; + var headsign = data.routes[i].itineraries[0].merged_headsign; + var departure_time = data.routes[i].itineraries[0].schedule_items[0].departure_time ? data.routes[i].itineraries[0].schedule_items[0].departure_time : 0; + var stop_name = data.routes[i].itineraries[0].closest_stop.stop_name; + var route_color = data.routes[i].route_color; + var route_highlight = darkenColor(hexToRGB(route_color)); + route_highlight = RGBToHex(route_highlight[0], route_highlight[1], route_highlight[2]); + console.log("Route: " + route_short_name + ", Mode: " + mode_name + ", Destination: " + headsign + ", Departure Time: " + departure_time + ", Stop: " + stop_name); + // Convert to data useful for Pebble + + // are we black and white? + if (Pebble.getActiveWatchInfo) { + var watch = Pebble.getActiveWatchInfo(); + if (watch.platform === "aplite" || watch.platform === "diorite") { + route_color = "#AAAAAA"; + route_highlight = "#FFFFFF"; + } + } + + console.log(unixToMinutes(departure_time)); + + pebble.push({ + "name": route_short_name, + "time": unixToMinutes(departure_time), + "destination": headsign, + "color": convertHex(route_color), + "highlight": convertHex(route_highlight) + }); + } + + resolve(pebble); + } else { + console.log("State: " + xhr.readyState) + console.log("Resp. Text: " + xhr.responseText) + console.log("Status: " + xhr.status) + console.log("Error: " + xhr.statusText); + } + }; + + xhr.onerror = function () { + reject(this.statusText); + }; + xhr.send(); + }); +} + +module.exports = { + data: data +}; \ No newline at end of file