Hello, Paul... I stumbled-onto a question you left on Stack Overflow more than a year ago, asking about a Google Music API, specifically mentioning that you'd been toying with the idea of creating a Roku channel for it. This is exactly the thing I've been starting to think about, and in asking-around, it looks like there is still nothing (apparently). I'm wondering if you've given it any further thought?

tom92024

Nope, I never went ahead with that idea. I just added it to the huge list of cool projects that I don’t have time to work on :-)


Cloud9 IDE - Develop code from your browser

Great to see more advanced applications like IDEs being moved to the cloud. This one currently only supports the Node JS/Javascript/Python stack.

I’ll be the first to sign up if they offer support for .Net. Possible business venture for someone else? Replace Visual Studio with an awesome browser based equivalentthat’s a powerful idea.



I’ve needed a clock that shows multiple time zones so I can schedule meetings with remote offices during times that overlap regular business hours. I couldn’t find anything on the market that did that, so I decided to build this product myself. This blog post shows how it was built.

Programming with .Net Gadgeteer

The software was written in C# for the .Net Micro Framework. It uses hardware that is compatible with the .Net Gadgeteer platform.

Shematic Diagram

This is the view from the designer in Visual Studio

image

Location Configuration

Each RFID card has an associated location stored on the Micro SD card. Here is an example of the configuration file stored on the card:

<configuration>
  <appSettings>
    <add key="LogLevel" value="Debug" />
    <add key="Wifi.Network" value="ssid-here" />
    <add key="Wifi.Password" value="network-password-here" />
    <add key="RFID.4D00559A66.Location" value="Portland, OR" />
    <add key="RFID.4D006CE088.Location" value="Georgia, GA" />
    <add key="RFID.4D005589A1.Location" value="Auckaland, New Zealand" />
    <add key="RFID.4D0055D211.Location" value="Bangalore, India" />
    <add key="RFID.4D0055D01C.Location" value="Tel Aviv, Israel" />
    <add key="RFID.4D00558F43.Location" value="London, UK" />
  </appSettings>
</configuration>

You’ll notice the pattern of “RFID.car id.Location”, the “card id” is what is read when you place an RFID card over a reader. This is used to get the corresponding location, like “Portland, OR” from the configuration file. The location is then used to get the current time and sun profile.

private TimeZoneInfo GetTimeZone(string cardId)
{
    string location;
    TimeZoneInfo timeZoneInfo;
    if (!locations.Contains(cardId))
    {
        var cacheKey = "RFID." + cardId + ".Location";
        location = configurationManager.GetSetting(cacheKey);
        locations.Put(cardId, location);
    }
    else
        location = (string) locations.Get(cardId);

    if (!timeZones.Contains(cardId))
    {
        var geoPoint = geoLocationService.GetLocationGeoPoint(location);
        timeZoneInfo = geoTimeZoneService.GetTimeZoneInfo(geoPoint);
        timeZones.Put(cardId, timeZoneInfo);
    }
    else
        timeZoneInfo = (TimeZoneInfo) timeZones.Get(cardId);

    return timeZoneInfo;
}

The current time is displayed on the LED matrix modules. The sun profile is used to display “sunny hours” with blue dots.

Green dots are used to show “standard work hours” (8am to 5pm / Mon-Fri). This is helpful when arranging ad hock meetings with various locations because it gives a quick indicator when there will be overlap during standard business hours. 

The main part of the program

