complies but not working yet

* The thing is crashing :/
This commit is contained in:
dyedgreen
2016-06-22 20:38:53 +02:00
parent dfe7360648
commit 3eeb297eda
10 changed files with 421 additions and 36 deletions
+23 -3
View File
@@ -18,15 +18,17 @@
"location" "location"
], ],
"watchapp": { "watchapp": {
"watchface": false "watchface": false,
"hiddenApp": false,
"onlyShownOnCommunication": false
}, },
"messageKeys": [ "messageKeys": [
"READY",
"SEARCH", "SEARCH",
"SUCCESS", "SUCCESS",
"DISTANCE", "DISTANCE",
"TIME", "TIME",
"STEPS", "INSTRUCTIONS[20]"
"STEPS_DISTANCES"
], ],
"resources": { "resources": {
"media": [ "media": [
@@ -77,6 +79,24 @@
"name": "ICON_WALK_WHITE", "name": "ICON_WALK_WHITE",
"targetPlatforms": null, "targetPlatforms": null,
"type": "bitmap" "type": "bitmap"
},
{
"file": "images/error_network.png",
"name": "ICON_ERROR_NETWORK",
"targetPlatforms": null,
"type": "bitmap"
},
{
"file": "images/error_api.png",
"name": "ICON_ERROR_API",
"targetPlatforms": null,
"type": "bitmap"
},
{
"file": "images/error_other.png",
"name": "ICON_ERROR_OTHER",
"targetPlatforms": null,
"type": "bitmap"
} }
] ]
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 895 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

