MQTT Inside Sticker Engine

For a bit of fun round a project last year I created some Moo “MQTT Inside” stickers to put on the cases.

First sticker deployed

These became very popular around the office, with everybody wanting to label up their MQTT enabled projects and the first batch of 90 quickly disappeared.

Given demand was so high Andy Piper suggested it might be worth making it possible for others to order their own sets and pointed me at the Moo API.

The Moo API Doc is pretty good, but there aren’t any examples so it took a bit of trial and error. The API works by building up an object called a ‘pack‘. The Moo website uses the same API for the wizard you use to manually create any of their products and there is a very nice little Greasemonkey script called ‘Show API JSON’ which shows you the state of the pack object at each step. The API also lets you skip any steps in the process by just uploading a pack object already filled in. This meant I could reproduce the stickers by choosing to edit my original set and then using the script to save the pack.json file.

{
    "productVersion" : "1",
    "cards" : [
    ],
    "numCards" : 90,
    "extras" : [
        {
            "value" : "blue",
            "key" : "pack_colour"
        }
    ],
    "imageBasket" : {
        "name" : null,
        "immutable" : false,
        "items" : [
            {
                "cacheId" : "partner_interface_uploader:e34bb9c2-637b-558545db-4e61502d-ff34.png",
                "imageBox" : null,
                "imageItems" : [
                    {
                        "rotation" : 0,
                        "height" : 297,
                        "resourceUri" : "http://www.moo.com/is/o/e34bb9c2-637b-558545db-4e61502d-ff34.png",
                        "width" : 297,
                        "type" : "print"
                    },
                    {
                        "rotation" : 0,
                        "height" : 1024,
                        "resourceUri" : "http://www.moo.com/is/r/1024/e34bb9c2-637b-558545db-4e61502d-ff34.png",
                        "width" : 1024,
                        "type" : "preview"
                    },
                    {
                        "rotation" : 0,
                        "height" : 75,
                        "resourceUri" : "http://www.moo.com/is/t/75/e34bb9c2-637b-558545db-4e61502d-ff34.png",
                        "width" : 75,
                        "type" : "thumbnail"
                    }
                ],
                "copyrightOwner" : null,
                "resourceUri" : "filestore://image_original/e34bb9c2-637b-558545db-4e61502d-ff34.png",
                "croppable" : true,
                "shouldEnhance" : false,
                "type" : "front",
                "removable" : true
            }
        ],
        "type" : null
    },
    "productCode" : "sticker",
    "sides" : [
        {
            "type" : "image",
            "data" : [
                {
                    "imageStoreFileId" : "e34bb9c2-637b-558545db-4e61502d-ff34",
                    "resourceUri" : "filestore://image_original/e34bb9c2-637b-558545db-4e61502d-ff34.png",
                    "linkId" : "variable_image_front",
                    "enhance" : false,
                    "imageBox" : {
                        "center" : {
                            "y" : 12,
                            "x" : 12
                        },
                        "height" : 20.88,
                        "width" : 20.88,
                        "angle" : 0
                    },
                    "type" : "imageData"
                }
            ],
            "templateCode" : "sticker_image",
            "sideNum" : 1
        }
    ]
}

Resubmitting this with the ‘moo.pack.createPack‘ method and then using the ‘finish’ Drop in point to direct the user to Moo checkout page to pay for their new stickers.

I used a little library called scrib to do the oAuth and the whole thing can be done with just these few lines:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	String authTokenString = request.getParameter("oauth_token");
	String authVerifyString = request.getParameter("oauth_verifier");

	Token authToken = MemoryStore.data.get(authTokenString);
	MemoryStore.data.remove(authTokenString);

	Verifier verifier = new Verifier(authVerifyString);
	Token accessToken = service.getAccessToken(authToken, verifier);

	String createPack = rootURL + "method=moo.pack.createPack&product=sticker&pack=" + pack;
	createPack = createPack + "&friendlyName=" + URLEncoder.encode("MQTT Inside", "UTF-8");

	OAuthRequest oAuthRequest = new OAuthRequest(Verb.POST, createPack);

	service.signRequest(accessToken, oAuthRequest);
	Response oAuthResponse = oAuthRequest.send();
	if (oAuthResponse.getCode() == 200) {
		System.err.println(oAuthResponse.getBody());
		JSONTokener tok = new JSONTokener(oAuthResponse.getBody());
		try {
			JSONObject json = new JSONObject(tok);
			JSONObject dropings = json.getJSONObject("dropIns");
			String finishURL = dropings.getString("finish");
			response.sendRedirect(finishURL);
		} catch (JSONException e) {
			e.printStackTrace();
		}
	} else {
		System.err.println(oAuthResponse.getBody());
	}
}