private void ProgramStarted()
{
    configurationManager = new XmlConfigurationManager(sdCard);
    logger = new DebugLogger(configurationManager);
    networkManager = new WifiNetworkManager(wifi, configurationManager, logger);
    timeManager = new NativeTimeManager(configurationManager, logger);
    geoLocationService = new GoogleGeoLocationService(logger);
    geoTimeZoneService = new EarthToolsGeoTimeZoneService(logger);
    bitmapProvider = new DoubleNumberBitmapProvider();

    RFID1.DebugPrintEnabled = true;
    RFID2.DebugPrintEnabled = true;
    RFID3.DebugPrintEnabled = true;

    RFID1.CardIDReceived += (sender, id) =>
                                {
                                    if (timeZoneId1 == id) return;
                                    timeZoneId1 = id;
                                    multipleTimeZoneDisplay.UpdateTimeZoneForRow(0, GetTimeZone(id));
                                };
    RFID2.CardIDReceived += (sender, id) =>
                                {
                                    if (timeZoneId2 == id) return;
                                    timeZoneId2 = id;
                                    multipleTimeZoneDisplay.UpdateTimeZoneForRow(1, GetTimeZone(id));
                                };
    RFID3.CardIDReceived += (sender, id) =>
                                {
                                    if (timeZoneId3 == id) return;
                                    timeZoneId3 = id;
                                    multipleTimeZoneDisplay.UpdateTimeZoneForRow(2, GetTimeZone(id));
                                };

    networkManager.Connected += (sender, args) =>
                                    {
                                        timeManager.ApplySettings();
                                        timeManager.StartTimeService();
                                    };
    timeManager.TimeServiceStarted += OnTimeServiceStarted;

    timeManager.MinuteChanged += (sender, args) => multipleTimeZoneDisplay.WriteCurrentTime();

    networkManager.Connect();
}

As you can see in the above code each RFID card can raise an event “CardIDReceived”, which is programmed to update the display for the specific row it’s on.

There are several “managers” that abstract the details of things, like a geoTimeZoneService that integrates with Earth Tools to get the current offset (daylight time) and sunrise/sunset hours. Another geoLocationService that integrates with Google to get latitude and longitude for a given location. The timeManager synchronizes time with a time server. Finally, the wifiNetworkManager is used to establish a internet connection with a local Wifi network.

Parts / Costs

The whole thing has about $500 worth of electronics, and about $75 worth of wood. Here is the invoice of some key parts I bought from GHI Electronics:

  • FEZ Spider Mainboard (1 @ $119.95) $119.95
  • Gadgeteer Standoff Pack (3 @ $1.95) $5.85
  • Extender Module (1 @ $4.95) $4.95
  • 5x Breakout Module Set (1 @ $4.99) $4.99
  • USB Client DP Module (1 @ $24.95) $24.95
  • RFID Reader Module (3 @ $24.95) $74.85
  • SD Card Module (1 @ $6.95) $6.95
  • LED Matrix Module (DaisyLink) (6 @ $19.95) $119.70
  • WiFi RS21 Module (1 @ $79.95) $79.95

From Amazon.com, you can find the RGB LED strips:


Twitter Box Unveiled at Portland Maker Faire


Nothing tends to materialize man, and to deprive his work of the faintest trace of mind, more than extreme division of labour.


GCM is Google’s new cloud messaging system, that is replacing C2DM.

Here is the bare bones, quick tutorial on how to get notifications working.

Register Application with Google

First go to Google’s API console. Setup a new project for your application.

Enable “Google Cloud Messaging for Android” service.

Click the “API Access” link and grab the API Key for later use.

Write the Client Side Code

In your AndroidManifest.xml you’ll need setup your configuration like this:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="fiserv.mobile.poc"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="15" />    
    <permission android:name="fiserv.mobile.poc.permission.C2D_MESSAGE" 
        android:protectionLevel="signature"/>    
    <uses-permission android:name="fiserv.mobile.poc.permission.C2D_MESSAGE" />     
    <!-- App receives GCM messages. -->
	<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
	<!-- GCM connects to Google Services. -->
	<uses-permission android:name="android.permission.INTERNET" /> 
	<!-- GCM requires a Google account. -->
	<uses-permission android:name="android.permission.GET_ACCOUNTS" />
	<!-- Keeps the processor from sleeping when a message is received. -->
	<uses-permission android:name="android.permission.WAKE_LOCK" />  
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>                
        <receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" 
            android:permission="com.google.android.c2dm.permission.SEND" >
		  <intent-filter>
		    <action android:name="com.google.android.c2dm.intent.RECEIVE" />
		    <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
		    <category android:name="fiserv.mobile.poc" />
		  </intent-filter>
		</receiver>		
		<service android:name=".GCMIntentService" />
    </application>
