Madrobots
Компания
86,97
рейтинг
1 декабря 2013 в 23:43

Разработка → Программируем под Pebble. Урок первый: Глупые часы tutorial

Когда мне привезли часы Pebble, я думал это просто умные часы. Ну, там смс на экранчике показать, время в двух поясах, поставить вместо цифровых — хипстерские аналоговые. И так далее.



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

Итак, что у нас есть? Три кнопки справа, одна кнопка слева, экран разрешением 144х168 пикселей.
Два типа программ — watchface, скины для часов и watchapp — приложения для часов. Первые не могут реагировать на кнопки, вторые могут. Первые перелистываются кнопками вверх и вниз в режиме отображения часов, вторые — показываются в конце меню после нажатия средней кнопки. У приложений по умолчанию есть верхний бар, в котором при запуске отображается название приложения, а во время работы — часы, но его можно отключить. Все внутренности полностью одинаковы, можно поменять тип приложения пересборкой, не внося изменений в код.

Начинаем


Заходим на cloudpebble.net, создаем аккаунт, нажимаем Create Project, выбираем SDK 2.

Сбоку видим:
Settings — настройки проекта
Compilation — сборка проекта
main.c — наш единственный файл проекта

Заходим в Settings.

App kind — это как раз тип, скин для часов или приложение.
Short Name отображается в меню часов, Long name — в приложении на телефоне(менюшка, из которой можно удалять приложения)
Menu image — картинка в меню часов.
UUID — идентификатор часов. Используется, например, при обновлении приложения. Если у загружаемого приложения такой же номер, как у одного из старых, оно будет заменено на новое.

В разделе Compilation можно собрать программу(кнопка Run build), после чего вам дадут ссылку на бинарник и QR-код для скачивания оного. Его можно сосканировать телефоном, и сразу же установить на часы. Делать это придется часто…

Теперь открываем main.c, и копируем вместо того, что там есть, вот такой код:
#include "pebble.h"

Window *window; /*создаем окно по имени... окно! человек человеку волк, а зомби зомби зомби. */

int main(void) {
  window = window_create(); /* выделяем память и создаем окно с параметрами по умолчанию  http://goo.gl/mdb5B9*/
  window_stack_push(window, true); /* настраиваем анимацию при открытии этого окна. Так как оно у нас единственное - 	анимания будет показываться при переходе из меню в приложение.  http://goo.gl/jXG3aw */
  app_event_loop(); /* ждем действий в бесконечном цикле  http://goo.gl/7hLyRX */
  window_destroy(window); /* очищаем память и уничтожаем окно http://goo.gl/G3FJ6i */
}
После описания — ссылки на страницы API по той или иной функции. Сынок, это наша библия… Нет батя, это наша камасутра.
Приведенная выше программа не делает ничего полезного, просто показывает пустой экран. Не реагирует на кнопки, при нажатии кнопки назад — завершается.


Выведем какую-нибудь надпись. Для начала, установим фоновый цвет окна программы:
window_set_background_color(window, GColorBlack);

Второй параметр может принимать значения: GColorBlack — черный цвет, GColorWhite — белый цвет, GColorClearпрозрачная краска прозрачный фон, через который будет виден предыдущий слой(если бы он был). По умолчанию он равен White, вот почему у первой программы был белый фон. Само-собой, это надо делать уже после функции window_create.
Для того, чтобы вывести текст, нам потребуется текстовый слой.
Создаем слой:
TextLayer *text_layer;

Инициализируем и задаем координаты:
text_layer = text_layer_create(GRect(0, 0, 144, 168));

GRect — функция создания прямоугольника. Координаты она получает в следующем порядке — первые два числа это координаты верхнего левого угла треугольника — x, y. Вторые два числа — это ширина и высота нашего прямоугольника. Для удобства сделал вот такую картинку:

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

Открыв ее в любом редакторе очень удобно рассчитывать координаты. К сожалению, среда разработки такой возможности не предоставляет.

По-умолчанию, цвет шрифта — черный, цвет фона — белый, выравнивание по левому краю, шрифт — Raster Gothic 14.
Меняем все это. Фон у нас черный, значит цвет букв должен быть белым:
text_layer_set_text_color(text_layer, GColorWhite);

