added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.leapmotion-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
<feature name="openhab-binding-leapmotion" description="LeapMotion Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.leapmotion/${project.version}</bundle>
<configfile finalname="${openhab.userdata}/tmp/lib/libLeap.dylib" override="false">mvn:${project.groupId}/openhab-addons-external/${project.version}/lib/libLeap</configfile>
<configfile finalname="${openhab.userdata}/tmp/lib/libLeapJava.dylib" override="false">mvn:${project.groupId}/openhab-addons-external/${project.version}/lib/libLeapJava</configfile>
</feature>
</features>

View File

@@ -0,0 +1,43 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.leapmotion.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.type.ChannelTypeUID;
/**
* The {@link LeapMotionBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Kai Kreuzer - Initial contribution
*/
@NonNullByDefault
public class LeapMotionBindingConstants {
public static final String BINDING_ID = "leapmotion";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_CONTROLLER = new ThingTypeUID(BINDING_ID, "controller");
// List of all Channel ids
public static final String CHANNEL_GESTURE = "gesture";
public static final ChannelTypeUID CHANNEL_GESTURE_UID = new ChannelTypeUID(BINDING_ID, CHANNEL_GESTURE);
// List of all gestures
public static final String GESTURE_TAP = "tap";
public static final String GESTURE_CLOCKWISE = "clockwise";
public static final String GESTURE_ANTICLOCKWISE = "anticlockwise";
public static final String GESTURE_FINGERS = "fingers";
public static final String GESTURE_NOHAND = "nohand";
}

View File

@@ -0,0 +1,100 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.leapmotion.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.thing.profiles.ProfileCallback;
import org.openhab.core.thing.profiles.ProfileTypeUID;
import org.openhab.core.thing.profiles.TriggerProfile;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link LeapMotionColorProfile} class implements the behavior when being linked to a Color item.
*
* @author Kai Kreuzer - Initial contribution
*/
@NonNullByDefault
public class LeapMotionColorProfile implements TriggerProfile {
private final Logger logger = LoggerFactory.getLogger(LeapMotionColorProfile.class);
private ProfileCallback callback;
private HSBType lastState = HSBType.BLACK;
public LeapMotionColorProfile(ProfileCallback callback) {
this.callback = callback;
}
@Override
public ProfileTypeUID getProfileTypeUID() {
return LeapMotionProfileFactory.UID_COLOR;
}
@Override
public void onStateUpdateFromItem(State state) {
if (state instanceof HSBType) {
lastState = (HSBType) state;
} else {
PercentType currentBrightness = state.as(PercentType.class);
if (currentBrightness != null) {
lastState = new HSBType(lastState.getHue(), lastState.getSaturation(), currentBrightness);
}
}
}
@Override
public void onTriggerFromHandler(String event) {
if (event.equals(LeapMotionBindingConstants.GESTURE_TAP)) {
callback.sendCommand(lastState.getBrightness().equals(PercentType.ZERO) ? OnOffType.ON : OnOffType.OFF);
} else if (event.equals(LeapMotionBindingConstants.GESTURE_CLOCKWISE)) {
HSBType color = changeColor(lastState, true);
callback.sendCommand(color);
lastState = color;
} else if (event.equals(LeapMotionBindingConstants.GESTURE_ANTICLOCKWISE)) {
HSBType color = changeColor(lastState, false);
callback.sendCommand(color);
lastState = color;
} else if (event.startsWith(LeapMotionBindingConstants.GESTURE_FINGERS)) {
// the brightness is determined by the height of the palm over the sensor, where higher means brighter
int fingers = Integer
.valueOf(Character.toString(event.charAt(LeapMotionBindingConstants.GESTURE_FINGERS.length())));
if (fingers == 5) {
try {
int height = Integer
.valueOf(event.substring(LeapMotionBindingConstants.GESTURE_FINGERS.length() + 2));
height = Math.min(100 * height / LeapMotionDimmerProfile.MAX_HEIGHT, 100); // don't use values over
// 100
PercentType brightness = new PercentType(height);
callback.sendCommand(brightness);
lastState = new HSBType(lastState.getHue(), lastState.getSaturation(), brightness);
} catch (NumberFormatException e) {
logger.error("Found illegal format of finger event: {}", event, e);
}
}
}
}
private HSBType changeColor(HSBType color, boolean clockwise) {
int hue = clockwise ? (color.getHue().toBigDecimal().intValue() - 20 + 360) % 360
: (color.getHue().toBigDecimal().intValue() + 20 + 360) % 360;
logger.debug("New hue value: {}", hue);
HSBType newState = new HSBType(new DecimalType(hue), color.getSaturation(), color.getBrightness());
return newState;
}
}