</manifest>

Now develop an Intent Service, this is a service that will handle all aspects of communication with GCM. Just extend GCMBaseIntentService Here is why your Intent Service should look like:

 
package fiserv.mobile.poc;

import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.google.android.gcm.GCMBaseIntentService;

public class GCMIntentService extends GCMBaseIntentService {

	@Override
	protected void onError(Context arg0, String arg1) {
		Log.e("Registration", "Got an error!");
		Log.e("Registration", arg0.toString() + arg1.toString());
	}

	@Override
	protected void onMessage(Context arg0, Intent arg1) {
		Log.i("Registration", "Got a message!");
		Log.i("Registration", arg0.toString() + " " + arg1.toString());
		// Note: this is where you would handle the message and do something in your app.		
	}

	@Override
	protected void onRegistered(Context arg0, String arg1) {
		Log.i("Registration", "Just registered!");
		Log.i("Registration", arg0.toString() + arg1.toString());	
		// This is where you need to call your server to record the device toekn and registration id.
	}

	@Override
	protected void onUnregistered(Context arg0, String arg1) {
	}
}

Finally in your Main Activity’s onCreate operation, call a method that looks like this:

    private void RegisterWithGCM()
    {    	 	
    	GCMRegistrar.checkDevice(this);
    	GCMRegistrar.checkManifest(this);
    	final String regId = GCMRegistrar.getRegistrationId(this);
    	if (regId.equals("")) {
    	  GCMRegistrar.register(this, SENDER_ID); // Note: get the sender id from configuration.
    	} else {
    		
    	  Log.v("Registration", "Already registered, regId: " + regId);
    	}
    }

Notice the SENDER_ID needs to come from configuration. You can get this value from the Google API Console. Just grab it off the end of your project URL.

Now fire up your app, it should register with GCM and print out your registration ID. You’ll want to copy that ID so you can send a test notification to your device.

You’ll want to record this registration id with your server, so you can start sending notifications from your server.

Send Notifications from Server

Here is a C# / .Net server example for sending notifications to GCM:

                using (var wc = new WebClient())
                {
                    wc.Headers.Add("Authorization", "key=" + serviceKey);
                    var nameValues = new NameValueCollection
                                         {
                                             {"registration_id", registrationId},
                                             {"collapse_key", Guid.NewGuid().ToString()},
                                             {"data.payload", HttpUtility.UrlEncode(message)}
                                         };
                    var resp = wc.UploadValues("https://android.googleapis.com/gcm/send", nameValues);
                    var respMessage = Encoding.Default.GetString(resp);
                    loggingServiceClient.Debug("Got respose from GCM: " + respMessage);
                }

This is just a simple example to show exactly how you send the message, I recommend using a framework like PushSharp when you implement this for real.

Notice the “serviceKey” variable in this example should be the value you got from Google API Console.

Once you send your message you should see log statements in your Android console or hit a breakpoint in your onMessage method of your Intent Service.

Note: make sure you are logged in with a Google account on you device, since that’s a requirement for GCM to work.


Daylight saving time was invented by George Vernon Hudson in New Zealand. Its intention is to save money by reducing the costs of keeping lights on at night. Today, its main purpose is to make software programmers’ lives hard.


Semantic Versioning

Quick reminder on how API versioning should work and what the numbers mean.

Consider a version format of X.Y.Z (Major.Minor.Patch)

  • Bug fixes not affecting the API increment the patch version.
  • Backwards compatible API additions/changes increment the minor version.
  • Backwards incompatible API changes increment the major version.

GIGX Options Chart

GIGX Options Chart


A great introduction to Mobile Push over the most common networks (Apple, Android, Windows, Blackberry) by Mike Willbanks.