/**
*
* @author greg (at) myrobotlab.org
*
* This file is part of MyRobotLab (http://myrobotlab.org).
*
* MyRobotLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version (subject to the "Classpath" exception
* as provided in the LICENSE.txt file that accompanied this code).
*
* MyRobotLab is distributed in the hope that it will be useful or fun,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* All libraries in thirdParty bundle are subject to their own license
* requirements - please refer to http://myrobotlab.org/libraries for
* details.
*
* Enjoy !
*
* */
package org.myrobotlab.service;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.HashMap;
import org.myrobotlab.framework.Service;
import org.myrobotlab.framework.ServiceType;
import org.myrobotlab.logging.Level;
import org.myrobotlab.logging.LoggerFactory;
import org.myrobotlab.logging.Logging;
import org.myrobotlab.logging.LoggingFactory;
import org.slf4j.Logger;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import wiiusej.WiiUseApiManager;
import wiiusej.Wiimote;
import wiiusej.wiiusejevents.physicalevents.ExpansionEvent;
import wiiusej.wiiusejevents.physicalevents.IREvent;
import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent;
import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent;
import wiiusej.wiiusejevents.utils.WiimoteListener;
import wiiusej.wiiusejevents.wiiuseapievents.ClassicControllerInsertedEvent;
import wiiusej.wiiusejevents.wiiuseapievents.ClassicControllerRemovedEvent;
import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent;
import wiiusej.wiiusejevents.wiiuseapievents.GuitarHeroInsertedEvent;
import wiiusej.wiiusejevents.wiiuseapievents.GuitarHeroRemovedEvent;
import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent;
import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent;
import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent;
/**
*
* Wii - support for the wiimote as a controller.
*
* http://diy.sickmods.net/Tutorials/Wii/Disassemble_Wiimote/
* http://procrastineering.blogspot.com/2008/09/working-with-pixart-camera-
* directly.html
* http://www.bot-thoughts.com/2010/12/connecting-mbed-to-wiimote-ir-camera.html
*
*/
public class Wii extends Service implements WiimoteListener, SerialPortEventListener {
public static class IRData implements Serializable {
private static final long serialVersionUID = 1L;
public long time;
transient public IREvent event;
public IRData(long t, int s) {
this.time = t;
}
public IRData(long t, IREvent ir) {
this.time = t;
this.event = ir;
}
}
private static final long serialVersionUID = 1L;
public final static Logger log = LoggerFactory.getLogger(Wii.class);
transient Wiimote[] wiimotes = null;
transient Wiimote wiimote = null;
int cnt = 0;
boolean serialInitialized = false;
private long bitCount = 0;
private boolean strobeState = true;
public static class Blah {
public String name;
Integer pos = 0;
Integer x = 7;
}
/**
* Static list of third party dependencies for this service. The list will be
* consumed by Ivy to download and manage the appropriate resources
*
* @return
*/
public static void main(String[] args) {
LoggingFactory.init(Level.DEBUG);
try {
Object object = new Object();
Class<Object> c = Object.class;
int loops = 1000000;
long start = System.currentTimeMillis();
for (int i = 0; i < loops; i++) {
object.toString();
}
System.out.println(loops + " regular method calls:" + (System.currentTimeMillis() - start) + " milliseconds.");
java.lang.reflect.Method method = c.getMethod("toString", (Class<?>[]) null);
HashMap<String, Method> mcache = new HashMap<String, Method>();
mcache.put("toString", method);
System.out.println(loops + " reflective method calls without lookup:" + (System.currentTimeMillis() - start) + " milliseconds.");
start = System.currentTimeMillis();
for (int i = 0; i < loops; i++) {
// Integer x = new Integer(7);
method = c.getMethod(String.format("%s", "toString"));
method.invoke(object, (Object[]) null);
}
System.out.println(loops + " reflective method calls with lookup:" + (System.currentTimeMillis() - start) + " milliseconds.");
Wii wii = new Wii("wii");
// add the port as a possible option for the Arduino
/*
* Arduino.addPortName("wiicom", CommPortIdentifier.PORT_SERIAL,
* (CommDriver) new WiiDriver(wii));
*/
/*
* try { portId = CommPortIdentifier.getPortIdentifier("wiicom"); } catch
* (NoSuchPortException e1) { // TODO Auto-generated catch block
* e1.printStackTrace(); }
*/
Arduino arduino = new Arduino("arduino");
arduino.startService();
Servo servo = new Servo("servo");
servo.startService();
// GUIService gui = new GUIService("gui");
// gui.startService();
wii.getWiimotes();
wii.initSerial();
wii.setSensorBarAboveScreen();
wii.activateIRTRacking();
wii.setIrSensitivity(5); // 1-5 (highest)
wii.activateListening();
} catch (Exception e) {
Logging.logError(e);
}
}
public Wii(String n) {
super(n);
}
public void activateIRTRacking() {
wiimote.activateIRTRacking();
}
public void activateListening() {
wiimote.addWiiMoteEventListeners(this);
}
// button publishing/event hooks end -------
public void activateMotionSensing() {
wiimote.activateMotionSensing();
}
public Wiimote[] getWiimotes() {
wiimotes = WiiUseApiManager.getWiimotes(1, true);
wiimote = wiimotes[0];
return wiimotes;
}
public Wiimote[] getWiimotes(int n, boolean rumble) {
return WiiUseApiManager.getWiimotes(n, rumble);
}
public boolean initSerial() {
// magic 3 bytes - this is to synch the protocol
// when the wii connects the leds are flashing
// the arduino will disregard this garbage data
// the wii should stop with the first led high
// these 3 bytes should stop the arduino from
// continuing to disregard
// synced
if (wiimote == null) {
log.error("wii is not connected - can not initialize");
log.error("please press the (1) & (2) buttons of the wii - and re-run program while lights are flashing");
return false;
}
if (!serialInitialized) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
logException(e);
} // must slow down to initialize
// force to correct state strobe state
wiimote.setLeds(true, false, false, false);
// break out of init
wiimote.setLeds(false, false, true, false);
wiimote.setLeds(true, false, false, false);
wiimote.setLeds(false, false, false, false); // last 2 bits
// disregarded !
wiimote.setLeds(true, false, false, false);
wiimote.setLeds(false, false, false, false);
wiimote.setLeds(true, false, false, false); // last 2 bits
// disregarded
wiimote.setLeds(false, false, false, false);
wiimote.setLeds(true, true, true, true);
wiimote.setLeds(false, true, true, true);
serialInitialized = true;
} else {
log.warn("wii serial already initialized");
}
return true;
}
// button publishing/event hooks begin -------
public void onButtonDownJustPressed() {
log.info("buttonDownJustPressed");
}
public void onButtonLeftJustPressed() {
log.info("onButtonLeftJustPressed");
}
public void onButtonRightJustPressed() {
log.info("onButtonRightJustPressed");
}
// TODO - support shutdown()
@Override
public void onButtonsEvent(WiimoteButtonsEvent arg0) {
log.debug("{}", arg0);
// if (arg0.isButtonAPressed()){
// WiiUseApiManager.shutdown();
// }
if (arg0.isButtonDownJustPressed()) {
invoke("onButtonDownJustPressed");
}
if (arg0.isButtonUpJustPressed()) {
invoke("onButtonUpJustPressed");
}
if (arg0.isButtonLeftJustPressed()) {
invoke("onButtonLeftJustPressed");
}
if (arg0.isButtonRightJustPressed()) {
invoke("onButtonRightJustPressed");
}
}
public void onButtonUpJustPressed() {
log.info("onButtonUpJustPressed");
}
@Override
public void onClassicControllerInsertedEvent(ClassicControllerInsertedEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void onClassicControllerRemovedEvent(ClassicControllerRemovedEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void onDisconnectionEvent(DisconnectionEvent arg0) {
log.debug("disconnect event {}", arg0);
}
@Override
public void onExpansionEvent(ExpansionEvent arg0) {
log.debug("expansion event {}", arg0);
}
@Override
public void onGuitarHeroInsertedEvent(GuitarHeroInsertedEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void onGuitarHeroRemovedEvent(GuitarHeroRemovedEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void onIrEvent(IREvent arg0) {
// log.debug(arg0);
++cnt;
if (cnt % 100 == 0) {
log.error("cnt {}", cnt);
}
IRData ir = new IRData(System.currentTimeMillis(), arg0);
// t.add(ir);
invoke("publishIR", ir);
}
@Override
public void onMotionSensingEvent(MotionSensingEvent arg0) {
log.debug("motion sensing event {}", arg0);
}
@Override
public void onNunchukInsertedEvent(NunchukInsertedEvent arg0) {
log.debug("NunchukInsertedEvent {}", arg0);
}
@Override
public void onNunchukRemovedEvent(NunchukRemovedEvent arg0) {
log.debug("NunchukRemovedEvent {}", arg0);
}
@Override
public void onStatusEvent(StatusEvent arg0) {
log.debug("status event {}", arg0);
}
public IRData publishIR(IRData ir) {
return ir;
}
// NOT THREAD SAFE
// true = 0 | false = 1 - thats how the hardware works :P
public void sendSerial(int data) {
if (!serialInitialized) {
initSerial();
}
strobeState = (bitCount % 2 == 0);
// 1st 3 MSB bits
wiimote.setLeds(strobeState, (data & 128) == 0, (data & 64) == 0, (data & 32) == 0);
++bitCount;
// 2nd 3 bits
wiimote.setLeds(!strobeState, (data & 16) == 0, (data & 8) == 0, (data & 4) == 0);
++bitCount;
// last 2 bits
wiimote.setLeds(strobeState, (data & 2) == 0, (data & 1) == 0, false);
++bitCount;
}
@Override
public void serialEvent(SerialPortEvent arg0) {
// TODO Auto-generated method stub
log.info("serialEvent - YAY!");
}
public void setIrSensitivity(int level) {
wiimote.setIrSensitivity(level);
}
public void setLeds(boolean l1, boolean l2, boolean l3, boolean l4) {
wiimote.setLeds(l1, l2, l3, l4);
}
public void setSensorBarAboveScreen() {
wiimote.setSensorBarAboveScreen();
}
public void setSensorBarBelowScreen() {
wiimote.setSensorBarBelowScreen();
}
/**
* This static method returns all the details of the class without it having
* to be constructed. It has description, categories, dependencies, and peer
* definitions.
*
* @return ServiceType - returns all the data
*
*/
static public ServiceType getMetaData() {
ServiceType meta = new ServiceType(Wii.class.getCanonicalName());
meta.addDescription("Wii mote control and sensor info");
meta.addCategory("control", "sensor");
meta.addDependency("wiiuse.wiimote", "0.12b");
return meta;
}
}