Wednesday, September 16, 2015

Aspects of User Interface Framework Design




I like to compare frameworks with multi sided cubes...
Each side of the cube exposes a key aspect of the framework morphology.
The collection of all aspects is often called a Meta Model.
What are the various aspects that come to mind when thinking about User Interface Framework Design?
In this post, you will see the ones that I find important...
You can use it as a check list or reflection board when you plan on writing your own framework.
Feel free to comment on this post if you have remarks or like to share some thoughts of your own.

I. Data Model


Data Representation
  • What Objects does your framework use to represent Data (PODOs, Value Objects, ...)?

Meta Data
  • What is the Meta Data model of your Data Object (field definition, field data types, field default values, ...)?

Data Access
  • How can your framework read / insert / update / delete data and invoke remote view actions (database queries, web services, ...)?

Data Validation
  • Does your framework support Data Validation (definition and enforcement of Validation rules: not null, min / max length, email address, telephone number, ...)?

Data Transformation
  • Does your framework support Data Transformation (definition and enforcement of Transformation rules: lowercase / uppercase / numeric only, ...)?

Calculated Fields
  • Does your framework support Calculated Fields?

Cursors & Pagination
  • How does your framework implement navigation and pagination through small and big data sets?

II. User Interface


Data Binding
  • How does your framework bind Data Objects to UI Components (does it have support for distributing change to multiple observers)?

UI Components
  • How does your framework present Data Object values for editing / visualisation (text fields, combo boxes, checkboxes, date pickers, tables, trees, charts, ...)?

UI Component Configuration
  • Does your framework support configuring UI Components (enabled / disabled / visible / invisible, value format, colours, font...)?

UI Containers
  • Does your framework support creation of UI Component compositions (panels, tabbed pane, split pane, ...)?

UI Screens
  • Does your framework support creation of functional / logical pages of UI Components and Containers?

III. Behaviour


Social Behaviour
  • How does your framework allow UI Components to interact with each other (auto change values / colours / fonts, enabling / disabling / hiding / showing of a UI Component in reaction to a change of a neighbour UI Component)?

Scenarios
  • How does your framework enable UI Component Containers, Screens and Data Access to interact with each other?

View Actions
  • Does your framework allow the User to invoke certain view actions on the server (buttons, popup menus, ...)?

Exception Handling
  • How does your framework handle Exceptions?

IV. Applications


Standard Functionality
  • What standard functionality does your framework support (refresh, insert, update, delete, save, print data, import data, export data, undo, redo, cut, copy, paste, delete, ...)?

Application Security
  • How does your framework implement authentication, authorisation & auditing?

Navigation
  • How does your framework support navigation between Screens (menu of screens, search screen, ...)?

Global State
  • Does your framework support Global Application State (application context)?

External Applications
  • Does your framework (use or) support interaction with other external applications?

V. User Preferences


Look & Feel
  • Does your framework support multiple (configurable) look and feels?

Customisations
  • Does your application support screen customisation per user (dynamically assemble screen UI Components, define a list of favourite screens, show User recent visits, remember sorting and ordering of table columns, user specific default values for search criteria, ...)?

Internationalisation
  • Does your framework have multi language support?

VI. Development


Application Configuration
  • How to implement or configure applications in your framework (define screens, data model, data access, behaviour, ...)?

Custom Implementations
  • Is there support for overriding certain parts of the framework to implement custom behaviour (modular architecture, anchor points, overriding functionality, ...)?

Software Factory
  • How to do Rapid Application Development?


Mind Map




Links


https://en.wikipedia.org/wiki/Metamodeling
https://en.wikipedia.org/wiki/Model-driven_software_development
http://www.w3.org/TR/mbui-intro/


Tuesday, May 26, 2015

Android: One Configuration To Build Them All

In the past, finding an Android build configuration that works on Android Studio, IntelliJ as well as command line has proven to be extremely difficult. On each new SDK-, IDE- or Gradle version, things seemed to be broken again. It wasn't a stable working environment at all, and I'm glad that Google decided to work on that (source: http://tools.android.com/tech-docs/new-build-system/version-compatibility).

Now, I'm using a build configuration that seems to work on all platforms, and I'd like to explain to you what I've done to make it work (and hopefully help you save a lot of time).


1. Install the Android SDK


First, I've downloaded android-sdk_r24.0.2-macosx.zip (Android SDK 24.0.2) from the Android website, and unzipped it (I've used directory /Users/Stefan/android-sdk).  I'm building on Mac, but you can also find the Windows and Linux releases on the website.