Andy is working to get a page set up on the mqtt.org site, but in the mean time you can click on the image bellow to order own set.

EDIT:

Andy has now added a Goodies page to the mqtt.org site that you can use to order stickers


Tracks2Miles 1.1.14

Finally got round to spending some more time on Tracks2Miles.

This release is an attempt to make use of a lot of what is left of the API.

New features:

  1. New Workout types:
    • - Commute
    • - Spinning
    • - Rowing
    • - Cross Training
  2. Support for multi-media posts, Uploaded Images and links to Youtube and Vimeo are now shown in your timeline
  3. Like your friends workouts
  4. See when you get Motivational comments
  5. Added pull to refresh support to the timeline
  6. Slightly improved look and feel, the white background looks better

All that plus a couple of bugs I spotted along the way.

There is a new introduction video with a walk through of all the features

YouTube Preview Image

As always you can get the very latest version from the Android Market here: https://market.android.com/details?id=uk.me.hardill.dailymile

The next version should have better support for tablets and ICS devices that support Activity Fragments to make better use of large screens. I’ve also managed to arrange to borrow a Sony Ericsson X10 mini to see about trying to improve the UI for those of you with really small screen devices.


Timelapse photography

As I mentioned at the end of my last post I have been playing around with gphoto2 to create some time lapse videos of the assembly of one of my Christmas gifts.

I have played with making time lapse video before, when I set up my MMS CCTV system with motion I enabled a feature that creates a video from a sample image every 30 seconds. Motion uses the web cam (or other Video4Linux src) and all the web cams I had access to up at my folks are pretty low resolution so this wasn’t what I was looking for.

I did have my Canon 350D and the little point and shoot Canon A520 that lives on the end of my work bag so I thought I’d see what I could do with them. The 350D is 8 Megapixel and the A520 is 4 Megapixel so both will take a frame way bigger than 720p that I can crop down.

I had a bit of a look round and found an app called gphoto2 that claimed to be able to drive both cameras via the USB port to take images at a set interval. I plugged the 350D in and tried to get it to work but I kept getting the following error*:

*** Error ***
Sorry, your camera does not support generic capture
ERROR: Could not capture.
*** Error (-6: 'Unsupported operation') ***

So I swapped over to the A520 and things seamed to work fine. So I set it up on the tripod and fired off the following command:

[hardillb@bagend ~]$ gphoto2 --capture-image -I 120

This triggers the camera every 2 mins which I thought should be enough time to see some progress in each frame.

Apart from having to swap the batteries twice it all went rather well, I soon started to ignore the little beep from the camera as it took each shot. At the end I copied all the images off the SD card for processing. Each image started out at 2272×1704 so they would have been big enough to use in 1080p video but I decided to shrink them down to 720p.

The following little ImageMagik script resizes the images down and adds 2 black bars down the sides to pad it out to a full 16:9 720p frame size.

#!/bin/sh
for x in `ls *.JPG`
do
   convert $x -resize 1280x720 -bordercolor black -border 160x0 resized/$x
done

The first bit -resize 1280×720 resized the original image down to 720 pixels high and the second bit -bordercolor black -border 160×0 adds on the 2 x 160 pixel wide black bars to pad the image up to the required 1280 pixels wide before writing a copy out to the resized directory.

And this mencoder line to stitch them together as a video with 2 frame per second so each second of video is equivalent to about 4 minutes of real time.

mencoder "mf://*.JPG" -mf fps=2 -o day1.avi -ovc lavc -lavcopts \\
vcodec=msmpeg4v2:vbitrate=800

Here is a sample of the output

YouTube Preview Image

*I have since found this gphoto bug report that mentioned changing the camera’s USB mode from PTP mode to normal mode. After finding this setting on the camera I managed to get the 350D to work with gphoto2 as well.


Christmas Project

I’ve always been a fan of Lego*, Technic especially. As a kid I was lucky enough to get hold of a few different sets to build, some of them can still be found in my old room at home.

On Christmas morning I was lucky enough to unwrap one of these.

The kits have been getting more and more complex over the years this one comes with 4 volumes of assembly instructions

And enough parts to set up a shop.

So come Boxing day I set about putting it all together.

4 Hours on Day 1 and I managed to get through the first 2 sets of instructions
YouTube Preview Image

Day 2 finishing off
YouTube Preview Image

It was great fun putting it all together and seeing how the tech has moved on. The gear box in the middle of this model that makes it all work is amazing, with just one motor it drives the stabilizers and the crane jib arm.

The videos were made using gphoto2 hooked up to my old Canon Powershot A520 (I couldn’t get it to work with my 350D) to take a picture every 2mins. The images were then resized down to 720p and black bars added before being stitched together with mencoder. I’ll try and remember to do a post about the details later

