Writing about technology, traveling, politics and more

Tuesday, December 07, 2010

Conversion utilities in Java

Since the beginning of 2010, I have been involved in AsTeRICS. This is an EU-funded project aiming to provide a software construction toolset for allowing prototyping of Assistive Technology (AT) applications. These applications should be adapted to the motor abilities of end-users.

My involvement in the project varies as a result of my main workload, which this semester includes teaching an introductory computer science course, and a postgraduate course in software engineering. Lately, a request was placed for a clear way for converting a primitive type (or string) in Java to a byte array, and back. This is required to enable a custom protocol that will allow the configuration and test module to connect remotely to the AsTeRICS middleware.

I had done something similar before, but only for integer primitive data types. After searching the web for an answer, I realized that there are some methods available but none is clear enough. I quickly realized that this functionality is "almost" built-in Java via the java.nio.ByteBuffer class. This class allows for converting primitive types such as short, int, and long to byte arrays. Scalar data types such as float and double can also be converted to byte arrays through an intermediate conversion to int and long respectively.

The resulting code is posted here, and is available for download as a Java class named ConversionUtils.
import java.nio.ByteBuffer;

public class ConversionUtils
{
    public static final byte FALSE_BITS = 0x00;
    public static final byte TRUE_BITS = 0x01;

    static public boolean booleanFromByte(final byte bits)
    {
        return bits != FALSE_BITS;
    }

    static public byte booleanToByte(final boolean b)
    {
        return b ? TRUE_BITS : FALSE_BITS;
    }

    static public short shortFromBytes(final byte [] bytes)
    {
        return ByteBuffer.wrap(bytes).getShort();
    }

    static public byte [] shortToBytes(final short s)
    {
        return new byte [] {
                (byte)(s >>> 8),
                (byte) s};
    }

    static public int intFromBytes(final byte [] bytes)
    {
        return ByteBuffer.wrap(bytes).getInt();
    }

    static public byte [] intToBytes(final int i)
    {
        return new byte [] {
                (byte)(i >>> 24),
                (byte)(i >>> 16),
                (byte)(i >>> 8),
                (byte) i};
    }

    static public long longFromBytes(final byte [] bytes)
    {
        return ByteBuffer.wrap(bytes).getLong();
    }

    static public byte [] longToBytes(final long l)
    {
        return new byte [] {
                (byte)(l >>> 56),
                (byte)(l >>> 48),
                (byte)(l >>> 40),
                (byte)(l >>> 32),
                (byte)(l >>> 24),
                (byte)(l >>> 16),
                (byte)(l >>> 8),
                (byte) l};
    }

    static public float floatFromBytes(byte [] bytes)
    {
        final int bits = intFromBytes(bytes);
        return Float.intBitsToFloat(bits);
    }

    static public byte [] floatToBytes(final float f)
    {
        int i = Float.floatToRawIntBits(f);
        return intToBytes(i);
    }

    static public byte [] doubleToBytes(final double d)
    {
        long l = Double.doubleToRawLongBits(d);
        return longToBytes(l);
    }

    static public double doubleFromBytes(byte [] bytes)
    {
        final long bits = longFromBytes(bytes);
        return Double.longBitsToDouble(bits);
    }

    static public byte [] stringToBytes(final String s)
    {
        return s.getBytes();
    }

    static public String stringFromBytes(byte [] bytes)
    {
  return new String(bytes);
    }
}

The above code can be tested using the following:
import java.nio.ByteBuffer;

