105.

previous chapter table of contents next chapter
  

RCXLoaderFrameFactory

The factory object for the RCX is now easy to define ”it just returns a RCXLoaderFrame in the getUI() method:

 /**  * RCXLoaderFrameFactory.java   */ package rcx.jini; import net.jini.lookup.ui.factory.FrameFactory; import net.jini.core.lookup.ServiceItem; import java.awt.Frame; public class RCXLoaderFrameFactory implements FrameFactory {     public Frame getFrame(Object roleObj) {         ServiceItem item= (ServiceItem) roleObj;         RCXPortInterface port = (RCXPortInterface) item.service;         return new RCXLoaderFrame(port);     } } // RCXLoaderFrameFactory 

Exporting the FrameFactory

The factory object is exported by making it a part of a UIDescriptor entry object with a role, toolkit, and attributes:

 Set typeNames = new HashSet(); typeNames.add(FrameFactory.TYPE_NAME); Set attribs = new HashSet(); attribs.add(new UIFactoryTypes(typeNames)); // add other attributes as desired MarshalledObject factory = null; try {     factory = new MarshalledObject(new                                    RCXLoaderFrameFactory()); } catch(Exception e) {     e.printStackTrace();     System.exit(2); } UIDescriptor desc = new UIDescriptor(MainUI.ROLE,                                      FrameFactory.TOOLKIT,                                      attribs,                                      factory); Entry[] entries = {desc}; JoinManager joinMgr = new JoinManager(impl,                                       entries,                                       this,                                       new LeaseRenewalManager()); 

Customized User Interfaces

The RCXLoaderFrame is a general interface to any RCX robot. Of course, there could be many other such interfaces, differing in the classes used, the amount of international support, the appearance, etc. All the variations, however, will just use the standard RCXPortInterface , because that is all they know about.

The LEGO pieces can be combined in a huge variety of ways, and the RCX itself is programmable, so you can build an RCX car, an RCX crane , an RCX mazerunner, and so on. Each different robot can be driven by the general interface, but most could benefit from a custom-built interface for that type of robot. This is typical: for example, every blender could be driven from a general blender user interface (using the possibly forthcoming standard blender interface :-). But the blenders from individual vendors would have their own customized user interface for their brand of blender.

I have been using an RCX car. While it can do lots of things, it has been convenient to use five commands for demonstrations : forward, stop, back, left, and right, with a user interface as shown in Figure 19-3.


Figure 19-3: This is a control panel taken from the LEGO MINDSTORMS ¢ Robotics Invention System RCX programming system.

In Chapter 17, this appearance was hard-coded into the client. Since the client was just searching for any MINDSTORMS robot, it really shouldn't know about this sort of detail and should get this user interface from the robot service.

CarJFrame