* Yes that’s right Lego, not ‘Legos’ my American friends, it’s a trade mark and the singular is a Lego Brick. While we’re on the subject it’s Maths, not Math….


Final Gingerbread House 2011

As mentioned in my last post it’s that time of year again so it’s time. So here is this years creation.

This years gingerbread house

The key point learnt this year is how to make extra strength icing by using egg whites and icing sugar.


Gingerbread Architecture

Last years Gingerbread Christmas Tree was OK, but not up to the standard of the previous efforts. This led me to have a bit of a look round and I spotted this book – The Gingerbread Architect

I started out just getting my eye in with a little Gingerbread Cottage this weekend.

Gingerbread Cottage

I’ll stick an update online once this years proper edifice is complete.


Tracks2Miles 1.1.10

Just a quick update while I’m still working on a 2.x release*.

This release has 2 updates:

  1. A small update to the import code to make use of the patch I managed to get included in the latest (1.1.11) release of My Tracks
  2. A new setting in the preferences to block uploading GPX data with a workout imported from My Tracks. This was a feature requested to help people with privacy concerns

You can download Tracks2Miles here: https://market.android.com/details?id=uk.me.hardill.dailymile

* The plan is for 2.x to have a updated UI making use of fragments for tablet and ICS devices.


New My Tracks Patch

After my last My Tracks patch had to be pulled (to be honest it did break sharing routes by anything other than Tracks2Miles) a new (safe) patch was accepted a few days ago.

This patch passes just the My Tracks track id along with the URL for the exported file in the SHARE intent. The key for the extra reuses the same key that is used by the My Tracks library when sending Broadcasts on starting and stopping recording a new track. The track id can be recovered from the intent with the following code:

long track_id =
    intent.getLongExtra(getString(R.string.track_id_broadcast_extra), -1);

Once you have the track id then looking up all the details of that track using the My Tracks Library project is trivial (Once you got the user to allow 3rd party apps access).

MyTracksProviderUtils utils =
    new MyTracksProviderUtilsImpl(this.getContentResolver());
Track track = utils.getTrack(track_id);
TripStatistics stats = track.getStatistics();
double totalDistance = stats.getTotalDistance();
long movingTime = stats.getMovingTime();
String cat = track.getCategory();
String desc = track.getDescription();
long lastLocId = utils.getLastLocationId(track_id);
Location loc = utils.getLocation(lastLocId);

The latest version of Tracks2TitanXT has already been updated to use this method and Tracks2Miles will get an update for this as well as some better tablet support before the next version of My Tracks ships.


Tracks2Miles 1.1.9 release

So the My Tracks guys released version 1.1.10 last week. This normally would be a good thing as they have been adding lots of nice new features and generally improving things.

Unfortunately in this release they also included a feature that stops 3rd party apps using their database without the user having to go into the their settings and allowing it.

I don’t agree with what the change is looking to achieve, My Tracks already has a set of Permissions that need to be requested by an application before it can access the data. If the user does not want to grant access then they should not install the 3rd party apps. I know nobody really reads closely the list of Permissions apps ask for at install time, but this is a problem for the Market application to solve by better high lighting the Permissions being asked for and explaining the consequences of accepting them.

On top of that there is no easy way to check if the “Allow access” option is set before you try and access the data. I will be raising a issue about this shortly as well as submitting another change to mean that I don’t have to try and guess the name of the track being exported.

It also would have been nice to get more than a couple of hours notice that the this new “feature” was about to ship. While I know it has been discussed on the site, I have a not been following the updates recently because the day job has been particularly busy. It would have at least been courteous to send the email that notified the owners of those with apps about the change a little sooner. So we had time to make the required changes rather than just get a whole slew of bug reports.

Anyway that’s the bitching out of the way. There is now a new version of Tracks2Miles that will show a dialog box if it can not access the data and return you to My Tracks to enable the access to the data.

You can grad the latest version from the Market here


New Eightbar post

I’ve just pushed a new post to Eightbar about a little work project using MQTT and Arduinos to control a video wall I’ve just finished. Check it out here


  • Twitter

    • @alfa yeah forms, not my anything I would do for fun on a Sunday night 19 hours ago
    • @alfa I need to go back to 2006, it's getting hard, as long as they signed off my expenses I didn't pay that much attention ;-) 19 hours ago
    • @alfa If only I could get away with that. Don't suppose you remember when Andy got the 2nd line job? 19 hours ago
    • Trying to remember all my previous managers names 19 hours ago
    • Really enjoying tonights The Last Explorers on BBC 2 at the moment. So many cool memories of Yosemite. http://t.co/4gtkJup6 20 hours ago
  • Copyright © 1996-2010 Ben's Place. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress

    Switch to our mobile site