View File

@@ -0,0 +1,88 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.leapmotion.internal;
import java.math.BigDecimal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.thing.profiles.ProfileCallback;
import org.openhab.core.thing.profiles.ProfileContext;
import org.openhab.core.thing.profiles.ProfileTypeUID;
import org.openhab.core.thing.profiles.TriggerProfile;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link LeapMotionDimmerProfile} class implements the behavior when being linked to a Dimmer item.
* It supports two modes: Either the dim level is determined by the number of shown fingers or by the height of the hand
* over the controller.
*
* @author Kai Kreuzer - Initial contribution
*/
@NonNullByDefault
public class LeapMotionDimmerProfile implements TriggerProfile {
static final int MAX_HEIGHT = 400; // in mm over controller
private static final String MODE = "mode";
private final Logger logger = LoggerFactory.getLogger(LeapMotionDimmerProfile.class);
private ProfileCallback callback;
private BigDecimal lastState = BigDecimal.ZERO;
private boolean fingerMode = false;
public LeapMotionDimmerProfile(ProfileCallback callback, ProfileContext profileContext) {
this.callback = callback;
fingerMode = "fingers".equals(profileContext.getConfiguration().get(MODE));
}
@Override
public ProfileTypeUID getProfileTypeUID() {
return LeapMotionProfileFactory.UID_DIMMER;
}
@Override
public void onStateUpdateFromItem(State state) {
PercentType currentState = state.as(PercentType.class);
if (currentState != null) {
lastState = currentState.toBigDecimal();
}
}
@Override
public void onTriggerFromHandler(String event) {
if (event.equals(LeapMotionBindingConstants.GESTURE_TAP)) {
callback.sendCommand(lastState.equals(BigDecimal.ZERO) ? OnOffType.ON : OnOffType.OFF);
} else if (event.startsWith(LeapMotionBindingConstants.GESTURE_FINGERS)) {
int fingers = Integer
.valueOf(Character.toString(event.charAt(LeapMotionBindingConstants.GESTURE_FINGERS.length())));
if (fingerMode) {
// the brightness is determined by the number of shown fingers, 20% for each.
callback.sendCommand(new PercentType(fingers * 20));
} else if (fingers == 5) {
// the brightness is determined by the height of the palm over the sensor, where higher means brighter
try {
int height = Integer
.valueOf(event.substring(LeapMotionBindingConstants.GESTURE_FINGERS.length() + 2));
height = Math.min(100 * height / MAX_HEIGHT, 100); // don't use values over 100
callback.sendCommand(new PercentType(height));
} catch (NumberFormatException e) {
logger.error("Found illegal format of finger event: {}", event, e);
}
}
}
}
}

View File

@@ -0,0 +1,56 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.leapmotion.internal;
import static org.openhab.binding.leapmotion.internal.LeapMotionBindingConstants.THING_TYPE_CONTROLLER;
import java.util.Collections;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.leapmotion.internal.handler.LeapMotionHandler;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.annotations.Component;
/**
* The {@link LeapMotionHandlerFactory} is responsible for creating things and thing handlers.
*
* @author Kai Kreuzer - Initial contribution
*/
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.leapmotion")
@NonNullByDefault
public class LeapMotionHandlerFactory extends BaseThingHandlerFactory {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_CONTROLLER);
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
}
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(THING_TYPE_CONTROLLER)) {
return new LeapMotionHandler(thing);
}
return null;
}
}

View File

