Archive

Archive for April, 2012

Console Based UI Development on BeagleBone

April 21, 2012 1 comment

When experimenting with various devices on the BeagleBone I often get to a point with my test programs where streaming output messages (i.e. printf) to a console is no long feasible. What’s really needed at that point is a UI that displays current state information such as the value of a GPIO pin. Depending on which OS the BeagleBone is running there are a variety of graphic user interfaces (GUI) available for use. But GUI’s are never simple and with the BeagleBone you either needs to invested in a display or use X/Windows to display the GUI on another personal computer. Another alternative is to use a console based UI.

The Angstrom release of Linux that ships with the BeagleBone includes the curses and it’s newer incarnation ncurses. If you’re familiar with C programming getting a ncurses application up and running will only take a few minutes. Here is a very simple ncurses program.

poll.c

#include <ncurses.h>

void main() {
initscr();
mvprintw(5, 3, "Hello world!");
getch();
endwin();
}

Compile it with …

gcc poll.c -lncurses -o poll

Executing poll will display “Hello world!” starting at Y, X position 5, 3 on the console and then wait for a key hit before exiting.

The next step is to monitor something. The BeagleBone pulses one of its LED’s like a heart beat. poll has been adapted to monitor if the brightness value is on (255) or off (0) and count the number of times it catches it on.

poll.c

#include <ncurses.h>
#include <stdio.h>
#include <stdlib.h>

void monitor(FILE *fp) {
        int run = 1;
        int count = 0;

        nodelay(stdscr, true);
        noecho();

        mvprintw(1, 1, "brightness:");
        mvprintw(2, 1, "     count:");

        while (run) {
                char buffer[16];
                memset(buffer, 0, sizeof(buffer));

                fseek(fp, 0, 0);
                fread(buffer, sizeof(char), sizeof(buffer), fp);

                int value = atoi(buffer);
                if (value != 0) {
                        count++;
                }

                mvprintw(1, 12, "%-3s", (value != 0 ? "on" : "off"));
                mvprintw(2, 12, "%d", count);

                int c = getch();
                switch(c) {
                        case 'q':
                                run = 0;
                                break;
                }
        }
}

void main() {
        char *file = "/sys/class/leds/beaglebone::usr0/brightness";
        FILE *fp;
        if ((fp = fopen(file, "r")) == NULL) {
                fprintf(stderr, "error: cannont open %s\n", file);
        }
        else {
                initscr();
                monitor(fp);
                endwin();

                fclose(fp);
        }
}

The program opens the sys-fs file that will provide the brightness value. After initializing ncurses it goes into a loop that reads the brightness value, increments the count if the LED is on, outputs the data, and checks if the user has hit the quit (‘q’) key.

The call to nodelay() prevents getch() from blocking and noecho() configures ncurses not to echo key hits.

Running poll.

When running poll I noticed that it seems to stagger at times. The application will noticeably pause on occasion. Since the application has to share clock cycles with the other applications it only gets a slice of CPU time. The size of the slice will vary over time and depends on what other things the CPU is being asked to execute. Linux provides the nice command which specifies the application’s priority on the kernel’s run queue. Running poll with a nice of -20 (the maximum) significantly improved its responsiveness.

As a next step I’ve been exploring how to use ncurses to create an application that treats input from a device (i.e. push button) wired to a BeagleBone expansion pin as UI input. For example, pressing a push button would be like pressing a key on the keyboard. More on that in the future.

 

 

Advertisements
Categories: BeagleBone

Open Lane Changes

April 21, 2012 3 comments

My Open Lane application has undergone some significant changes. I’ve added:

  1. Entity classes for a swim meet and events within the meet.
  2. Enumerators for Gender and Stroke.
  3. An AgeGroup class to encapsulate an event’s age category.
  4. JSF DataModel subclasses for Meet and Event along with a refactored SignUp backing bean.
  5. JPA services for all data input and output.
  6. JSF Converter classes for Gender, Stroke, and AgeGroup.
  7. CSV file initialization functions to populate the Swimmer, Meet, Event, and User tables.

Gender and stroke each represent a fixed set of constants which can be objectified in Java as an enumerator. An enumerator provides a clean, self-documenting, and an efficient way of coding an object model. Java enumerators can also be used to encapsulated conversion functionality.

In the case of this application the meet, event, swimmer, and entry records are imported from a CSV file. Within the event record is a stroke (i.e. Freestyle, Backstroke) filed that is coded using a number.  A “1” represents Freestyle, a “2” represents Backstroke, and so on. Stroke has been coded so that each enumerator has its import field number code associated with it. During the import process a simple call to Stroke.parse(string) generates the correct enumerator.

Instead of putting parse into Stroke I could have created a distinct converter. That would have been a cleaner separation of the code. But I don’t anticipate the conversion changing or needing to be adaptable. This way the code is simpler and straight forward.

Stroke.java

package org.bwgz.swim.openlane.data.model;

public enum Stroke {
    FREE("1"),
    BACK("2"),
    BREAST("3"),
    FLY("4"),
    IM("5");

    private String code;

    Stroke(String code) {
    	this.code = code;
    }

     public String getCode() {
          return code;
     }

     public void setCode(String code) {
          this.code = code;
     }

    public static Stroke parse(String string) {
    	Stroke result = null;

    	for (Stroke stroke : Stroke.values() ) {
    		if (stroke.getCode().equalsIgnoreCase(string)) {
				result = stroke;
				break;
			}
		}

		return result;
    }
}

This is an example of using the Gender enumerator within a JPA query to abstract away the codes used in the database. I don’t have to concern myself with how the data is coded once it is imported into the database.