Фон(текстового слоя) делаем прозрачным:
text_layer_set_background_color(text_layer, GColorClear);

Выравнивание — по центру:
text_layer_set_text_alignment(text_layer, GTextAlignmentCenter);

А шрифт делаем чуть больше:
text_layer_set_font(text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD));
Вот список всех стандартных шрифтов
FONT_KEY_GOTHIC_14
FONT_KEY_GOTHIC_14_BOLD
FONT_KEY_GOTHIC_18
FONT_KEY_GOTHIC_18_BOLD
FONT_KEY_GOTHIC_24
FONT_KEY_GOTHIC_24_BOLD
FONT_KEY_GOTHIC_28
FONT_KEY_GOTHIC_28_BOLD
FONT_KEY_BITHAM_30_BLACK
FONT_KEY_BITHAM_42_BOLD
FONT_KEY_BITHAM_42_LIGHT
FONT_KEY_BITHAM_42_MEDIUM_NUMBERS
FONT_KEY_BITHAM_34_MEDIUM_NUMBERS
FONT_KEY_BITHAM_34_LIGHT_SUBSET
FONT_KEY_BITHAM_18_LIGHT_SUBSET
FONT_KEY_ROBOTO_CONDENSED_21
FONT_KEY_ROBOTO_BOLD_SUBSET_49
FONT_KEY_DROID_SERIF_28_BOLD

Делаем ребенка Добавляем созданный нами слой к слою главного экрана в качестве дочернего:
layer_add_child(window_get_root_layer(window), text_layer_get_layer(text_layer));

И наконец записываем в слой наш текст:
text_layer_set_text(text_layer, "Hi, habrahabr!");

А при выходе — не забываем освобождать память:
 
text_layer_destroy(text_layer);
Наша программа уже выглядить вот так:


А вот ее исходник. Можно скопировать в редактор, собрать и запустить на часах, чтобы похвастать: я написал программу для часов(!)
#include "pebble.h"

Window *window; 
TextLayer *text_layer; /* создаем текстовый слой по имени... ну вы поняли */

int main(void) {
  window = window_create(); 
  window_set_background_color(window, GColorBlack);  /* http://goo.gl/B6tj94 */
  window_stack_push(window, true);
  text_layer = text_layer_create(GRect(0, 0, 144, 168)); /* создаем прямоугольник (http://goo.gl/00eAW6) и 
  кидаем указателем в функцию создания слоя http://goo.gl/kYuFh5 */
  text_layer_set_text_color(text_layer, GColorWhite);  /* устанавливаем цвет шрифта http://goo.gl/wt4ZIC */
  text_layer_set_background_color(text_layer, GColorClear); /*  устанавливаем цвет фона слоя http://goo.gl/Y7HARg */
  text_layer_set_font(text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD)); /*  устанавливаем шрифт
  http://goo.gl/MOhxNe */
  text_layer_set_text_alignment(text_layer, GTextAlignmentCenter); /* Выравниваем по центру http://goo.gl/K6LWeG */
  layer_add_child(window_get_root_layer(window), text_layer_get_layer(text_layer)); /* Делаем слой дочерним и помещаем его перед слоем окна http://goo.gl/jFy8LV  */
  text_layer_set_text(text_layer, "Hi, habrahabr!"); /* Выводим текст http://goo.gl/KT1hD6 */
  app_event_loop(); 
  text_layer_destroy(text_layer);
  window_destroy(window); 
}


Наконец, можно добавить в наши часы отображение времени.
Создаем переменную нужного типа(время в секундах) и кладем в нее текущее время в формате POSIX
 time_t now = time(NULL);
Создаем структуру, которая будет хранить значение текущего времени в более читабельном формате — год, месяц, день, час, минута, секунда, а так же день в недели, день в году, и AM/PM:
struct tm *current_time = localtime(&now);
А после этого записываем в нее время, конвертированное функцией localtime из POSIX в читабельный вид.

Так как нам нужно только время, а в переменной у нас валяется вся информация до кучи, надо выделить нужные нам части. Делается это функцией strftime. В качестве аргументов она принимает следующие переменные: переменная записи результата, ее размер, формат записи, переменная в которой находится время. Так как функции нужна переменная(она не может писать в текстовый слой), и ее размер, надо сначала создать такую переменную.
static char time[] = "00:00:00"; 