@@ -0,0 +1,114 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.leapmotion.internal;
import java.util.Collection;
import java.util.Locale;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.library.CoreItemFactory;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.profiles.Profile;
import org.openhab.core.thing.profiles.ProfileAdvisor;
import org.openhab.core.thing.profiles.ProfileCallback;
import org.openhab.core.thing.profiles.ProfileContext;
import org.openhab.core.thing.profiles.ProfileFactory;
import org.openhab.core.thing.profiles.ProfileType;
import org.openhab.core.thing.profiles.ProfileTypeBuilder;
import org.openhab.core.thing.profiles.ProfileTypeProvider;
import org.openhab.core.thing.profiles.ProfileTypeUID;
import org.openhab.core.thing.profiles.TriggerProfileType;
import org.openhab.core.thing.type.ChannelType;
import org.openhab.core.thing.type.ChannelTypeUID;
import org.osgi.service.component.annotations.Component;
/**
* This class defines and provides all profiles and their types of this binding.
*
* @author Kai Kreuzer - Initial contribution
*
*/
@NonNullByDefault
@Component
public class LeapMotionProfileFactory implements ProfileFactory, ProfileAdvisor, ProfileTypeProvider {
static final ProfileTypeUID UID_SWITCH = new ProfileTypeUID(LeapMotionBindingConstants.BINDING_ID, "switch");
static final ProfileTypeUID UID_DIMMER = new ProfileTypeUID(LeapMotionBindingConstants.BINDING_ID, "dimmer");
static final ProfileTypeUID UID_COLOR = new ProfileTypeUID(LeapMotionBindingConstants.BINDING_ID, "color");
private static final TriggerProfileType SWITCH_TYPE = ProfileTypeBuilder.newTrigger(UID_SWITCH, "Toggle Switch")
.withSupportedItemTypes(CoreItemFactory.SWITCH, CoreItemFactory.DIMMER, CoreItemFactory.COLOR)
.withSupportedChannelTypeUIDs(LeapMotionBindingConstants.CHANNEL_GESTURE_UID).build();
private static final TriggerProfileType DIMMER_TYPE = ProfileTypeBuilder.newTrigger(UID_DIMMER, "Dimmer Control")
.withSupportedItemTypes(CoreItemFactory.DIMMER, CoreItemFactory.COLOR)
.withSupportedChannelTypeUIDs(LeapMotionBindingConstants.CHANNEL_GESTURE_UID).build();
private static final TriggerProfileType COLOR_TYPE = ProfileTypeBuilder.newTrigger(UID_COLOR, "Color Control")
.withSupportedItemTypes(CoreItemFactory.COLOR)
.withSupportedChannelTypeUIDs(LeapMotionBindingConstants.CHANNEL_GESTURE_UID).build();
@Override
public Collection<ProfileTypeUID> getSupportedProfileTypeUIDs() {
return Stream.of(UID_SWITCH, UID_DIMMER, UID_COLOR).collect(Collectors.toSet());
}
@Override
public Collection<ProfileType> getProfileTypes(@Nullable Locale locale) {
return Stream.of(SWITCH_TYPE, DIMMER_TYPE, COLOR_TYPE).collect(Collectors.toSet());
}
@Override
public @Nullable ProfileTypeUID getSuggestedProfileTypeUID(Channel channel, @Nullable String itemType) {
return getSuggestedProfileTypeUID(channel.getChannelTypeUID(), itemType);
}
@Override
public @Nullable ProfileTypeUID getSuggestedProfileTypeUID(ChannelType channelType, @Nullable String itemType) {
return getSuggestedProfileTypeUID(channelType.getUID(), itemType);
}
private @Nullable ProfileTypeUID getSuggestedProfileTypeUID(@Nullable ChannelTypeUID channelTypeUID,
@Nullable String itemType) {
if (LeapMotionBindingConstants.CHANNEL_GESTURE_UID.equals(channelTypeUID) && itemType != null) {
switch (itemType) {
case CoreItemFactory.SWITCH:
return UID_SWITCH;
case CoreItemFactory.DIMMER:
return UID_DIMMER;
case CoreItemFactory.COLOR:
return UID_COLOR;
default:
return null;
}
}
return null;
}
@Override
public @Nullable Profile createProfile(ProfileTypeUID profileTypeUID, ProfileCallback callback,
ProfileContext profileContext) {
if (UID_SWITCH.equals(profileTypeUID)) {
return new LeapMotionSwitchProfile(callback);
} else if (UID_DIMMER.equals(profileTypeUID)) {
return new LeapMotionDimmerProfile(callback, profileContext);
} else if (UID_COLOR.equals(profileTypeUID)) {
return new LeapMotionColorProfile(callback);
} else {
return null;
}
}
}

View File