After unzipping, you create an environment variable called ANDROID_HOME, that points to the directory of the SDK that you've just unzipped:
export ANDROID_HOME="/Users/Stefan/android-sdk"
(on Mac or Linux, just add it to your ~/.profile file so that it will automatically be set each time you open your terminal)

Next, start the Android SDK manager, using:
$ANDROID_HOME/tools/android
Here, you have to install the following packages (this will take some time):

  • Android SDK Tools v24.0.2
  • Android 5.0.1 (API 21)
  • Android SDK Build-tools v21.1.2

Your SDK is now ready.


2. Install the IDE


Install the IDE of your choosing (Android Studio or IntelliJ).

For testing, I've downloaded both:
  • android-studio-ide-135.1740770-mac.dmg (Android Studio 1.1.0 build 135.1740770)
  • ideaIC-14.0.3.dmg (IntelliJ 14.0.3)


3. Create a new project (Hello World)


Now we're ready to create a new project.

Execute in your terminal:

$ANDROID_HOME/tools/android create project  
-t "Google Inc.:Google APIs:21" 
-p testproject  
-a TestActivity  
-k be.ad.testproject 
-g  
-v 1.1.0

This will create a directory called testproject, in which a Hello World application is generated (under package name be.ad.testproject).  The application will just have one activity, called TestActivity.  It will use Google APIs version 21 and Gradle build tools version 1.1.0.

Next, open testproject/gradle/wrapper/gradle-wrapper.properties and
  • change the Gradle version to gradle-2.2.1-all.zip.

Open testproject/build.gradle and
  • remove runProguard false line
  • replace the Android plugin with "com.android.application"


4. Test the build configuration


Ready to test it?

Execute in your terminal (in the testproject directory):

./gradlew clean assembleDebug

It should compile without any problems.

Next, try to open the build.gradle file using IntelliJ and/or Android Studio (be sure to select Use Default Gradle Wrapper when opening the project.  And when asked, choose to use the Project SDK instead of the IDE SDK).

It should open and build on both IDEs, without ANY problems.

And if you deploy the application on your device or emulator, you will see a nice Hello World application...

I prefer creating my projects command line, not by IDE.  When creating a project using the IDE, a lot of additional files will be generated that you might not need in your project.


5. Links


Tuesday, March 18, 2014

Point Geo Fencing - Sample Code

Point Geo Fencing is easier than polygon Geo Fencing.

As described in my first blog (read it here), you just have to calculate the distance between the point and your current location, and compare it with the radius of your point (circle).

First we need an object for representing our Point Geo Fence:


When your radius is defined in meters, you will need the Haversine formula.  This formula will calculate the distance between two points (in meters) while taking into account the earth curvation:


Now, we can calculate if we're inside the Geo Fence or not:


X and Y are your current longitude and -latitude.
The method will return true, when we're inside the Geo Fence and false when we're not.

More information can be found here:
http://en.wikipedia.org/wiki/Haversine_formula
http://stefanbangels.blogspot.be/2012/12/for-several-years-now-i-have-been.html
http://stefanbangels.blogspot.nl/2013/10/geo-fencing-sample-code.html

Wednesday, March 12, 2014

Odo Meter: Behind the Magic

An odo meter is a clever component that measures the total distance travelled (like the mileage counter in your car).

In Mobile software development, we also use an odo meter for calculating the travelled distance in:
  • track-and-trace applications
  • mileage administration applications
  • sports tracker applications (like Endomondo, RunKeeper, Strava...)
  • bike computers
  • taxi meters
  • ...
There are multiple strategies for calculating the total distance travelled.


STRATEGY 1: Calculate distance using delta time and current speed

Imagine a process that fetches the current GPS speed at a fixed interval of x time.

At each interval, we can calculate the distance by multiplying the delta time with the current speed:

d = v * t

for example (at an interval of 5 seconds, the current speed is 10 meters/second):

d = 10 meters/second * 5 seconds = 50 m