The CarJFrame class produces the user interface as a Swing JFrame , with the buttons generating specific RCX code for this model.

 package rcx.jini; import java.awt.*; import java.awt.event.*; import javax.swing.*; import net.jini.core.event.RemoteEventListener; import net.jini.core.event.RemoteEvent; import net.jini.core.event.UnknownEventException; import java.net.URL; import java.rmi.RemoteException; class CarJFrame extends JFrame     implements RemoteEventListener, ActionListener {     public static final int STOPPED = 1;     public static final int FORWARDS = 2;     public static final int BACKWARDS = 4;     protected int state = STOPPED;     protected RCXPortInterface port = null;     JFrame frame;     JTextArea text;     public CarJFrame(RCXPortInterface port) {         super() ;         this.port = port;         frame = new JFrame("LEGO MINDSTORMS");         Container content = frame.getContentPane();         JLabel label = null;         ImageIcon icon = null;         try {             icon = new ImageIcon(new                         URL("http://www.LEGOMINDSTORMS.com/images/home_logo.ps"));             switch (icon.getImageLoadStatus()) {             case MediaTracker.ABORTED:              case MediaTracker.ERRORED:                 System.out.println("Error");                 icon = null;                 break;             case MediaTracker.COMPLETE:                 System.out.println("Complete");                 break;             case MediaTracker.LOADING:                 System.out.println("Loading");                 break;             }         } catch(java.net.MalformedURLException e) {             e.printStackTrace();         }         if (icon != null) {             label = new JLabel(icon);         } else {             label = new JLabel("MINDSTORMS");         }         JPanel pane = new JPanel();         pane.setLayout(new GridLayout(2, 3));         content.add(label, "North");         content.add(pane, "Center");         JButton btn = new JButton("Forward");         pane.add(btn);         btn.addActionListener(this);         btn = new JButton("Stop");         pane.add(btn);         btn.addActionListener(this);         btn = new JButton("Back");         pane.add(btn);         btn.addActionListener(this);         btn = new JButton("Left");         pane.add(btn);         btn.addActionListener(this);         label = new JLabel("");         pane.add(label);         btn = new JButton("Right");         pane.add(btn);         btn.addActionListener(this);         frame.pack();         frame.setVisible(true);     }     public void sendCommand(String comm) {         byte[] command;         try {             command = port.parseString(comm);             if (! port.write(command)) {                 System.err.println("command failed");             }         } catch(RemoteException e) {             e.printStackTrace();         }     }     public void forwards() {         sendCommand("e1 85");         sendCommand("21 85");         state = FORWARDS;     }     public void backwards() {         sendCommand("e1 45");         sendCommand("21 85");         state = BACKWARDS;     }     public void stop() {         sendCommand("21 45");         state = STOPPED;     }     public void restoreState() {         if (state == FORWARDS)             forwards();         else if (state == BACKWARDS)             backwards();         else             stop();     }     public void actionPerformed(ActionEvent evt) {         String name = evt.getActionCommand();         byte[] command;         if (name.equals("Forward")) {             forwards();         } else if (name.equals("Stop")) {             stop();         } else if (name.equals("Back")) {             backwards();         } else if (name.equals("Left")) {             sendCommand("e1 84");             sendCommand("21 84");             sendCommand("21 41");             try {                 Thread.sleep(100);             } catch(InterruptedException e) {             }             restoreState();         } else if (name.equals("Right")) {             sendCommand("e1 81");             sendCommand("21 81");             sendCommand("21 44");             try {                 Thread.sleep(100);             } catch(InterruptedException e) {             }             restoreState();         }     }     public void notify(RemoteEvent evt) throws UnknownEventException,         java.rmi.RemoteException {         // System.out.println(evt.toString());         long id = evt.getID();         long seqNo = evt.getSequenceNumber();         if (id == RCXPortInterface.MESSAGE_EVENT) {             byte[] message = port.getMessage(seqNo);             StringBuffer sbuffer = new StringBuffer();             for(int n = 0; n < message.length; n++) {                 int newbyte = (int) message[n];                 if (newbyte < 0) {                     newbyte += 256;                 }                 sbuffer.append(Integer.toHexString(newbyte) + " ");             }             System.out.println("MESSAGE: " + sbuffer.toString());         } else if (id == RCXPortInterface.ERROR_EVENT) {             System.out.println("ERROR: " + port.getError(seqNo));         } else {             throw new UnknownEventException("Unknown message " + evt.getID());         }     } } 

CarJFrameFactory

The factory generates a CarJFrame object, like this:

 /**   * CarJFrameFactory.java  */ package rcx.jini; import net.jini.lookup.ui.factory.JFrameFactory; import net.jini.core.lookup.ServiceItem; import javax.swing.JFrame; public class CarJFrameFactory implements JFrameFactory {     public JFrame getJFrame(Object roleObj) {         ServiceItem item  = (ServiceItem) roleObj;         RCXPortInterface port = (RCXPortInterface) item.service;         return new CarJFrame(port);     } } // CarJFrameFactory 

Exporting the FrameFactory

Both of the user interfaces discussed ”the RCXLoaderFrame and the CarJFrame ”can be exported by expanding the set of Entry objects.

 // generic UI Set genericAttribs = new HashSet(); Set typeNames = new HashSet(); typeNames.add(FrameFactory.TYPE_NAME); genericAttribs.add(new UIFactoryTypes(typeNames)); MarshalledObject genericFactory = null; try {     genericFactory = new MarshalledObject(new                                   RCXLoaderFrameFactory()); }catch(Exception e) {    e.printStackTrace();            System.exit(2); } UIDescriptor genericDesc = new UIDescriptor(MainUI.ROLE,                                             FrameFactory.TOOLKIT,                                                genericAttribs,                                             genericFactory); // car UI Set carAttribs = new HashSet(); typeNames = new HashSet(); typeNames.add(JFrameFactory.TYPE_NAME); carAttribs.add(new UIFactoryTypes(typeNames)); MarshalledObject carFactory = null; try {     carFactory = new MarshalledObject(new CarJFrameFactory()); } catch(Exception e) {     e.printStackTrace();     System.exit(2); } UIDescriptor carDesc = new UIDescriptor(MainUI.ROLE,                                         JFrameFactory.TOOLKIT,                                         carAttribs,                                         carFactory); Entry[] entries = {genericDesc, carDesc}; JoinManager joinMgr = new JoinManager(impl,                                       entries,                                       this,                                       new LeaseRenewalManager()); 

The RCX Client

The following client will start up all user interfaces that implement the main UI role and that use a Frame or JFrame:

 package client; import rcx.jini.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.rmi.RMISecurityManager; import net.jini.discovery.LookupDiscovery; import net.jini.discovery.DiscoveryListener; import net.jini.discovery.DiscoveryEvent; import net.jini.core.lookup.ServiceRegistrar; import net.jini.core.lookup.ServiceTemplate; import net.jini.core.event.RemoteEventListener; import net.jini.core.event.RemoteEvent; import net.jini.core.event.UnknownEventException; import java.rmi.server.UnicastRemoteObject; import java.rmi.RemoteException; import net.jini.core.entry.Entry; import net.jini.core.lookup.ServiceMatches; import net.jini.core.lookup.ServiceItem; import net.jini.lookup.entry.UIDescriptor; import net.jini.lookup.ui.MainUI; import net.jini.lookup.ui.attribute.UIFactoryTypes; import net.jini.lookup.ui.factory.FrameFactory; import net.jini.lookup.ui.factory.JFrameFactory; import java.util.Set; import java.util.Iterator; /**  * TestRCX2.java  */ public class TestRCX2 implements DiscoveryListener {     public static void main(String argv[]) {         new TestRCX2();         // stay around long enough to receive replies         try {             Thread.currentThread().sleep(1000000L);         } catch(java.lang.InterruptedException e) {             // do nothing         }     }     public TestRCX2() {         System.setSecurityManager(new RMISecurityManager());         LookupDiscovery discover = null;         try {             discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS);         } catch(Exception e) {             System.err.println(e.toString());             System.exit(1);         }         discover.addDiscoveryListener(this);     }     public void discovered(DiscoveryEvent evt) {         ServiceRegistrar[] registrars = evt.getRegistrars();         Class [] classes = new Class[] {RCXPortInterface.class};         RCXPortInterface port = null;         UIDescriptor desc = new UIDescriptor(MainUI.ROLE, null, null, null);         Entry[] entries = {desc};         ServiceTemplate template = new ServiceTemplate(null, classes,                                                        entries);         for (int n = 0; n < registrars.length; n++) {             System.out.println("Service found");             ServiceRegistrar registrar = registrars[n];             ServiceMatches matches = null;             try {                 matches = registrar.lookup(template, 10);             } catch(java.rmi.RemoteException e) {                 e.printStackTrace();                 System.exit(2);              }             for (int nn = 0; nn < matches.items.length; nn++) {                 ServiceItem item = matches.items[nn];                 port = (RCXPortInterface) item.service;                 if (port == null) {                     System.out.println("port null");                     continue;                 }                 Entry[] attributes = item.attributeSets;                 for (int m = 0; m < attributes.length; m++) {                     Entry attr = attributes[m];                     if (attr instanceof UIDescriptor) {                         showUI(port, item, (UIDescriptor) attr);                     }                 }             }          }     }     public void discarded(DiscoveryEvent evt) {         // empty     }     private void showUI(RCXPortInterface port,                         ServiceItem item,                         UIDescriptor desc) {         Set attribs = desc.attributes;         Iterator iter = attribs.iterator();         while (iter.hasNext()) {             Object obj = iter.next();             if (obj instanceof UIFactoryTypes) {                 UIFactoryTypes types = (UIFactoryTypes) obj;                 Set typeNames = types.getTypeNames();                 if (typeNames.contains(FrameFactory.TYPE_NAME)) {                     FrameFactory factory = null;                     try {                         factory = (FrameFactory) desc.getUIFactory(this.getClass().                                                                  getClassLoader());                     } catch(Exception e) {                         e.printStackTrace();                         continue;                     }                     Frame frame = factory.getFrame(item);                     frame.setVisible(true);                 } else if (typeNames.contains(JFrameFactory.TYPE_NAME)) {                     JFrameFactory factory = null;                     try {                        factory = (JFrameFactory) desc.getUIFactory(this.getClass().                                                                  getClassLoader());                     } catch(Exception e) {                         e.printStackTrace();                         continue;                     }                     JFrame frame = factory.getJFrame(item);                     frame.setVisible(true);                 }             } else {                 System.out.println("non-gui entry");             }         }     } } // TestRCX 
  


A Programmer[ap]s Guide to Jini Technology
A Programmer[ap]s Guide to Jini Technology
ISBN: 1893115801
EAN: N/A
Year: 2000
Pages: 189

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net