@@ -0,0 +1,53 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.leapmotion.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.profiles.ProfileCallback;
import org.openhab.core.thing.profiles.ProfileTypeUID;
import org.openhab.core.thing.profiles.TriggerProfile;
import org.openhab.core.types.State;
/**
* The {@link LeapMotionSwitchProfile} class implements the behavior when being linked to a Switch item.
*
* @author Kai Kreuzer - Initial contribution
*/
@NonNullByDefault
public class LeapMotionSwitchProfile implements TriggerProfile {
private ProfileCallback callback;
private boolean lastState = false;
public LeapMotionSwitchProfile(ProfileCallback callback) {
this.callback = callback;
}
@Override
public ProfileTypeUID getProfileTypeUID() {
return LeapMotionProfileFactory.UID_SWITCH;
}
@Override
public void onStateUpdateFromItem(State state) {
lastState = OnOffType.ON.equals(state.as(OnOffType.class));
}
@Override
public void onTriggerFromHandler(String event) {
if (event.equals(LeapMotionBindingConstants.GESTURE_TAP)) {
callback.sendCommand(lastState ? OnOffType.OFF : OnOffType.ON);
}
}
}

View File

@@ -0,0 +1,97 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.leapmotion.internal.discovery;
import java.util.Collections;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.leapmotion.internal.LeapMotionBindingConstants;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.thing.ThingUID;
import org.osgi.service.component.annotations.Component;
import com.leapmotion.leap.Controller;
import com.leapmotion.leap.Listener;
/**
* This is a discovery service, which finds locally attached LeapMotion controllers and adds them to the Inbox
*
* @author Kai Kreuzer - Initial contribution
*
*/
@NonNullByDefault
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.leapmotion")
public class LeapMotionDiscoveryService extends AbstractDiscoveryService {
private @NonNullByDefault({}) Controller leapController;
private @NonNullByDefault({}) Listener listener;
public LeapMotionDiscoveryService() throws IllegalArgumentException {
super(Collections.singleton(LeapMotionBindingConstants.THING_TYPE_CONTROLLER), 10, true);
}
@Override
protected void activate(@Nullable Map<String, @Nullable Object> configProperties) {
leapController = new Controller();
listener = new Listener() {
@Override
public void onConnect(@Nullable Controller c) {
createDiscoveryResult();
}
@Override
public void onDisconnect(@Nullable Controller c) {
removeDiscoveryResult();
}
};
super.activate(configProperties);
}
@Override
protected void deactivate() {
leapController.removeListener(listener);
listener = null;
leapController.delete();
leapController = null;
super.deactivate();
}
@Override
protected void startScan() {
if (leapController.isConnected()) {
createDiscoveryResult();
}
}
@Override
protected void startBackgroundDiscovery() {
super.startBackgroundDiscovery();
leapController.addListener(listener);
}
private void createDiscoveryResult() {
DiscoveryResult result = DiscoveryResultBuilder
.create(new ThingUID(LeapMotionBindingConstants.THING_TYPE_CONTROLLER, "local"))
.withLabel("Leap Motion Controller").build();
thingDiscovered(result);
}
private void removeDiscoveryResult() {
removeOlderResults(System.currentTimeMillis());
}
}

View File