The problem with this strategy is that, in order to have an accurate result, time (t) has to be very small. In other words: you have to fetch the GPS speed a lot (draining your device battery).

A second problem is: sudden (short) accelerations, can cause an huge increase in distance, even if this speed has only occurred for just a little while... causing the result to be less accurate.


STRATEGY 2: Calculate distance between two points, at a fixed interval

Instead of fetching the GPS speed, we can also use the GPS position (longitude/latitude).

At each interval, we calculate the distance between the previous position and the current position.

As with the previous strategy, the results become more accurate when the interval becomes smaller. But the results aren't affected by speed fluctuations. The problem with this strategy is: we don't drive a straight line.  If we were driving circles, passing the same location at each interval, we could get into a situation where the calculated distance is zero.


STRATEGY 3: Calculate distance between positions, at a dynamic interval

When calculating the distance between positions at a dynamic interval instead of a fixed interval, we could decrease the problems of the previous strategies.

The interval can increase or decrease due to criteria like:

  • movement detected by an hardware acceleration- or gyro-meter.
  • ignition detected by an input port, canbus or sensing power drop.
  • an on/off switch.
  • increased speed levels at the previous interval.
  • distance threshold (for example, see Android LocationManager).
  • course changes (like a compass).
  • maps street information.
  • ...

Conclusion

Applications that operate in environments with a fairly stable speed (like space applications, airplanes, machine measurements, ...), strategy 1 (calculate distance using delta time and current speed) will be suitable.

But for most applications, strategy 2 (calculate distance between two points, at a fixed interval) will be the best solution.

Just keep in mind, when you require more control (to save battery life or in environments with repetitive reoccurring locations, ...), strategy 3 (calculate distance between positions at a dynamic interval) can also be a solution.

Friday, October 18, 2013

Geo Fencing - Sample Code

My first blog was about geofencing (read it here). The point-in-polygon algorithm may seem easy enough, but when actually trying to implement it, you will notice that there are some tricky parts to it (like when your point is on the edge of the polygon, or when your polygon contains horizontal lines, etc.). Therefor, I've decided to add some java sample code.

So, here goes...

Points, lines and polygons


First, we'll create some objects to represent our points, lines and polygons:
A point is a position with an x- and an y-coordinate. To apply it to geofencing, you can just think of x-coordinates as longitudes and y-coordinates as latitudes.

A line is a straigth line with a direction (vertex). It has a from-point and a to-point. We will use it to represent the edges of our polygon.

A polygon, obviously, is a multi-sided shape that consists of a number of points.


Objective


Our objective is to create a method for calculating if we are inside the polygon or not.

As described in my first blog post, this method will:

  • calculate the lines of the polygon
  • filter the lines that intersect with our y-position
  • calculate the exact points on which the lines intersect with the y-position
  • sort the points by x-position
  • use ray casting (out-in-out-in) algorithm for checking if we are inside or outside of the polygon.

In java, it would look something like this:
Now, let's try to implement each sub-method separately...


Calculate the polygon lines


First, the method for calculating the lines of a polygon.

We just take the points of the polygon and connect them together. We then close the polygon by connecting the last point to the first point:
There's no real magic here, it's a very simple method.


Filter the lines that intersect with the y-axis


Next, we need to filter the lines that intersect with our y-axis...


Calculate the x-intersection points at the y-axis


Next we calculate the x-intersection points of the lines at the given y-position, using the following method:
We calculate the x-position of every line, at the provided y, using standard calculus.


Sort the points by x-position


Sorting the points by X-position is easy, we just use a java double comparator:


Check if we are inside or outside of the polygon


And finally, we check if we are inside or outside the polygon, using the ray-casting algorithm:


Initially, we are outside of the polygon. At each point, we invert our status (inside - outside - inside - outside - ...). Until we have reached our x-position. We then know if we're inside or outside of the polygon.

That's it!

We just use simple java code, it can easily be ported to Android, iOS, ...

This code can still be optimized a lot, but the idea was to show how geofencing works (technically).

References:

Tuesday, September 17, 2013

Named placeholders for SQL parameters


JDBC is great.

But there seems to be a useful feature missing:

"Named placeholders for SQL parameters"