em.createQuery("select e from Event e where e.meet = :meet and (e.gender = :mixed or e.gender = :gender")
.setParameter("meet", meet)
.setParameter("mixed", Gender.MIXED)
.setParameter("gender", gender)
.getResultList();
 

Later in this article is an example of how the enumerator’s parse method is used.

Eventually the JSF tables will support sorting and paging. In preparation for that I’ve moved from List and Collection to JSF’s DataModel. DataModel is a wrapper that abstracts the underlying data. I’ve also used it to store which record (object) may have been selected by the user. Previously there was an independent bean to handle that. Putting it here keeps thing a bit tidier. I created DataModel’s for Event and Meet. Later I’ll reuse the pattern for a user’s open lane applications.

I’ve decided to build out services for each entity in the data model. This provides a level of encapsulation and organization that make the code more manageable. Using @Autowired I can also create services that are built upon other services. For example, the SignUpService uses the SwimmerService.

SignUpService.java snippet.

@Service("signupService")
@Repository
public class SignUpServiceImpl implements SignUpService, Serializable {

     private EntityManager em;
     @Autowired
     private SwimmerService swimmerService;

    @PersistenceContext
    public void setEntityManager(EntityManager em) {
    	this.em = em;
    }
….
    @Transactional
     public Boolean doSignUp(SignUp signUp) {
     Boolean result = Boolean.FALSE;

     Swimmer swimmer = swimmerService.findSwimmer(signUp.getUsasId());

As a general rule the code should have a clean separation between how data is represented internally and externally. JSF’s Converter class is one way to accomplish that. I needed a Converter for Gender, Stroke, and AgeGroup. Since Gender and Stroke were enumerators I create an abstract base class to simplify things. The Gender and Stroke converters need only supply the mappings between the internal representation (an enumerator) and string (display value).

AbstractEnumConverter.java

package org.bwgz.swim.openlane.faces.converter;

import java.util.Hashtable;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;

public abstract class AbstractEnumConverter<T> implements Converter {
	private final static int ASSOCIATION_ENUM	= 0;
	private final static int ASSOCIATION_STRING	= 1;

	private Class<T> clazz;
	private final Map<T, String> toStringMap = new Hashtable<T, String>();
	private final Map<String, T> toEnumMap = new Hashtable<String, T>();

	@SuppressWarnings("unchecked")
	public AbstractEnumConverter(Class<T> clazz, Object[][] associations) {
		this.clazz = clazz;

		for (Object[] association : associations) {
			toEnumMap.put((String) association[ASSOCIATION_STRING], (T) association[ASSOCIATION_ENUM]);
			toStringMap.put((T) association[ASSOCIATION_ENUM], (String) association[ASSOCIATION_STRING]);
		}
	}

	public Object getAsObject(FacesContext context, UIComponent component, String value) {
		return toEnumMap.get(value);
	}

	@SuppressWarnings("unchecked")
	public String getAsString(FacesContext context, UIComponent component, Object value) {
            if (value.getClass() == clazz) {
        	 return toStringMap.get((T) value);
            }
            else
            {
                throw new IllegalArgumentException(String.format("Cannot convert object - not of type %s", clazz.getSimpleName()));
            }
	}
}

StrokeConverter.java

package org.bwgz.swim.openlane.faces.converter;

import javax.faces.convert.FacesConverter;
import org.bwgz.swim.openlane.data.model.Stroke;

@FacesConverter(value="strokeConverter")
public class StrokeConverter extends AbstractEnumConverter<Stroke> {
	private final static Object associations[][] = {
		{ Stroke.FREE,		"Free" },
		{ Stroke.BACK,		"Back" },
		{ Stroke.BREAST,	"Breast" },
		{ Stroke.FLY,		"Fly" },
		{ Stroke.IM,		"IM" },
	};

	public StrokeConverter() {
		super(Stroke.class, associations);
	}
}

The AgeGroup converter encapsulates the four rules used to describe an age category.

AgeGroupConverter.java

package org.bwgz.swim.openlane.faces.converter;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;

import org.bwgz.swim.openlane.data.model.AgeGroup;

@FacesConverter(value="ageGroupConverter")
public class AgeGroupConverter implements Converter {
	private static final String SENIOR		= "Senior";
	private static final String UNDER		= "Under";
	private static final String OVER		= "Over";
	private static final String AMPERSAND	= "&";
	private static final String HYPHEN		= "-";

	private static final int LEFT	= 0;
	private static final int RIGHT	= 1;

	private Object getAsObject(String string) {
		long min = 0;
		long max = 0;

		if (string.equals(SENIOR)) {
			min = 0;
			max = 0;
		}
		else if (string.contains(AMPERSAND)) {
			String[] fields = string.split(AMPERSAND);

			if (fields[RIGHT].equals(UNDER)) {
				min = 0;
				max = Long.parseLong(fields[LEFT]);
			}
			else if (fields[RIGHT].equals(OVER)) {
				min = Long.parseLong(fields[LEFT]);
				max = 0;
			}
		}
		else if (string.contains(HYPHEN)) {
			String[] fields = string.split(HYPHEN);

			min = Long.parseLong(fields[LEFT]);
			max = Long.parseLong(fields[RIGHT]);
		}

		return new AgeGroup(min, max);
	}

	public Object getAsObject(FacesContext context, UIComponent component, String value) {
		return getAsObject(value);
	}

	private String getAsString(AgeGroup ageGroup) {
		String string;

		if (ageGroup.getMin() == 0 & ageGroup.getMax() == 0) {
			string = SENIOR;
		}
		else {
			String left;
			String seperator;
			String right;

			if (ageGroup.getMin() == 0) {
				left = String.valueOf(ageGroup.getMax());
				seperator = AMPERSAND;
				right = UNDER;
			}
			else if (ageGroup.getMax() == 0) {
				left = String.valueOf(ageGroup.getMin());
				seperator = AMPERSAND;
				right = OVER;
			}
			else {
				left = String.valueOf(ageGroup.getMin());
				seperator = HYPHEN;
				right = String.valueOf(ageGroup.getMax());
			}

			string = left + seperator + right;
		}

		return string;
	}

	public String getAsString(FacesContext context, UIComponent component, Object value) {
            if (value instanceof AgeGroup) {
                return getAsString((AgeGroup) value);
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert object - not of type AgeGroup");
            }
	}
}

Meet, event, swimmer, and later entry records are imported from another system. Unfortunately the limitations of that system prevent the application from accessing them directly. Instead the data is exported to CSV files and then imported into the application.

Eventually I’ve incorporate a form of file upload within the application to provide live data import. For now some dummy (test) CSV files are included in the application and imported when the application is first accessed. Some services now have an initialize method. When called the method will read a CSV file and write the data to the database using JPA.

Using <on-start> within home-flow.xml I trigger the initializations. This is a hack for testing purposes only.

home-flow.xml snippet

<on-start>
        <evaluate expression="swimmerService.initialize()" />
        <evaluate expression="meetService.initialize()" />
        <evaluate expression="signupService.initialize()" />
</on-start>

I use FlatPack to process the CSV files. It’s a nice CSV library that I’ve used many times in the past. I particularly like that it allows you to create a map of the column names. On the other hand the map requires names for every column. This can be a bit tedious when you only need the first few columns. It can also choke when the file contains records with differing number of columns.

SwimmerServiceImpl.java snippet.

    @Transactional
    public void initialize() {
    if (!initialized) {
        DataSet dataSet;

        Parser parser;
        parser = DefaultParserFactory.getInstance().newDelimitedParser(
            new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("/test/data/athlete.pzmap.xml")), // xml column mapping
            new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("/test/data/athlete.csv")),  // csv file to parse
            ';', // delimiter
             '"', // text qualfier
             false); // ignore the first record (may need to be done if first record contain column names)

            dataSet = parser.parse();
            while (dataSet.next()) {
                Swimmer swimmer = new Swimmer();

                swimmer.setId(dataSet.getString("Reg_ID"));
                swimmer.setFirst(dataSet.getString("First_name"));
                swimmer.setLast(dataSet.getString("Last_name"));
                swimmer.setGender(Gender.parse(dataSet.getString("Ath_Sex")));
                swimmer.setId(dataSet.getString("Reg_ID"));
                swimmer.setBirthdate(stringToDate(dataSet.getString("Birth_date")));

                em.persist(swimmer);
                }

            initialized = true;
        }
     }
 

The code is available here on GitHub.

Open Lane Sign Up

April 17, 2012 Leave a comment

Time for Open Lane to get more real with a user sign up feature. The application already has some user management along with authentication and authorization. Now it needs the ability for someone to sign up and create a user account. Here’s what needs to change.

Add a table and service for all eligible users (swimmers). It contains an unique identifier for each swimmer along with important name and demographic information. The data for this table is loaded from another system and should exist prior to a user attempting to sign up. The sign up process involves gathering some additional information and associating (linking) the user account with their pre-existing swimmer data.

I created entity and service classes to deal with this data. These classes cover the basics.

Swimmer.java

package org.bwgz.swim.openlane.model;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "Swimmers")
public class Swimmer implements Serializable {
	private static final long serialVersionUID = 1816256078842365678L;

	private String id;
	private String first;
	private String last;
	private String middle;
	private String gender;
	private Date birthdate;

	public Swimmer() {
	}

	public Swimmer(String id) {
		this.id = id;
	}

	@Id
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getFirst() {
		return first;
	}

	public void setFirst(String first) {
		this.first = first;
	}

	public String getLast() {
		return last;
	}

	public void setLast(String last) {
		this.last = last;
	}

	public String getMiddle() {
		return middle;
	}

	public void setMiddle(String middle) {
		this.middle = middle;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public Date getBirthdate() {
		return birthdate;
	}

	public void setBirthdate(Date birthdate) {
		this.birthdate = birthdate;
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}

	@Override
        public String toString() {
              return String.format("%s@%x; Id: %s; First: %s; Middle: %s; Last: %s; Gender: %s; Birthdate: %s;",
              this.getClass().getName(), this.hashCode(),
              getId(), getFirst(), getMiddle(), getLast(), getGender(), getBirthdate());
}

}

SwimmerService.java

package org.bwgz.swim.openlane.service;

import java.util.List;

import org.bwgz.swim.openlane.model.Swimmer;

public interface SwimmerService {
public List<Swimmer> findSwimmers(String id);
public Swimmer findSwimmer(String id);
}

SwimmerServiceImpl.java

package org.bwgz.swim.openlane.service;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.bwgz.swim.openlane.model.Swimmer;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

@Service("swimmerService")
@Repository
public class SwimmerServiceImpl implements SwimmerService, Serializable {
	private static final long serialVersionUID = -7264545602862288436L;

	private EntityManager em;

	@PersistenceContext
	public void setEntityManager(EntityManager em) {
		this.em = em;
	}

	private Query findSwimmerQuery(String id) {
		return em.createQuery("select u from Swimmer u where u.id = :id")
				.setParameter("id", id);
	}

	@SuppressWarnings("unchecked")
	public List<Swimmer> findSwimmers(String id) {
		List<Swimmer> list = null;

		if (id != null) {
			list = (List<Swimmer>) findSwimmerQuery(id).getResultList();
		}

		return list;
	}

	public Swimmer findSwimmer(String id) {
		Swimmer swimmer = null;

		if (id != null) {
			try {
				swimmer = (Swimmer) findSwimmerQuery(id).getSingleResult();
			} catch (Exception e) {
			}
		}

		return swimmer;
	}

}

Not just anyone can sign up for a user account. Only someone who’s eligible to participate in a swim meet can apply for an open lane. The process has to account for this when a prospective user signs up. I created an JSF Validator to check if the id given during sign-up matches an existing swimmer. If it does not then the Validator will throw an exception and the JSF form will catch it.

USwimmerValidator.java

package org.bwgz.swim.openlane.faces.validator;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

import org.bwgz.swim.openlane.model.Swimmer;
import org.bwgz.swim.openlane.service.SwimmerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class USwimmerValidator implements Validator {

	@Autowired
	private SwimmerService service;

	public void setService(SwimmerService service) {
		this.service = service;
	}

	public void validate(FacesContext context, UIComponent component,
			Object value) throws ValidatorException {
		System.out.printf("USwimmerValidator.validate(%s, %s, %s)\n", context,
				component, value);
		System.out.printf("\t component.getId: %s\n", component.getId());
		System.out.printf("\t component.getClientId: %s\n",
				component.getClientId(context));
		System.out.printf("\t component.getContainerClientId: %s\n",
				component.getContainerClientId(context));
		System.out.printf("\t service: %s\n", service);

		Swimmer membership = service.findSwimmer((String) value);
		if (membership == null) {
			FacesMessage message = new FacesMessage();
			message.setSeverity(FacesMessage.SEVERITY_ERROR);
			message.setSummary("Swimmer not found.");
			message.setDetail("Swimmer not found.");
			context.addMessage(component.getClientId(context), message);
			throw new ValidatorException(message);
		}
	}
}

I decided to create a sub-flow to handle the sign up process. I also needed a backing bean for the sign up form. The heart of the flow involves capturing the username, email, password, and swimmer id in a JSF form, validating the input, and then creating the user account.

On start up the sub-flow instantiates a backing bean (signupBean) which will be used throughout the sub-flow and then discarded. A sign up page (signup.xhtml) is called by the view state and when the form on that page is submitted the flow will execute the action state adduser. adduser calls the User service to create a user record in the the database. If that succeeds the sub flow exits. If not, it takes the user back to the sign up form for another attempt. At anytime during the sub flow the user can exit by selecting a home link.

signup-flow.xml

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/webflow
		http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

	<on-start>
            <evaluate expression="signupBean" result="flowScope.signup" />
	</on-start>

	<view-state id="signup">
		<transition on="submit" to="adduser"/>
		<transition on="home" to="home"/>
	</view-state>

	<action-state id="adduser">
		<evaluate expression="userService.addUser(signup, swimmerService.findSwimmer(signup.usasId))" />
                <transition on="yes" to="success" />
                <transition on="no" to="signup" />
	</action-state>

	<end-state id="home"/>
	<end-state id="success"/>

</flow>

All the of input fields on the sign up page are validated. That validation is defined using annotations in Setup.java. There’s also the JSF Validator mentioned above. The user can’t get past the sign-up page unless they enter legitimate answers.

Setup.java

package org.bwgz.swim.openlane.model;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

@ManagedBean
@RequestScoped
public class SignUp implements Serializable {
	private static final long serialVersionUID = 4957886416619036377L;

	@Size(min = 5, max=20, message = "Please enter a valid username (5-20 characters)")
	private String username;

	@Size(min = 5, max=20, message = "Please enter a valid password (5-20 characters)")
	private String password;

	@Size(min = 1, message = "Please enter the Email")
	@Pattern(regexp = "[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]+", message = "Email format is invalid.")
	private String email;

	@Size(min = 14, max=14, message = "Please enter a valid USA Swimming ID (14 characters)")
	@Pattern(regexp = "[a-zA-Z0-9]+", message = "USA Swimming ID format is invalid.")
	private String usasId;

	public SignUp() {
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getUsasId() {
		return usasId;
	}

	public void setUsasId(String usasId) {
		this.usasId = usasId;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

    @Override
    public String toString() {
    	return String.format("%s@%x; Username: %s; Password: %s; Email: %s; UsasId: %s;",
    			this.getClass().getName(), this.hashCode(),
    			getUsername(), getPassword(), getEmail(), getUsasId());
    }
}

Here’s the the JSF form code from signup.xhtml.

<h:form id="signup">
	<h:outputLabel>User Name: </h:outputLabel>
	<h:inputText id="username" value="${signup.username}"/>
	<br/>
	<h:outputLabel>Password: </h:outputLabel>
	<h:inputText id="password" value="${signup.password}"/>
	<br/>
	<h:outputLabel>Your Email: </h:outputLabel>
	<h:inputText id="email" value="${signup.email}"/>
	<br/>
	<h:outputLabel>Your USA Swimming Id: </h:outputLabel>
	<h:inputText id="usasId" value="${signup.usasId}">
	    <f:validator binding="${USwimmerValidator}"/>
	</h:inputText>

	<br/>
	<h:commandButton id="submit" action="submit" value="Sign Up" update="@form" />
</h:form>

Note the validator tag on the Id inputText tag. I took me quite some time to get this to work correctly.

First, I created the Validator using @FacesValidator and  then added  @Autowired to the SwimmerService variable is needed during validation. It looked something like this.

@FacesValidator("swimmerValidator")
public class USwimmerValidator implements Validator {

    @Autowired
    private SwimmerService service;

This only half worked. The JSF form was able to execute the validator but SwimmerService was not set. After scouring the Internet I learned that the validator was know to JSF but not Spring. I had to drop @FacesValidator and go with @Component inside. This meant in the JSF form I needed to use binding instead of validatorId.

Second, my code original used a different Validator class name called USASMemberValidator. When I refactored it to SwimmerValidator the auto-wiring stopped working. I don’t know why. When I renamed it to USwimmerValidator everything worked fine. Something like this shouldn’t happen. This isn’t the first time in my career that I’ve seen something as flaky as this but it surprised me that I’d see it here.

While investigating all this I came across javax.inject (@Inject). I’m going to looking into this as an alternative.

Finally, I re-factored User by adding a Swimmer variable and annotating it with a one to one relationship. Here’s a snippet from User.java.

	@OneToOne(fetch=FetchType.EAGER)
	public Swimmer getSwimmer() {
		return swimmer;
	}

This is a unidirectional relationship and sufficient for now. I’ll probably re-factor it to a bidirectional relationship to provide some referential capabilities. I also need to ensure that when when a user record is deleted the associated swimmer record is not.

Next step is to get down to the business of an open lane application submission. More on that in my next Open Lane post.

As always, the code is available here on GitHub.

Open Lane – Sunday Housekeeping

April 16, 2012 Leave a comment

Up to now I’ve been focused on get Open Lane up and running. Today I went back and made it more manageable. I don’t want to get too far down the road without being able to build it from a shell using Maven. Also I don’t want to keep committing Eclipse specific files to my version code system Git. I want to be able to:

  • Download the latest version from github.
  • Build a war package using Maven.
  • Deploy that package to a Tomcat server and bring up Open Lane in a browser.
  • Generate an Eclipse project using Maven.

There’s plenty of  good Maven and Git documentation on the Internet. So I won’t get into the details on how to much to technologies work. With that in mind, I will highlight a few things.

The Maven pom file that comes with Spring Web Flow’s booking-faces sample was a good place to start. It very vanilla and doesn’t invoke exotic or highly customized commands or dependenicies. It expects the source tree to follow Maven defaults such as src/main/java. The only significant change was to add my application id’s and fix some the version in some Spring dependencies that were sharing the version.

	<groupId>org.bwgz.swim.openlane</groupId>
	<artifactId>open-lane</artifactId>
	<name>Open Lane</name>
	<version>0.0.1.RELEASE</version>

This results in a pom file that can be found here. After modifying my source tree the new pom could generate a war file and Eclipse project.

Command Description
mvn package Creates a war file in the target directory.
mvn eclipse:eclipse Creates an Eclipse project.

When creating the Eclipse project I found that I needed to ensure I didn’t have any old Eclipse directories hanging around. If I did then things didn’t go well when running the project in Eclipse.

The generated Eclipse project also defaults to Java 1.5 and Web 2.5. I’d prefer it to Java 1.6 or event 1.7 and Web 3.0. Those changes will come later.

During all of this I found a bug in home-flow.xml. The problem was with the evaluation expression …

expression="userService.findUser(currentUser.name)" result="viewScope.user"

Spring Web Flow (SWF) sets currentUser only if a user has been authenticated. Starting up the application on a clean install meant that no one was authenticated and in turn currentUser was not initialized (null). That caused my home flow to blow up because I was attempting to access a member of a null object. I fixed this by changing the expression to …

expression="currentUser != null ? userService.findUser(currentUser.name) : null"

This bug still perplexes me a bit because with the old code, if I logged out the user, there wasn’t a problem. I was as if currentUser was an empty (vs. null) object.

BeagleBone, GPIO, & IRQ

April 15, 2012 9 comments

My last BeagleBone post looked at interfacing the the bone with an incremental rotary encoder. I wasn’t satisfied with the polling loop I used to read inputs from the encoder so I began investigating alternate methods. While reviewing the sysfs GPIO documentation I noticed that …

Inputs can often be used as IRQ signals, often edge triggered but sometimes level triggered. Such IRQs may be configurable as system wakeup events, to wake the system from a low power state.

Later in the documentation it states …

/sys/class/gpio/gpioN/ …

“value” … reads as either 0 (low) or 1 (high). … If the pin can be configured as interrupt-generating interrupt and if it has been configured to generate interrupts (see the description of “edge”), you can poll(2) on that file and poll(2) will return whenever the interrupt was triggered. If you use poll(2), set the events POLLPRI and POLLERR. If you use select(2), set the file descriptor in exceptfds. After poll(2) returns, either lseek(2) to the beginning of the sysfs file and read the new value or close the file and re-open it to read the value.

“edge” … reads as either “none”, “rising”, “falling”, or “both”. Write these strings to select the signal edge(s) that will make poll(2) on the “value” file return.

This file exists only if the pin can be configured as an interrupt generating input pin.

If all this is truly working on the bone then it’s a better method than polling in user space. It should eliminate a bunch of context switching between kernel and user space  in my current code. I had to try this out.

Using poll(2), with a properly configured GPIO, my code could now react to changes generated by the encoder rather than continually polling it on my own. For simplicity I configured the GPIO’s using some shell commands.

echo 70 > /sys/class/gpio/export
echo 71 > /sys/class/gpio/export

echo in > /sys/class/gpio/gpio70/direction
echo in > /sys/class/gpio/gpio71/direction

echo both > /sys/class/gpio/gpio70/edge
echo both > /sys/class/gpio/gpio71/edge

Using a the following C program I monitored a incremental rotary encoder wired to a BeagleBone.

#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>

#define A 0
#define B 1

void dump_value(int fd) {
        char buffer[1024];
        lseek(fd, 0, 0);

        int size = read(fd, buffer, sizeof(buffer));
        buffer[size] = NULL;

        printf("\t\t size: %d  buffer: %s\n", size, buffer);
}

void dump_event(int fd, struct pollfd *pfd) {
        short revents = pfd->revents;

        printf("revents: 0x%04X\n", revents);
        if (revents & POLLERR) {
                printf("\t POLLERR  errno: %d\n", errno);

                if (errno == EAGAIN) {
                        printf("\t\t EAGAIN\n");
                }
                if (errno == EINTR) {
                        printf("\t\t EINTR\n");
                }
                if (errno == EINVAL) {
                        printf("\t\t EINVAL\n");
                }
        }

        if (revents & POLLHUP) {
                printf("\t POLLHUP\n");
        }

        if (revents & POLLNVAL) {
                printf("\t POLLINVAL\n");
        }

        if (revents & POLLIN) {
                printf("\t POLLIN\n");

                dump_value(fd);
        }
        if (revents & POLLPRI) {
                printf("\t POLLPRI\n");

                dump_value(fd);
        }
        if (revents & POLLOUT) {
                printf("\t POLLOUT\n");
        }
        if (revents & POLLRDNORM) {
                printf("\t POLLNORM\n");
        }
        if (revents & POLLRDBAND) {
                printf("\t POLLRDBAND\n");
        }
        if (revents & POLLWRNORM) {
                printf("\t POLLWRNORM\n");
        }
        if (revents & POLLWRBAND) {
                printf("\t POLLWRBAND\n");
        }
}

int get_lead(int fd) {
        int value;
        lseek(fd, 0, 0);

        char buffer[1024];
        int size = read(fd, buffer, sizeof(buffer));
        if (size != -1) {
                buffer[size] = NULL;
                value = atoi(buffer);
        }
        else {
                value = -1;
        }

        return value;
}

void main() {
        int fd[2];

        fd[A] = open("/sys/class/gpio/gpio70/value", O_RDONLY);
        fd[B] = open("/sys/class/gpio/gpio71/value", O_RDONLY);

        struct pollfd pfd[2];

        pfd[A].fd = fd[A];
        pfd[A].events = POLLPRI;
        pfd[A].revents = 0;

        pfd[B].fd = fd[B];
        pfd[B].events = POLLPRI;
        pfd[B].revents = 0;

        int lead[2];
        while (1) {
                int ready = poll(pfd, 2, -1);
                printf("ready: %d\n", ready);

                if (pfd[A].revents != 0) {
                        printf("\t Lead A\n");
                        //dump_event(fd[A], &pfd[A]);
                        lead[A] = get_lead(fd[A]);
                }
                if (pfd[B].revents != 0) {
                        printf("\t Lead B\n");
                        //dump_event(fd[B], &pfd[B]);
                        lead[B] = get_lead(fd[B]);
                }

                printf("\t\t A: %d  B: %d\n", lead[A], lead[B]);
        }
}

Using a timeout of -1 the poll will wait indefinitely. The code is simply waiting for an edge event to occur. That would be one of the encoder leads transitioning from low to high or high to low. This produced the following output when I turned the encoder knob.

ready: 2
         Lead A
         Lead B
                 A: 1  B: 1
ready: 1
         Lead A
                 A: 0  B: 1
ready: 1
         Lead B
                 A: 0  B: 0
ready: 1
         Lead A
                 A: 1  B: 0
ready: 1
         Lead B
                 A: 1  B: 1

In the above example, both leads start out on a detent. As I rotate the knob clockwise lead A goes low and then lead B does the same. At this point the knob is half way between detents. As rotation continues A goes high and then B follows. The knob has settled on the next detent.

I noticed two interesting artifacts.

  1. The first poll will always returns immediately with values for all the GPIO’s being polled.
  2. When I turned the knob quickly I did see some polls return changes on both GPIO’s. This means an intermediate state was lost. This isn’t a fatal problem. It just has to be accounted for when monitoring the encoder’s phases and calculating its position.
  3. Once the GPIO value is read it can’t be read again until another edge event occurs. If you try the read function will fail.

I’d like to see how well this new code can keep up with a fast turning encoder. Since nothing is being buffered by the sysfs GPIO kernel driver there’s a very good chance that the user space code still can’t service the edge events quickly enough.

At some point soon I’ll refactor the rotary code in my BeagleBone library to reflect this method.

Open Lane – Supporting a User Part 2

April 14, 2012 Leave a comment

Having added some user authentication to my open lane application the next step involved associating the user with a profile. Things can start to get complex quickly when you need more than simple authentication and authorization. At lot of applications do not need their own form of user management because they’re part of a larger solution that already has it. Those application tap into the existing service for authentication and authorization. In our case we don’t have that. So there are a couple of options. I could add a separate user management service from another provider into the solution or I could write my own user management service.

At this point I don’t want to get into integrating with another solution. I’m sure that day will come but not today. For now I’m going to write some code that supports Spring Security and gives me enough of what I need to continue building out the application.

So what do I really need:

  1. My core user is a swimmer. Someone who will apply for an open lane swim. I’ll also need operational users such as an administrator but that can wait. I need to gather and store enough information about a swimmer to process the application. I’ll call this the user’s profile.
  2. A means to authentication a user via a login. I’ll be working with Spring Security to implement this.
  3. A means to secure pages and actions to authorized users. Again I’ll use Spring Security to implement this.
  4. A registration process to add new user.

In the previous post I used Spring’s in-memory UserDetailsService to handle authentication.

<security:authentication-manager>
	<security:authentication-provider>
		<security:password-encoder hash="md5" />
		<security:user-service>
			<security:user name="keith" password="417c7382b16c395bc25b5da1398cf076" authorities="ROLE_USER, ROLE_SUPERVISOR" />
			<security:user name="erwin" password="12430911a8af075c6f41c6976af22b09" authorities="ROLE_USER, ROLE_SUPERVISOR" />
			<security:user name="jeremy" password="57c6cbff0d421449be820763f03139eb" authorities="ROLE_USER" />
			<security:user name="scott" password="942f2339bf50796de535a384f0d1af3e" authorities="ROLE_USER" />
		</security:user-service>
	</security:authentication-provider>
</security:authentication-manager>

Given the Spring centricity of this application I’ll stick with Spring Security. The question is how to get authentication/authorization with customized user management. I’ve got specific profile information that I need to capture and store.

I could continue to use a Spring Security implementation and create a look aside table but this mean creating/updating two distinct elements when a change occurs. Or, I could subclass UserDetailsService but I’m concerned that this could be a rabbit hole that I don’t want to go down right now. Instead I’ll take a look at Spring Security’s JdbcDaoImpl. JdbcDaoImpl is an implementation of UserDetailsService which uses a database to fetch the authentication and authorization data.

<security:authentication-manager>
	<security:authentication-provider>
		<security:jdbc-user-service data-source-ref="dataSource"/>
		<security:password-encoder hash="md5" />
	</security:authentication-provider>
</security:authentication-manager>

When using JdbcDaoImpl you must ensure that you’ve correctly configured the database tables. You can find details on this here. I created two JPA entities – User,  and Authority. I’m using Hibernate on the backside.

User combines the fields that JdbcDaoImpl requires with user profile fields that the application needs.

User.java

package org.bwgz.swim.openlane.model;

import java.io.Serializable;
import java.util.Collection;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "Users")
public class User implements Serializable {
	private static final long serialVersionUID = -3475658623185783516L;

	private String username;
	private String password;
	private Boolean enabled;
	private String name;
	private String email;
	private String usasId;

	private Collection<Authority> authorities;

	public User() {
	}

	public User(String username, String name) {
		this.username = username;
		this.name = name;
	}

	@Id
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getUsasId() {
		return usasId;
	}

	public void setUsasId(String usasId) {
		this.usasId = usasId;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Boolean getEnabled() {
		return enabled;
	}

	public void setEnabled(Boolean enabled) {
		this.enabled = enabled;
	}

    @OneToMany(mappedBy = "username", fetch=FetchType.EAGER)
    public Collection<Authority> getAuthorities() {
        return authorities;
    }

	public void setAuthorities(Collection<Authority> authorities) {
		this.authorities = authorities;
	}

    @Override
    public String toString() {
    	return String.format("%s@%x; Username: %s; Password: %s; Enabled: %s; Authorities: %s; Name: %s; Email: %s; UsasId: %s;",
    			this.getClass().getName(), this.hashCode(),
    			getUsername(), getPassword(), getEnabled(), getAuthorities(),
    			getName(), getEmail(), getUsasId());
    }

}

Authority.java

package org.bwgz.swim.openlane.model;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "Authorities")
public class Authority implements Serializable {
	private static final long serialVersionUID = -3475658623185783516L;

	private String username;
	private String authority;

	public Authority() {
	}

	public Authority(String username, String authority) {
		this.username = username;
		this.setAuthority(authority);
	}

	@Id
        public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getAuthority() {
		return authority;
	}

	public void setAuthority(String authority) {
		this.authority = authority;
	}

    @Override
    public String toString() {
    	return String.format("%s@%x; Username: %s; Authority: %s;", this.getClass().getName(), this.hashCode(), getUsername(), getAuthority());
    }

}

For now I’ll use an in-memory instance of HSQLDB to store my data. I initialize the tables with a SQL file that Hibernate loads when the application starts up.

import.sql

insert into Users (username, password, enabled, name, email, usasId) values ('keith', '417c7382b16c395bc25b5da1398cf076', TRUE, 'Keith Lee', 'keith@email.com', 'leemkei0891' )

insert into Authorities (username, authority) values ('keith', 'ROLE_USER, ROLE_SUPERVISOR, ROLE_SWIMMER' )

Now when I go to the profile page I can see that SWF’s currentUser and the user’s profile are set.

Current User: Name: keith
Credentials: [ROLE_USER, ROLE_SUPERVISOR, ROLE_SWIMMER]
Principal: org.springframework.security.core.userdetails.User@0: Username: keith; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER, ROLE_SUPERVISOR, ROLE_SWIMMER
Autorities: [ROLE_USER, ROLE_SUPERVISOR, ROLE_SWIMMER]
Details: org.springframework.security.web.authentication.WebAuthenticationDetails@255f8: RemoteIpAddress: 127.0.0.1; SessionId: 543BB337D17562B62F8CFFC8428272FB
User Profile: Object: org.bwgz.swim.openlane.model.User@3c8c7; Username: keith; Password: 417c7382b16c395bc25b5da1398cf076; Enabled: true; Authorities: [org.bwgz.swim.openlane.model.Authority@14bda9d; Username: keith; Authority: ROLE_USER, ROLE_SUPERVISOR, ROLE_SWIMMER;]; Name: Keith Lee; Email: keith@email.com; UsasId: leemkei0891;
Username: keith
Name: Keith Lee
Email: keith@email.com
UsasId: leemkei0891

Source code is available at github.

Open Lane – Supporting a User Part 1

April 13, 2012 Leave a comment

Open lane applications are restricted to swimmers already entered into the meet. A swimmer wanting to use the application first needs to establish their identity (register and login). The next iteration of the application adds the concept of a user to the application. User management, authentication, and authorization is a domain unto itself. This can become quite complex. At this early stage I’ll keep things simple and refactor as necessary later.

Spring Web Flow (SWF) provides a currentUser variable to access the authenticated principal. In this case principal relates to a Java object (UsernamePasswordAuthenticationToken) that Spring Security provides.  In order to take advantage of currentUser I have to be in a flow. Most examples like booking-faces start the user on a non-flow page and then provides a link into a flow. I want to use currentUser on the home page so I’ll route the user directly into a flow.

index.html

<html>
<head>
  <meta http-equiv="Refresh" content="0; URL=spring/home">
</head>
</html>

home-flow.xml

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/webflow
	http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

	<view-state id="home"></view-state>
</flow>

home.xhtml

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:c="http://java.sun.com/jsp/jstl/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">

<f:view contentType="text/html">

<h:head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>Open Lane</title>
</h:head>
<h:body>
<h1>Open Lane</h1>
<table border="1">
	<tr>
	<td>
		<b>Date:</b>
	</td>
	<td>
		${currentDate}
	</td>
	</tr>

	<tr>
		<td>
			<b>Current User:</b>
		</td>
		<td>
			<c:if test="${not empty currentUser.name}">
			  	<b>Name:</b> ${currentUser.name}
			  	<br/>
				<b>Credentials:</b> ${currentUser.authorities}
			  	<br/>
				<b>Principal:</b> ${currentUser.principal}
			  	<br/>
				<b>Autorities:</b> ${currentUser.authorities}
			  	<br/>
				<b>Details:</b> ${currentUser.details}
			</c:if>
			<c:if test="${empty currentUser.name}">
				Name: none
			</c:if>
		</td>
	</tr>

	<tr>
		<td>
			<b>User Actions:</b>
		</td>
		<td>
			<c:if test="${not empty currentUser.name}">
				Logout
			</c:if>
			<c:if test="${empty currentUser.name}">
			   	Login | Register
			</c:if>
		</td>
	</tr>
</table>
</h:body>
</f:view>
</html>

When a user is logged in this JSF produces a informational table such as this:

Date: Thu Apr 12 16:48:04 CDT 2012
Current User: Name: keith
Credentials: [ROLE_SUPERVISOR, ROLE_USER]
Principal: org.springframework.security.core.userdetails.User@fd0ef400: Username: keith; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_SUPERVISOR,ROLE_USER
Autorities: [ROLE_SUPERVISOR, ROLE_USER]
Details: org.springframework.security.web.authentication.WebAuthenticationDetails@380f4: RemoteIpAddress: 127.0.0.1; SessionId: 627E651937975B65B3248F7AD3ED6F78
User Actions: Logout

Integrating SWF with Spring Security requires adding security configurations to the application. Here’s the important part.

<security:http auto-config="true" use-expressions="true">
    <security:form-login login-page="/spring/login" login-processing-url="/spring/loginProcess"
        default-target-url="/spring/home" authentication-failure-url="/spring/login?login_error=1" />
    <security:logout logout-url="/spring/logout" logout-success-url="/spring/home" />
    <security:intercept-url pattern="/secure" method="POST" access="hasRole('ROLE_SUPERVISOR')"/>
</security:http>

A call to /spring/loginProcess will route the flow to a login.xhtmllogin.xhtml presents the user with a login form. If the login is successful the flow is routed to /spring/home. A user will be logged out if the flow is later routed to /spring/logout. Here is the login.xhtml I took from booking-faces.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">

<f:view contentType="text/html">

<h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Open Lane</title>
</h:head>
<h:body>
<div>
    <p>Valid username/passwords are:</p>
    <ul>
        <li>keith/melbourne</li>
        <li>erwin/leuven</li>
        <li>jeremy/atlanta</li>
        <li>scott/rochester</li>
    </ul>
</div>
<div>
    <c:if test="${not empty param.login_error}">
        <div class="error">
            Your login attempt was not successful, try again.<br />
            Reason: #{sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}
        </div>
    </c:if>
    <form name="f" action="${request.contextPath}/spring/loginProcess" method="post">
        <fieldset>
            <legend>Login Information</legend>
                <p>
                    User:
                    <br />
                    <c:if test="${not empty param.login_error}">
                        <c:set var="username" value="${sessionScope.SPRING_SECURITY_LAST_USERNAME}"/>
                    </c:if>
                    <input type="text" name="j_username" value="#{username}"/>
                </p>
                <p>
                    Password:
                    <br />
                    <input type="password" name="j_password" />
                </p>
                <p>
                    <input type="checkbox" name="_spring_security_remember_me"/>
                    Don't ask for my password for two weeks:
                </p>
                <p>
                    <input name="submit" type="submit" value="Login" />
                </p>
        </fieldset>
    </form>
</div>
</h:body>
</f:view>
</html>

With all this in place I’ll now change to the “User Action” on my home page to present either a login or logout link based on the currentUser. Here’s is the change to home.xhtml.

<tr>
    <td>
        <b>User Actions:</b>
    </td>
    <td>
        <c:if test="${not empty currentUser.name}">
            Welcome, ${currentUser.name} | <a href="${request.contextPath}/spring/logout">Logout</a>
        </c:if>
        <c:if test="${empty currentUser.name}">
             <a href="${request.contextPath}/spring/login">Login</a>
        </c:if>
    </td>
</tr>

Now I can login and logout at user. Source code is available at github.