@@ -0,0 +1,173 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.leapmotion.internal.handler;
import static org.openhab.binding.leapmotion.internal.LeapMotionBindingConstants.*;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.types.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.leapmotion.leap.CircleGesture;
import com.leapmotion.leap.Controller;
import com.leapmotion.leap.FingerList;
import com.leapmotion.leap.Frame;
import com.leapmotion.leap.Gesture;
import com.leapmotion.leap.GestureList;
import com.leapmotion.leap.Hand;
import com.leapmotion.leap.Listener;
/**
* The {@link LeapMotionHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Kai Kreuzer - Initial contribution
* @author Thomas Eichstädt-Engelen - Initial version of listener logic
*
*/
@NonNullByDefault
public class LeapMotionHandler extends BaseThingHandler {
private final Logger logger = LoggerFactory.getLogger(LeapMotionHandler.class);
private @NonNullByDefault({}) LeapMotionListener listener;
private @NonNullByDefault({}) Controller leapController;
public LeapMotionHandler(Thing thing) {
super(thing);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
}
@Override
public void initialize() {
this.listener = new LeapMotionListener();
leapController = new Controller();
leapController.setPolicyFlags(Controller.PolicyFlag.POLICY_BACKGROUND_FRAMES);
leapController.addListener(this.listener);
if (leapController.isConnected()) {
updateStatus(ThingStatus.ONLINE);
} else {
updateStatus(ThingStatus.OFFLINE);
}
}
@Override
public void dispose() {
leapController.removeListener(this.listener);
listener = null;
leapController.delete();
leapController = null;
}
private class LeapMotionListener extends Listener {
private static final int RATE_LIMIT_IN_MS = 200;
private long lastEvent = 0;
private boolean noHand;
public LeapMotionListener() {
}
@Override
public void onConnect(@Nullable Controller controller) {
if (controller != null) {
controller.enableGesture(Gesture.Type.TYPE_KEY_TAP);
controller.enableGesture(Gesture.Type.TYPE_CIRCLE);
}
updateStatus(ThingStatus.ONLINE);
}
@Override
public void onDisconnect(@Nullable Controller controller) {
updateStatus(ThingStatus.OFFLINE);
}
@Override
public void onFrame(@Nullable Controller controller) {
if (controller == null) {
return;
}
Frame frame = controller.frame();
GestureList gestures = frame.gestures();
for (int i = 0; i < gestures.count(); i++) {
Gesture gesture = gestures.get(i);
switch (gesture.type()) {
case TYPE_KEY_TAP:
logger.debug("Key tap");
triggerChannel(CHANNEL_GESTURE, GESTURE_TAP);
break;
case TYPE_CIRCLE:
CircleGesture circle = new CircleGesture(gesture);
// Calculate clock direction using the angle between circle normal and pointable
boolean clockwiseness;
if (circle.pointable().direction().angleTo(circle.normal()) <= Math.PI / 4) {
// Clockwise if angle is less than 90 degrees
clockwiseness = true;
} else {
clockwiseness = false;
}
// Calculate angle swept since last frame
if (circle.state() == com.leapmotion.leap.Gesture.State.STATE_UPDATE) {
if (System.nanoTime() > lastEvent + TimeUnit.MILLISECONDS.toNanos(RATE_LIMIT_IN_MS)) {
logger.debug("Circle (clockwise={})", clockwiseness);
if (clockwiseness) {
triggerChannel(CHANNEL_GESTURE, GESTURE_CLOCKWISE);
} else {
triggerChannel(CHANNEL_GESTURE, GESTURE_ANTICLOCKWISE);
}
lastEvent = System.nanoTime();
}
}
break;
default:
logger.debug("Unknown gesture type.");
break;
}
}
if (!frame.hands().isEmpty()) {
noHand = false;
// Get the first hand
Hand hand = frame.hands().get(0);
// Check if the hand has any fingers
FingerList fingers = hand.fingers();
if (System.nanoTime() > lastEvent + TimeUnit.MILLISECONDS.toNanos(RATE_LIMIT_IN_MS)) {
int height = (int) hand.palmPosition().getY();
logger.debug("Fingers shown {} @ {}", fingers.count(), height);
triggerChannel(CHANNEL_GESTURE, GESTURE_FINGERS + fingers.count() + "_" + height);
lastEvent = System.nanoTime();
}
} else {
if (!noHand) {
noHand = true;
logger.debug("No hand");
triggerChannel(CHANNEL_GESTURE, GESTURE_NOHAND);
}
}
}
}
}

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="leapmotion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
<name>Leap Motion Binding</name>
<description>This is the binding for Leap Motion controllers.</description>
</binding:binding>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<config-description:config-descriptions
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0
https://openhab.org/schemas/config-description-1.0.0.xsd">
<config-description uri="profile:leapmotion:dimmer">
<parameter name="mode" type="text" required="false">
<label>Mode</label>
<description>The mode for interpreting gestures. Either it dims depending on the number of shown fingers or it uses
the height of the hand over the controller.</description>
<options>
<option value="fingers">Number of Fingers</option>
<option value="height">Height of Hand</option>
</options>
</parameter>
</config-description>
</config-description:config-descriptions>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="leapmotion"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="controller">
<label>Leap Motion Controller</label>
<description>A Leap Motion Gesture Sensor</description>
<channels>
<channel id="gesture" typeId="gesture"/>
</channels>
</thing-type>
<channel-type id="gesture">
<kind>trigger</kind>
<label>Gestures</label>
<description>Provides recognized gestures from the controller</description>
</channel-type>
</thing:thing-descriptions>