// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2016 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.google.appinventor.components.runtime;
import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.DesignerProperty;
import com.google.appinventor.components.annotations.PropertyCategory;
import com.google.appinventor.components.annotations.SimpleEvent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.annotations.SimpleProperty;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.common.PropertyTypeConstants;
import com.google.appinventor.components.common.YaVersion;
import android.os.Handler;
/**
* A component that provides a high-level interface to a touch sensor on a LEGO
* MINDSTORMS EV3 robot.
*
* @author jerry73204@gmail.com (jerry73204)
* @author spaded06543@gmail.com (Alvin Chang)
*/
@DesignerComponent(version = YaVersion.EV3_TOUCHSENSOR_COMPONENT_VERSION,
description = "A component that provides a high-level interface to a touch sensor on a " +
"LEGO MINDSTORMS EV3 robot.",
category = ComponentCategory.LEGOMINDSTORMS,
nonVisible = true,
iconName = "images/legoMindstormsEv3.png")
@SimpleObject
public class Ev3TouchSensor extends LegoMindstormsEv3Sensor implements Deleteable {
private static final int SENSOR_VALUE_THRESHOLD = 50;
private static final int SENSOR_TYPE = 16;
private static final int SENSOR_MODE_TOUCH = 0;
private static final String SENSOR_MODE_TOUCH_STRING = "touch";
private static final int DELAY_MILLISECONDS = 50;
private String modeString = SENSOR_MODE_TOUCH_STRING;
private int mode = SENSOR_MODE_TOUCH;
private Handler eventHandler;
private final Runnable sensorValueChecker;
private int savedPressedValue = -1;
private boolean pressedEventEnabled;
private boolean releasedEventEnabled;
/**
* Creates a new Ev3TouchSensor component.
*/
public Ev3TouchSensor(ComponentContainer container) {
super(container, "Ev3TouchSensor");
eventHandler = new Handler();
sensorValueChecker = new Runnable() {
public void run() {
String functionName = "";
if (bluetooth != null && bluetooth.IsConnected()) {
int currentPressedValue = getPressedValue(functionName);
if (savedPressedValue < 0) {
savedPressedValue = currentPressedValue;
eventHandler.postDelayed(this, DELAY_MILLISECONDS);
return;
}
if (savedPressedValue < SENSOR_VALUE_THRESHOLD) {
if (releasedEventEnabled && currentPressedValue >= SENSOR_VALUE_THRESHOLD)
Pressed();
} else {
if (pressedEventEnabled && currentPressedValue < SENSOR_VALUE_THRESHOLD)
Released();
}
savedPressedValue = currentPressedValue;
}
eventHandler.postDelayed(this, DELAY_MILLISECONDS);
}
};
eventHandler.post(sensorValueChecker);
PressedEventEnabled(false);
ReleasedEventEnabled(false);
}
/**
* Returns true if the touch sensor is pressed.
*/
@SimpleFunction(description = "Returns true if the touch sensor is pressed.")
public boolean IsPressed() {
String functionName = "IsPressed";
return getPressedValue(functionName) >= SENSOR_VALUE_THRESHOLD;
}
/**
* Specifies whether the Pressed event should fire when the touch sensor is
* pressed.
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_BOOLEAN,
defaultValue = "False")
@SimpleProperty
public void PressedEventEnabled(boolean enabled) {
pressedEventEnabled = enabled;
}
/**
* Returns whether the Pressed event should fire when the touch sensor is
* pressed.
*/
@SimpleProperty(description = "Whether the Released event should fire when the touch sensor is " +
"pressed.",
category = PropertyCategory.BEHAVIOR)
public boolean PressedEventEnabled() {
return pressedEventEnabled;
}
/**
* Called when the touch sensor is pressed.
*/
@SimpleEvent(description = "Called when the touch sensor is pressed.")
public void Pressed() {
EventDispatcher.dispatchEvent(this, "Pressed");
}
/**
* Returns whether the Released event should fire when the touch sensor is
* released.
*/
@SimpleProperty(description = "Whether the Released event should fire when the touch sensor is " +
"released.",
category = PropertyCategory.BEHAVIOR)
public boolean ReleasedEventEnabled() {
return releasedEventEnabled;
}
/**
* Specifies whether the Released event should fire when the touch sensor is
* released.
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_BOOLEAN,
defaultValue = "False")
@SimpleProperty
public void ReleasedEventEnabled(boolean enabled) {
releasedEventEnabled = enabled;
}
/**
* Called when the touch sensor is pressed.
*/
@SimpleEvent(description = "Called when the touch sensor is pressed.")
public void Released() {
EventDispatcher.dispatchEvent(this, "Released");
}
private int getPressedValue(String functionName) {
int value = readInputPercentage(functionName,
0, // assume layer = 0
sensorPortNumber,
SENSOR_TYPE,
mode);
return value;
}
// Deleteable implementation
@Override
public void onDelete() {
eventHandler.removeCallbacks(sensorValueChecker);
super.onDelete();
}
}