Archive

Monthly Archives: December 2013

Woke up today to multiple bug reports. Apparently I didn’t test the new versions of the Android apps against the 1.X versions of the watchapps enough! Downgrading is easy enough a process, so after a while I had found that changing the old AppSync implementation for my newer AppMessage paradigm (Package whole Dictionaries, iterate and process all Tuples for each Dictionary received) seemed to resolve the problems!

Thus the bug fix update was sent to Google Play this morning after only a modicum of panicking. All users will need to re-install their appropriate watchapp, and the Android app will guide them:

Screenshot_2013-12-31-14-17-18

So, with that out the way, I’ve moved on to applying the new dymanically allocated Animation system developed during the course of writing the SDK 2.0 Tutorial #4 to the Beam Up watchfaces, which should hopefully eliminate this ugly bug:

IMG_20131226_185234If it’s successful I’ll packages all four of those and the two new versions of Watch Trigger (+) into Watch App Selector and update that to the Play Store too. Exciting times!

After reading the Pebble UX Guidelines document last week, I realized that I had not changed the UI on either the watch app or phone app for Watch Trigger / Watch Trigger + for quite some time. Now is that time!

Planned changes are:

  1. New UX compliant watch app with changeable settings
  2. Re-built phone app Settings and underlying Preferences system.
  3. A new ‘Welcome’ screen for first run to try and mitigate SDK 2.0 vs SDK 1.X confusion in new users.
  4. A possible overhaul of the phone app UI, if I have the energy.

The new watch app will be SDK 2.0 only for new, as the release is just around the corner, but if another delay is announced I will try and find the time to upgrade the 1.X watch app as well. To clarify, the 1.X watchapp will still be compatible with the new version, but will not carry the additional features.

Here is a sneak peek!

pebble-screenshot_2013-12-30_16-42-52

Required Reading

Pebble SDK 2.0 Tutorial #1: Your First Watchapp

Pebble SDK 2.0 Tutorial #2: Telling the Time

Pebble SDK 2.0 Tutorial #3: Images and Fonts

Introduction

After adding custom images and fonts to our watch face, the next logical way to improve it is to add non-static elements, movement if you will. For this we have Animations! Using the Pebble SDK provided Animation structure we can schedule movements of a Layer‘s bounds whenever we want. This sort of “start here and go here” animation is called ‘tweened’ animation. The alternative kind offers greater flexibility and is achieved through the use of AppTimers.

Tweened Animation

Firstly, we will apply a simple example of a tweened animation to our tutorial watch face. Start by importing the project code from the last section into CloudPebble and giving it a new name, such as ‘SDKTut4’ for example. Be sure to change the short and long app names in the ‘Settings’ section! We are going to animate the TextLayer showing the time when the minute changes. The first step is to change the type of tick event we subscribe to to SECOND_UNIT in init():

tick_timer_service_subscribe(SECOND_UNIT, (TickHandler) tick_handler);

This will enable us to be more precise about when the time display changes, which should ideally be as close to the zero-second mark as possible. To carry out a tweened animation we create a PropertyAnimation instance and specify its duration, delay after scheduling (allowing sub-second timing) and a handler function to be called when it has finished to free up the memory we used in creating it in the first place. This process is summarized in the code segment below, which should be added before the tick_handler() function:

void on_animation_stopped(Animation *anim, bool finished, void *context)
{
	//Free the memory used by the Animation
	property_animation_destroy((PropertyAnimation*) anim);
}

void animate_layer(Layer *layer, GRect *start, GRect *finish, int duration, int delay)
{
	//Declare animation
	PropertyAnimation *anim = property_animation_create_layer_frame(layer, start, finish);

	//Set characteristics
	animation_set_duration((Animation*) anim, duration);
	animation_set_delay((Animation*) anim, delay);

	//Set stopped handler to free memory
	AnimationHandlers handlers = {
		//The reference to the stopped handler is the only one in the array
		.stopped = (AnimationStoppedHandler) on_animation_stopped
	};
	animation_set_handlers((Animation*) anim, handlers, NULL);

	//Start animation!
	animation_schedule((Animation*) anim);
}

Note: If you are compiling for the Basalt platform, you do not need to manually destroy your animation, so leave the handler out. 

You can cast a PropertyAnimation* pointer to a Animation* pointer and vice versa where needed. In addition, for simplicity the GRects describing the start and finish positions of the animated Layer are created on the heap, and then specified to the animate_layer() wrapper function as pointers using the ‘&’ operator.

