7 package com.google.appinventor.components.runtime;
16 import android.util.Log;
18 import java.io.UnsupportedEncodingException;
19 import java.util.Collections;
20 import java.util.HashMap;
31 private static final int TOY_ROBOT = 0x0804;
35 ERROR_MESSAGES =
new HashMap<Integer, String>();
36 ERROR_MESSAGES.put(0x20,
"Pending communication transaction in progress");
37 ERROR_MESSAGES.put(0x40,
"Specified mailbox queue is empty");
38 ERROR_MESSAGES.put(0x81,
"No more handles");
39 ERROR_MESSAGES.put(0x82,
"No space");
40 ERROR_MESSAGES.put(0x83,
"No more files");
41 ERROR_MESSAGES.put(0x84,
"End of file expected");
42 ERROR_MESSAGES.put(0x85,
"End of file");
43 ERROR_MESSAGES.put(0x86,
"Not a linear file");
44 ERROR_MESSAGES.put(0x87,
"File not found");
45 ERROR_MESSAGES.put(0x88,
"Handle already closed");
46 ERROR_MESSAGES.put(0x89,
"No linear space");
47 ERROR_MESSAGES.put(0x8A,
"Undefined error");
48 ERROR_MESSAGES.put(0x8B,
"File is busy");
49 ERROR_MESSAGES.put(0x8C,
"No write buffers");
50 ERROR_MESSAGES.put(0x8D,
"Append not possible");
51 ERROR_MESSAGES.put(0x8E,
"File is full");
52 ERROR_MESSAGES.put(0x8F,
"File exists");
53 ERROR_MESSAGES.put(0x90,
"Module not found");
54 ERROR_MESSAGES.put(0x91,
"Out of boundary");
55 ERROR_MESSAGES.put(0x92,
"Illegal file name");
56 ERROR_MESSAGES.put(0x93,
"Illegal handle");
57 ERROR_MESSAGES.put(0xBD,
"Request failed (i.e. specified file not found)");
58 ERROR_MESSAGES.put(0xBE,
"Unknown command opcode");
59 ERROR_MESSAGES.put(0xBF,
"Insane packet");
60 ERROR_MESSAGES.put(0xC0,
"Data contains out-of-range values");
61 ERROR_MESSAGES.put(0xDD,
"Communication bus error");
62 ERROR_MESSAGES.put(0xDE,
"No free memory in communication buffer");
63 ERROR_MESSAGES.put(0xDF,
"Specified channel/connection is not valid");
64 ERROR_MESSAGES.put(0xE0,
"Specified channel/connection not configured or busy");
65 ERROR_MESSAGES.put(0xEC,
"No active program");
66 ERROR_MESSAGES.put(0xED,
"Illegal size specified");
67 ERROR_MESSAGES.put(0xEE,
"Illegal mailbox queue ID specified");
68 ERROR_MESSAGES.put(0xEF,
"Attempted to access invalid field of a structure");
69 ERROR_MESSAGES.put(0xF0,
"Bad input or output specified");
70 ERROR_MESSAGES.put(0xFB,
"Insufficient memory available");
71 ERROR_MESSAGES.put(0xFF,
"Bad arguments");
84 super(container.
$form());
106 description =
"The BluetoothClient component that should be used for communication.",
121 bluetooth.removeBluetoothConnectionListener(
this);
126 if (bluetoothClient !=
null) {
128 bluetooth.attachComponent(
this, Collections.singleton(TOY_ROBOT));
129 bluetooth.addBluetoothConnectionListener(
this);
137 protected final void setOutputState(String functionName,
int port,
int power,
int mode,
138 int regulationMode,
int turnRatio,
int runState,
long tachoLimit) {
140 byte[] command =
new byte[12];
141 command[0] = (byte) 0x80;
142 command[1] = (byte) 0x04;
158 protected final void setInputMode(String functionName,
int port,
int sensorType,
int sensorMode) {
159 byte[] command =
new byte[5];
160 command[0] = (byte) 0x80;
161 command[1] = (byte) 0x05;
169 byte[] command =
new byte[3];
170 command[0] = (byte) 0x00;
171 command[1] = (byte) 0x07;
175 if (returnPackage.length == 16) {
176 return returnPackage;
178 Log.w(
logTag, functionName +
": unexpected return package length " +
179 returnPackage.length +
" (expected 16)");
186 byte[] command =
new byte[3];
187 command[0] = (byte) 0x80;
188 command[1] = (byte) 0x08;
194 byte[] command =
new byte[3];
195 command[0] = (byte) 0x00;
196 command[1] = (byte) 0x0E;
200 if (returnPackage.length == 4) {
203 Log.w(
logTag, functionName +
": unexpected return package length " +
204 returnPackage.length +
" (expected 4)");
210 protected final void lsWrite(String functionName,
int port,
byte[] data,
int rxDataLength) {
211 if (data.length > 16) {
212 throw new IllegalArgumentException(
"length must be <= 16");
214 byte[] command =
new byte[5 + data.length];
215 command[0] = (byte) 0x00;
216 command[1] = (byte) 0x0F;
220 System.arraycopy(data, 0, command, 5, data.length);
225 protected final byte[]
lsRead(String functionName,
int port) {
226 byte[] command =
new byte[3];
227 command[0] = (byte) 0x00;
228 command[1] = (byte) 0x10;
232 if (returnPackage.length == 20) {
233 return returnPackage;
235 Log.w(
logTag, functionName +
": unexpected return package length " +
236 returnPackage.length +
" (expected 20)");
266 return receiveReturnPackage(functionName);
269 protected final void sendCommand(String functionName,
byte[] command) {
270 byte[] header =
new byte[2];
276 private byte[] receiveReturnPackage(String functionName) {
278 if (header.length == 2) {
281 if (returnPackage.length >= 3) {
282 return returnPackage;
287 ErrorMessages.ERROR_NXT_INVALID_RETURN_PACKAGE);
291 protected final boolean evaluateStatus(String functionName,
byte[] returnPackage,
byte command) {
292 int status =
getStatus(functionName, returnPackage, command);
296 handleError(functionName, status);
301 protected final int getStatus(String functionName,
byte[] returnPackage,
byte command) {
302 if (returnPackage.length >= 3) {
303 if (returnPackage[0] != (
byte) 0x02) {
304 Log.w(
logTag, functionName +
": unexpected return package byte 0: 0x" +
305 Integer.toHexString(returnPackage[0] & 0xFF) +
" (expected 0x02)");
307 if (returnPackage[1] != command) {
308 Log.w(
logTag, functionName +
": unexpected return package byte 1: 0x" +
309 Integer.toHexString(returnPackage[1] & 0xFF) +
" (expected 0x" +
310 Integer.toHexString(command & 0xFF) +
")");
314 Log.w(
logTag, functionName +
": unexpected return package length " +
315 returnPackage.length +
" (expected >= 3)");
320 private void handleError(String functionName,
int status) {
327 String errorMessage = ERROR_MESSAGES.get(status);
328 if (errorMessage !=
null) {
330 ErrorMessages.ERROR_NXT_ERROR_CODE_RECEIVED, errorMessage);
333 ErrorMessages.ERROR_NXT_ERROR_CODE_RECEIVED,
334 "Error code 0x" + Integer.toHexString(status & 0xFF));
340 bytes[offset] = value ? (byte) 1 : (
byte) 0;
344 bytes[offset] = (byte) value;
348 bytes[offset] = (byte) value;
352 bytes[offset] = (byte) (value & 0xff);
354 bytes[offset + 1] = (byte) (value & 0xff);
358 bytes[offset] = (byte) (value & 0xff);
360 bytes[offset + 1] = (byte) (value & 0xff);
364 bytes[offset] = (byte) (value & 0xff);
366 bytes[offset + 1] = (byte) (value & 0xff);
368 bytes[offset + 2] = (byte) (value & 0xff);
370 bytes[offset + 3] = (byte) (value & 0xff);
374 bytes[offset] = (byte) (value & 0xff);
376 bytes[offset + 1] = (byte) (value & 0xff);
378 bytes[offset + 2] = (byte) (value & 0xff);
380 bytes[offset + 3] = (byte) (value & 0xff);
385 if (value.length() > maxCount) {
386 value = value.substring(0, maxCount);
390 valueBytes = value.getBytes(
"ISO-8859-1");
391 }
catch (UnsupportedEncodingException e) {
392 Log.w(
logTag,
"UnsupportedEncodingException: " + e.getMessage());
393 valueBytes = value.getBytes();
395 int lengthToCopy = Math.min(maxCount, valueBytes.length);
396 System.arraycopy(valueBytes, 0, bytes, offset, lengthToCopy);
400 return bytes[offset] != 0;
404 return bytes[offset];
408 return bytes[offset] & 0xFF;
412 return (bytes[offset] & 0xFF) |
413 (bytes[offset + 1] << 8);
417 return (bytes[offset] & 0xFF) |
418 ((bytes[offset + 1] & 0xFF) << 8);
422 return (bytes[offset] & 0xFF) |
423 ((bytes[offset + 1] & 0xFF) << 8) |
424 ((bytes[offset + 2] & 0xFF) << 16) |
425 (bytes[offset + 3] << 24);
429 return (bytes[offset] & 0xFFL) |
430 ((bytes[offset + 1] & 0xFFL) << 8) |
431 ((bytes[offset + 2] & 0xFFL) << 16) |
432 ((bytes[offset + 3] & 0xFFL) << 24);
438 for (
int i = offset; i < bytes.length; i++) {
449 return new String(bytes, offset, count,
"ISO-8859-1");
450 }
catch (UnsupportedEncodingException e) {
451 Log.w(
logTag,
"UnsupportedEncodingException: " + e.getMessage());
452 return new String(bytes, offset, count);
457 if (motorPortLetter.length() == 1) {
460 throw new IllegalArgumentException(
"Illegal motor port letter " + motorPortLetter);
464 if (motorPortLetter ==
'A' || motorPortLetter ==
'a') {
466 }
else if (motorPortLetter ==
'B' || motorPortLetter ==
'b') {
468 }
else if (motorPortLetter ==
'C' || motorPortLetter ==
'c') {
471 throw new IllegalArgumentException(
"Illegal motor port letter " + motorPortLetter);
475 if (sensorPortLetter.length() == 1) {
478 throw new IllegalArgumentException(
"Illegal sensor port letter " + sensorPortLetter);
482 if (sensorPortLetter ==
'1') {
484 }
else if (sensorPortLetter ==
'2') {
486 }
else if (sensorPortLetter ==
'3') {
488 }
else if (sensorPortLetter ==
'4') {
491 throw new IllegalArgumentException(
"Illegal sensor port letter " + sensorPortLetter);
496 Log.w(
logTag,
"power " + power +
" is invalid, using -100.");
500 Log.w(
logTag,
"power " + power +
" is invalid, using 100.");
507 if (turnRatio < -100) {
508 Log.w(
logTag,
"turnRatio " + turnRatio +
" is invalid, using -100.");
511 if (turnRatio > 100) {
512 Log.w(
logTag,
"turnRatio " + turnRatio +
" is invalid, using 100.");
535 bluetooth.removeBluetoothConnectionListener(
this);