import java.io.*; import java.net.*; /** * This class provides location awareness to the granularity of a room * inside a building based on the reception of 802.11 broadcasts and the * corresponding detection of ultrasound. This class is intended to be used * by an application running on a mobile device. If the mobile device moves * close to a desktop running the ServerBeacon class/application, it will * know that it is in the same room as the desktop based on the information * provided by this MobileClient class. *

* An application using this class needs to provide a reference to itself in * the MobileClient class's constructor. The application must also have a * roomChanged() method so that the MobileClient class can signal the * application when a room change has occurred. * * @author Tony Offer * @author Chris Palistrant * @version 1.0 */ public class MobileClient { // Reference to the object/application that instantiated this MobileClient private Object notifyApp = null; // The multicast socket that will be collecting 802.11 broadcasts // directed toward a certain multicast group. private MulticastSocket socket = null; // The ultrasound listener object that will be responsible for // recording and analyzing the sound in the room in order to detect // the presence of ultrasound. private UltrasoundListener ultrasound = null; // This string identifies the current room in which this // MobileClient object perceives itself to exist. private String room = null; // The multicast group that this MobileClient's socket should join in // order to receive 802.11 broadcasts. public static final String GROUPADDR = "239.255.255.254"; // The port number on which to listen for the 802.11 broadcasts. public static final int PORTNUM = 8019; /** * This is the only constructor for this class. It takes a reference * to the object that instantiated it so that the MobileClient class * can notify the object when a room change has occurred. No other * constructor is provided because the MobileClient class must have * access to a roomChanged() method. * * @param extApp Reference to the external object/application that * instantiated this MobileClient object. */ public MobileClient(Object extApp) { notifyApp = extApp; try { // Instantiate a new multicast socket with the appropriate port // number. socket = new MulticastSocket(PORTNUM); // Get the InetAddress corresponding to the string stored in // GROUPADDR and make the socket join this group so that it // can receive messages directed to this group address. InetAddress group = InetAddress.getByName(GROUPADDR); socket.joinGroup(group); } catch (SocketException se) { se.printStackTrace(); System.exit(1); } catch (SecurityException se) { se.printStackTrace(); System.exit(1); } catch (IOException ioe) { ioe.printStackTrace(); System.exit(1); } catch (UnknownHostException uhe) { uhe.printStackTrace(); System.exit(1); } // Instantiate a new UltrasoundListener for the purpose of // detecting ultrasound. ultrasound = new UltrasoundListener(); // Start a new Listener thread so that this MobileClient class // can be made aware of room changes. new Listener(this, socket, ultrasound).start(); } /** * This is the method that will be called by Listener threads when * the threads are done detecting 802.11 and ultrasound. Based on * the 802.11 room string and ultrasound boolean decision it * receives, the update() method will decide whether a room change * has occurred, signalling the external application if necessary. * * @param roomString The 802.11 room-identifying message that was * received by the Listener thread. * @param ultrasoundPresent Boolean decision indicating whether * or not ultrasound was found to be * present by the Listener thread. */ public void update(String roomString, boolean ultrasoundPresent) { // If the room string is different and ultrasound was detected, // a change in room location has occurred. Otherwise, if the // room string is the same and ultrasound was not detected, then // the device running this MobileClient class is no longer in // the room identified by 'room'. if ( !roomString.equals(room) && ultrasoundPresent ) { // Update this MobileClient's 'room' identifier room = roomString; // Notify the external application of a room change. notifyApp.roomChanged(roomString); else if ( roomString.equals(room) && !ultrasoundPresent ) { // Update this MobileClient's 'room' identifier -- the // mobile device is currently not in a room. room = null; // Notify the external application of a room change. notifyApp.roomChanged(room); } } }