+2
View File
@@ -4,3 +4,5 @@
#define COLOR_BIKE GColorTiffanyBlue #define COLOR_BIKE GColorTiffanyBlue
#define COLOR_TRAIN GColorSunsetOrange #define COLOR_TRAIN GColorSunsetOrange
#define COLOR_WALK GColorChromeYellow #define COLOR_WALK GColorChromeYellow
#define COLOR_ERROR GColorLightGray
+158 -10
View File
@@ -1,11 +1,11 @@
#include <pebble.h>
#include "colors.h"
#include "directions_window.h"
#include <pebble.h> #include <pebble.h>
#include "colors.h" #include "colors.h"
#include "select_window.h" #include "select_window.h"
#include "directions_window.h" #include "directions_window.h"
#include "error_window.h"
#define MAX_STEP_COUNT 20
#define MAX_STEP_CHARS 128
// The main window // The main window
static Window *window; static Window *window;
@@ -17,6 +17,18 @@ static GColor selected_type_color;
static DictationSession *dictation_session; static DictationSession *dictation_session;
static char *address; static char *address;
// TODO: implement a timer, that kills the proccess if the message is never send (needed?)
static bool AppMessageIsReady;
static bool AppMessageSendOnCallback;
static int RouteDataDistance;
static int RouteDataTime;
static char RouteDataSteps[MAX_STEP_COUNT][MAX_STEP_CHARS];
static int RouteDataStepsCount;
// Function declarations
static void app_message_send_search_data();
void window_display_error(enum ErrorType err);
// ****************************** // ******************************
// * DIRECTON LIST (MENU LAYER) * // * DIRECTON LIST (MENU LAYER) *
@@ -51,6 +63,7 @@ static void draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuIndex
} }
} }
// FIXME: Will probably not be necessary later!
static void selection_will_change_callback(struct MenuLayer *menu_layer, MenuIndex *new_index, MenuIndex old_index, void *context) { static void selection_will_change_callback(struct MenuLayer *menu_layer, MenuIndex *new_index, MenuIndex old_index, void *context) {
// Change the highlight color // Change the highlight color
#ifdef PBL_COLOR #ifdef PBL_COLOR
@@ -62,7 +75,6 @@ static void selection_will_change_callback(struct MenuLayer *menu_layer, MenuInd
// All other cells // All other cells
default: default:
menu_layer_set_highlight_colors(directions_list, GColorWhite, selected_type_color); menu_layer_set_highlight_colors(directions_list, GColorWhite, selected_type_color);
break;
} }
#endif #endif
} }
@@ -77,22 +89,150 @@ static void dictation_session_callback(DictationSession *session, DictationSessi
if (status == DictationSessionStatusSuccess) { if (status == DictationSessionStatusSuccess) {
// Store the address and load a route // Store the address and load a route
address = transcript; address = transcript;
// TODO load route data // Send the search data
app_message_send_search_data();
} else { } else {
// TODO display proper error window // Dictation failed, remove this window
window_stack_remove(window, true); window_stack_remove(window, true);
} }
} }
// ****************** // *********************
// * APP SYNC STUFF * // * APP MESSAGE STUFF *
// ****************** // *********************
// Accept data from the watch
static void app_message_inbox_recived_callback(DictionaryIterator *iter, void *context) {
// Test all possible message types
Tuple *message;
// Test if the recived message is for key READY
message = dict_find(iter, MESSAGE_KEY_READY);
if (message) {
// Set status to ready
AppMessageIsReady = (bool)message->value->int16;
// Send pending search data
if (AppMessageSendOnCallback) {
app_message_send_search_data();
}
}
// Test if the recived message is for key SUCCESS
message = dict_find(iter, MESSAGE_KEY_SUCCESS);
if (message) {
// Respond with the correct UI
switch ((int)message->value->int32) {
// Success
case 0:
// TODO: update the ui in some way
window_display_error(Other);
break;
// Route not found / api error
case 1:
window_display_error(Api);
break;
// Too many steps (== route not found error)
case 2:
window_display_error(Api);
break;
default:
window_display_error(Other);
}
}
// Test if the recived message is for key DISTANCE
message = dict_find(iter, MESSAGE_KEY_DISTANCE);
if (message) {
RouteDataDistance = (int)message->value->int32;
}
// Test if the recived message is for key TIME
message = dict_find(iter, MESSAGE_KEY_TIME);
if (message) {
RouteDataTime = (int)message->value->int32;
}
// Test if the recived message is for key INSTRUCTIONS
for (int i = 0; i < MAX_STEP_COUNT; i++) {
message = dict_find(iter, MESSAGE_KEY_INSTRUCTIONS + i);
if (message) {
// Copy the string into the string array
static char *empty;
strncat(empty, message->value->cstring, MAX_STEP_CHARS);
strcpy(RouteDataSteps[i], empty);
// Store the new length of the RouteDataSteps
RouteDataStepsCount = i + 1;
}
}
}
// Respond with error, if any data is lost
static void app_message_inbox_dropped_callback(AppMessageResult reason, void *context) {
// Display the network error
window_display_error(Network);
}
// Respond with error, if data can not be send to watch
static void app_message_outbox_failed_callback(DictionaryIterator *iter, AppMessageResult reason, void *context) {
// Display the network error
window_display_error(Network);
}
// Send the search data to the phone
static void app_message_send_search_data() {
// Send the data to the phone if conn is ready
if (AppMessageIsReady) {
// Create a string with the correct length
char message[sizeof(address) + 1];
// Add the type as the first char
message[0] = '0' + selected_type_enum;
// Add the address
strcat(message, address);
// Make sure the string is terminated correctely, just in case
message[sizeof(message) - 1] = '\n';
// Write string to bluetooth storage
DictionaryIterator *iter;
if (app_message_outbox_begin(&iter) == APP_MSG_OK) {
dict_write_cstring(iter, MESSAGE_KEY_SEARCH, message);
// Send the outbox
app_message_outbox_send();
} else {
// Display network error
window_display_error(Network);
}
} else {
AppMessageSendOnCallback = true;
}
}
// Set up the whole app message thing (once the address is worked out)
static void app_message_start() {
// Set initial values
AppMessageIsReady = true;
AppMessageSendOnCallback = false;
// Register all callbacks
app_message_register_inbox_received(app_message_inbox_recived_callback);
app_message_register_inbox_dropped(app_message_inbox_dropped_callback);
app_message_register_outbox_failed(app_message_outbox_failed_callback);
// Open the app-message
app_message_open(APP_MESSAGE_INBOX_SIZE_MINIMUM, APP_MESSAGE_OUTBOX_SIZE_MINIMUM);
}
// ******************** // ********************
// * WINDOW LIFECYCLE * // * WINDOW LIFECYCLE *
// ******************** // ********************
// Network error callback
void window_display_error(enum ErrorType err) {
// Show the error window
error_window_push(err);
// Remove this window from the window stack
window_stack_remove(window, false);
}
// Window unload handler // Window unload handler
static void window_unload() { static void window_unload() {
// Destroy the menu layer // Destroy the menu layer
@@ -101,6 +241,9 @@ static void window_unload() {
// Destroy the dictation session // Destroy the dictation session
dictation_session_destroy(dictation_session); dictation_session_destroy(dictation_session);
// Remove all app message callbacks
app_message_deregister_callbacks();
// Destroy the window // Destroy the window
window_destroy(window); window_destroy(window);
window = NULL; window = NULL;
@@ -175,4 +318,9 @@ void directions_window_push() {
// Start the dictation session TODO: Change this, once app sync stuff is working // Start the dictation session TODO: Change this, once app sync stuff is working
// dictation_session_start(dictation_session); // dictation_session_start(dictation_session);
address = "Meerbusch Brockhofweg 9"; // WIP address string address = "Meerbusch Brockhofweg 9"; // WIP address string
// Open the connection to the phone
app_message_start();
// TODO: Remove this for final version; this is a playeholder implementation (skipping the dictation)
app_message_send_search_data();
} }
+112
View File
@@ -0,0 +1,112 @@
#include <pebble.h>
#include "colors.h"
#include "error_window.h"
// The main window
static Window *window;
static BitmapLayer *error_icon_layer;
static TextLayer *error_text_layer;
// The error to be displayed
int display_error_type;
// Error icon / text
static GBitmap *icon_error;
static char *text_error;
static void window_unload() {
// Destroy the text layer & the error icon layer
bitmap_layer_destroy(error_icon_layer);
text_layer_destroy(error_text_layer);
// Destroy the image resource
gbitmap_destroy(icon_error);
// Destroy the window
window_destroy(window);
window = NULL;
}
static void window_load() {
// Get the root layer
Layer *window_layer = window_get_root_layer(window);
GRect bounds = layer_get_bounds(window_layer);
switch(display_error_type) {
// Network
case 0:
icon_error = gbitmap_create_with_resource(RESOURCE_ID_ICON_ERROR_NETWORK);
text_error = "Could not reach phone";
break;
// Api
case 1:
icon_error = gbitmap_create_with_resource(RESOURCE_ID_ICON_ERROR_API);
text_error = "No route could be found";
break;
// Other / Undefined
case 2:
icon_error = gbitmap_create_with_resource(RESOURCE_ID_ICON_ERROR_OTHER);
text_error = "Something went wrong";
break;
}
// Set up the error image layer GRect(x, y, w, h)
#ifdef PBL_ROUND
// Round spacing / Align
error_icon_layer = bitmap_layer_create(GRect(0, 0, bounds.size.w, 110));
bitmap_layer_set_alignment(error_icon_layer, GAlignBottom);
#else
// Square spacing / Align
error_icon_layer = bitmap_layer_create(GRect(0, 0, bounds.size.w, 100));
bitmap_layer_set_alignment(error_icon_layer, GAlignCenter);
#endif
bitmap_layer_set_bitmap(error_icon_layer, icon_error);
bitmap_layer_set_compositing_mode(error_icon_layer, GCompOpSet);
#ifdef PBL_COLOR
// Color only
bitmap_layer_set_background_color(error_icon_layer, COLOR_ERROR);
#endif
layer_add_child(window_layer, (Layer *)error_icon_layer);
// Set up the error text
#ifdef PBL_ROUND
// Round spacing
error_text_layer = text_layer_create(GRect(0, 110, bounds.size.w, bounds.size.h - 110));
#else
// Square spacing
error_text_layer = text_layer_create(GRect(0, 100, bounds.size.w, bounds.size.h - 100));
#endif
text_layer_set_text(error_text_layer, text_error);
text_layer_set_font(error_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD));
text_layer_set_text_alignment(error_text_layer, GTextAlignmentCenter);
text_layer_set_text_color(error_text_layer, GColorBlack);
#ifdef PBL_COLOR
// Color only
text_layer_set_background_color(error_text_layer, COLOR_ERROR);
#endif
layer_add_child(window_layer, (Layer *)error_text_layer);
#ifdef PBL_ROUND
// Round text insets
text_layer_enable_screen_text_flow_and_paging(error_text_layer, 0);
#endif
}
void error_window_push(enum ErrorType error_type) {
display_error_type = error_type;
if (!window) {
// Create the window
window = window_create();
// Set up the window handlers
window_set_window_handlers(window, (WindowHandlers) {
.load = window_load,
.unload = window_unload,
});
}
// Display the window
window_stack_push(window, true);
}
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <pebble.h>
enum ErrorType {
// Problem connection to phone
Network = 0,
// Error response from api
Api = 1,
// Something simply went wrong
Other = 2
};
void error_window_push(enum ErrorType);
+112 -22
View File
@@ -1,33 +1,123 @@
/**
* SETUP OVERVIEW
*
* About the send messages
* –––
* (1) Overview data is send (distance, time needed)
* (2) Step data array is send (each step string, max 20 entrys) -> THE LAST SEND INDEX IS THE LENGTH!
* (3) Success value is send (terminates the transmittion; it's true/false
* value determines whether the transmition was successfull or not (E.g.
* if false is send as the success first, no route was found)
*
* About the success codes:
* –––
* 0 = Success; 1 = Route not found; 2 = Too many steps; ...
*
* About the recived message:
* –––
* Field: SEARCH
* Contents: {selected_type}{address} (e.g. 0Brockhofweg 9)
* The first character is always the type selected, the rest
* is the written address.
* {selected_type} vals: 0 = Car; 1 = Bike; 2 = Train; 3 = Walk;
*/
// Data keys // Data keys
var keys = require('message_keys'); var keys = require('message_keys');
var maxStepCount = 20;
// Common functions
function createData(success, distance, time, steps, stepsDistances) { // App Message functions
function sendSuccess(code) {
// Build message
var key = keys.SUCCESS;
var dict = {}; var dict = {};
dict[keys.SUCCESS] = success; dict[key] = +code;
dict[keys.DISTANCE] = distance;
dict[keys.TIME] = time; // Send message to pebble
dict[keys.STEPS] = steps; Pebble.sendAppMessage(dict, function() {
dict[keys.STEPS_DISTANCES] = stepsDistances; // Success!
return dict; console.log('Transmission completed');
}, function() {
// Error
console.log('Transmission failed at [SUCCESS MESSAGE]');
});
} }
// Some dummy data (let's make the c app work first ;) function sendStepItem(stepList, index) {
// Build message
var key = keys.INSTRUCTIONS + index;
var dict = {};
dict[key] = stepList[index];
// Send message to pebble
Pebble.sendAppMessage(dict, function() {
// Success, send next item
index ++;
if (index < stepList.length && index < maxStepCount) {
// Recursive callbacks, hell yeah!
sendStepItem(stepList, index);
} else {
// We are finished
sendSuccess(0);
}
}, function() {
// Error
console.log('Transmission failed at index '.concat(index));
});
}
function sendRoute(success, distance, time, stepList) {
// Send message to pebble if a route was found
if (success) {
// Build message
var keyDistance = keys.DISTANCE;
var keyTime = keys.TIME;
dict[keyDistance] = +distance;
dict[keyTime] = +time;
// Transmit
Pebble.sendAppMessage(dict, function() {
// Success!
sendStepItem(stepList, 0);
}, function() {
// Error
console.log('Transmission failed at [OVERVIEW]');
});
} else {
// Send error message (route not found)
sendSuccess(1);
}
}
// Api data functions FIXME: Acutally use api
function fetchAndSendRoute(routeType, destination) {
// TODO: Add api data here (+ use geolocation etc)
console.log(routeType);
console.log(destination);
/* dummy data: */
sendRoute(true, 560, 16, ['This is the first step', 'This is the second step', 'This is the third step', 'This is the final step']);
}
// Accept data from the pebble watch
Pebble.addEventListener('appmessage', function(e) { Pebble.addEventListener('appmessage', function(e) {
// Get the dictionary from the message // Get the dictionary from the message
var dict = e.payload; var dict = e.payload;
console.log(dict.SEARCH);
var message = createData( // Does the SEARCH field exist?
true, if (dict['SEARCH']) {
140, fetchAndSendRoute(dict['SEARCH'].substr(0, 1), dict['SEARCH'].substr(1));
13, }
["Do sometoing", "Step 3", "the very last step"], });
[11, 0, 5321]
); // Ready event
Pebble.sendAppMessage(message, function() { Pebble.addEventListener('ready', function() {
console.log('Message sent successfully: ' + JSON.stringify(message)); // Tell the watch that the js part is ready
}, function(e) { var key = keys.READY;
console.log('Message failed: ' + JSON.stringify(message)); var dict = {};
}); dict[key] = true;
Pebble.sendAppMessage(dict);
console.log('Js part is ready!');
}); });
+1 -1
View File
@@ -27,7 +27,7 @@ static uint16_t get_num_rows_callback(struct MenuLayer *menu_layer, uint16_t sec
static int16_t get_cell_height_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *context) { static int16_t get_cell_height_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *context) {
// This part is for round watches only // This part is for round watches only
#if defined(PBL_ROUND) #ifdef PBL_ROUND
// Round // Round
bool selected = menu_layer_is_index_selected(menu_layer, cell_index); bool selected = menu_layer_is_index_selected(menu_layer, cell_index);
if (selected) { if (selected) {