public static String toString(final byte [] bits)
    {
        final StringBuffer stringBuffer = new StringBuffer(bits.length * 8);
        for(final byte b : bits)
        {
            stringBuffer.append(toString(b));
        }
        return stringBuffer.toString();
    }

    public static String toString(final byte bits)
    {
        final int displayMask = 1 << 7;
        final StringBuffer buf = new StringBuffer(8);

        byte value = bits;
        for(int c = 1; c <= 8; c++)
        {
            buf.append((value & displayMask) == 0 ? '0' : '1' );
            value <<= 1;
        }

        return buf.toString();
    }

    public static void main(String[] args)
    {
        {
            System.out.println("----------------------------------------");
            final boolean b_f = false;
            System.out.println("boolean false: " + b_f);
            final byte bits = booleanToByte(b_f);
            System.out.println("bits: " + toString(bits));
            final boolean new_b = booleanFromByte(bits);
            System.out.println("new boolean: " + new_b);
        }

        {
            System.out.println("----------------------------------------");
            final boolean b_t = true;
            System.out.println("boolean true: " + b_t);
            final byte bits = booleanToByte(b_t);
            System.out.println("bits: " + toString(bits));
            final boolean new_b = booleanFromByte(bits);
            System.out.println("new boolean: " + new_b);
        }

        {
            System.out.println("----------------------------------------");
            final short s = 123;
            System.out.println("short: " + s);
            final byte [] bytes = shortToBytes(s);
            System.out.println("byte array: " + toString(bytes));
            final short new_s = shortFromBytes(bytes);
            System.out.println("new short: " + new_s);
        }

        {
            System.out.println("----------------------------------------");
            final int i = 12345;
            System.out.println("int: " + i);
            final byte [] bytes = intToBytes(i);
            System.out.println("byte array: " + toString(bytes));
            final int new_i = intFromBytes(bytes);
            System.out.println("new int: " + new_i);
        }

        {
            System.out.println("----------------------------------------");
            final long l = 123456789012345L;
            System.out.println("long: " + l);
            final byte [] bytes = longToBytes(l);
            System.out.println("byte array: " + toString(bytes));
            final long new_l = longFromBytes(bytes);
            System.out.println("new long: " + new_l);
        }

        {
            System.out.println("----------------------------------------");
            final float f = 12345.6789e-2f;
            System.out.println("float: " + f);
            final byte [] bytes = floatToBytes(f);
            System.out.println("byte array: " + toString(bytes));
            final float new_f = floatFromBytes(bytes);
            System.out.println("new float: " + new_f);
        }

        {
            System.out.println("----------------------------------------");
            final double d = 123456789.0123456789e-7;
            System.out.println("double: " + d);
            final byte [] bytes = doubleToBytes(d);
            System.out.println("byte array: " + toString(bytes));
            final double new_d = doubleFromBytes(bytes);
            System.out.println("new double: " + new_d);
        }

        {
            System.out.println("----------------------------------------");
            final String s = "Hello World!";
            System.out.println("string: " + s);
            final byte [] bytes = stringToBytes(s);
            System.out.println("byte array: " + toString(bytes));
            final String new_s = stringFromBytes(bytes);
            System.out.println("new string: " + new_s);
        }
    }

Wednesday, May 19, 2010

Making "MUSIC"

The Self-adapting applications for mobile users in ubiquitous Computing Environments (MUSIC) project I have been working on for the last 3.5 years is coming to an end (at least its EU-funded period). CORDIS has posted a nice review of the project, that I attach below. I am particularly proud to see a link to the context plug-ins repository which I prepared :-)

The project webpage is: http://ist-music.berlios.de/site.