PreparedStatement provides a precompiled Statement that can be executed multiple times. The statement can be created by calling the factory method on the java.sql.Connection class:

public PreparedStatement prepareStatement(String sql) 
  throws SQLException;

This method takes an SQL String as an argument, which can contain (?) place holders, for example:

"SELECT name FROM users WHERE id = ?"

You can change the value of the place holders, by parameter index using methods:

public void setString(int parameterIndex, String theString)
  throws SQLException;

public void setLong(int parameterIndex, long theLong) 
  throws SQLException;

...


Very nice indeed.

But shouldn't it be easier if we (additionally) could use NAMED placeholders like this:

"SELECT name FROM users WHERE id = ?{ID}"

And set the place holders values like this:

public void setString(String parameterName, String theString)
  throws SQLException;

public void setLong(
String parameterName, int theLong) 
  throws SQLException;

...


Using indexes is error prone. You often need to re-count which index number is used for what parameter. Especially when you're refactoring, bug-fixing or implementing new functionality. Also, when using parameter indexes, you sometimes need to duplicate parameter values, which makes it even less readable.

In my projects, I prefer using my own helper class for adding functionality to Prepared Statements.

Some sample code:

public class PreparedStatementTemplate {

    private enum ParameterType {LONG, STRING}


    private final Pattern placeHolderPattern = Pattern.compile(

        "(\\?\\{([A-Za-z0-9]*)\\})"
    );

    private final PreparedStatement preparedStatement;


    private List<String> placeHolders;


    public PreparedStatementTemplate(

      Connection connection, String sql) throws SQLException {
        this.preparedStatement = connection.prepareStatement(
            extractPlaceHolders(sql)
        );
    }

    private String extractPlaceHolders(String sql) {

        List<String> placeHolders = new LinkedList<String>();
        Matcher matcher = placeHolderPattern.matcher(sql);
        while (matcher.find()) {
            placeHolders.add(matcher.group(2));
        }
        this.placeHolders = placeHolders;
        return matcher.replaceAll("?");
    }

    public void setString(String key, String value) throws SQLException {

        setParameterValue(key, value, ParameterType.STRING);
    }

    public void setLong(String key, long value) throws SQLException {

        setParameterValue(key, value, ParameterType.LONG);
    }
    private void setParameterValue(
        String key, Object value, ParameterType type) throws SQLException {
        for (Integer index : findPlaceHolderIndexes(key)) {
            if (type == ParameterType.LONG) {
                preparedStatement.setLong(index, (Long) value);
            } else if (type == ParameterType.STRING) {
                preparedStatement.setString(index, (String) value);
            } else {
                throw new SQLException("unknown parameter type: " + type);
            }
        }
    }

    public List<Integer> findPlaceHolderIndexes(String key) {

        List<Integer> indexes = new LinkedList<Integer>();
        int n = 1;
        for (String placeHolder : placeHolders) {
            if (key.equalsIgnoreCase(placeHolder)) {
                indexes.add(n);
            }
            n++;
        }
        return indexes;
    }

    public ResultSet executeQuery() throws SQLException {

        return preparedStatement.executeQuery();
    }

    public int executeUpdate() throws SQLException {

        return preparedStatement.executeUpdate();
    }

    public void close() throws SQLException {

        preparedStatement.close();
    }

}


You can use it like this:

PreparedStatementTemplate template = new PreparedStatementTemplate(
    connection, "SELECT name FROM users WHERE id = ?{ID}"
);
try {
    template.setLong("ID", userId);
    ResultSet rs = template.executeQuery();
    try {
        while (rs.next()) {
            System.out.println(rs.getString("NAME"));
        }
    } finally {
        rs.close();
    }
} finally {
    template.close();
}
        
Why isn't this feature embedded in the standard JDBC?  It would make life much easier!

More information about JDBC Prepared Statements can be found here:
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html
http://www.tutorialspoint.com/jdbc/jdbc-statements.htm

Monday, December 10, 2012

Geo Fencing: Behind the Magic

