Java tutorial
/** * Squidy Interaction Library is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * Squidy Interaction Library is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Squidy Interaction Library. If not, see * <http://www.gnu.org/licenses/>. * * 2009 Human-Computer Interaction Group, University of Konstanz. * <http://hci.uni-konstanz.de> * * Please contact info@squidy-lib.de or visit our website * <http://www.squidy-lib.de> for further information. */ package org.squidy.nodes; import java.awt.event.KeyEvent; import java.util.Collection; import javax.swing.JFrame; import javax.swing.JLabel; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlType; import motej.IrPoint; import motej.Mote; import motej.event.AccelerometerEvent; import motej.event.AccelerometerListener; import motej.event.CoreButtonEvent; import motej.event.CoreButtonListener; import motej.event.IrCameraEvent; import motej.event.IrCameraListener; import motej.event.MoteDisconnectedEvent; import motej.event.MoteDisconnectedListener; import motej.request.ReportModeRequest; import motejx.adapters.IrDistanceAdapter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.squidy.manager.controls.TextField; import org.squidy.manager.data.IData; import org.squidy.manager.data.Processor; import org.squidy.manager.data.Property; import org.squidy.manager.data.Processor.Status; import org.squidy.manager.data.impl.DataButton; import org.squidy.manager.data.impl.DataInertial; import org.squidy.manager.data.impl.DataKey; import org.squidy.manager.data.impl.DataPosition2D; import org.squidy.manager.data.impl.DataPosition3D; import org.squidy.manager.model.AbstractNode; import org.squidy.nodes.wiimote.SimpleMoteFinder; /** * <code>WiiMote</code>. * * <pre> * Date: Feb 13, 2008 * Time: 12:49:13 AM * </pre> * * @author Roman Rädle, <a * href="mailto:Roman.Raedle@uni-konstanz.de">Roman.Raedle@uni-konstanz.de</a>, * University of Konstanz * @version $Id: Wiimote.java 772 2011-09-16 15:39:44Z raedle $ */ @XmlType(name = "Wiimote") @Processor(name = "Wiimote", icon = "/org/squidy/nodes/image/48x48/wiimote.png", types = { Processor.Type.INPUT, Processor.Type.OUTPUT }, description = "/org/squidy/nodes/html/Wiimote.html", tags = { "wiimote", "nintendo", "wii", "tracking", "ir", "infrared", "camera" }, status = Status.UNSTABLE) public class Wiimote extends AbstractNode { // Log to log info, error, debug,... messages. private static final Log LOG = LogFactory.getLog(Wiimote.class); // ################################################################################ // BEGIN OF ADJUSTABLES // ################################################################################ // -Dbluecove.jsr82.psm_minimum_off=true // @XmlValue() // @XmlElementWrapper(name = "bluetooth-addresses") private Collection<String> bluethoothAddresses; @XmlAttribute(name = "bluetooth-address") @Property(name = "Bluetooth address", description = "Bluetooth address of Wiimote device.") @TextField private String bluetoothAddress = "00:00:00:00:00"; /** * @return the bluetoothAddress */ public String getBluetoothAddress() { return bluetoothAddress; } /** * @param bluetoothAddress * the bluetoothAddress to set */ public void setBluetoothAddress(String bluetoothAddress) { this.bluetoothAddress = bluetoothAddress; if (mote != null) { mote.rumble(rumbleTime); } } // ################################################################################ // @XmlAttribute(name = "ir-light-distance") // @Adjustable(@Description("Distance between IR light transceivers.")) // private double irLightDistance = 150d; // // /** // * @return the irLightDistance // */ // public double getIrLightDistance() { // return irLightDistance; // } // // /** // * @param irLightDistance // * the irLightDistance to set // */ // public void setIrLightDistance(double irLightDistance) { // this.irLightDistance = irLightDistance; // // if (irCamera3D != null) { // irCamera3D.setIrLightDistance(irLightDistance); // } // // if (mote != null) { // mote.rumble(rumbleTime); // } // } @XmlAttribute(name = "rumble-time") @Property(name = "Rumble time", description = "Rumble time in milliseconds") @TextField private long rumbleTime = 100; /** * @return the rumbleTime */ public long getRumbleTime() { return rumbleTime; } /** * @param rumbleTime * the rumbleTime to set */ public void setRumbleTime(long rumbleTime) { this.rumbleTime = rumbleTime; if (mote != null) { mote.rumble(rumbleTime); } } // ################################################################################ // END OF ADJUSTABLES // ################################################################################ // The connected mote. protected Mote mote; // The core button listener. protected CoreButtonListener coreButtonListener; // The 2 dimensional IR adapter. protected IrCameraListener irCamera2DListener; // The 3 dimensional IR adapter. protected IrDistanceAdapter irCamera3DListener; // The accelerometer listener. protected AccelerometerListener<Mote> accelerometerListener; /* (non-Javadoc) * @see org.squidy.manager.ReflectionProcessable#onStart() */ @Override public void onStart() { System.out.println("start"); // BlueCoveImpl.setConfigProperty(BlueCoveConfigProperties.PROPERTY_JSR_82_PSM_MINIMUM_OFF, "true"); if (LOG.isDebugEnabled()) { LOG.debug("Initializing Wiimote."); } coreButtonListener = createCoreButtonListener(); irCamera2DListener = createIrCameraListener2D(); irCamera3DListener = createIrCameraListener3D(); accelerometerListener = createAccelerometerListener(); Thread startup = new Thread(new Runnable() { /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ public void run() { final JFrame frame = new JFrame("Waiting for WiiMote"); frame.add(new JLabel("Waiting for WiiMote - Please press button 1 and 2!")); frame.pack(); frame.setVisible(true); mote = null; if (mote == null) { // If bluetooth address has been set using this address // instead // of searching for WiiMote devices. // Declaration of bluetooth address will result in a faster // connection. if (bluetoothAddress == null || "00:00:00:00:00".equals(bluetoothAddress) || "".equals(bluetoothAddress)) { SimpleMoteFinder moteFinder = new SimpleMoteFinder(); mote = moteFinder.findMote(); } else { mote = new Mote(bluetoothAddress); } } else { System.out.println("using mote: " + mote); } mote.remoteMoteDisconnectedListener(new MoteDisconnectedListener<Mote>() { /* (non-Javadoc) * @see motej.event.MoteDisconnectedListener#moteDisconnected(motej.event.MoteDisconnectedEvent) */ public void moteDisconnected(MoteDisconnectedEvent<Mote> evt) { System.out.println("Mote has been disconnected: " + evt.getSource()); } }); internalInitialize(frame, mote); frame.setVisible(false); } }, "WiimoteStartup"); startup.start(); } /** * @param frame * @param mote */ private void internalInitialize(JFrame frame, Mote mote) { // Add button listener. mote.addCoreButtonListener(coreButtonListener); // Add accelerometer listener. mote.addAccelerometerListener(accelerometerListener); // Add IR camera listener for 2 dimensional position. mote.addIrCameraListener(irCamera2DListener); // Add IR camera listener for 3 dimensional position. // todo [RR]: do not sample both (DataPosition2D and DataPosition3D) at // the same time. // mote.addIrCameraListener(irCamera3D); mote.enableIrCamera(); mote.setReportMode(ReportModeRequest.DATA_REPORT_0x37); mote.setPlayerLeds(new boolean[] { true, false, false, false }); mote.rumble(rumbleTime); frame.setVisible(false); } /* (non-Javadoc) * @see org.squidy.manager.ReflectionProcessable#onStop() */ @Override public void onStop() { System.out.println("stop"); if (LOG.isDebugEnabled()) { LOG.debug("Closing Wiimote."); } Thread shutdown = new Thread(new Runnable() { /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ public void run() { System.out.println("Shuttinng down Wiimote"); final JFrame frame = new JFrame("Shutting down Wiimote"); frame.add(new JLabel("Shutting down Wiimote")); frame.pack(); frame.setVisible(true); if (mote != null) { mote.setPlayerLeds(new boolean[] { false, false, false, true }); mote.setReportMode(ReportModeRequest.DATA_REPORT_0x30); mote.removeCoreButtonListener(coreButtonListener); mote.removeIrCameraListener(irCamera2DListener); mote.removeAccelerometerListener(accelerometerListener); mote.disableIrCamera(); mote.disconnect(); } frame.setVisible(false); // BlueCoveImpl.shutdown(); } }, "WiimoteShutdown"); shutdown.start(); } /* * (non-Javadoc) * * @see org.squidy.manager.input.AbstractDriver#process(org.squidy.manager.data.IData) */ public IData process(IData data) { // Tactile feedback. if (mote != null) { mote.rumble(rumbleTime); } return null; } /** * Adds a <code>CoreButtonListener</code> to the parameter mote. * * @param mote * The mote that gets the core button listener. */ private CoreButtonListener createCoreButtonListener() { return new CoreButtonListener() { /* * (non-Javadoc) * * @see motej.event.CoreButtonListener#buttonPressed(motej.event.CoreButtonEvent) */ public void buttonPressed(CoreButtonEvent evt) { // Propagate buttons as button events. publish(new DataButton(Wiimote.class, DataButton.BUTTON_1, evt.isButtonAPressed())); // TODO Roman: Change button back to BUTTON_3. publish(new DataButton(Wiimote.class, DataButton.BUTTON_10, evt.isButtonBPressed())); publish(new DataButton(Wiimote.class, DataButton.BUTTON_A, evt.isButtonAPressed())); publish(new DataButton(Wiimote.class, DataButton.BUTTON_B, evt.isButtonBPressed())); // Home button pressed results in a VK_H key event. publish(new DataKey(Wiimote.class, KeyEvent.VK_H, evt.isButtonHomePressed())); // Propagate pad keys. -> UP, RIGHT, DOWN, LEFT result in VK_UP, // VK_RIGHT, VK_DOWN, VK_LEFT. publish(new DataKey(Wiimote.class, KeyEvent.VK_UP, evt.isDPadUpPressed())); publish(new DataKey(Wiimote.class, KeyEvent.VK_RIGHT, evt.isDPadRightPressed())); publish(new DataKey(Wiimote.class, KeyEvent.VK_DOWN, evt.isDPadDownPressed())); publish(new DataKey(Wiimote.class, KeyEvent.VK_LEFT, evt.isDPadLeftPressed())); // Button (-) and (+) pressed -> result in VK_MINUS and VK_PLUS // key event. publish(new DataKey(Wiimote.class, KeyEvent.VK_MINUS, evt.isButtonMinusPressed())); publish(new DataKey(Wiimote.class, KeyEvent.VK_PLUS, evt.isButtonPlusPressed())); publish(new DataButton(Wiimote.class, DataButton.BUTTON_PLUS, evt.isButtonPlusPressed())); // Button (1) and (2) pressed -> result in VK_1 and VK_2 key // event. publish(new DataKey(Wiimote.class, KeyEvent.VK_1, evt.isButtonOnePressed())); publish(new DataKey(Wiimote.class, KeyEvent.VK_2, evt.isButtonTwoPressed())); } }; } /** * Creates the IR camera listener for 2 dimensional positions. * * @return The configured 2D IR camera listener. */ private IrCameraListener createIrCameraListener2D() { return new IrCameraListener() { /* * (non-Javadoc) * * @see motej.event.IrCameraListener#irImageChanged(motej.event.IrCameraEvent) */ public void irImageChanged(IrCameraEvent evt) { IrPoint point = evt.getIrPoint(0); // Adjust coordinates to relative values from either minimum 0 // or maximum 1. // !!! y value could be more than 1 caused by a 1023 value if IR // transceiver diode is out-of-reach. double x = point.getX() / 1023; double y = point.getY() / 767; // Send data position event. publish(new DataPosition2D(Wiimote.class, x, y)); } }; } /** * Creates the IR camera listener for 3 dimensional positions. * * @return The configured 3D IR camera listener. */ private IrDistanceAdapter createIrCameraListener3D() { // return new IrDistanceAdapter(irLightDistance) { return new IrDistanceAdapter(150d) { /* * (non-Javadoc) * * @see motejx.adapters.IrDistanceAdapter#positionChanged(double, * double, double) */ @Override public void positionChanged(double x, double y, double z) { publish(new DataPosition3D(Wiimote.class, x, y, z, -1)); } }; } /** * Creates an accelerometer listener. * * @return The configured accelerometer listener. */ private AccelerometerListener<Mote> createAccelerometerListener() { return new AccelerometerListener<Mote>() { /* * (non-Javadoc) * * @see motej.event.AccelerometerListener#accelerometerChanged(motej.event.AccelerometerEvent) */ public void accelerometerChanged(AccelerometerEvent<Mote> evt) { int x = evt.getX(); int y = evt.getY(); int z = evt.getZ(); publish(new DataInertial(Wiimote.class, x, y, z, false)); } }; } }