I copy from ICT Results page (http://cordis.europa.eu/ictresults):


Adaptive software – a late bloomer

Adaptive software is the largely unfulfilled promise of mobile technology, but now a new platform developed by European researchers promises to finally deliver software that reconfigures itself depending on the context.
Adaptive software – software that can configure itself automatically to deliver the maximum functionality for a given context – is finally coming. One of the long-promised fruits of the mobile technology tree, adaptation has proven a late bloomer, in large part due to the number of extremely tough problems that dog the idea.

For starters, there are thousands of different potential devices, from mobile phones to media players to computers. Added to that are the even vaster number of applications.

“The MUSIC project wanted to create a platform for adaptive applications that could work on any device and with any software,” explains Geir Horn, researcher with SINTEF in Norway and coordinator of the project. “[It’s] because people often want software to work differently in different contexts.”

Faulty defaults


For example, most emailing software downloads each email with all attachments in the order they were received. On a slow internet connection, it can mean waiting an hour or more to retrieve all the emails a user has received, and the connection could even drop out before the important last mail has been downloaded.

But email clients have a ‘slow connection’ setting that lets users download just the basic information: the subject, the sender and the size of the file, and it can be very useful when roaming data feeds or when the bandwidth is limited.

And it is not just download options that can be optimised for particular contexts. Encryption, too, can be usefully adjusted for office use or when on the move, with simple or even no encryption for the office, but extremely strong encryption outside the office.

Functions like these are typically buried behind obscure menu items and several dialogue boxes, and there are literally hundreds of possible options for all the different software on one device, and even more options for other devices. Users would quickly become overwhelmed if they have to change settings manually.

“Of course, the email software developers could write their software so that it adapts when the internet connection is slow, or when the user is moving, or when the user is in a particular location, but there are possibly hundreds of different situations that they would need to think of, and it quickly gets prohibitively expensive,” stresses Horn. “And that is just for one application.”

MUSIC handles all these issues. It takes account of a user’s location, whether it is at home, the office, in a car or on public transport. It notes the device in use, whether a mobile phone, netbook or desktop, and it is aware of dozens of other variables, from the strength of the internet connection to the time of day, from light levels to the condition of the battery.

Good guesses

By combining all this information, the MUSIC middleware can make a very good guess of the users’ context, what the user will want to do at a particular time, in a specific location with a given device.

The MUSIC platform does not need to be configured by the user, it derives its possible settings from the high-level behaviour descriptions that are part of most software developed today. High-level behaviours describe functions such as displaying SMS messages via text or using audio.

These descriptions tell the MUSIC software what settings can be altered, and MUSIC then simply uses the most appropriate settings for a given context. In the SMS example, it would render the message in text when the user is in a restaurant, but render it in audio when he or she is in a car.

“The biggest challenge that the MUSIC consortium faced was trying to create software that would install on any device, whether it is a mobile phone, PDA, netbook or server,” Horn relates. “In the end, we decided to use Java, which we thought was the most appropriate cross-platform development language.”

The developers also used a plugin paradigm so the software can be extended in useful ways. For example, any software can take advantage of MUSIC functionality simply by developing a plugin for the platform. Similarly, the platform can expand its functionality via plugins too.

So while the base MUSIC configuration may take account of location via GPS and time via the device clock, plugins could expand the base configuration to take advantage of other sensors, such as a compass, accelerometer or light meter.

Mission accomplished


The MUSIC project achieved all its design goals and has created a robust prototype platform. The software is designated open source and is freely available. There is a fledgling development community coalescing around the platform and, while there is no formal commercialisation plan as such, it is very likely that MUSIC will slowly, almost surreptitiously, become part of the mobile landscape.

That is because the platform is tiny, just a few hundred kilobytes in its base configuration. “So if a company wants to offer services that depend on MUSIC, they can just bundle the software with the service,” Horn remarks.

He offers the example of a tourist office in, say, Turin. The tourism office can develop a package that will show users specific information at a precise location – say the history of a famous church – when the user is standing there.When the user subscribes to the service, the software can be downloaded to their phone directly. That makes the MUSIC functionality available to any other MUSIC-enabled software on the user’s phone.

By degrees and utility, then, MUSIC has a very strong chance of becoming a very common platform and then, finally, mobile technology will evolve to become truly ‘adaptive’.

The MUSIC project received funding from the ICT strand of the EU’s Sixth Framework Programme for research.

Check out the plugins repository on the MUSIC website.

Thursday, March 04, 2010

Geosensing for your Windows 7

If you enjoy your Windows 7 and you would like to add some geosensing capabilities (especially if you travel a lot), I suggest you read this article from lifehacker: How to Add Location Awareness to Your Windows 7 PC.

If you do choose to install the Geosense for Windows software, please make sure that you carefully read the installation guidelines (including the terms of use). You will be surprisingly amused :-)

Tuesday, January 05, 2010

Android LiveBlog

I am following my first LiveBlog: Google Nexus One event on http://live.gizmodo.com/. Extremely entertaining and fun (even before the "actual event" had started). I am looking forward to more LiveBlogs in the future.