For several years now, I have been developing software for embedded systems. Not your everyday device (loaded with Android or iOS), but specialized devices: custom made devices for one customer or a group of customers. Its operating system is Linux, and you can basically run whatever-you-want on it (as long as it's ARM compiled).

The hardware architecture of the device is comparable with that of Beagle Board. On board you will find some add-ons (like for example: GPS, GPRS, WIFI, Bluetooth, In- and Output Ports, Serial Ports, Accelerometers, Gyrometers, Dallas Key, Temperature Sensors, Hydrometers, Ignition Detection, Canbus Interfacing, Touch Screen, etc) which can be used by my applications.

I have worked for a wide range of customers, in many different sectors, and have written a variety of applications (geotracking, geofencing, mileage/hour administration, driver profiling, canbus, car engine optimizers, taxi software, navigation software, task management, messaging, driver identification, radar detection, theft detection, etc).

Something I've noticed over all these years: in embedded development, there aren't that many different kinds of applications. The vast variety of applications can be reduced to only a hand ful. Of which geotracking and geofencing are considered the most popular.

I have been planning to write a blog for a while now. It's only logical that my first post will be on embedded software. As the subject reveiled: my first talk will be on geofencing, because it's popular and also because it's an interesting topic to talk about.

Geo Fencing

For the readers that are new to the topic, geofencing stands for geo (geographical) fencing (setting a perimeter). For me, geofencing really means: The process of checking whether an object (vehicle, person, animal, asset, etc) has entered or left a geographical area. This area can be pre-defined (calculation happens in real time on the device itself or on a server), or post-processed (the data is being stored and post-processed on a server).

Some applications of geofencing are:
  • prisoner tracker systems (ankle monitor)
  • notifying parents if their child leaves a designated area
  • sending alerts when a vehicle leaves predefined borders (reporting a stolen vehicle)
  • gps wildlife tracking: notifying rangers when wildlife leaves their habitat
  • taxi drivers getting notified of customers in their current sector
  • navigation software: knowing if the driver has reached its destination
  • asset tracking: notifying when a power generator leaves a working site

For me, geofencing only means the process of checking if an object has entered or left an area. It doesn't dictate the actions to be taken whenever such an event happens. This is always application specific: sending an SMS, notifying a server, write to a log file, trigger an output port, play a sound, etc.

The form in which a geographical area is described, (in my applications) can be resolved to two different types: Point Geofencing (a circle, with a specific radius) and Polygon Geofencing


Point


Point geofencing is the easiest to implement. You just take the current GPS position of the device, and if the distance between the center of the point and current longitude/latitude is smaller than the radius of the point then you are inside the area. If not, you are outside of the area. It's just a small state machine that remembers the current state for each defined area.

For calculating the distance, take into account the earths curvature. Use the Haversine formula to calculate the distance between two points. Many code examples can be found on the web.

Some customers like to define two circles, with a different radius: one for entering, and one for leaving the area (a Schmitt Trigger, a threshold to filter GPS drift).

Polygon

Polygon Geofencing is a little bit more complicated, but still easy to implement. For detecting if the current longitude/latitude is inside the polygon, we use a simple algorithm called Ray Casting algorithm.

  This is a short description of the algorithm:

  • Take the lines of the polygon, and retain only the lines of which the latitude (Y) intersects with the current latitude:
    Y1 < Y < Y2
  • For each of the lines, calculate the exact longitude-position (X) at which each line intersects the current latitude (Y). To do this, first calculate the Slope (the steepness at which the Y of the line rises/drops for each change in X). For each line:
    m = (Y2 - Y1) / (X2 - X1)
  • Then, calculate the longitude (X) for each line at the current latitude (Y):
    X = X1 + (Y - Y1) / m
  • Sort the longitudes ascending.
  • Iterate over all longitudes. The first longitude you cross, you are inside the polygon. The second longitude, you are outside again. The third, you are in again, ...


  • Compare your current longitude with the longitudes that you've iterated, to determine if you're inside or outside the polygon area.


Keep in mind that this algorithm also doesn't take into account earth curvature. So for big areas, the calculation can be inaccurate. But for most applications, this approach is good enough.

The difficulty in implementing this algorithm lies in the special cases: when your point is on the border of the polygon or when your polygon contains horizontal lines (calculating your slope will cause a divide by zero).

For a code sample, read my next blogs:
http://stefanbangels.blogspot.be/2013/10/geo-fencing-sample-code.html
http://stefanbangels.blogspot.be/2014/03/point-geo-fencing-sample-code.html