Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Klaus/issue#277/rest endpoint for keyboard events #278

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ARE/middleware/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
<property name="dist" location="."/>
<property name="runtime" location="../../bin/ARE"/>
<property name="osgi" location="../osgi"/>
<property name="services" location="../services"/>
<property name="classpath" location=".."/>
<path id="asterics.classpath">
<pathelement location="${classpath}"/>
<pathelement location="bin"/>
<pathelement location="${osgi}/org.eclipse.osgi_3.6.0.v20100517.jar"/>
<pathelement location="${services}/asterics.mw.jnativehook.jar"/>
<pathelement location="src/main/resources/lib/libthrift.jar"/>
<pathelement location="src/main/resources/lib/slf4j-api-1.6.0.jar"/>
<pathelement location="src/main/resources/lib/slf4j-simple-1.6.0.jar"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -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);

}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -74,6 +77,8 @@ public class NativeHookServices implements NativeKeyListener {

private AsapiSupport as;

private Set<IAREKeyboardListener> keyboardListeners = new HashSet<>();

private NativeHookServices() {
AstericsErrorHandling.instance.getLogger().fine("Registering native hooks...");
try {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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()) {
Expand Down
1 change: 1 addition & 0 deletions ARE/services/WebService/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<pathelement location="${middleware}/asterics.ARE.jar"/>
<pathelement location="${services}/grizzly-httpservice-bundle-2.3.23.jar"/>
<pathelement location="${services}/org.eclipse.osgi.services_3.2.100.v20100503.jar"/>
<pathelement location="${services}/asterics.mw.jnativehook.jar"/>
<pathelement location="src/main/resources/lib/hk2-api-2.4.0-b06.jar"/>
<pathelement location="src/main/resources/lib/hk2-locator-2.4.0-b06.jar"/>
<pathelement location="src/main/resources/lib/hk2-utils-2.4.0-b06.jar"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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("/")
Expand All @@ -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();
Expand All @@ -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();
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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;
}

}
Original file line number Diff line number Diff line change
@@ -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));
}
}