Конечно, не обязательно писать при инициализации 00:00:00, можно и «ХХХХХХХХ», а можно и ничего не писать, а просто задать размер во втором аргументе функции числом, но это будет не очень понятно.
strftime(time, sizeof(time), "%T", current_time);

Если в current_time у нас всегда актуальное время, то начиная с этого момента, в переменной time остается форматированое значение времени на момент выполнения strftime. То, как оно форматируется — зависит от третьего аргумента — %T. Документация на формат легко гуглится по названию функции, например вот. В данном случае %T — это тоже самое что и "%H:%M:%S". Часы, минуты и секунды, разделенные двоеточиями.

Теперь можно записать это значение в текстовый слой:
text_layer_set_text(text_layer, time);

Вроде как у нас получились часы. И при запуске они покажут правильное время. Вот только проблема — они не обновляются, и показывают правильное время только один раз в сутки.
Нам надо как-то каждую секунду пересчитывать время и выводить его на экран. Делается это вот как.
Создаем функцию, которая будет это делать, и переносим туда все, что касается пересчета и вывода времени:

static void second_tick(struct tm* tick_time, TimeUnits units_changed) {
static char time[] = "00:00:00"; 
strftime(time, sizeof(time), "%T", current_time);
text_layer_set_text(text_layer, time);
}


Подписываемся на сервис таймера:

tick_timer_service_subscribe(SECOND_UNIT, &second_tick);


Первый аргумент означает, что функция во втором аргументе будет вызываться каждую секунду. Если в часах не будет секунд, то можно экономить энергию, и будить процессор в 60 раз меньше, вызывая функцию каждую минуту: MINUTE_UNIT
Или каждый час: HOUR_UNIT
Или каждый день: DAY_UNIT
Ну, вы поняли логику: MONTH_UNIT, YEAR_UNIT

После этого желательно вызвать эту функцию принудительно, не дожидаясь очередного тика таймера — ну просто для красоты, чтобы секунду не смотреть на пустой экран. Это хорошо если секунду. А если таймер каждую минуту тикает?

second_tick(current_time, SECOND_UNIT);


В итоге наши часы выглядят вот так:



Исходник:

#include "pebble.h"

Window *window; 
TextLayer *text_layer; 

static void second_tick(struct tm* tick_time, TimeUnits units_changed) /* функция, вызываемая при тике таймера */
{
	static char time[] = "00:00:00"; /* создаем переменную и определяем ее размер */
	strftime(time, sizeof(time), "%T", tick_time); /* форматируем строку с временем */
	text_layer_set_text(text_layer, time); /* записываем строку со временем в тестовый слой */
}

int main(void) 
{
	window = window_create(); 
	window_set_background_color(window, GColorBlack);  
	window_stack_push(window, true);
	text_layer = text_layer_create(GRect(0, 0, 144, 168)); 
	text_layer_set_text_color(text_layer, GColorWhite); 
	text_layer_set_background_color(text_layer, GColorClear); 
	text_layer_set_font(text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD));
	text_layer_set_text_alignment(text_layer, GTextAlignmentCenter);
	layer_add_child(window_get_root_layer(window), text_layer_get_layer(text_layer)); 
	time_t now = time(NULL); /* создаем переменную и пишем в нее POSIX-время */
	struct tm *current_time = localtime(&now); /* получаем из POSIX значения времени и даты */
	tick_timer_service_subscribe(SECOND_UNIT, &second_tick); /* подписываемся на секундный таймер */
	second_tick(current_time, SECOND_UNIT); /* вызываем обновление времени не дожидаясь тика */

	app_event_loop(); 

	text_layer_destroy(text_layer);
	window_destroy(window); 
	tick_timer_service_unsubscribe(); 

}


Ссылки:

Httpeble: библиотека, реализующая http-запросы внутри программ
[EN]Проект по-настоящему умных часов(календарь, погода, напоминания, поиск телефона, HTTP-запросы для управления умным домом, управление музыкой, управление камерой, GPS, биржевые сводки)
PapaBubaDiop пишет о разработке игры под Pebble.
Огромная коллекция различных приложений для pebble, большинство — с исходниками.


Автор: @vvzvlad
Madrobots
рейтинг 86,97
Компания прекратила активность на сайте

