user5313398
user5313398

Reputation: 753

Encoding issue for sending data via java socket?

I have the following code. I can do the reading all well and convert data into hex. The issue is when I send back String replyMessage = "7E81";, the device receives it as "3745". What is wrong? Is it due to my encoding, or do I need to do some conversion before I send back?

w =  new BufferedWriter(new OutputStreamWriter(receivedSocketConn1.getOutputStream(),"ISO-8859-15")); //
r = new BufferedReader(new InputStreamReader(receivedSocketConn1.getInputStream(),"ISO-8859-15"));
int nextChar=0;
while ((nextChar=r.read()) != -1) {               
    StringBuilder sb = new StringBuilder();
    sb.append(Integer.toHexString(nextChar));
    if (sb.length() < 2) {
        sb.insert(0, '0'); // pad with leading zero if needed
    }
    String hexChar = sb.toString();
    System.out.println("\n\n hex value is "+Integer.toHexString(nextChar).toUpperCase()+"   "+"Int value is:"+nextChar);          
    message = message+hexChar; 
    String messageID=message.substring(2,6);
    System.out.println("messageId is :"+messageID);
    if(messageID.equals("0100")){
        String replyMessage = "7E81";
        w.write(replyMessage+"\r\n");
        w.flush();
    }
}

Upvotes: 0

Views: 234

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 598134

Based on comments in chat:

the documentation say

Start Byte (1 Byte) 7e
Message ID (2 Byte) 01 00
Message Body Nature (2 Byte) 00 19
Phone no. of Device (6 Byte) 09 40 27 84 94 70
Message Serial number (2 Byte) 00 01
Message Body (N Byte) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 40 27 84 94 70 00
Check Code (1Byte) 19
End Byte (1Byte) 7E

so the start and termination is 7E

for outgoing

Start Byte (1 Byte) 7e
Message ID (2 Byte) 81 00
Message Body Nature (2 Byte) 00 13
Phone no. of Device (6 Byte) 09 40 27 84 94 70
Message Serial number (2 Byte) 00 01
Message Body (N Byte) 00 01 00 32 30 31 31 31 31 30 38 31 31 33 33 32 31 39 36
Check Code (1Byte) 9A
End Byte (1Byte) 7e

This means the protocol in question is a binary protocol, not a textual protocol that sends hex strings, like you thought. As such, your use of OutputStreamWriter, InputStreamReader, StringBuilder, toHexString(), etc are all completely wrong for this protocol.

Each message received and sent begins with a fixed 13-byte header, followed by a variable-length body (the header specifies the body length), and terminated by a fixed 2-byte footer.

With that in mind, try something more like this instead:

final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    for ( int j = 0; j < bytes.length; j++ ) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}

...

w = new DataOutputStream(new BufferedOutputStream(receivedSocketConn1.getOutputStream()));
r = new DataInputStream(new BufferedInputStream(receivedSocketConn1.getInputStream()));

...

if (r.readByte() != 0x7E) // start byte
{
    // ah oh, something went wrong!!
    receivedSocketConn1.close();
    return;
}

int messageID = r.readUnsignedShort();     // message ID
int bodyLen = r.readUnsignedShort();       // message body nature (body length)
byte[] phoneNum = new byte[6];
r.readFully(phoneNum);                     // device phone number
int serialNum = r.readUnsignedShort();     // message serial number
byte[] messageBody = new byte[bodyLen];    // message body
r.readFully(messageBody);
byte checkCode = r.readByte();             // check code

if (r.readByte() != 0x7E) // end byte
{
    // ah oh, something went wrong!!
    receivedSocketConn1.close();
    return;
}

// TODO: validate checkCode if needed...

System.out.println("messageId is : 0x" + Integer.toHexString(messageID));
System.out.println("phoneNum is : " + bytesToHex(phoneNum));
System.out.println("serialNum is : 0x" + Integer.toHexString(serialNum));
System.out.println("messageBody is : " + bytesToHex(messageBody));

// process message data as needed...

switch (messageID)
{
    case 0x100:
    {
        // ...

        byte[] replyBody = new byte[19];
        replyBody[0] = 0x00;
        replyBody[1] = 0x01;
        replyBody[2] = 0x00;
        replyBody[3] = 0x32;
        // and so on...

        checkCode = 0x9A; // calculate as needed...

        w.writeByte(0x7e);               // start byte
        w.writeShort(0x8100);            // message ID
        w.writeShort(replyBody.length);  // message body nature (body length)
        w.write(phoneNum);               // device phone number
        w.writeShort(0x0001);            // message serial number
        w.write(replyBody);              // message body
        w.writeByte(checkCode);          // check code
        w.writeByte(0x7e);               // end byte

        break;
    }

    // other message IDs as needed...
}

w.flush();

Upvotes: 2

Related Questions