0

I can write to a mailbox on the NXT but cannot (yet) read from it.

the Setup is to use MindDroid from GitHub as a starter.

sendBTCmessage(0, BTCommunicator.START_PROGRAM, "bt1.rxe");
            sendBTCmessage(1000, BTCommunicator.SENDMAILBOX, "Kilroy was here");
            sendBTCmessage(3000, BTCommunicator.READMAILBOX,"",1);

the SendBTCmessage (int,int,String,int) is new...

void sendBTCmessage(int delay, int message, String name, int mBox) { Bundle myBundle = new Bundle(); myBundle.putInt("message", message); myBundle.putString("name", name); myBundle.putInt ("MailBox",mBox); Message myMessage = myHandler.obtainMessage(); myMessage.setData(myBundle); Log.d(TAG,String.format("sendBTCmessageStringMbox %d %d %s mBox=%d",delay, message,name,mBox));

    if (delay == 0)
        btcHandler.sendMessage(myMessage);
    else
        btcHandler.sendMessageDelayed(myMessage, delay);
}

This sends the request to a handler where...

case SENDMAILBOX:
                Log.d(TAG,String.format("case SENDMAILBOX %d %s",myMessage.getData().getInt("value1"), myMessage.getData().getString("name")));
                sendMailbox(myMessage.getData().getInt("MailBox"),myMessage.getData().getString("name"));
                break;
            case READMAILBOX:
                Log.d(TAG,String.format("case ReadMAILBOX %d %s",myMessage.getData().getInt("MailBox"), myMessage.getData().getString("name")));
                readMailbox(myMessage.getData().getInt("MailBox")); 
                break;
            case START_PROGRAM:
                startProgram(myMessage.getData().getString("name"));
                break;

the message is further prepared, the "startProgram" is standard and works fine...

    private void startProgram(String programName) {
    byte[] message = LCPMessage.getStartProgramMessage(programName);
    Log.d(TAG,String.format("startProgram %s %s",programName,LCPMessage.getStartProgramMessage(programName)));
    sendMessageAndState(message);
}
private void readMailbox(int mBox){
    byte[] message = LCPMessage.getReadMailboxMessage(mBox);
    Log.d(TAG,String.format("readMailbox %d",mBox));
    logByteArray(TAG,"sendMailBox",message);
    sendMessageAndState(message);
}
private void sendMailbox(int mBox,String text){
    byte[] message = LCPMessage.getMailBoxMessage(mBox,text);
    Log.d(TAG,String.format("mail box message %s %d",text,message.length));
    logByteArray(TAG,"sendMailBox",message);
    sendMessageAndState(message);
}

The final preparation is ...

    public static byte[] getMailBoxMessage(int mBox, String text){
    byte[] message = new byte[text.length()+5];
    message[0] = DIRECT_COMMAND_NOREPLY;
    message[1] = MESSAGE_WRITE;
    message[2] =  (byte)mBox;
    message[3] =  (byte)(text.length()+1);
    for (int pos=0; pos<text.length(); pos++)
        message[4+pos] = (byte) text.charAt(pos);
    message[text.length()+4] = 0;
    return message;
}
public static byte[] getReadMailboxMessage(int mBox){
    byte[] message = new byte[5];
    message[0] = DIRECT_COMMAND_REPLY;
    message[1] = MESSAGE_READ;
    message[2] = (byte)(mBox+10);
    message[3] = (byte)mBox;
    message[4] = (byte)0x01; //true 
    return message;
}
public static byte[] getStartProgramMessage(String programName) {
    byte[] message = new byte[22];

    message[0] = DIRECT_COMMAND_NOREPLY;
    message[1] = START_PROGRAM;

    // copy programName and end with 0 delimiter
    for (int pos=0; pos<programName.length(); pos++)
        message[2+pos] = (byte) programName.charAt(pos);

    message[programName.length()+2] = 0;

    return message;
}

The problem I have is that the NXT program to receive the message works fine, but I cannot figure out how to read what is in the mailbox http://www.android-tele-health.com/bt1.rbt is the program running in the NXT.

Any help appreciated...Thanks John

user462990
  • 5,472
  • 3
  • 33
  • 35

1 Answers1

2

The MESSAGE_READ command requests the remote NXT to send the first available message in the mailbox back to you as a reply. That's why you have to use DIRECT_COMMAND_REPLY as the command type, instead of DIRECT_COMMAND_NOREPLY.

You don't show how you're reading reply data from your Bluetooth stream, but it looks like your method SendMessageAndState() needs to be able to read reply data from the remote NXT and return it to you as an appropriate data type, if you request a reply from the NXT using either DIRECT_COMMAND_REPLY or SYSTEM_COMMAND_REPLY.

The code snippets below showed how I solved this problem (excuse me if it isn't the most elegant Java code in the world!)

public synchronized byte[] sendBTMessage(byte[] request) {
    int lsb = request.length;
    int msb = request.length >>> 8;
    try {
        mOut.write((byte) lsb);
        mOut.write((byte) msb);
        mOut.write(request);
    } catch (IOException e) {
        Log.e(TAG, "sendBTMessage: Write failed.");
    }
    if ((request[0] & MASK_NOREPLY) == 0) { // Reply requested
        byte[] reply = readBTMessage();
        if (reply == null) {
            return null;
        }
        if (reply[0] != 0x02) {
            // Not a reply?
            Log.e(TAG, "sendBTMessage read a message that was not a reply.");
            Log.e(TAG, "Hex: " + HexValues(reply));
            return new byte[] {(byte) 0xFF}; 
        }
        if (reply[1] != request[1]) {
            // Reply for incorrect request?
            Log.e(TAG, "sendBTMessage received a reply for the wrong request.");
            Log.e(TAG, "Hex: " + HexValues(reply));
            return new byte[] {(byte) 0xFF}; 
        }
        byte[] replymessage = new byte[reply.length - 2];
        System.arraycopy(reply, 2, replymessage, 0, replymessage.length);               
        return replymessage;
    }
    return new byte[] {0};
}

public byte[] readBTMessage() {
    byte[] buffer = new byte[66];  // All BT messages are a maximum of 66 bytes long
    int numBytes;
    try {
        numBytes = mIn.read(buffer);
    } catch (IOException e) {
        Log.e(TAG, "readBTMessage: Read failed.");
        return null;
    }
    if (numBytes <= 0) return null;
    int msgLength = buffer[0] + (buffer[1] << 8);
    if (numBytes != msgLength + 2) {
        Log.e(TAG, "readBTMessage: BT Message wrong length.");
        Log.e(TAG, "BT Message: " + HexValues(buffer));
        return null;
    }
    byte[] result = new byte[msgLength];
    System.arraycopy(buffer, 2, result, 0, msgLength);
    return result;
}

mIn and mOut are the Bluetooth socket's InputStream and OutputStream respectively, returned by calling getInputStream() and getOutputStream() on the BluetoothSocket returned by createRfcommSocketToServiceRecord(SPP_UUID). MASK_NOREPLY is defined elsewhere in my package as:

  public static byte MASK_NOREPLY = (byte) 0x80;

So, your message sending method (or somewhere nearby) should be prepared to read the reply from the remote NXT if you've requested one. Then you will be able to see the mailbox message you've requested from the remote NXT.

Your NXT-G program looks fine, BTW. -- Mike

dnlcrl
  • 5,022
  • 3
  • 32
  • 40