7 package com.google.appinventor.components.runtime;
20 import android.os.Handler;
29 @DesignerComponent(version = YaVersion.NXT_SOUNDSENSOR_COMPONENT_VERSION,
30 description =
"A component that provides a high-level interface to a sound sensor on a " +
31 "LEGO MINDSTORMS NXT robot.",
32 category = ComponentCategory.LEGOMINDSTORMS,
34 iconName =
"images/legoMindstormsNxt.png")
38 private enum State { UNKNOWN, BELOW_RANGE, WITHIN_RANGE, ABOVE_RANGE }
39 private static final String DEFAULT_SENSOR_PORT =
"2";
40 private static final int DEFAULT_BOTTOM_OF_RANGE = 256;
41 private static final int DEFAULT_TOP_OF_RANGE = 767;
43 private Handler handler;
44 private final Runnable sensorReader;
45 private State previousState;
46 private int bottomOfRange;
47 private int topOfRange;
48 private boolean belowRangeEventEnabled;
49 private boolean withinRangeEventEnabled;
50 private boolean aboveRangeEventEnabled;
56 super(container,
"NxtSoundSensor");
57 handler =
new Handler();
58 previousState = State.UNKNOWN;
59 sensorReader =
new Runnable() {
62 SensorValue<Integer> sensorValue = getSoundValue(
"");
63 if (sensorValue.valid) {
65 if (sensorValue.value < bottomOfRange) {
66 currentState = State.BELOW_RANGE;
67 }
else if (sensorValue.value > topOfRange) {
68 currentState = State.ABOVE_RANGE;
70 currentState = State.WITHIN_RANGE;
73 if (currentState != previousState) {
74 if (currentState == State.BELOW_RANGE && belowRangeEventEnabled) {
77 if (currentState == State.WITHIN_RANGE && withinRangeEventEnabled) {
80 if (currentState == State.ABOVE_RANGE && aboveRangeEventEnabled) {
85 previousState = currentState;
88 if (isHandlerNeeded()) {
89 handler.post(sensorReader);
105 setInputMode(functionName,
port, SENSOR_TYPE_SOUND_DB, SENSOR_MODE_RAWMODE);
113 defaultValue = DEFAULT_SENSOR_PORT)
119 @
SimpleFunction(description =
"Returns the current sound level as a value between 0 and 1023, " +
120 "or -1 if the sound level can not be read.")
122 String functionName =
"GetSoundLevel";
127 SensorValue<Integer> sensorValue = getSoundValue(functionName);
128 if (sensorValue.valid) {
129 return sensorValue.value;
136 private SensorValue<Integer> getSoundValue(String functionName) {
138 if (returnPackage !=
null) {
142 return new SensorValue<Integer>(
true, normalizedValue);
147 return new SensorValue<Integer>(
false,
null);
154 @SimpleProperty(description =
"The bottom of the range used for the BelowRange, WithinRange," +
155 " and AboveRange events.",
156 category = PropertyCategory.BEHAVIOR)
158 return bottomOfRange;
166 defaultValue =
"" + DEFAULT_BOTTOM_OF_RANGE)
169 this.bottomOfRange = bottomOfRange;
170 previousState = State.UNKNOWN;
177 @
SimpleProperty(description =
"The top of the range used for the BelowRange, WithinRange, and" +
178 " AboveRange events.",
189 defaultValue =
"" + DEFAULT_TOP_OF_RANGE)
192 this.topOfRange = topOfRange;
193 previousState = State.UNKNOWN;
200 @
SimpleProperty(description =
"Whether the BelowRange event should fire when the sound level" +
201 " goes below the BottomOfRange.",
204 return belowRangeEventEnabled;
214 boolean handlerWasNeeded = isHandlerNeeded();
216 belowRangeEventEnabled = enabled;
218 boolean handlerIsNeeded = isHandlerNeeded();
219 if (handlerWasNeeded && !handlerIsNeeded) {
220 handler.removeCallbacks(sensorReader);
222 if (!handlerWasNeeded && handlerIsNeeded) {
223 previousState = State.UNKNOWN;
224 handler.post(sensorReader);
228 @
SimpleEvent(description =
"Sound level has gone below the range.")
237 @
SimpleProperty(description =
"Whether the WithinRange event should fire when the sound level" +
238 " goes between the BottomOfRange and the TopOfRange.",
241 return withinRangeEventEnabled;
251 boolean handlerWasNeeded = isHandlerNeeded();
253 withinRangeEventEnabled = enabled;
255 boolean handlerIsNeeded = isHandlerNeeded();
256 if (handlerWasNeeded && !handlerIsNeeded) {
257 handler.removeCallbacks(sensorReader);
259 if (!handlerWasNeeded && handlerIsNeeded) {
260 previousState = State.UNKNOWN;
261 handler.post(sensorReader);
265 @
SimpleEvent(description =
"Sound level has gone within the range.")
274 @
SimpleProperty(description =
"Whether the AboveRange event should fire when the sound level" +
275 " goes above the TopOfRange.",
278 return aboveRangeEventEnabled;
288 boolean handlerWasNeeded = isHandlerNeeded();
290 aboveRangeEventEnabled = enabled;
292 boolean handlerIsNeeded = isHandlerNeeded();
293 if (handlerWasNeeded && !handlerIsNeeded) {
294 handler.removeCallbacks(sensorReader);
296 if (!handlerWasNeeded && handlerIsNeeded) {
297 previousState = State.UNKNOWN;
298 handler.post(sensorReader);
302 @
SimpleEvent(description =
"Sound level has gone above the range.")
307 private boolean isHandlerNeeded() {
308 return belowRangeEventEnabled || withinRangeEventEnabled || aboveRangeEventEnabled;
315 handler.removeCallbacks(sensorReader);