Комментарии (42)

  • +3
    Чёрт, кажется, я знаю, какой подарок хочу на новый год:)
  • 0
    сегодня последний день бесплатной доставки.
    • +1
      Где?
    • +3
      madrobots.ru — 7499 а на офф сайте 130 $ с доставкой, не хилая наценка вам не кажется?
      • 0
        Доставки в россию нет вообще, прибавляйте $50 посреднику.
        • 0
          Поясню, если кто-то не верит. Обычной почтой они не отправляют, а отправляют только ups, dhl и иже с ними. А они такой доставкой привозят только юрлицам. Или комапния отправляет только на аккаунт юрлица в транспортной компании, не суть. Следовательно, надо заказывать доставку у посредника. Вот цены у бандерольки:
          Услуги почты, упаковка, страховка и комиссия за перевод денег обойдутся нам примерно от 52$ до 64$ — в зависимости от версии устройства и способа доставки.
          • +2
            Эм. DHL прекрасно доставляет физикам. Часы на сайте getpebble.com сейчас стоятт 130$, 25$ возьмут за доставку DHL. Я говорил в твиттере с Мириам из Engadget (она с недавнего времени Евангелист Pebble) и она подтвердила, что доставляют в Россию.
            • +2
              Я ориентируюсь на форум — 4pda и у них на сайте русскоязычный. У людей отменяют заказы и просят номер договора с юрлицом.
              • +1
                Кто именно отменяет? Сам pebble, тогда зачем им это? DHL мне ни разу не отказывал, получал 6 или 7 отправлений от них, даже важные документы и договора спокойно на физ. лицо ходят.
                • +1
                  Давайте вы будете не мне доказывать, а тем, кто заказать не может. Вот тут например.
                  сейчас при оформлении заказа просто отказываются поставлять в РФ. :angry:
                  Kolchin, сейчас только через посредников, на их адреса должны отправлять без проблем
                  проблема с заказом напрямую с сайта Pebble только у россиян
                  -Так вроде бы Пеббл поменял доставку с обычной почты на DHL, или с DHL в России тоже проблема?
                  -В DHL надо регистрироваться, а чтобы зарегистрироваться, надо указать название компании, которое как я понимаю не у всех есть…
                  -Dhl и ups, которыми пебл доставляет в Россию, работают только с юридическими лицами.
                  Пебл в письмах говорит что это такая новая политика таможни России, что теперь все должны иметь какую-то лицензию на импорт. Далее, надо иметь аккаунт номер в юпс или дхл или федекс. Но их дают только юрикам. Юпс пишет что можно как-то получить этот номер, если написать им. Но по моему это как-то маловероятно. Ну и в том же письме пеббл пишут что отправка будет стоить 35-45 баксов плюс прочие расходы.
                  Напрямую от магазина в Россию на данный момент могут получить только юридические лица. Есть вариант через посредника. Мне сейчас на бандерольку уже идут часики.
                  Ребята, проблема с доставкой в Россию. Они вроде требуют, что бы я был зареган в FedEx или DHL.
                  У меня такая же беда, друзей со своим ИП и acc number нет, поэтому попросил refund, жаль но очень хотелось такие часики


                  Или письмо от компании прочитаете:
                  Unfortunately, new shipments to Russia must follow a new process due to new regulations set forth by Russian customs. All Russians—including individual customers—must now have an import license for any product purchased out of the country.
                  In order to clear your Pebble order for shipping:
                  1) Addresses must be in Western/English characters.
                  2) We are now required to ask you for a valid DHL, FedEX or UPS account number that we can charge for shipping costs—this means that Pebble's $150 retail price no longer includes shipping to Russia.
                  The account number you provide us will automatically contain import license information required by Russian Customs. You can likely expect a shipping charge of about $35–45, plus any customs/importation fees.
                  If you do not currently have an account with DHL, FedEx, or UPS, you can sign up for one on their respective websites.
                • +1
  • 0
    Скажите, что там с новой версией прошивки? Запилили для нее уже русский язык без косяков?

    Товарищи, ни у кого нет желания поднять информационный ресурс для русскоязычных прошивок Pebble? Мониторить тему на 4PDA нет никакой мочи. Хочется одним взглядом получать актуальную информацию.

    Я могу собрать статический сайт, могу писать внятные инструкции, но в теме Pebble совершенно не ориентируюсь.
    • 0
      Успешно прошился вот этим файлом прошивки: 4pda.ru/forum/index.php?showtopic=418195&view=findpost&p=27086644

      Версия 1.13, русский язык работает.
      • 0
        Опаньки. Не мог установить WatchApp, решил сделать Factory Reset. После этого часики не подключаются ни к компу, ни к телефону. :(
        • 0
          При помощи Recovery Mode удалось откатиться на 1.12.1. Фух, чуть не брикнул…

          Понял, в чем проблема. Это была прошивка только для версий Pebble, серийный номер которых начинается с Q.
          • 0
            Как вообще можно убить устройство с зашитым бутлоадером?
            • +2
              image
  • +1
    Вот только проблема — они не обновляются, и показывают правильное время только один раз в сутки :)

    Если вместо 24-х часового режима отображения установить 12-ти часовой, то они будут показывать правильное время уже два раза в сутки!

    Как бы еще в этот индикатор вводить внешние данные? Применений было бы намного больше!
    • 0
      Неправильно выразился. Внешние данные в Pebble ввести можно по Bluetooth. Но интересно было бы управлять экраном на электронных чернилах посредством проводов. Это очень обширная ниша для экономичных устройств. Может кто-то знает уже готовые и доступные решения с экраном на электронных чернилах? Во многих устройствах его можно использовать вместо ЖКИ.
  • 0
    Часы + сенсор движения = sleeptracker
    Можно обойтись без управления с телефона. Три кнопки для настройки будильника — более чем достаточно.
    Остается вопрос к качеству сенсора и живучести батареи при включенном сенсоре.
    • 0
      Вот, слиптрекер уже есть: www.mypebblefaces.com/apps/9400/7424/
      • 0
        Спасибо! Позор, я не догадался выбрать в поиске SDK 2.
      • 0
        При попытке установить слиптрекер, приложение Pebble на айфоне вышибает(
        • 0
          А прошивка вторая?
          • 0
            ага. и софт на айфоне тоже под бету.
            5 айфон с 7.0.4.
  • 0
    CamelCase? нет_что_вы_не_слышал…
    • 0
      А чем лучше?
      • 0
        Глаза не вытекают от просмотра кода?
        • 0
          Нет. А должны?
    • 0
      этоЖеНеJavaScript
  • 0
    От таймера не отписались
    • 0
      Тогда часы обновляться перестанут.
      • 0
        Если добавить после app_event_loop(), туда где вы ресурсы освобождаете, то не перестанут.
        • 0
          Да, точно. Посыпаю голову пеплом, не подумал что его надо освобождать.
  • 0
    Никак не могу найти информацию насколько часы функциональны без телефона. Не подскажете?

    И вообще, какие требования к телефону? Что-то пишут про андроид или iPhone, но разве не любой Blutooth телефон подойдёт?
    • +1
      Надо было сначала обзор написать мне, а потом за программирование браться. Часы вполне функциональны без телефона — на них могут работать програмки и показываться скины часов. Единственное, если совсем без телефона — с заливкой придется повозиться, но на форуме было решение.

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

        Хм, а API по которому Pebble общается с телефоном и код программы компаньёна на телефоне открытые? Был бы хороший проект портировать их, если открытые.
        • 0
          Код программы закрыт, насколько я знаю, но API где-то есть, люди с компьютера отправляли на часы увдеомления.
        • 0
          Есть сторонний проект — github.com/Hexxeh/libpebble (люди разобрали протокол и сделали свою реализацию). Управление powerpoint'ом уже делали, кажется. А учитывая, что в часах акселерометр, можно попробовать сделать управление жестами!
          • 0
            Управление с помощью акселерометра будет эффектным первые два слайда. Если слайдов уже за 30, то заколеблешься переходить и исправлять ложные срабатывания. Все-таки руками во время презы жестикулируют.
            • 0
              Ага, я думал об этом. Можно попробовать придумать жесты, который нельзя будет перепутать с обычной жестикуляцией.
  • –1
    Добавлю еще свой простой пример разработки цифровых циферблатов: https://habrahabr.ru/post/278627/

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

    Также в примере есть ссылка на уже готовые простые но симпатичные интерфейсы.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка