Finding iButton Adapters Quickly

August 16th, 2007 by peasleer

The attendance database project I’ve recently written about requires the use of iButtons for verifying the physical presence of members at meetings. Having never worked with either the hardware other than as a user of it nor the software SDK in any capacity, it was a learning experience. One thing I quickly ran across when developing the software to locate a plugged-in adapter and read the iButton’s ID was the incredible amount of time it took to enumerate through the available ports just to find a connected adapter. The SDK provided examples on how to go about locating connected adapters, but to improve the speed at which it runs we can take advantage of what we know about the system and exploiting the code’s error conditions.

During installation of the 1-Wire drivers needed to communicate with iButton adapters, you have the option of selecting a default port to which the adapter will be connected. This information is stored as a property the SDK knows how to locate. The first step to increasing the speed of locating an adapter is to use this information - simply check the default port before searching all other ports on the machine. Odds are higher that the adapter is located on that port than any other port on the system, and by placing it as the first check before serially searching all other ports you increase your chances of getting on the first attempt.

The second enhancement requires a bit of background information. The example provided in the SDK shows you how to search all possible adapter types, then all possible ports for that adapter, and print them out. To be useful we would want instead of printing out the adapter and port names to attempt retrieving the device connected there. This would logically be done using the static getAdapter(String adapterName, String portName) method of the DSPortAdapter class. However, the time this method takes to return whether the adapter exists could be measured in seconds. To make this faster using our understanding of the system, we could skip over adapters we know we won’t be using (network adapters, parallel adapters, serial adapters, etc) and avoid scanning for them over all ports entirely. Reducing the size of the problem reduces the time it takes to come to a solution.

That is not all we can do, however. For some reason, if you try to retrieve an adapter using the getAdapter method and attempt to tell if it is successful by comparing the return object against null, it takes a long time. In comparison, the method throws an exception if it cannot locate the adapter much more quickly. Using this last bit of information, by putting a continue statement in your exception catching code you can just skip the attempt to open the obviously unavailable reader and enjoy a nice speed boost.

Here is some example code illustrating what I’ve talked about, excluding rolling over adapters we don’t care about. The speed of this is much faster than my first attempt, from taking around five minutes to locate an adapter to around 30 seconds. Base of code taken from the examples provided in the 1-Wire Java API. Sorry about the indenting, I gave up trying to figure out how to adjust the tabstop!


/**
 * Locate a reader to communicate with.
 *
 * @return boolean - true if adapter was found, false otherwise.
 */
public boolean locateAdapter( ) {
	boolean found = false;
	while( !found ) {
		try {
			DSPortAdapter adapter = OneWireAccessProvider.getDefaultAdapter();
			System.out.println(”Adapter ” + adapter.getAdapterName() +
						” found on port ” + adapter.getPortName());
			this.adapter = adapter;
			this.port = adapter.getPortName();
			found = true;
		} catch(Exception e) {
			System.out.println(”Adapter not found on default port, trying all ” +
					“available to the system…”);
		}
		if( !found ) {
			DSPortAdapter adapter;
			String port;
			// get the adapters
			for (Enumeration adapter_enum = (Enumeration) OneWireAccessProvider.enumerateAllAdapters();
				adapter_enum.hasMoreElements(); )
			{
				adapter = ( DSPortAdapter ) adapter_enum.nextElement();
				System.out.println(”Trying adapter ” + adapter.getAdapterName() );
				// get the ports
				for (Enumeration port_enum = adapter.getPortNames();
					port_enum.hasMoreElements(); )
				{
					port = ( String ) port_enum.nextElement();
					System.out.println(”trying port ” + port );
					try {
						OneWireAccessProvider.getAdapter(adapter.getAdapterName(), port);
						this.adapter = adapter;
						this.port = port;
						found = true;
					} catch( OneWireException owe ) {
						// Just continue…
						continue;
					}
				}
				if( found ) {
					break;
				}
			}
		}

		if( found ) {
			System.out.println(”Adapter found! Using ” + this.adapter.getAdapterName() +
					” on port ” + this.port );
		} else {
			// Wait 5 seconds before trying again
			try {
				Thread.sleep( 5000 );
			} catch (InterruptedException ie ) {}
		}
	}

	return found;
}

1 Response to “Finding iButton Adapters Quickly”

Feed for this Entry Trackback Address
  1. 1

    Debugging Serial Applications Using Screen

    [...] Software Engineering department through a serial interface. I really like writing code that interfaces with hardware, so this was one I enjoyed [...]

Leave a Reply