1 заметка с тегом

geolocation

Геолокация в Pebble

3 декабря 2014, 23:52

Сегодня рассмотрим, как получить географические координаты в своем приложении.

Для начала создадим новый проект:

$ pebble new-project Geolocation-Pebble

В созданном проекте, в папке src, добавим новый каталог js, а в нем новый файл pebble-js-app.js
В файле напишем 2 функции, одна будет вызываться при успешном получении координат, другая при ошибке:

function locationSuccess(pos) {
  var coordinates = pos.coords;
  Pebble.sendAppMessage({
    "KEY_LATITUDE"  : coordinates.latitude.toString(),
    "KEY_LONGITUDE" : coordinates.longitude.toString()
  });
  console.log("lat: " + coordinates.latitude);
  console.log("lon: " + coordinates.longitude);
}
function locationError(err) {
  console.warn('location error (' + err.code + '): ' + err.message);
}
var locationOptions = {
  enableHightAccuracy : true,
  timeout             : 60000, 
  maximumAge          : 10000
};

Когда мы получили координаты, мы их собираем в объект и отправляем в часы функцией Pebble.sendAppMessage.
Также добавим опции, такие как enableHightAccuracy — повышенная точность определения местоположения, timeout — максимальное время на получение координат и maximumAge — максимальный допустимый возраст координат. Подробнее о спецификации можно почитать на сайте W3C.
После этого добавить слушатель, который будет получать команду из часов и запускать процесс определения координат:

Pebble.addEventListener("appmessage",
  function(e) {
    window.navigator.geolocation.getCurrentPosition(locationSuccess, locationError, locationOptions);
  }
);

Далее перейдем к файлу appinfo.json и добавим туда 2 ключа, в одном будет передаваться широта, в другом долгота и добавим разрешение на использование геолокационного сервиса:

"capabilities": [ "location" ],
"appKeys": {
  "KEY_LATITUDE"  : 0,
  "KEY_LONGITUDE" : 1
},

Перейдем к написанию самого приложения для часов, оно будет состоять из 2х текстовых полей и одного события. При нажатии на кнопку «выбор» будет происходить обновление координат.
В функции windows_load опишем текстовые поля:

static void window_load(Window *window) {
  Layer *window_layer = window_get_root_layer(window);
  
  latitude_layer = text_layer_create(GRect(0, 45, 144, 68));
  text_layer_set_text_color(latitude_layer, GColorWhite);
  text_layer_set_background_color(latitude_layer, GColorClear);
  text_layer_set_font(latitude_layer, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD));
  text_layer_set_text_alignment(latitude_layer, GTextAlignmentCenter);
  layer_add_child(window_layer, text_layer_get_layer(latitude_layer));
  text_layer_set_text(latitude_layer, "Press SELECT for update");

  longitude_layer = text_layer_create(GRect(0, 90, 144, 68));
  text_layer_set_text_color(longitude_layer, GColorWhite);
  text_layer_set_background_color(longitude_layer, GColorClear);
  text_layer_set_font(longitude_layer, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD));
  text_layer_set_text_alignment(longitude_layer, GTextAlignmentCenter);
  layer_add_child(window_layer, text_layer_get_layer(longitude_layer));
  text_layer_set_text(longitude_layer, "N/A");
}

Создадим функции для отслеживания нажатий на кнопку «выбор» и передачи команды в JavaScript Framework для обновления координат:

static void select_click_handler(ClickRecognizerRef recognizer, void *context) {
  Tuplet initial_values[] = {
    TupletCString(KEY_LATITUDE, "N/A"),
    TupletCString(KEY_LONGITUDE, "N/A"),
  };
  app_sync_init(&sync, sync_buffer, sizeof(sync_buffer), initial_values, ARRAY_LENGTH(initial_values),
      sync_tuple_changed_callback, sync_error_callback, NULL);

  send_cmd();
}
static void click_config_provider(void *context) {
  window_single_click_subscribe(BUTTON_ID_SELECT, select_click_handler);
}

Опишем функцию передачи данных в JavaScript Framework, хотя мы и будем передавать пустой объект, это все для того чтобы запустить Pebble.addEventListener:

static void send_cmd(void) {
  Tuplet value = TupletInteger(2, 1);
  DictionaryIterator *iter;
  app_message_outbox_begin(&iter);
  if (iter == NULL) {
    return;
  }
  dict_write_tuplet(iter, &value);
  dict_write_end(iter);
  app_message_outbox_send();
}

В следующей функции мы принимаем объект состоящий из 2х ключей и обновляем наши соответствующие текстовые поля:

static void sync_tuple_changed_callback(const uint32_t key, const Tuple* new_tuple, const Tuple* old_tuple, void* context) {
  switch (key) {
    case KEY_LATITUDE:
      text_layer_set_text(latitude_layer, new_tuple->value->cstring);
      break;
    case KEY_LONGITUDE:
      text_layer_set_text(longitude_layer, new_tuple->value->cstring);
      break;
  }
}

Незабываем добавить пару строчек в  функцию init:

app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum());
window_set_click_config_provider(window, click_config_provider);

При желании или необходимости можно добавить таймер и через определенный интервал обновлять координаты, а потом, например, рисовать пройденный трек, но мне для своего приложения этого не требовалось, поэтому об этом расскажу может в следующий раз.

Полную версию исходников можно посмотреть на GitHub.

geolocation   Pebble   tutorial