Creación de una esfera funcional para el Pebble

En el último artículo vimos los pasos que hay que seguir para preparar el entorno de programación del reloj Pebble en Ubuntu. Es importante realizar ese artículo antes de empezar con este artículo ya que se usan algunas herramientas del SDK. Al final del artículo tendréis en el reloj una esfera básica pero completamente funcional. La esfera está formada por una única pantalla en la que se muestra la hora del reloj. En las siguientes entregas añadiremos nuevas funcionas para que sea útil y práctica. He subido el código fuente del proyecto a mi página de GitHub. Cada paso del artículo tiene un commit diferente por lo que podréis pasar de uno a otro con facilidad.

Como he comentado partimos de que el SDK de Pebble está correctamente instalado y podemos hacer una captura de pantalla del reloj desde la línea de comandos. Hay dos formas de seguir el artículo. La primera consiste en ir paso a paso con el programa básico mientras que la segunda consiste en descargar el código que está publicado en Git y trabajar de forma local. La carpeta del proyecto incluye todos los archivos necesarios para compilar la esfera e instalarla en el reloj Pebble. Podéis añadir las sugerencias o los bugs en la página del proyecto o en los comentarios del artículo.

Nota:En el artículo uso como base el tutorial de la Web de Pebble.

Creación del esqueleto de la aplicación

Cualquier proyecto de Pebble necesita un esqueleto sobre el que se irán montando todos los elementos que forman la esfera o la aplicación. Este esqueleto se puede crear usando las funciones que da el SDK de Pebble. Abrimos una consola y creamos la carpeta de trabajo con el comando:

mkdir ~/Proyectos

Entramos en la carpeta que contendrá el proyecto:

cd ~/Proyectos

Para crear el esqueleto ejecutamos:

pebble new-project NombreEsfera

Dentro de la carpeta hay varios archivos de configuración y dos carpetas que contienen el código fuente en C y los recursos de la aplicación.

Archivos del proyecto de programación

Archivos del proyecto de programación

 

Modificaciones a los archivos del proyecto

El archivo appinfo.json con tiene información de la aplicación como el editor o el tipo de aplicación que es. Abrimos el archivo con un editor de texto y sustituimos la línea que contiene la palabra “whatchafe”: false por “watchface”: true

Guardamos el archivo y entramos en la carpeta src. Editamos el archivo para hacer algunos cambios. Pegamos el esqueleto en el archivo. En la primera línea hay que incluir el archivo pebble.h (el editor de la página elimina el código).

static void init() {}

static void deinit() {}

int main(void) {
  init();
  app_event_loop();
  deinit();
}
Cualquier aplicación del reloj Pebble tiene que tener un esqueleto parecido. El método main() es el punto de inicio del programa y en él se gestionan los elementos de la aplicación y se ejecuta el bucle de eventos. De momento dejaremos el funcionamiento que tiene por defecto el método app_event_loop() y nos centraremos en los dos otros métodos. El método init() se encarga de iniciarlizar los elementos que intervienen en la aplicación como son las pantallas de la aplicación, los campos de texto o los gráficos. Por su parte deinit() hace una función similar pero liberando los recursos que se han definido en init(). Es importante que nada más hemos inicializado un recurso escribamos también su liberación en el método correspondiente.

Haremos tres iteraciones en la esfera:

  • Crear una pantalla en blanco e instalarla en el Pebble.
  • Crear un campo de texto y añadirlo a la pantalla.
  • Actualizar el campo de texto para que muestre la hora.

Crear una pantalla en blanco e instalarla en el Pebble

Definimos la estructura que formará la pantalla

// Pantallas que forman la esfera static Window *s_main_window;

Usaremos dos métodos para inicializar los recursos de la pantalla y posteriormente liberarlos. Dentro de estos métodos definiremos más adelante un campo de texto que mostrará la hora del sistema.

/**  
 * @fn static void main_window_load(Window *window)  
 * @brief Inicialización de la pantalla principal  */
static void main_window_load(Window * window) {}

/**  
 * @fn static void main_window_unload(Window *window)  
 * @brief Liberación de la pantalla principal  */
static void main_window_unload(Window * window) {}

En el método init() inicializaremos la pantalla, asociaremos los métodos de reserva y liberación de los recursos y añadiremos la pantalla como pantalla principal de la esfera.

/** 
 * @fn static void init()  
 * @brief Inicialización de los recursos de la esfera  
 */
static void init() {
  // Creación de las pantallas     
  s_main_window = window_create();

  // Asociación de los handlers que gestionan la pantalla   
  window_set_window_handlers(s_main_window, (WindowHandlers) {
    .load = main_window_load,
      .unload = main_window_unload
  });

  // Mostramos la pantalla en el reloj   
  window_stack_push(s_main_window, true);
}

Recordad que al mismo tiempo que hay que liberar los recursos que hemos usado en el método deinit()

/**  
 * @fn static void deinit()
 * @brief Liberación de los recursos de la esfera 
 */
static void deinit() {
  // Liberación de los recursos que usa la pantalla de la esfera  
  window_destroy(s_main_window);
}

Compilación del proyecto

Guardamos el archivo y volvemos a la consola. Para compilar el proyecto simplemente tenemos que ejecutar el comando pebble build en la carpeta que contiene el proyecto.

Compilación de la esfera

Compilación de la esfera

Instalación de la esfera

Si no hay ningún error el siguiente paso es instalarlo en el Pebble.

pebble install --phone 192.168.1.100

A los pocos segundos aparecerá la esfera en el reloj. Podemos hacer una captura de pantalla con:

pebble screenshot --phone 192.168.1.100

Esfera inicialEsfera inicial