Now that these new functions are in place, it is time to use them! The animation we will add will slide the time display out to the right hand side at seconds == 59 and then change the time and slide it back in from the left on seconds == 0. To do this, we simply modify our tick_handler() function to create the GRects and call the wrapper function to schedule the animations. This is shown by annotated example below:

void tick_handler(struct tm *tick_time, TimeUnits units_changed)
{
	//Format the buffer string using tick_time as the time source
	strftime(buffer, sizeof("00:00"), "%H:%M", tick_time);

	int seconds = tick_time->tm_sec;

	if(seconds == 59)
	{
		//Slide offscreen to the right
		GRect start = GRect(0, 53, 144, 168);
		GRect finish = GRect(144, 53, 144, 168);
		animate_layer(text_layer_get_layer(text_layer), &start, &finish, 300, 500);
	}

	else if(seconds == 0)
	{
		//Change the TextLayer text to show the new time!
		text_layer_set_text(text_layer, buffer);

		//Slide onscreen from the left
		GRect start = GRect(-144, 53, 144, 168);
		GRect finish = GRect(0, 53, 144, 168);
		animate_layer(text_layer_get_layer(text_layer), &start, &finish, 300, 500);
	}

	else
	{
		//Change the TextLayer text to show the new time!
		text_layer_set_text(text_layer, buffer);
	}
}

Compile this and check it works. If you are unsure about the timing, remove the if statements and have the Animation run every second (although perhaps only the first one!) and work your way up to two working in tandem.

Timers

The other main method of moving elements around is to use an AppTimer. These allow you to schedule something to happen whenever and how often you like. The paradigm is that you register some callback (another name for handler) function to run after a given delay. When that delay has elapsed, the callback function is called and performs your task. You can think of an Animation as a task executed by an AppTimer but with a very small delay. The example we are going to create is a small shape that moves back and forth above the time display as an extra aesthetic touch.

To enable a smooth animation effect, the rate at which the shape moves its position should be at least 25 frames per second. At this rate, the delay in milliseconds between AppTimer callback executions will be 1000ms / 25 frames per second = 40ms delay. The first step is to create a new TextLayer to be our shape (here, a square). Do this at the top of the C file to accompany the other pointers:

TextLayer *text_layer, *square_layer;

We are using a TextLayer for the convenience of being able to set just its bounds and background colour. Otherwise we would have go into graphics and update procedures, which are beyond the scope of this section. Also, we will need to declare the other elements of our moving cube; the AppTimer, its size, the time delta between frames and its movement direction, which will be either 1 or -1:

AppTimer *timer;
const int square_size = 10;
const int delta = 40;
int dx = 1;

Next, we define the timer callback to update the position of the square. As you will see below, there are several stages to complete each time the callback is called:

void timer_callback(void *data) {
	//Get current position
	GRect current = layer_get_frame(text_layer_get_layer(square_layer));

	//Check to see if we have hit the edges
	if(current.origin.x > 144 - square_size)
	{
		dx = -1;	//Reverse
	}
	else if(current.origin.x < 0)
	{
		dx = 1;	//Forwards
	}

	//Move the square to the next position, modifying the x value
	GRect next = GRect(current.origin.x + dx, current.origin.y, square_size, square_size);
	layer_set_frame(text_layer_get_layer(square_layer), next);

	//Register next execution
	timer = app_timer_register(delta, (AppTimerCallback) timer_callback, NULL);
}

Make sure this callback is defined before its first use, which will be in window_load() after the TextLayer itself is allocated, as shown below:

//Create the square layer
square_layer = text_layer_create(GRect(0, 55, square_size, square_size));
text_layer_set_background_color(square_layer, GColorWhite);
layer_add_child(window_get_root_layer(window), text_layer_get_layer(square_layer));

Then, at the end of the function, start the chain reaction with an initial timer registration:

//Start the square moving
timer = app_timer_register(delta, (AppTimerCallback) timer_callback, NULL);

Finally, we must add function calls to window_unload() to tear down the elements related to the moving square and free the memory used:

//Cancel timer
app_timer_cancel(timer);

//Destroy square layer
text_layer_destroy(square_layer);

Finally, recompile and test the resulting watch face, and see the results! A thing to note is that waking up the Pebble’s CPU this often will incur battery life penalties, so use timers sparingly!

Conclusions

So that’s how to use Animations and AppTimers! If you think about it, there is a way to replace the moving square’s AppTimer with a PropertyAnimation, rendering its use here void. A more robust example is my Starfield Demo, which uses such timers as the core of its operation. A link to the finished product from this section can be found HERE. Enjoy! If you have queries or comments, make them below, or Tweet me.

