|
NetKernel News Volume 2 Issue 39
July 29th 2011
What's new this week?
- Repository Updates
- The Curious Tale of the QRCode Clock
- Barcode Library
- The QRCode Clock Demo
- Why You Get What You Ask For
Catch up on last week's news here
Repository Updates
The following update is available in the NKEE repository...
- nkee-apposite 1.26.1
- Fixes over aggressive synchronization optimization to ensure all sets are checked for updates.
- image-barcode1.1.1
- NEW A new barcode processing library. See below
The Curious Tale of the QRCode Clock
This is the story of the QRCode clock. The barcode image on the left is a real live clock. It is showing the current time and date. It rotates through 360 degrees every hour. Ladies and Gentlemen - this is the world's first (and let us hope last) QRCode clock.
If you have an Android or iPhone you might already have a barcode scanner application. You'll find this QRCode tag is encoding the current date/time in the format... Fri, 29 Jul 2011 08:15 BST
The rise of the barcode as "smart" label is just beginning. Point your camera phone at a barcode and the scanner reader will extract the encoded information and usually make a good guess at what application could make use of it. For example, a URL encoded in a barcode will launch your browser, an ISBN barcode might do a lookup on the book title etc.
Barcodes come in many standard forms. But the 2D barcode, most commonly seen in the QRCode (recognisable by its three square alignment markers on the corners), is now able to encode a surprisingly rich amount of data.
You can put anything you like as a text message in the encoded image. However NTT Docomo has created a defacto standard QRcode markup which is widely supported in client readers.
So how did this stupid clock come into existance...
Wind back the clock
Earlier in the week I had the need to do some "real representative development" with NetKernel as a way to sanity check and test a bunch of new updates we have in progress. (I won't steal Tony's thunder - but we have some cool and pretty amazing things coming together which we want to release as a coherent set, probably at the backend of the summer).
So I had a need to use NetKernel for some representative development.
By coincidence I've also just moved into the 21st century and got one of those miniature personal computers you see people carrying these days. Apparently it runs the Linux operating system - in fact it runs it a lot better than my first ever Linux box did back in 1998. It also, to my surprise comes with a GSM/WCDMA cellphone chipset, a 800x480 colour display, camera, etc etc.
OK its an Android phone. But its significant in one respect. It is an extremely cheap, bottom of the range entry-level Android phone. (Actually a ZTE Blade).
Having a history in the mobile PC space back in the last millenia, I have quite atypical expectations of cellphones. My last cellphone, a Nokia 6500 is a case in point. I actually found it about 5 years ago buried in a snow drift - someone must have lost it weeks earlier. It was soaked and didn't work. I accepted this as a challenge - so I dried it out, took it apart, cleaned it up, bought some replacement parts off ebay for pennies and got it going. Its been my daily phone ever since.
However I am not unaware of the trend for youngsters to want to connect with the internet whilst away from the mainframe. I'd resisted the early adopter generation-1,2 phones because there was too much churn going on. But more importantly I wanted a computer that I could own and do what I wanted with. Also I wanted to be able to "take it apart" without worrying about screwing it up. In short I was prepared to wait in order to get a commodity item.
So, armed with a ZTE Blade locked to the UK's Orange network for about a hundred quid. I got home, threw away the bundled SIM, downloaded a custom linux image, unlocked it, rooted it and installed a clean vanilla Android 2.3 (Gingerbread) image. I had another Linux box to play with...
Nerds paradise
So the first question that comes to mind. Can I run NetKernel on this? ARM 6 core, 600MHz, 512MB RAM. Hell yes.
As we demoed at the conference in April, NK runs sweetly on a plug-computer - which is a much lesser machine (ARM 5 core, 512MB RAM) - it surely will run on a basic Android linux image.
So then we go looking for Java. Hmmmm not so good. Open a shell and type "java -version" and nothing doing. Android apps are written in Java but they execute on the custom Android stack. Not a standard J2SE. That's a pain.
Conclusion, it would be very simple to run the NK kernel as an embedded component on that stack. The NetKernel ROC application server is a dynamic and completely hot-swapable modular architecture and requires the full flexibility of the standard Java classloading architecture - I haven't had chance to investigate what level of dynamic classloading the Android pseudo-Java supports - will leave that for a rainy day.
But to use NK out of the box without fiddling around would just require a standard J2SE implementation. Maybe the Arm 5 JVM we used in the plug-demo will work? Maybe I'll have to talk nicely to these guys at Apogee who have a full J2SE for Android? Anyone know of any other source of a J2SE on the ARM6?
OK, for now, I'm satisified that I know enough about this that getting NK up on it will be pretty trivial. What next. Well its a toy so better play with it...
Barcode Reader
One of the toys I installed was a barcode reader app. There's a growing trend to provide QRCode tags with embedded URLs - even, somewhat bizarrely in web pages as links. Either way, its kind-of-fun to suddenly be able to view a barcode's physical foot-print as just a gateway into cyberspace. All very Daemon-like (Daniel Suarez understood this before the rest of us).
But reading them is no fun. To really be in control you need to be able to create these tags and plaster the world with them. Aha! I'd found, my "real development" exercise to test the NK updates.
An hour later I'd...
- reviewed the possiblities for an open source barcode library and decided that ZXing looked a likely candidate - its actually meant as an android app, but it has the necessary libraries I was really interested in.
- Downloaded and built and got copies of the core J2SE libraries.
- Created a NK module with a multi-format barcode scanner accessor, *and* my real plaything, a QRCode generator.
- By using the ImageAspect representation model, automatically integerated with the existing NK image pipeline processing libraries.
- Had working unit tests and an nCoDE example roundtrip processs that generates the "Hello World" QR Code, rotates it by 33 degrees, decodes the rotated image back to "Hello World"...
But more importantly, the updates to NK were looking good (more of which at a later date)...
Barcode Library
We've shipped a polished and documented version as the image-barcode package available in the multiverse Apposite repository. Being in multiverse means this is unsupported code which is available for access at your own risk.
However, its pretty simple stuff, so I don't anticipate any problems. The only unknown is the thread-safety and memory leak quality of the ZXing library - although I'm pretty optimistic since looking at the source the development team are doing sensible things like using immutable objects that clone on update etc. However take care, Java image processing is somewhat notorious so it will need to be monitored til we've got some experience with it.
After installing you can get the docs here...
http://localhost:1060/book/view/book:util:image:barcode:book/
Or a static online copy is available here...
http://docs.netkernel.org/book/view/book:util:image:barcode:book/
The QRCode Clock Demo
Which brings me to the QRCode Clock demo embedded above. When generating a QRCode is so easy and pipelining it with other image processing tools is too, the obvious thing to do is to create a stupid clock.
Actually this is joke on a joke. In British culture there's a very famous Goon show sketch called What time is it, Eccles?. The Goon show was on the radio in the 1950s and is the godfather of comedy to Monty Python etc. Here's the start of the sketch...
Bluebottle What time is it Eccles? Eccles Err, just a minute. I, I've got it written down 'ere on a piece of paper. A nice man wrote the time down for me this morning. Bluebottle Ooooh, then why do you carry it around with you Eccles? Eccles Well, umm, if a anybody asks me the ti-ime, I ca-can show it to dem. Bluebottle Wait a minute Eccles, my good man... Eccles What is it fellow? Bluebottle It's writted on this bit of paper, what is eight o'clock, is writted.
So the QRCode Clock is a joke - What time is it? Its writted down in this QRCode, is writted.
It took a couple of minutes to "writ this demo". Heres' the source...
import org.netkernel.layer0.representation.* import org.netkernel.layer0.representation.impl.* import java.text.* c=Calendar.getInstance() sdf=new SimpleDateFormat("EEE, d MMM yyyy HH:mm z") message=sdf.format(c.getTime(), new StringBuffer(), new FieldPosition(0)).toString() angle=(new Float(360*(c.get(Calendar.MINUTE)/60.0))).intValue().toString() req1=context.createRequest("active:barcodeQRCode") req1.addArgumentByValue("operand",message) req=context.createRequest("active:imageRotate") req.addArgumentByRequest("operand", req1) b=new HDSBuilder() b.pushNode("transform") b.pushNode("angle", angle) req.addArgumentByValue("operator", b.getRoot()) req.setRepresentationClass(IReadableBinaryStreamRepresentation.class) r=context.issueRequestForResponse(req) response=context.createResponseFrom(r) response.setExpiry( response.EXPIRY_MIN_CONSTANT_DEPENDENT, System.currentTimeMillis()+60000 //Cache for 1 minute )
For what its worth (maybe as a test for your phone's barcode reader), the demo is permanently linked here...
http://www.netkernel.org/demo/The_NetKernel_QRCode_Clock
If you're curious here's a jar with the module in it...
http://resources.1060research.com/packages/2011/07/urn.org.netkernel.demo.qrcode.clock-1.1.1.jar
Let us know if the library is any use for you and, of course, please ping us if you get anything weird going on with it.
Why You Get What You Ask For
Earlier in the week I got the following note from Arun Batchu at BestBuy.com...
Peter,
In the XRL2 documentation, I see a gap that can be filled:
<identifier>active:xrl2+template@res:/resources/test.html+mimetype@text/html+sku@[[arg:sku]]</identifier>
</request>
is equivalent to:
<identifier>active:xrl2</identifier>
<argument name="template">res:/resources/test.html</argument>
<argument name="mimetype">text/html</argument>
<argument name="sku">[[arg:sku]]</argument>
</request>
But the documentation does not say that. Or , did I miss it? Anyway, the Active URL format expresses succinctly. Like it.
Which to summarize, is that Arun has rediscovered the ancient art of hand-crafting active URIs. For those that didn't grow up with us on NK1,NK2 and NK3, but came straight in at NK4 then this skill may be new to you.
In the good old days you wrote your active URIs for every request "by hand". So for example you might have made a request for a hand crafted identifier such as this...
active:xslt+operand@foo+operator@bar
In NK4 we've added some bells and whistles. Both the NetKernel Foundation API and the Declarative Request provide safe and simple automated request construction mechanisms.
So for example these are all exactly equivalent...
Raw Hand-Crafted
active:barcodeQRCode+operand@res:/mymessage/resource
NKF
req=context.createRequest("active:barcodeQRCode") req.addArgument("operand","res:/mymessage/resource")
Declarative Request
<identifier>active:barcodeQRCode</identifier>
<argument name="operand">res:/mymessage/resource</argument>
</request>
Hand Crafted and NKF
req=context.createRequest("active:barcodeQRCode+operand@res:/mymessage/resource")
Hand Crafted and Declarative Request
<identifier>active:barcodeQRCode+operand@res:/mymessage/resource</identifier>
</request>
And the reason why these are all equivalent is very simple. Ultimately every request gets issued to the kernel and the kernel has absolutely no idea what an identifier is. To the ROC abstraction it is purely and simply an opaque token. It makes no difference how the identifier is constructed. A token identifies the resource and that's what you get - every single time.
In which case, what's so special about the NKF and Declarative Request in NK4?
Well since the kernel doesn't know what an identifier is then its important that you (the application level) do. Since the kernel will get you what you ask for.
Now consider the barcode generator with the size argument added...
active:barcodeQRCode+operand@res:/mymessage/resource+size@res:/mysize/resource
This generates a barcode for your message at some specified size. Like all resources, its cacheable under this opaque token.
So then, what about this...
active:barcodeQRCode+size@res:/mysize/resource+operand@res:/mymessage/resource
Same resource right? Resolves to the same endpoint, generates the same image.
Correct. But not to the kernel.
Notice that we switched the order of the arguments. This is a different opaque token. So if we have two parts of our application use different orders for the arguments then we'll have two independent cached representations for what we, in the application domain, know is the same resource.
Its kind of obvious if you think about the kernel's ROC abstraction and the nature of an opaque identifier token. But clearly in an active URI (any URI) argument order is significant.
OK so now I can explain how NK4 helps out. Whenever you construct an identifier with the NKF or declarative request APIs then it will always normalize the opaque request token (a fancy way of saying we sort the argument order).
So for example these ...
NKF
req=context.createRequest("active:barcodeQRCode") req.addArgument("operand","res:/mymessage/resource") req.addArgument("size","res:/mysize/resource")
Declarative Request
<identifier>active:barcodeQRCode</identifier>
<argument name="size">res:/mysize/resource</argument>
<argument name="operand">res:/mymessage/resource</argument>
</request>
Will both request this raw identifier token...
active:barcodeQRCode+operand@res:/mymessage/resource+size@res:/mysize/resource
There's no ambiguity. You'll both hit the same cache representation if its already been reified.
So whilst you (and Arun) are very welcome to use the convenience of hand-crafted syntax - its worth keeping in mind that when you do you are taking full responsibility. And, you'll get what you ask for.
The Grammar Converse
Of course this also holds true for endpoint grammars. You only invoke one if its grammar matches your opaque token.
But we also do something to help here too.
When you use the active grammar syntax it automatically compiles a standard grammar with interleaves for the argument parts of the identifier token. So a standard grammar does the converse of the request construction - it creates a denormalized pattern matching grammar that will match arguments in arbitrary order! So that's why all of the examples above will work with one single grammar.
Belgium Bootcamp
Keep your diaries open for October in Brussels. This will definitely happen. We need to fix a date and sort out logistics but be ready for a ROC Fall (Autumn geddit?) in Brussels. But hey its the summer and everyone's at the beach. Enjoy.
Have a great weekend,
Comments
Please feel free to comment on the NetKernel Forum
Follow on Twitter:
@pjr1060 for day-to-day NK/ROC updates
@netkernel for announcements
@tab1060 for the hard-core stuff
To subscribe for news and alerts
Join the NetKernel Portal to get news, announcements and extra features.