Puede parecer poca cosa tener una pantalla en blanco en el Pebble. Ésto es cierto pero también hay que tener en cuenta que es una esfera muy básica que apenas contiene una pantalla. Veremos a continuación la forma de añadir un campo de texto para mostrar la hora.

Crear un campo de texto y añadirlo a la pantalla

El primer paso es definir la estructura que hará la función de un campo de texto.

static TextLayer *s_time_layer;

En el apartado anterior hemos definido las características de la pantalla en el método init() junto con dos métodos auxiliares que reservan y liberan los recursos de la pantalla. Modificamos el método main_window_load (..) para añadir el campo de texto.

/**  
 * @fn static void main_window_load(Window *window) 
 * @brief Inicialización de la pantalla principal 
 */
static void main_window_load(Window * window) {
  // Creación del campo de texto. Definimos con un rectángulo las  	
  // coordenadas del campo de texto    
  s_time_layer = text_layer_create(GRect(0, 55, 144, 50));
  text_layer_set_background_color(s_time_layer, GColorClear);
  text_layer_set_text_color(s_time_layer, GColorBlack);
  text_layer_set_text(s_time_layer, "00:00");

  // Formato  
  text_layer_set_font(s_time_layer, fonts_get_system_font(FONT_KEY_BITHAM_42_BOLD));
  text_layer_set_text_alignment(s_time_layer, GTextAlignmentCenter);

  // Insertamos el campo de texto en la pantalla principal  
  layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_time_layer));
}

De la misma forma escribimos el código equivalente para liberar el campo de texto cuando se cierre la esfera.

/**  
 * @fn static void main_window_unload(Window *window) 
 * @brief Liberación de la pantalla principal 
 */
static void main_window_unload(Window * window) {
  // Liberamos los recursos del campo de texto    
  text_layer_destroy(s_time_layer);
}

Guardamos los cambios, compilamos el proyecto y lo instalamos en el Pebble. No es necesario eliminar la esfera anterior para poner la nueva versión.

Esfera con texto

Esfera con texto

El texto es estático. Como un reloj que no muestra la hora es algo inutil tendremos que añadir un nuevo método que se encargue de actualizar el campo de texto con la hora del sistema.

Actualizar el campo de texto para que muestre la hora

En el funcionamiento normal de una aplicación de Pebble se ejecutan en segundo plano una serie de eventos que ofrecen diferentes funcionalidades. Por ejemplo, hay un evento que nos avisa con una frecuencia constante y es el que usaremos para actualizar la hora. Es posible "escuchar" el evento con diferentes filtros para las horas, los minutos o los segundos. No hay en principio una limitación en su uso pero hay que tener en cuenta el consumo de la esfera. Si ejecutamos código cada segundo el consumo será superior a ejecutar ese mismo código cada minuto.

El método update_time() se encargará de actualizar el campo de texto que mostrará la hora.

/** 
 * @fn static void update_time()  
 * @brief Actualiza la hora que se muestra en el campo de texto
 */
static void update_time() {

  // Leemos la hora del sistema       
  time_t temp = time(NULL);
  struct tm * tick_time = localtime( & amp; temp);

  // Creamos un buffer para guardar la hora    
  static char buffer[] = "00:00";

  // Actualizamos el buffer con la hora actual   
  if (clock_is_24h_style() == true) {

    // 24 h              
    strftime(buffer, sizeof("00:00"), "%H:%M", tick_time);
  } else {
    // 12 h            
    strftime(buffer, sizeof("00:00"), "%I:%M", tick_time);
  }

  // Actualizamos el campo de texto       
  text_layer_set_text(s_time_layer, buffer);
}

El método update_time() no se ejecuta de forma continúa porque gastaría en poco tiempo la batería del Pebble (aparte de no tener mucho sentido). Para configurar la frecuencia con la que se ejecuta el método usaremos el método tick_handler (). Su funcionamiento es simple: seleccionamos la frecuencia de ejecución del código y el runtime de Pebble lo ejecutará por nosotros.

/**  
 * @fn static void tick_handler(struct tm *tick_time, TimeUnits units_changed) 
 * @brief 
 */
static void tick_handler(struct tm * tick_time, TimeUnits units_changed) {

  // Actualizamos el campo de texto de la hora     
  update_time();
}

Base de tiempos del reloj

Por último modificamos el método init() para configurar la base de tiempos del reloj para que nos notifique cada minuto y se actualice la hora.

    // Servicio TickTimerService (cambios cada minuto)    
    tick_timer_service_subscribe(MINUTE_UNIT, tick_handler);

    // Mostramos la pantalla en el reloj       
    window_stack_push(s_main_window, true);

    // Actualizamos la hora en la primera ejecución      
    update_time();

Compilamos el proyecto y lo instalamos en el Pebble. En esta ocasión el campo de texto mostrará la hora.

Esfera con la hora

Esfera con la hora

Conclusiones

Este artículo ha quedado un poco denso pero no es complicado de seguir. El primer paso para crear una esfera es usar los comandos del SDK para crear el esqueleto del proyecto. Después sólo hay que crear la pantalla principal y los elementos que ésta contiene como los campos de texto. Si hacéis la esfera de forma progresiva es sencillo de entender. Hay que tener un poco de base de programación en C pero no son necesarios conocimientos avanzados.

Recordad que el código fuente está disponible en GitHub y cada apartado del artículo está en un commit diferente. Podéis ver el código fuente de forma general y los cambios introducidos entre los diferentes commits. Cualquier duda o sugerencia que tengáis la podéis preguntar en los comentarios o en la página de GitHub.

0 comentarios

Dejar un comentario

¿Quieres unirte a la conversación?
Siéntete libre de contribuir!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.