As with the Pebble smartwatch, I also backed another project called Spark Core, which promised the idea of a small, compact and easy to use Wi-Fi-enabled Arduino like device. And I must say, they certainly delivered!

IMG_20131223_140517

After a few initial problems programming the device from the Spark Cloud (a browser based IDE) which turned out to be mainly my fault (The device appears to rely on a rapid loop() completion to stay in contact with the Spark Cloud and I was inhibiting it with a habitual while(true) loop within that loop, preventing Cloud access) I have succeeded in my first very minor project – interfacing with an Arduino Uno.

The idea is simple: The Adruino sends the characters ‘1’, ‘2’ and ‘3’ in sequence and the Core flashes an attached LED the corresponding number of times.

The Arduino sketch:

void flash(int pin)
{
  digitalWrite(pin, HIGH);
  delay(50);
  digitalWrite(pin, LOW);
  delay(50);
}

void setup()
{
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop()
{
  Serial.print('1');
  flash(13);
  delay(1000);
  Serial.print('2');
  flash(13);
  delay(1000);
  Serial.print('3');
  flash(13);
  delay(1000);
}

And the Core code:

int output_led = D0;
int onboard_led = D7;

void flash(int pin);

void setup()
{
    Serial1.begin(9600);
    pinMode(output_led, OUTPUT);
    pinMode(onboard_led, OUTPUT);
}

void loop()
{
    if(Serial1.available() > 0)
    {
        flash(onboard_led);

        char c = (char)Serial1.read();

        switch(c) {
            case '1':
            {
                flash(output_led);
                break;
            }
            case '2':
            {
                flash(output_led);
                flash(output_led);
                break;
            }
            case '3':
            {
                flash(output_led);
                flash(output_led);
                flash(output_led);
            }
        }
    }
}

void flash(int pin)
{
    digitalWrite(pin, HIGH);
    delay(50);
    digitalWrite(pin, LOW);
    delay(50);
}

And finally a video!

Aside from taking a while to discover that the TX RX pins are actually Serial1 and not Serial, the project was simple enough to implement. The Spark Cloud IDE is easy to use and satisfyingly hands-free!

Required Reading

Pebble SDK 2.0 Tutorial #1: Your First Watchapp

Pebble SDK 2.0 Tutorial #2: Telling the Time

Introduction

So now you’ve learned how to create a watchface and spice it up a bit with a well placed InverterLayer. But it’s still pretty dull. A much better way to improve it is to use your own images and fonts. That’s what this section will focus on.

In a Pebble watch app or watchface, images and fonts are referred to in the app’s appinfo.json file, which is managed automatically for you by CloudPebble, and so will not be covered in great detail right now. Of much more importance to you now is that in the C code file, images are stored in GBitmap structures and fonts in GFont structures. Just like all the Layer types, they are created and allocated memory dynamically, with the function names syntactically very similar, so you will hopefully find yourself looking them up in the API Documentation a lot less.

Making a Better First Impression

You have probably noticed that all your favorite watchapps have their own icon in the Pebble system menu, and so the first thing we’re going to do is add one to our tutorial face we’ve been building up over the last couple of sections. Once again, create a new project over at CloudPebble and add a main.c file containing the finished code from the last tutorial section.

Next, select ‘Add new’ from the ‘Resources’ menu on the left, leave the type as PNG and browse for a file of 8-bit 2-colour PNG format with a size of 24×28 pixels. Below is one you can use for now:

menu_iconGive it an identifier, such as ‘MENU_ICON’ and click ‘Save’. Next, go to ‘Settings’ and choose the file you just added from the ‘Menu image’ dropdown menu.  Then click ‘Save changes’.

Making the Watchface More Appealing

Let’s add some more artistic direction to our watch face. At the moment, it probably looks like this:

pebble-screenshot_2013-12-22_13-59-31Not very appealing. Let’s use images to add detail to the InverterLayer. Below are two samples I created that we can use to do just that:

future past As with the menu icon, the first step is to add both images as Resources in CloudPebble and give them appropriate identifiers, such as FUTURE and PAST respectively. Next, go back to the C source file and declare two global pointers of type GBitmap and two of type BitmapLayer, like so:

GBitmap *future_bitmap, *past_bitmap;
BitmapLayer *future_layer, *past_layer;

The GBitmaps will contain the image data, and the BitmapLayers will present the images to the user as a Layer. So, in window_load(), add the appropriate function calls to create these elements. Here is how it is done. Try and understand what each line does, using your previous knowledge of the TextLayer and InverterLayer:

//Load bitmaps into GBitmap structures
//The ID you chose when uploading is prefixed with 'RESOURCE_ID_'
future_bitmap = gbitmap_create_with_resource(RESOURCE_ID_FUTURE);
past_bitmap = gbitmap_create_with_resource(RESOURCE_ID_PAST);

//Create BitmapLayers to show GBitmaps and add to Window
//Sample images are 144 x 50 pixels
future_layer = bitmap_layer_create(GRect(0, 0, 144, 50));
bitmap_layer_set_bitmap(future_layer, future_bitmap);
layer_add_child(window_get_root_layer(window), bitmap_layer_get_layer(future_layer));

past_layer = bitmap_layer_create(GRect(0, 112, 144, 50));
bitmap_layer_set_bitmap(past_layer, past_bitmap);
layer_add_child(window_get_root_layer(window), bitmap_layer_get_layer(past_layer));

Once again, we need to add the de-init code to free up the memory again:

//Destroy GBitmaps
gbitmap_destroy(future_bitmap);
gbitmap_destroy(past_bitmap);

//Destroy BitmapLayers
bitmap_layer_destroy(future_layer);
bitmap_layer_destroy(past_layer);

Are you beginning to spot patterns in how the API function calls are named? This way once you’ve worked with a new layer it is easier to guess correctly what to call for newer elements and reducing your dependence on the API documentation. Once all this has been done, your watchface should look like this:
pebble-screenshot_2013-12-22_14-43-19

Custom Fonts

Another good way to add your own influence to your watchface is to use a custom font. The procedure for doing so it almost identical to that for images, so let’s do it now.

First, again, add the font as a Resource in CloudPebble. This time set the format to ‘TrueType font’. The font you choose will need to the a ‘.ttf’ font file. Here’s a sample for you to use now. Once you have browsed for the file, give it an identifier such as IMAGINE_42. The number after the name tells the SDK what font size you want. The rest of the settings can be left alone for now, so click ‘Save’ and go back to the C file.

The process for using the font in the watchface is almost the same as that for the images. First, load the resource into a ResHandle (Handle on the Resource, so to speak) structure BEFORE the TextLayer is created (We will be using it for the time display itself):

//Load font
ResHandle font_handle = resource_get_handle(RESOURCE_ID_IMAGINE_42);

Now, modify the call to text_layer_set_font() to use our custom font and a slight layout modification to the text position by modifying the GRect to have a width of 144 pixels, like so:

text_layer = text_layer_create(GRect(0, 53, 144, 168));

...

text_layer_set_font(text_layer, fonts_load_custom_font(font_handle));

After compilation, the watchface should finally look like so:
pebble-screenshot_2013-12-22_15-00-53

Much better!

Conclusion

So there you have using custom images and fonts. If you want, add some more or change the existing ones (being careful with the dimensions in the code!) to see for yourself what small modifications can do to the look an feel.

Next time: Animations: Tweens and Timers.

The full source code the the end result of this part of the tutorial can be found on GitHub.

I’ve recently upgraded my now 3-year old Galaxy S to a Nexus 5, and one difference I noticed in the stock 4.4.2 Kit Kat Android is that instead of toggling the radios (as would happen in the pull-down menu on CM 10.1), I was taken to the actual menu and then needed to perform the toggling myself.

This meant that in order to switch from Wi-Fi to Data (HSDPA here), I would have to tap 9 times to do so (not including entering my pin code on the lockscreen). Sure, I could flash the equivalent ROM or a similar one, but it would unnecessarily void my warranty (I am otherwise perfectly happy with stock Kit Kat at the moment). Another solution? Code my own!

The result is Data Toggle for Pebble, a combination of a Pebble Watchapp and Android Receiver/Service combo that performs the actual radio toggling, via AppMessage. Using the up and down buttons on the watch, the phone is asked to toggle either the Wi-Fi or Data radio and then waits for the confirmation from the phone. The one caveat (but not a deal breaker) that arises from the Android APIs is that toggling Data while Wi-Fi is connected appears to have no effect, so it is marked as ‘N/A’ in that case.

Here is an animated screenshot:

mockup

The Android app also doubles as an installer for the watchapp’s .pbw file, as well as links to more of my content.

Download

Both components can be installed as one from Google Play:

Get it on Google Play

Source code is available on GitHub.

Enjoy!

I’ve heard about the Lua language before, but never had the experience or drive to explore it, but now that I have lots of general experience and a love of Just Cause 2, I decided to give it a go.

The result, available on GitHub, is a script for the JC2 MP server that implements player commands such as teleports, vehicle/weapon spawns and per-player home spawns. It also reads admin setting from a file as well as cause-specific death messages.

It has grown much over the last few days in collaboration with another writer, and hopefully it will become even more feature filled as I discover more about Lua.