1   /*
2    * Copyright 2007-2008 Volker Fritzsch
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License. 
15   */
16  package motej.demos.nunchuk;
17  
18  import java.awt.Color;
19  import java.awt.Container;
20  import java.awt.Dimension;
21  import java.awt.FlowLayout;
22  import java.awt.Point;
23  import java.awt.event.ActionEvent;
24  import java.awt.event.WindowAdapter;
25  import java.awt.event.WindowEvent;
26  
27  import javax.swing.AbstractAction;
28  import javax.swing.Action;
29  import javax.swing.BorderFactory;
30  import javax.swing.JButton;
31  import javax.swing.JFrame;
32  import javax.swing.JLabel;
33  import javax.swing.SwingUtilities;
34  
35  import motej.Extension;
36  import motej.Mote;
37  import motej.MoteFinder;
38  import motej.MoteFinderListener;
39  import motej.event.AccelerometerEvent;
40  import motej.event.AccelerometerListener;
41  import motej.event.ExtensionEvent;
42  import motej.event.ExtensionListener;
43  import motej.request.ReportModeRequest;
44  import motejx.extensions.nunchuk.AnalogStickEvent;
45  import motejx.extensions.nunchuk.AnalogStickListener;
46  import motejx.extensions.nunchuk.Nunchuk;
47  import motejx.extensions.nunchuk.NunchukButtonEvent;
48  import motejx.extensions.nunchuk.NunchukButtonListener;
49  
50  /**
51   * 
52   * <p>
53   * @author <a href="mailto:vfritzsch@users.sourceforge.net">Volker Fritzsch</a>
54   */
55  @SuppressWarnings("serial")
56  public class NunchukGui implements MoteFinderListener, ExtensionListener, AccelerometerListener<Nunchuk>, AnalogStickListener, NunchukButtonListener {
57  	
58  	public static void main(String[] args) {
59  		SwingUtilities.invokeLater(new Runnable() {
60  		
61  			public void run() {
62  				new NunchukGui();
63  			}
64  		
65  		});
66  	}
67  	private JFrame frame;
68  	private Mote mote;
69  	private MoteFinder finder;
70  	
71  	private Nunchuk nunchuk;
72  	private JLabel maxPoint = new JLabel("cal (max)");
73  	private JLabel minPoint = new JLabel("cal (min)");
74  	
75  	private JLabel centerPoint = new JLabel("cal (center)");
76  	
77  	private AnalogStickPanel analogDisplay = new AnalogStickPanel();
78  	
79  	private AccelerometerPanel accelerometerPanel = new AccelerometerPanel();
80  	private JLabel moteLabel = new JLabel("none");
81  	
82  	private JLabel extensionLabel = new JLabel("none");
83  	
84  	private JButton zButton;
85  	
86  	private JButton cButton;
87  	
88  	private Color originalColor;
89  
90  	private Action startDiscoverAction = new AbstractAction() {
91  	
92  		public void actionPerformed(ActionEvent e) {
93  			finder.startDiscovery();
94  		}
95  	
96  	};
97  
98  	private Action cancelDiscoverAction = new AbstractAction() {
99  		
100 		public void actionPerformed(ActionEvent e) {
101 			finder.stopDiscovery();
102 		}
103 	
104 	};
105 	
106 	public NunchukGui() {
107 		finder = MoteFinder.getMoteFinder();
108 		finder.addMoteFinderListener(this);
109 		
110 		initGui();
111 	}
112 	
113 	public void accelerometerChanged(AccelerometerEvent<Nunchuk> evt) {
114 		accelerometerPanel.accelerometerValueChanged(evt.getX() & 0xff, evt.getY() & 0xff, evt.getZ() & 0xff);
115 	}
116 	
117 	public void analogStickChanged(AnalogStickEvent evt) {
118 		analogDisplay.setStickPoint(evt.getPoint());
119 		analogDisplay.repaint();
120 	}
121 
122 	public void buttonPressed(NunchukButtonEvent evt) {
123 		if (evt.isButtonCPressed()) {
124 			cButton.setBackground(Color.BLUE);
125 		} else {
126 			cButton.setBackground(originalColor);
127 		}
128 		
129 		if (evt.isButtonZPressed()) {
130 			zButton.setBackground(Color.BLUE);
131 		} else {
132 			zButton.setBackground(originalColor);
133 		}
134 	}
135 
136 	public void extensionConnected(ExtensionEvent evt) {
137 		final Extension ext = evt.getExtension();
138 		
139 		if (ext instanceof Nunchuk) {
140 			nunchuk = (Nunchuk) ext;
141 			nunchuk.addAccelerometerListener(this);
142 			nunchuk.addAnalogStickListener(this);
143 			nunchuk.addNunchukButtonListener(this);
144 			
145 			Thread t = new Thread(new Runnable() {
146 			
147 				public void run() {
148 					while (nunchuk.getCalibrationData() == null) {
149 						try {
150 							Thread.sleep(1l);
151 						} catch (InterruptedException ex) {
152 							ex.printStackTrace();
153 						}
154 					}
155 					analogDisplay.setNunchukCalibrationData(nunchuk.getCalibrationData());
156 					
157 					SwingUtilities.invokeLater(new Runnable() {
158 					
159 						public void run() {
160 							if (nunchuk != null && nunchuk.getCalibrationData() != null) {
161 								Point min = nunchuk.getCalibrationData().getMinimumAnalogPoint();
162 								Point max = nunchuk.getCalibrationData().getMaximumAnalogPoint();
163 								Point center = nunchuk.getCalibrationData().getCenterAnalogPoint();
164 								minPoint.setText("cal (min) - x: " + min.x + " / y: " + min.y);
165 								maxPoint.setText("cal (max) - x: " + max.x + " / y: " + max.y);
166 								centerPoint.setText("cal (center) - x: " + center.x + " / y: " + center.y);
167 
168 								int zero = nunchuk.getCalibrationData().getZeroForceX();
169 								int earth = nunchuk.getCalibrationData().getGravityForceX();
170 								accelerometerPanel.setCalibrationDataX(zero, earth);
171 								
172 								zero = nunchuk.getCalibrationData().getZeroForceY();
173 								earth = nunchuk.getCalibrationData().getGravityForceY();
174 								accelerometerPanel.setCalibrationDataY(zero, earth);
175 								
176 								zero = nunchuk.getCalibrationData().getZeroForceZ();
177 								earth = nunchuk.getCalibrationData().getGravityForceZ();
178 								accelerometerPanel.setCalibrationDataZ(zero, earth);
179 							}
180 						}
181 					
182 					});
183 				}
184 			
185 			});
186 			t.start();
187 			
188 			
189 			mote.setReportMode(ReportModeRequest.DATA_REPORT_0x32);
190 		}
191 		
192 		SwingUtilities.invokeLater(new Runnable() {
193 			
194 			public void run() {
195 				extensionLabel.setText(ext.toString());
196 			}
197 		
198 		});
199 	}
200 
201 	public void extensionDisconnected(ExtensionEvent evt) {
202 		SwingUtilities.invokeLater(new Runnable() {
203 		
204 			public void run() {
205 				extensionLabel.setText("none");
206 				minPoint.setText("");
207 				maxPoint.setText("");
208 				centerPoint.setText("");
209 			}
210 		
211 		});
212 	}
213 	
214 	protected void initGui() {
215 		frame = new JFrame("Nunchuk Gui");
216 		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
217 		frame.addWindowListener(new WindowAdapter() {
218 		
219 			@Override
220 			public void windowClosing(WindowEvent e) {
221 				if (mote != null) {
222 					mote.setReportMode(ReportModeRequest.DATA_REPORT_0x30);
223 					mote.disconnect();
224 				}
225 			}
226 		
227 		});
228 		
229 		JButton discoverButton = new JButton(startDiscoverAction);
230 		discoverButton.setText("Start Discovery");
231 		
232 		JButton cancelDiscoverButton = new JButton(cancelDiscoverAction);
233 		cancelDiscoverButton.setText("Cancel Discovery");
234 		
235 		cButton = new JButton("C");
236 		cButton.setEnabled(false);
237 		
238 		zButton = new JButton("Z");
239 		zButton.setEnabled(false);
240 		
241 		Container pane = frame.getContentPane();
242 		pane.setLayout(new FlowLayout());
243 		pane.add(discoverButton);
244 		pane.add(cancelDiscoverButton);
245 		pane.add(moteLabel);
246 		pane.add(extensionLabel);
247 		pane.add(cButton);
248 		pane.add(zButton);
249 		pane.add(minPoint);
250 		pane.add(maxPoint);
251 		pane.add(centerPoint);
252 		pane.add(analogDisplay);
253 		analogDisplay.setPreferredSize(new Dimension(250,250));
254 		analogDisplay.setBackground(Color.WHITE);
255 		analogDisplay.setBorder(BorderFactory.createLineBorder(Color.BLACK));
256 		
257 		pane.add(accelerometerPanel);
258 		
259 //		frame.setSize(800, 600);
260 		frame.pack();
261 		
262 		frame.setVisible(true);
263 		originalColor = zButton.getBackground();
264 	}
265 
266 	public void moteFound(final Mote mote) {
267 		this.mote = mote;
268 //		finder.stopDiscovery();
269 		mote.setPlayerLeds(new boolean[] {true, false, false, false} );
270 		SwingUtilities.invokeLater(new Runnable() {
271 		
272 			public void run() {
273 				moteLabel.setText(mote.toString());
274 			}
275 		
276 		});
277 		mote.addExtensionListener(this);
278 	}
279 }