6 package com.google.appinventor.components.runtime;
19 import android.os.Handler;
30 @DesignerComponent(version = YaVersion.EV3_ULTRASONICSENSOR_COMPONENT_VERSION,
31 description =
"A component that provides a high-level interface to an ultrasonic sensor on a " +
32 "LEGO MINDSTORMS EV3 robot.",
33 category = ComponentCategory.LEGOMINDSTORMS,
35 iconName =
"images/legoMindstormsEv3.png")
38 private static final int SENSOR_TYPE = 30;
39 private static final int SENSOR_MODE_CM = 0;
40 private static final int SENSOR_MODE_INCH = 1;
41 private static final String SENSOR_MODE_CM_STRING =
"cm";
42 private static final String SENSOR_MODE_INCH_STRING =
"inch";
44 private static final int DEFAULT_BOTTOM_OF_RANGE = 30;
45 private static final int DEFAULT_TOP_OF_RANGE = 90;
46 private static final String DEFAULT_SENSOR_MODE_STRING = SENSOR_MODE_CM_STRING;
47 private static final int DELAY_MILLISECONDS = 50;
49 private String modeString = SENSOR_MODE_CM_STRING;
50 private int mode = SENSOR_MODE_CM;
51 private Handler eventHandler;
52 private final Runnable sensorValueChecker;
53 private double previousDistance = -1.0;
54 private int bottomOfRange;
55 private int topOfRange;
56 private boolean belowRangeEventEnabled;
57 private boolean withinRangeEventEnabled;
58 private boolean aboveRangeEventEnabled;
64 super(container,
"Ev3UltrasonicSensor");
66 eventHandler =
new Handler();
67 sensorValueChecker =
new Runnable() {
69 String functionName =
"";
72 double currentDistance = getDistance(functionName);
74 if (previousDistance < 0.0) {
75 previousDistance = currentDistance;
76 eventHandler.postDelayed(
this, DELAY_MILLISECONDS);
80 if (currentDistance < bottomOfRange) {
81 if (belowRangeEventEnabled && previousDistance >= bottomOfRange)
83 }
else if (currentDistance > topOfRange) {
84 if (aboveRangeEventEnabled && previousDistance <= topOfRange)
87 if (withinRangeEventEnabled && (previousDistance < bottomOfRange || previousDistance > topOfRange))
91 previousDistance = currentDistance;
94 eventHandler.postDelayed(
this, DELAY_MILLISECONDS);
98 eventHandler.post(sensorValueChecker);
105 Unit(DEFAULT_SENSOR_MODE_STRING);
108 @
SimpleFunction(description =
"Returns the current distance in centimeters as a value between " +
109 "0 and 254, or -1 if the distance can not be read.")
111 String functionName =
"GetDistance";
112 return getDistance(functionName);
115 private double getDistance(String functionName) {
117 return distance == 255 ? -1.0 : distance;
124 @SimpleProperty(description =
"The bottom of the range used for the BelowRange, WithinRange, " +
125 "and AboveRange events.",
126 category = PropertyCategory.BEHAVIOR)
128 return bottomOfRange;
136 defaultValue =
"" + DEFAULT_BOTTOM_OF_RANGE)
139 this.bottomOfRange = bottomOfRange;
146 @
SimpleProperty(description =
"The top of the range used for the BelowRange, WithinRange, and " +
147 "AboveRange events.",
158 defaultValue =
"" + DEFAULT_TOP_OF_RANGE)
161 this.topOfRange = topOfRange;
168 @
SimpleProperty(description =
"Whether the BelowRange event should fire when the distance " +
169 "goes below the BottomOfRange.",
172 return belowRangeEventEnabled;
180 defaultValue =
"False")
183 belowRangeEventEnabled = enabled;
189 @
SimpleEvent(description =
"Called when the detected distance has gone below the range.")
198 @
SimpleProperty(description =
"Whether the WithinRange event should fire when the distance" +
199 " goes between the BottomOfRange and the TopOfRange.",
202 return withinRangeEventEnabled;
210 defaultValue =
"False")
213 withinRangeEventEnabled = enabled;
219 @
SimpleEvent(description =
"Called when the detected distance has gone within the range.")
228 @
SimpleProperty(description =
"Whether the AboveRange event should fire when the distance " +
229 "goes above the TopOfRange.",
232 return aboveRangeEventEnabled;
240 defaultValue =
"False")
243 aboveRangeEventEnabled = enabled;
249 @
SimpleEvent(description =
"Called when the detected distance has gone above the range.")
258 defaultValue = DEFAULT_SENSOR_MODE_STRING)
260 public void Unit(String unitName) {
261 String functionName =
"Unit";
264 }
catch(IllegalArgumentException e) {
272 @
SimpleProperty(description =
"The distance unit, which can be either \"cm\" or \"inch\".",
281 @
SimpleFunction(description =
"Measure the distance in centimeters.")
283 String functionName =
"SetCmUnit";
285 setMode(SENSOR_MODE_CM_STRING);
286 }
catch(IllegalArgumentException e) {
296 String functionName =
"SetInchUnit";
298 setMode(SENSOR_MODE_INCH_STRING);
299 }
catch(IllegalArgumentException e) {
304 private void setMode(String newModeString) {
305 previousDistance = -1.0;
307 if (SENSOR_MODE_CM_STRING.equals(newModeString)) {
308 mode = SENSOR_MODE_CM;
310 else if (SENSOR_MODE_INCH_STRING.equals(newModeString)) {
311 mode = SENSOR_MODE_INCH;
314 throw new IllegalArgumentException();
316 this.modeString = newModeString;
322 eventHandler.removeCallbacks(sensorValueChecker);