diff --git a/java/device.wiimote/build.gradle b/java/device.wiimote/build.gradle new file mode 100644 index 0000000..fa68d6b --- /dev/null +++ b/java/device.wiimote/build.gradle @@ -0,0 +1,5 @@ +dependencies { + compile project(':core.legacy') + compile project(':exec.mimis') + compile project(':device.lirc') +} \ No newline at end of file diff --git a/java/exec.mimis/src/main/java/mimis/device/wiimote/gesture/GestureDevice.java b/java/device.wiimote/src/gesture/GestureDevice.java similarity index 100% rename from java/exec.mimis/src/main/java/mimis/device/wiimote/gesture/GestureDevice.java rename to java/device.wiimote/src/gesture/GestureDevice.java diff --git a/java/exec.mimis/src/main/java/mimis/device/wiimote/WiimoteButton.java b/java/device.wiimote/src/main/java/mimis/device/wiimote/WiimoteButton.java similarity index 100% rename from java/exec.mimis/src/main/java/mimis/device/wiimote/WiimoteButton.java rename to java/device.wiimote/src/main/java/mimis/device/wiimote/WiimoteButton.java diff --git a/java/exec.mimis/src/main/java/mimis/device/wiimote/WiimoteDevice.java b/java/device.wiimote/src/main/java/mimis/device/wiimote/WiimoteDevice.java similarity index 100% rename from java/exec.mimis/src/main/java/mimis/device/wiimote/WiimoteDevice.java rename to java/device.wiimote/src/main/java/mimis/device/wiimote/WiimoteDevice.java diff --git a/java/exec.mimis/src/main/java/mimis/device/wiimote/WiimoteDiscovery.java b/java/device.wiimote/src/main/java/mimis/device/wiimote/WiimoteDiscovery.java similarity index 100% rename from java/exec.mimis/src/main/java/mimis/device/wiimote/WiimoteDiscovery.java rename to java/device.wiimote/src/main/java/mimis/device/wiimote/WiimoteDiscovery.java diff --git a/java/exec.mimis/src/main/java/mimis/device/wiimote/WiimoteService.java b/java/device.wiimote/src/main/java/mimis/device/wiimote/WiimoteService.java similarity index 100% rename from java/exec.mimis/src/main/java/mimis/device/wiimote/WiimoteService.java rename to java/device.wiimote/src/main/java/mimis/device/wiimote/WiimoteService.java diff --git a/java/exec.mimis/src/main/java/mimis/device/wiimote/WiimoteTaskMapCycle.java b/java/device.wiimote/src/main/java/mimis/device/wiimote/WiimoteTaskMapCycle.java similarity index 100% rename from java/exec.mimis/src/main/java/mimis/device/wiimote/WiimoteTaskMapCycle.java rename to java/device.wiimote/src/main/java/mimis/device/wiimote/WiimoteTaskMapCycle.java diff --git a/java/device.wiimote/src/main/java/mimis/device/wiimote/gesture/GestureDevice.java b/java/device.wiimote/src/main/java/mimis/device/wiimote/gesture/GestureDevice.java new file mode 100644 index 0000000..a185e29 --- /dev/null +++ b/java/device.wiimote/src/main/java/mimis/device/wiimote/gesture/GestureDevice.java @@ -0,0 +1,128 @@ +/** + * Copyright (C) 2015 Rik Veenboer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package mimis.device.wiimote.gesture; + +import mimis.value.Signal; + +import org.wiigee.device.Device; +import org.wiigee.event.AccelerationEvent; +import org.wiigee.event.AccelerationListener; +import org.wiigee.event.ButtonListener; +import org.wiigee.event.ButtonPressedEvent; +import org.wiigee.event.ButtonReleasedEvent; +import org.wiigee.event.GestureListener; +import org.wiigee.event.MotionStartEvent; +import org.wiigee.event.MotionStopEvent; + +import wiiusej.values.GForce; + +public class GestureDevice extends Device implements AccelerationListener { + public static final boolean AUTOFILTERING = true; + public static final boolean AUTOMOTION = false; + + public GestureDevice() { + this(AUTOFILTERING, AUTOMOTION); + } + + public GestureDevice(boolean autofiltering, boolean automotion) { + super(autofiltering); + if (automotion) { + addAccelerationListener(this); + } + this.setRecognitionButton(ButtonPressedEvent.BUTTON_A); + this.setTrainButton(ButtonPressedEvent.BUTTON_B); + this.setCloseGestureButton(ButtonPressedEvent.BUTTON_HOME); + } + + public void add(GestureListener gestureListener) { + addGestureListener(gestureListener); + } + + public void add(GForce gforce) { + add(new double[] { + gforce.getX(), + gforce.getY(), + gforce.getY()}); + } + + public void add(double[] vector) { + //System.out.printf("%f %f %f\n", vector[0], vector[1], vector[2]); + fireAccelerationEvent(vector); + } + + public void recognize(Signal signal) { + switch (signal) { + case BEGIN: + fireButtonPressedEvent(ButtonPressedEvent.BUTTON_A); + break; + case END: + fireButtonReleasedEvent(ButtonPressedEvent.BUTTON_A); + break; + } + } + + public void train(Signal signal) { + switch (signal) { + case BEGIN: + fireButtonPressedEvent(ButtonPressedEvent.BUTTON_B); + break; + case END: + fireButtonReleasedEvent(ButtonPressedEvent.BUTTON_B); + break; + } + } + + public void close(Signal signal) { + switch (signal) { + case BEGIN: + fireButtonPressedEvent(ButtonPressedEvent.BUTTON_HOME); + break; + case END: + fireButtonReleasedEvent(ButtonPressedEvent.BUTTON_HOME); + break; + } + } + + public void fireButtonPressedEvent(int button) { + ButtonPressedEvent buttonPressedEvent = new ButtonPressedEvent(this, button); + for (ButtonListener buttonListener : buttonlistener) { + buttonListener.buttonPressReceived(buttonPressedEvent); + } + if (buttonPressedEvent.isRecognitionInitEvent() || buttonPressedEvent.isTrainInitEvent()) { + resetAccelerationFilters(); + } + } + + public void fireButtonReleasedEvent(int button) { + ButtonReleasedEvent buttonReleasedEvent = new ButtonReleasedEvent(this, button); + for (ButtonListener buttonListener : buttonlistener) { + buttonListener.buttonReleaseReceived(buttonReleasedEvent); + } + } + + public void accelerationReceived(AccelerationEvent event) {} + + public void motionStartReceived(MotionStartEvent event) { + System.out.println("Motion start !" + System.currentTimeMillis()); + recognize(Signal.BEGIN); + } + + public void motionStopReceived(MotionStopEvent event) { + System.out.println("Motion stop! " + + System.currentTimeMillis()); + recognize(Signal.END); + } +} diff --git a/java/exec.mimis/src/main/java/mimis/device/wiimote/motion/MotionData.java b/java/device.wiimote/src/main/java/mimis/device/wiimote/motion/MotionData.java similarity index 100% rename from java/exec.mimis/src/main/java/mimis/device/wiimote/motion/MotionData.java rename to java/device.wiimote/src/main/java/mimis/device/wiimote/motion/MotionData.java diff --git a/java/exec.mimis/src/main/java/mimis/device/wiimote/motion/MotionDevice.java b/java/device.wiimote/src/main/java/mimis/device/wiimote/motion/MotionDevice.java similarity index 100% rename from java/exec.mimis/src/main/java/mimis/device/wiimote/motion/MotionDevice.java rename to java/device.wiimote/src/main/java/mimis/device/wiimote/motion/MotionDevice.java diff --git a/java/device.wiimote/src/motion/MotionData.java b/java/device.wiimote/src/motion/MotionData.java new file mode 100644 index 0000000..ffcd57c --- /dev/null +++ b/java/device.wiimote/src/motion/MotionData.java @@ -0,0 +1,45 @@ +/** + * Copyright (C) 2015 Rik Veenboer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package mimis.device.wiimote.motion; + +import java.io.Serializable; + +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; + +public class MotionData implements Serializable { + protected static final long serialVersionUID = 1L; + + protected int time; + protected MotionSensingEvent event; + + public MotionData(long time, MotionSensingEvent event) { + this((int) time, event); + } + + public MotionData(int time, MotionSensingEvent event) { + this.time = time; + this.event = event; + } + + public int getTime() { + return time; + } + + public MotionSensingEvent getEvent() { + return event; + } +} diff --git a/java/device.wiimote/src/motion/MotionDevice.java b/java/device.wiimote/src/motion/MotionDevice.java new file mode 100644 index 0000000..89d26fd --- /dev/null +++ b/java/device.wiimote/src/motion/MotionDevice.java @@ -0,0 +1,210 @@ +/** + * Copyright (C) 2015 Rik Veenboer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package mimis.device.wiimote.motion; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; + +import mimis.Component; +import mimis.device.lirc.LircButton; +import mimis.device.lirc.remote.PhiliphsRCLE011Button; +import mimis.device.wiimote.WiimoteDevice; +import mimis.input.Button; +import mimis.input.button.ColorButton; +import mimis.input.button.NumberButton; +import mimis.input.state.State; +import mimis.value.Action; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import base.exception.worker.ActivateException; +import base.exception.worker.DeactivateException; +import base.work.Work; + +public class MotionDevice extends Component { + protected WiimoteDevice wiimoteDevice; + protected int id; + protected long start; + protected boolean replay; + protected Action action; + + public ReplayWork replayWork; + public ArrayList motionList; + + public MotionDevice(WiimoteDevice wiimoteDevice) { + this.wiimoteDevice = wiimoteDevice; + id = 0; + start = -1; + replay = false; + action = Action.TRAIN; + replayWork = new ReplayWork(); + motionList = new ArrayList(); + } + + public void activate() throws ActivateException { + super.activate(); + listen(State.class); + } + + public void deactivate() throws DeactivateException { + replayWork.stop(); + super.deactivate(); + } + + public void exit() { + super.exit(); + replayWork.exit(); + } + + public void release(Button button) { + if (button instanceof LircButton) { + PhiliphsRCLE011Button lircButton = (PhiliphsRCLE011Button) button; + logger.debug(lircButton.getName()); + switch (lircButton) { + case CLOCK: + action = Action.TRAIN; + break; + case OUT: + action = Action.RECOGNIZE; + break; + case MUTE: + wiimoteDevice.begin(Action.CLOSE); + break; + case SCREEN_UP: + wiimoteDevice.begin(Action.SAVE); + break; + case SCREEN_DOWN: + wiimoteDevice.begin(Action.LOAD); + break; + default: + break; + } + } else if (button instanceof NumberButton) { + NumberButton numberButton = (NumberButton) button; + id = numberButton.ordinal(); + if (replay == false) { + release(ColorButton.YELLOW); + } else { + logger.debug("Set file to #" + id); + } + } else if (button instanceof ColorButton) { + ColorButton colorButton = (ColorButton) button; + logger.debug(colorButton.name()); + synchronized (motionList) { + switch (colorButton) { + case GREEN: + logger.debug("Start capturing motion"); + motionList.clear(); + start = System.currentTimeMillis(); + break; + case RED: + if (replayWork.active()) { + logger.debug("Stop replaying motion"); + replayWork.stop(); + } else { + logger.debug("Writing motion to file #" + id); + try { + FileOutputStream fileOutputStream = new FileOutputStream(String.format("tmp/motion #%d.bin", id)); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); + objectOutputStream.writeObject(motionList.size()); + for (MotionData motionData : motionList) { + objectOutputStream.writeObject(motionData); + } + objectOutputStream.close(); + } catch (IOException e) { + logger.error("", e); + } + motionList.clear(); + start = -1; + } + break; + case YELLOW: + logger.debug("Replaying motion from file #" + id); + replay = true; + replayWork.start(); + break; + default: + break; + } + } + } + } + + public void add(MotionSensingEvent event) { + if (start > 0) { + synchronized (motionList) { + motionList.add(new MotionData(System.currentTimeMillis() - start, event)); + } + } + } + + class ReplayWork extends Work { + protected ObjectInputStream objectInputStream; + protected int count, i, time; + + public void activate() throws ActivateException { + try { + FileInputStream fileInputStream = new FileInputStream(String.format("tmp/motion #%d.bin", id)); + objectInputStream = new ObjectInputStream(fileInputStream); + count = (Integer) objectInputStream.readObject(); + i = time = 0; + wiimoteDevice.begin(action); + super.activate(); + return; + } catch (FileNotFoundException e) { + logger.error("", e); + } catch (IOException e) { + logger.error("", e); + } catch (ClassNotFoundException e) { + logger.error("", e); + } + } + + public void deactivate() throws DeactivateException { + logger.debug(String.format("Replay stopped (%d ms)", time)); + wiimoteDevice.end(action); + replay = false; + try { + objectInputStream.close(); + } catch (IOException e) { + logger.debug("", e); + } + super.deactivate(); + } + + public void work() { + if (i++ < count) { + try { + Object object = objectInputStream.readObject(); + MotionData motionData = (MotionData) object; + wiimoteDevice.onMotionSensingEvent(motionData.getEvent()); + sleep(motionData.getTime() - time); + time = motionData.getTime(); + return; + } catch (IOException e) { + logger.error("", e); + } catch (ClassNotFoundException e) { + logger.error("", e); + } + } + stop(); + } + } +} \ No newline at end of file diff --git a/java/device.wiimote/src/wiimote/WiimoteButton.java b/java/device.wiimote/src/wiimote/WiimoteButton.java new file mode 100644 index 0000000..28acdf8 --- /dev/null +++ b/java/device.wiimote/src/wiimote/WiimoteButton.java @@ -0,0 +1,54 @@ +/** + * Copyright (C) 2015 Rik Veenboer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package mimis.device.wiimote; + +import mimis.exception.button.UnknownButtonException; +import mimis.input.Button; + +public enum WiimoteButton implements Button { + TWO (0x0001), + ONE (0x0002), + B (0x0004), + A (0x0008), + MINUS (0x0010), + HOME (0x0080), + LEFT (0x0100), + RIGHT (0x0200), + DOWN (0x0400), + UP (0x0800), + PLUS (0x1000), + ALL (0x1F9F); + + protected int code; + + private WiimoteButton(int code) { + this.code = code; + } + + public int getCode() { + return code; + } + + public static WiimoteButton create(int code) throws UnknownButtonException { + for (WiimoteButton button : WiimoteButton.values()) { + if (button.getCode() == code) { + return button; + } + } + throw new UnknownButtonException(); + } +} diff --git a/java/device.wiimote/src/wiimote/WiimoteDevice.java b/java/device.wiimote/src/wiimote/WiimoteDevice.java new file mode 100644 index 0000000..7dde851 --- /dev/null +++ b/java/device.wiimote/src/wiimote/WiimoteDevice.java @@ -0,0 +1,288 @@ +/** + * Copyright (C) 2015 Rik Veenboer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package mimis.device.wiimote; + +import mimis.Component; +import mimis.device.Device; +import mimis.device.wiimote.gesture.GestureDevice; +import mimis.device.wiimote.motion.MotionDevice; +import mimis.exception.button.UnknownButtonException; +import mimis.exception.device.DeviceNotFoundException; +import mimis.input.Button; +import mimis.input.Feedback; +import mimis.input.state.Press; +import mimis.input.state.Release; +import mimis.value.Action; +import mimis.value.Signal; + +import org.wiigee.event.GestureEvent; +import org.wiigee.event.GestureListener; +import org.wiigee.util.Log; + +import wiiusej.Wiimote; +import wiiusej.wiiusejevents.physicalevents.IREvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent; +import base.exception.worker.ActivateException; +import base.exception.worker.DeactivateException; +import base.util.ArrayCycle; +import base.work.Work; + +public class WiimoteDevice extends Component implements Device, GestureListener { + protected static final String TITLE = "Wiimote"; + protected static final int RUMBLE = 50; + protected static final int CONNECTED_TIMEOUT = 500; + protected static final int LED_TIMEOUT = 1000; + protected static final int LED_SLEEP = 50; + + protected static WiimoteService wiimoteService; + protected WiimoteTaskMapCycle taskMapCycle; + protected Wiimote wiimote; + protected boolean connected; + protected GestureDevice gestureDevice; + protected MotionDevice motionDevice; + protected int gestureId; + protected LedWork ledWork; + protected boolean disconnect; + + static { + WiimoteDevice.wiimoteService = new WiimoteService(); + Log.setLevel(Log.DEBUG); + } + + public WiimoteDevice() { + super(TITLE); + taskMapCycle = new WiimoteTaskMapCycle(); + gestureDevice = new GestureDevice(); + gestureDevice.add(this); + motionDevice = new MotionDevice(this); + gestureId = 0; + ledWork = new LedWork(); + } + + /* Worker */ + public void activate() throws ActivateException { + if (wiimote == null) { + motionDevice.setRouter(router); + motionDevice.start(); + parser(Action.ADD, taskMapCycle.player); + } + try { + connect(); + } catch (DeviceNotFoundException e) { + logger.warn("", e); + } + super.activate(); + } + + public synchronized boolean active() { + if (wiimote != null) { + connected = false; + wiimote.getStatus(); + try { + wait(CONNECTED_TIMEOUT); + } catch (InterruptedException e) { + logger.error("", e); + } + if (!connected) { + try { + connect(); + } catch (DeviceNotFoundException e) { + disconnect = true; + stop(); + } + } + } + return super.active(); + } + + public void deactivate() throws DeactivateException { + super.deactivate(); + ledWork.stop(); + motionDevice.stop(); + if (disconnect && wiimote != null) { + wiimote.disconnect(); + disconnect = false; + } + } + + public void exit() { + super.exit(); + ledWork.exit(); + if (wiimote != null) { + wiimote.disconnect(); + wiimote = null; + } + wiimoteService.exit(); + motionDevice.exit(); + } + + /* Events */ + public void begin(Action action) { + switch (action) { + case SHIFT: + logger.debug("Shift"); + parser(Action.RESET, taskMapCycle.player); + parser(Action.ADD, taskMapCycle.mimis); + parser(Action.ADD, taskMapCycle.like); + break; + case UNSHIFT: + logger.debug("Unshift"); + parser(Action.RESET, taskMapCycle.mimis); + parser(Action.RESET, taskMapCycle.like); + parser(Action.ADD, taskMapCycle.player); + break; + case RECOGNIZE: + logger.debug("Gesture recognize press"); + gestureDevice.recognize(Signal.BEGIN); + break; + case TRAIN: + logger.debug("Gesture train press"); + gestureDevice.train(Signal.BEGIN); + break; + case CLOSE: + logger.debug("Gesture close press"); + gestureDevice.close(Signal.BEGIN); + break; + case SAVE: + logger.debug("Gesture save"); + gestureDevice.close(Signal.END); + gestureDevice.saveGesture(gestureId, "tmp/gesture #" + gestureId); + ++gestureId; + break; + case LOAD: + logger.debug("Gesture load"); + for (int i = 0; i < gestureId; ++i) { + gestureDevice.loadGesture("tmp/gesture #" + gestureId); + } + break; + default: + break; + } + } + + public void end(Action action) { + switch (action) { + case RECOGNIZE: + logger.debug("Gesture recognize release"); + gestureDevice.recognize(Signal.END); + break; + case TRAIN: + logger.debug("Gesture train release"); + gestureDevice.train(Signal.END); + break; + case CLOSE: + logger.debug("Gesture close release"); + gestureDevice.close(Signal.END); + break; + default: + break; + } + } + + public void feedback(Feedback feedback) { + if (wiimote != null && active()) { + logger.debug("Wiimote rumble feedback"); + //wiimote.rumble(RUMBLE); + } + } + + /* Connectivity */ + public synchronized void connect() throws DeviceNotFoundException { + wiimote = wiimoteService.getDevice(this); + //wiimote.activateContinuous(); + //wiimote.activateMotionSensing(); + ledWork.start(); + } + + /* Listeners */ + public void onButtonsEvent(WiimoteButtonsEvent event) { + if (!active()) { + return; + } + int pressed = event.getButtonsJustPressed() - event.getButtonsHeld(); + int released = event.getButtonsJustReleased(); + try { + if (pressed != 0 && released == 0) { + Button button = WiimoteButton.create(pressed); + logger.trace("Press: " + button); + route(new Press(button)); + } else if (pressed == 0 && released != 0) { + Button button = WiimoteButton.create(released); + logger.trace("Release: " + button); + route(new Release(button)); + } + } catch (UnknownButtonException e) {} + } + + public void onMotionSensingEvent(MotionSensingEvent event) { + if (!active()) { + return; + } + gestureDevice.add(event.getGforce()); + motionDevice.add(event); + } + + public void onIrEvent(IREvent event) { + + } + + public void gestureReceived(GestureEvent event) { + if (event.isValid()) { + System.out.printf("id #%d, prob %.0f%%, valid %b\n", event.getId(), 100 * event.getProbability(), event.isValid()); + } + } + + class LedWork extends Work { + protected ArrayCycle ledCycle; + + public LedWork() { + ledCycle = new ArrayCycle(); + ledCycle.add(1); + ledCycle.add(3); + ledCycle.add(6); + ledCycle.add(12); + ledCycle.add(8); + ledCycle.add(12); + ledCycle.add(6); + ledCycle.add(3); + ledCycle.add(1); + } + + public void activate() throws ActivateException { + sleep(LED_TIMEOUT); + super.activate(); + } + + public void deactivate() throws DeactivateException { + super.deactivate(); + setLeds(1); + } + + public void work() { + setLeds(ledCycle.next()); + sleep(LED_SLEEP); + } + + protected void setLeds(int leds) { + if (wiimote != null) { + wiimote.setLeds((leds & 1) > 0, (leds & 2) > 0, (leds & 4) > 0, (leds & 8) > 0); + sleep((leds == 8 ? 2 : 1) * LED_SLEEP); + } + } + } +} diff --git a/java/device.wiimote/src/wiimote/WiimoteDiscovery.java b/java/device.wiimote/src/wiimote/WiimoteDiscovery.java new file mode 100644 index 0000000..fd84cc3 --- /dev/null +++ b/java/device.wiimote/src/wiimote/WiimoteDiscovery.java @@ -0,0 +1,99 @@ +/** + * Copyright (C) 2015 Rik Veenboer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package mimis.device.wiimote; + +import java.io.IOException; +import java.util.Scanner; + +import mimis.exception.device.DeviceNotFoundException; +import base.exception.worker.ActivateException; +import base.exception.worker.DeactivateException; +import base.work.Work; + +public class WiimoteDiscovery extends Work { + protected static final String WIISCAN = "wiiscan"; + protected static final int TIMEOUT = 1000; + protected WiimoteDevice wiimoteDevice; + protected Process process; + protected boolean disconnect; + + public WiimoteDiscovery(WiimoteDevice wiimoteDevice) { + this.wiimoteDevice = wiimoteDevice; + } + + protected boolean connect() { + logger.debug("Connect"); + return execute("-c nintendo"); // Nintendo RVL-CNT-01 RVL-WBC-01 Nintendo RVL-CNT-01-TR + } + + protected boolean disconnect() { + logger.debug("Disconnect"); + return execute("-d nintendo"); + } + + public boolean execute(String parameters) { + String command = WIISCAN + " -l wiiuse " + parameters; + try { + process = Runtime.getRuntime().exec(command); + Scanner scanner = new Scanner(process.getInputStream()); + while (scanner.hasNext()) { + String line = scanner.nextLine(); + if (line.contains("error: BluetoothSetServiceState()")) { + disconnect = true; + scanner.close(); + return false; + } else if (line.contains("[OK]")) { + scanner.close(); + return true; + } + } + scanner.close(); + } catch (IOException e) { + logger.error("", e); + } finally { + process = null; + } + return false; + } + + public void activate() throws ActivateException { + super.activate(); + } + + public void deactivate() throws DeactivateException { + super.deactivate(); + if (process != null) { + process.destroy(); + } + } + + public void work() { + if (disconnect) { + disconnect(); + disconnect = false; + } + if (connect()) { + logger.debug("Connected"); + try { + sleep(TIMEOUT); + wiimoteDevice.connect(); + } catch (DeviceNotFoundException e) { + disconnect = true; + } + } + } +} diff --git a/java/device.wiimote/src/wiimote/WiimoteService.java b/java/device.wiimote/src/wiimote/WiimoteService.java new file mode 100644 index 0000000..9b87b2a --- /dev/null +++ b/java/device.wiimote/src/wiimote/WiimoteService.java @@ -0,0 +1,136 @@ +/** + * Copyright (C) 2015 Rik Veenboer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package mimis.device.wiimote; + +import java.util.ArrayList; +import java.util.HashMap; + +import mimis.exception.device.DeviceNotFoundException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import wiiusej.WiiUseApiManager; +import wiiusej.Wiimote; +import wiiusej.wiiusejevents.GenericEvent; +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; + +public class WiimoteService extends WiiUseApiManager implements WiimoteListener { + protected Logger logger = LoggerFactory.getLogger(getClass()); + + public static void main(String[] args) { + Logger logger = LoggerFactory.getLogger(WiimoteService.class); + for (Wiimote wm : WiiUseApiManager.getWiimotes(1, false)) { + logger.debug("" + wm.getId()); + } + } + + protected final boolean RUMBLE = false; + + protected ArrayList wiimoteList; + protected Wiimote[] wiimoteArray; + protected HashMap wiimoteDeviceMap; + + public WiimoteService() { + wiimoteList = new ArrayList(); + wiimoteArray = new Wiimote[0]; + wiimoteDeviceMap = new HashMap(); + } + + public void exit() { + if (wiimoteArray != null) { + for (Wiimote wiimote : wiimoteArray) { + wiimote.disconnect(); + } + } + definitiveShutdown(); + } + + public Wiimote getDevice(WiimoteDevice wiimoteDevice) throws DeviceNotFoundException { + Wiimote[] wiimoteArray = getWiimotes(1, RUMBLE); + for (Wiimote wiimote : wiimoteArray) { + int id = wiimote.getId(); + if (!wiimoteList.contains(id)) { + wiimote.addWiiMoteEventListeners(this); + wiimoteList.add(id); + wiimoteDeviceMap.put(id, wiimoteDevice); + } + return wiimote; + } + throw new DeviceNotFoundException(); + } + + public Wiimote getWiimote(GenericEvent event) { + return wiimoteArray[event.getWiimoteId() - 1]; + } + + public WiimoteDevice getWiimoteDevice(GenericEvent event){ + return wiimoteDeviceMap.get(event.getWiimoteId()); + } + + public void onButtonsEvent(WiimoteButtonsEvent event) { + getWiimoteDevice(event).onButtonsEvent(event); + } + + public void onMotionSensingEvent(MotionSensingEvent event) { + + getWiimoteDevice(event).onMotionSensingEvent(event); + } + + public void onStatusEvent(StatusEvent event) { + if (event.isConnected()) { + WiimoteDevice wiimoteDevice = getWiimoteDevice(event); + wiimoteDevice.connected = true; + synchronized (wiimoteDevice) { + wiimoteDevice.notifyAll(); + } + } + } + + public void onIrEvent(IREvent event) { + getWiimoteDevice(event).onIrEvent(event); + } + + public void onExpansionEvent(ExpansionEvent event) {} + public void onDisconnectionEvent(DisconnectionEvent event) {} + public void onNunchukInsertedEvent(NunchukInsertedEvent event) {} + public void onNunchukRemovedEvent(NunchukRemovedEvent event) {} + public void onGuitarHeroInsertedEvent(GuitarHeroInsertedEvent event) {} + public void onGuitarHeroRemovedEvent(GuitarHeroRemovedEvent event) {} + public void onClassicControllerInsertedEvent(ClassicControllerInsertedEvent event) {} + public void onClassicControllerRemovedEvent(ClassicControllerRemovedEvent event) {} + + /*public void onBalanceBoardInsertedEvent(BalanceBoardInsertedEvent e) { + logger.debug("", e); + } + + public void onBalanceBoardRemovedEvent(BalanceBoardRemovedEvent e) { + + }*/ +} diff --git a/java/device.wiimote/src/wiimote/WiimoteTaskMapCycle.java b/java/device.wiimote/src/wiimote/WiimoteTaskMapCycle.java new file mode 100644 index 0000000..f826d5b --- /dev/null +++ b/java/device.wiimote/src/wiimote/WiimoteTaskMapCycle.java @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2015 Rik Veenboer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package mimis.device.wiimote; + +import mimis.input.Task; +import mimis.input.state.Release; +import mimis.state.TaskMap; +import mimis.state.TaskMapCycle; +import mimis.value.Action; +import mimis.value.Target; + +public class WiimoteTaskMapCycle extends TaskMapCycle { + protected static final long serialVersionUID = 1L; + + public TaskMap mimis, player, gesture, like; + + public WiimoteTaskMapCycle() { + /* Mimis */ + mimis = new TaskMap(); + mimis.add(WiimoteButton.HOME, new Task(Action.NEXT, Target.MAIN)); + mimis.add(new Release(WiimoteButton.B), new Task(Action.UNSHIFT, Target.SELF)); + + /* Gesture */ + gesture = new TaskMap(); + gesture.add(WiimoteButton.A, new Task(Action.TRAIN, Target.SELF)); + gesture.add(WiimoteButton.B, new Task(Action.SAVE, Target.SELF)); + gesture.add(WiimoteButton.DOWN, new Task(Action.LOAD, Target.SELF)); + gesture.add(WiimoteButton.HOME, new Task(Action.RECOGNIZE, Target.SELF)); + add(gesture); + + /* Player */ + player = new TaskMap(); + player.add(WiimoteButton.A, new Task(Action.PLAY, Target.CURRENT)); + player.add(WiimoteButton.B, new Task(Action.SHIFT, Target.SELF)); + player.add(WiimoteButton.HOME, new Task(Action.MUTE, Target.CURRENT)); + player.add(WiimoteButton.ONE, new Task(Action.SHUFFLE, Target.CURRENT)); + player.add(WiimoteButton.TWO, new Task(Action.REPEAT, Target.CURRENT)); + player.add(WiimoteButton.UP, new Task(Action.NEXT, Target.CURRENT)); + player.add(WiimoteButton.DOWN, new Task(Action.PREVIOUS, Target.CURRENT)); + player.add(WiimoteButton.RIGHT, new Task(Action.FORWARD, Target.CURRENT)); + player.add(WiimoteButton.LEFT, new Task(Action.REWIND, Target.CURRENT)); + player.add(WiimoteButton.MINUS, new Task(Action.VOLUME_DOWN, Target.CURRENT)); + player.add(WiimoteButton.PLUS, new Task(Action.VOLUME_UP, Target.CURRENT)); + add(player); + + /* Like */ + like = new TaskMap(); + like.add(WiimoteButton.PLUS, new Task(Action.LIKE, Target.CURRENT)); + like.add(WiimoteButton.MINUS, new Task(Action.DISLIKE, Target.CURRENT)); + add(like); + } +}