diff --git a/ARE/middleware/build.xml b/ARE/middleware/build.xml
index b6e7fb6a9..1f32c7768 100644
--- a/ARE/middleware/build.xml
+++ b/ARE/middleware/build.xml
@@ -7,11 +7,13 @@
+
+
diff --git a/ARE/middleware/src/main/java/eu/asterics/mw/services/IAREKeyboardListener.java b/ARE/middleware/src/main/java/eu/asterics/mw/services/IAREKeyboardListener.java
new file mode 100644
index 000000000..c5753d2bf
--- /dev/null
+++ b/ARE/middleware/src/main/java/eu/asterics/mw/services/IAREKeyboardListener.java
@@ -0,0 +1,49 @@
+package eu.asterics.mw.services;
+
+/*
+ * AsTeRICS - Assistive Technology Rapid Integration and Construction Set
+ *
+ *
+ * d8888 88888888888 8888888b. 8888888 .d8888b. .d8888b.
+ * d88888 888 888 Y88b 888 d88P Y88b d88P Y88b
+ * d88P888 888 888 888 888 888 888 Y88b.
+ * d88P 888 .d8888b 888 .d88b. 888 d88P 888 888 "Y888b.
+ * d88P 888 88K 888 d8P Y8b 8888888P" 888 888 "Y88b.
+ * d88P 888 "Y8888b. 888 88888888 888 T88b 888 888 888 "888
+ * d8888888888 X88 888 Y8b. 888 T88b 888 Y88b d88P Y88b d88P
+ * d88P 888 88888P' 888 "Y8888 888 T88b 8888888 "Y8888P" "Y8888P"
+ *
+ *
+ * homepage: http://www.asterics.org
+ *
+ * This project has been partly funded by the European Commission,
+ * Grant Agreement Number 247730
+ *
+ *
+ * Dual License: MIT or GPL v3.0 with "CLASSPATH" exception
+ * (please refer to the folder LICENSE)
+ *
+ */
+
+import org.jnativehook.keyboard.NativeKeyEvent;
+
+/**
+ * generic listener for NativeKeyEvents
+ */
+public interface IAREKeyboardListener {
+
+ /**
+ * to be called if a key is pressed
+ *
+ * @param nke
+ */
+ void keyPressed(NativeKeyEvent nke);
+
+ /**
+ * to be called if a key is released
+ *
+ * @param nke
+ */
+ void keyReleased(NativeKeyEvent nke);
+
+}
diff --git a/ARE/services/JNativeHook/src/main/java/eu/asterics/mw/jnativehook/AREKeyEvent.java b/ARE/services/JNativeHook/src/main/java/eu/asterics/mw/jnativehook/AREKeyEvent.java
new file mode 100644
index 000000000..7d5b2272f
--- /dev/null
+++ b/ARE/services/JNativeHook/src/main/java/eu/asterics/mw/jnativehook/AREKeyEvent.java
@@ -0,0 +1,41 @@
+/*
+ * AsTeRICS - Assistive Technology Rapid Integration and Construction Set
+ *
+ *
+ * d8888 88888888888 8888888b. 8888888 .d8888b. .d8888b.
+ * d88888 888 888 Y88b 888 d88P Y88b d88P Y88b
+ * d88P888 888 888 888 888 888 888 Y88b.
+ * d88P 888 .d8888b 888 .d88b. 888 d88P 888 888 "Y888b.
+ * d88P 888 88K 888 d8P Y8b 8888888P" 888 888 "Y88b.
+ * d88P 888 "Y8888b. 888 88888888 888 T88b 888 888 888 "888
+ * d8888888888 X88 888 Y8b. 888 T88b 888 Y88b d88P Y88b d88P
+ * d88P 888 88888P' 888 "Y8888 888 T88b 8888888 "Y8888P" "Y8888P"
+ *
+ *
+ * homepage: http://www.asterics.org
+ *
+ * This project has been funded by the European Commission,
+ * Grant Agreement Number 247730
+ *
+ *
+ * Dual License: MIT or GPL v3.0 with "CLASSPATH" exception
+ * (please refer to the folder LICENSE)
+ *
+ */
+
+package eu.asterics.mw.jnativehook;
+
+import org.jnativehook.keyboard.NativeKeyEvent;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class AREKeyEvent extends NativeKeyEvent {
+
+ public AREKeyEvent(int id, int modifiers, int rawCode, int keyCode, char keyChar, int keyLocation) {
+ super(id, modifiers, rawCode, keyCode, keyChar, keyLocation);
+ }
+
+ public AREKeyEvent(int id, int modifiers, int rawCode, int keyCode, char keyChar) {
+ super(id, modifiers, rawCode, keyCode, keyChar);
+ }
+}
diff --git a/ARE/services/JNativeHook/src/main/java/eu/asterics/mw/jnativehook/NativeHookServices.java b/ARE/services/JNativeHook/src/main/java/eu/asterics/mw/jnativehook/NativeHookServices.java
index 466f1c217..9deb61da7 100644
--- a/ARE/services/JNativeHook/src/main/java/eu/asterics/mw/jnativehook/NativeHookServices.java
+++ b/ARE/services/JNativeHook/src/main/java/eu/asterics/mw/jnativehook/NativeHookServices.java
@@ -30,9 +30,12 @@
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.MessageFormat;
+import java.util.HashSet;
+import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
+import eu.asterics.mw.services.IAREKeyboardListener;
import eu.asterics.mw.utils.OSUtils;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
@@ -74,6 +77,8 @@ public class NativeHookServices implements NativeKeyListener {
private AsapiSupport as;
+ private Set keyboardListeners = new HashSet<>();
+
private NativeHookServices() {
AstericsErrorHandling.instance.getLogger().fine("Registering native hooks...");
try {
@@ -205,15 +210,17 @@ protected void finalize() throws Throwable {
@Override
public void nativeKeyPressed(NativeKeyEvent nke) {
- // TODO Auto-generated method stub
-
+ for(IAREKeyboardListener listener : keyboardListeners) {
+ listener.keyPressed(nke);
+ }
}
@Override
public void nativeKeyReleased(NativeKeyEvent nke) {
- // TODO Auto-generated method stub
- // System.out.println("Native key released:
- // "+nke.getKeyText(nke.getKeyCode()));
+
+ for(IAREKeyboardListener listener : keyboardListeners) {
+ listener.keyReleased(nke);
+ }
if (nke.getKeyCode() == keyCodeStartModel) {
try {
as.runModel();
@@ -250,6 +257,24 @@ public void nativeKeyTyped(NativeKeyEvent nke) {
// System.out.println("Native key typed: "+nke);
}
+ /**
+ * register a new keyboard listener
+ * @param listener
+ * @return
+ */
+ public boolean registerAREKeyboardListener(IAREKeyboardListener listener) {
+ return this.keyboardListeners.add(listener);
+ }
+
+ /**
+ * deregisters a keyboard listener
+ * @param listener
+ * @return
+ */
+ public boolean unregisterAREKeyboardListener(IAREKeyboardListener listener) {
+ return this.keyboardListeners.remove(listener);
+ }
+
private String getCurrentRestPort() {
String port = AREProperties.instance.getProperty(PROPTERTY_REST_PORT);
if(port == null || port.isEmpty()) {
diff --git a/ARE/services/WebService/build.xml b/ARE/services/WebService/build.xml
index f1e83491a..2eb75a9ba 100644
--- a/ARE/services/WebService/build.xml
+++ b/ARE/services/WebService/build.xml
@@ -16,6 +16,7 @@
+
diff --git a/ARE/services/WebService/src/main/java/eu/asterics/mw/webservice/SseResource.java b/ARE/services/WebService/src/main/java/eu/asterics/mw/webservice/SseResource.java
index 6ffa9faf5..839bb10fd 100644
--- a/ARE/services/WebService/src/main/java/eu/asterics/mw/webservice/SseResource.java
+++ b/ARE/services/WebService/src/main/java/eu/asterics/mw/webservice/SseResource.java
@@ -38,6 +38,8 @@
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
+import eu.asterics.mw.jnativehook.NativeHookServices;
+import eu.asterics.mw.webservice.serverUtils.*;
import org.glassfish.jersey.media.sse.EventOutput;
import org.glassfish.jersey.media.sse.OutboundEvent;
import org.glassfish.jersey.media.sse.SseBroadcaster;
@@ -47,10 +49,6 @@
import eu.asterics.mw.model.deployment.IChannel;
import eu.asterics.mw.services.AREServices;
import eu.asterics.mw.services.AstericsErrorHandling;
-import eu.asterics.mw.webservice.serverUtils.AREEventListener;
-import eu.asterics.mw.webservice.serverUtils.AstericsAPIEncoding;
-import eu.asterics.mw.webservice.serverUtils.ObjectTransformation;
-import eu.asterics.mw.webservice.serverUtils.RuntimeListener;
@Singleton
@Path("/")
@@ -60,6 +58,8 @@ public class SseResource {
// Client broadcasters
private static SseBroadcaster deploymentBroadcaster = new SseBroadcaster();
+ private static SseBroadcaster keyboardPressedBroadcaster = new SseBroadcaster();
+ private static SseBroadcaster keyboardReleasedBroadcaster = new SseBroadcaster();
private static SseBroadcaster modelStateBroadcaster = new SseBroadcaster();
private static SseBroadcaster eventChannelBroadcaster = new SseBroadcaster();
private static SseBroadcaster propertyChangeBroadcaster = new SseBroadcaster();
@@ -68,14 +68,17 @@ public class SseResource {
// System listeners
private static AREEventListener eventListener;
private static RuntimeListener runtimeListener;
+ private static AREKeyboardListener keyboardListener;
public SseResource() {
// create and register listeners
SseResource.eventListener = new AREEventListener();
SseResource.runtimeListener = new RuntimeListener();
+ SseResource.keyboardListener = new AREKeyboardListener();
AREServices.instance.registerAREEventListener(eventListener);
AREServices.instance.registerRuntimeDataListener(runtimeListener);
+ NativeHookServices.getInstance().registerAREKeyboardListener(keyboardListener);
initializeDataChannelListeners();
}
@@ -122,6 +125,28 @@ public EventOutput subscribe_AREDeploymentEvents() {
return eventOutput;
}
+ @Path("/runtime/keyboard/pressed/listener")
+ @GET
+ @Produces(SseFeature.SERVER_SENT_EVENTS)
+ public EventOutput subscribe_keyboardPressedEvents() {
+ final EventOutput eventOutput = new EventOutput();
+
+ SseResource.keyboardPressedBroadcaster.add(eventOutput);
+
+ return eventOutput;
+ }
+
+ @Path("/runtime/keyboard/released/listener")
+ @GET
+ @Produces(SseFeature.SERVER_SENT_EVENTS)
+ public EventOutput subscribe_keyboardReleasedEvents() {
+ final EventOutput eventOutput = new EventOutput();
+
+ SseResource.keyboardReleasedBroadcaster.add(eventOutput);
+
+ return eventOutput;
+ }
+
@Path("/runtime/model/state/listener")
@GET
@Produces(SseFeature.SERVER_SENT_EVENTS)
@@ -206,6 +231,28 @@ public static String broadcastDeploymentEvent(String eventMessage) {
return eventMessage;
}
+ /**
+ * Static method that broadcasts an event to clients who were subscribed to keyboard pressed events.
+ *
+ * @param eventMessage JSON formatted native key event that was triggered
+ *
+ * @return the json that was sent to the SSE subscribers
+ */
+ public static String broadcastKeyboardPressedEvent(String eventMessage) {
+ return broadcastEvent(keyboardPressedBroadcaster, eventMessage, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ /**
+ * Static method that broadcasts an event to clients who were subscribed to keyboard released events.
+ *
+ * @param eventMessage JSON formatted native key event that was triggered
+ *
+ * @return the json that was sent to the SSE subscribers
+ */
+ public static String broadcastKeyboardReleasedEvent(String eventMessage) {
+ return broadcastEvent(keyboardReleasedBroadcaster, eventMessage, MediaType.APPLICATION_JSON_TYPE);
+ }
+
/**
* Static method that broadcasts an event to clients who were subscribed to model state events.
*
@@ -342,4 +389,15 @@ public static String broadcastPropertyChangedEvent(String componentId, String co
* BROADCASTER METHODS - end
**********************************/
+
+ private static String broadcastEvent(SseBroadcaster broadcaster, String eventMessage, MediaType eventType) {
+ OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();
+ eventBuilder.name("event");
+ eventBuilder.mediaType(eventType);
+ eventBuilder.data(String.class, eventMessage);
+ OutboundEvent event = eventBuilder.build();
+ broadcaster.broadcast(event);
+ return eventMessage;
+ }
+
}
\ No newline at end of file
diff --git a/ARE/services/WebService/src/main/java/eu/asterics/mw/webservice/serverUtils/AREKeyboardListener.java b/ARE/services/WebService/src/main/java/eu/asterics/mw/webservice/serverUtils/AREKeyboardListener.java
new file mode 100644
index 000000000..0e7bd8b1e
--- /dev/null
+++ b/ARE/services/WebService/src/main/java/eu/asterics/mw/webservice/serverUtils/AREKeyboardListener.java
@@ -0,0 +1,43 @@
+/*
+ * AsTeRICS - Assistive Technology Rapid Integration and Construction Set
+ *
+ *
+ * d8888 88888888888 8888888b. 8888888 .d8888b. .d8888b.
+ * d88888 888 888 Y88b 888 d88P Y88b d88P Y88b
+ * d88P888 888 888 888 888 888 888 Y88b.
+ * d88P 888 .d8888b 888 .d88b. 888 d88P 888 888 "Y888b.
+ * d88P 888 88K 888 d8P Y8b 8888888P" 888 888 "Y88b.
+ * d88P 888 "Y8888b. 888 88888888 888 T88b 888 888 888 "888
+ * d8888888888 X88 888 Y8b. 888 T88b 888 Y88b d88P Y88b d88P
+ * d88P 888 88888P' 888 "Y8888 888 T88b 8888888 "Y8888P" "Y8888P"
+ *
+ *
+ * homepage: http://www.asterics.org
+ *
+ * This project has been funded by the European Commission,
+ * Grant Agreement Number 247730
+ *
+ *
+ * Dual License: MIT or GPL v3.0 with "CLASSPATH" exception
+ * (please refer to the folder LICENSE)
+ *
+ */
+
+package eu.asterics.mw.webservice.serverUtils;
+
+import eu.asterics.mw.services.IAREKeyboardListener;
+import eu.asterics.mw.webservice.SseResource;
+import org.jnativehook.keyboard.NativeKeyEvent;
+
+public class AREKeyboardListener implements IAREKeyboardListener {
+
+ @Override
+ public void keyPressed(NativeKeyEvent nke) {
+ SseResource.broadcastKeyboardPressedEvent(ObjectTransformation.objectToJSON(nke));
+ }
+
+ @Override
+ public void keyReleased(NativeKeyEvent nke) {
+ SseResource.broadcastKeyboardReleasedEvent(ObjectTransformation.objectToJSON(nke));
+ }
+}